| Differences between
and this patch
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -6 / +38 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 546-551 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
546
		0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
548
		0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
547
		0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
549
		0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
548
		0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
550
		0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
551
		0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */; };
552
		0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
549
		0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
553
		0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
550
		0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
554
		0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
551
		0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
555
		0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
Lines 745-750 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
745
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
749
		0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
746
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
750
		0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
747
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
751
		0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
752
		0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
753
		0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
754
		0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; };
755
		0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
748
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
756
		0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
749
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
757
		0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
750
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
758
		0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 1917-1922 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
1917
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1925
		0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = "<group>"; };
1918
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1926
		0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
1919
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1927
		0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
1928
		0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = "<group>"; };
1929
		0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = "<group>"; };
1920
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1930
		0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
1921
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1931
		0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = "<group>"; };
1922
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
1932
		0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
Lines 2386-2391 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
2386
		0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
2396
		0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
2387
		0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
2397
		0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
2388
		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
2398
		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
2399
		0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInferredTypeCheck.cpp; path = dfg/DFGInferredTypeCheck.cpp; sourceTree = "<group>"; };
2400
		0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInferredTypeCheck.h; path = dfg/DFGInferredTypeCheck.h; sourceTree = "<group>"; };
2389
		0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
2401
		0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
2390
		0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
2402
		0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
2391
		0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; };
2403
		0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; };
Lines 2573-2578 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
2573
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2585
		0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = "<group>"; };
2574
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2586
		0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = "<group>"; };
2575
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2587
		0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = "<group>"; };
2588
		0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = "<group>"; };
2589
		0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = "<group>"; };
2590
		0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = "<group>"; };
2591
		0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
2576
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2592
		0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
2577
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2593
		0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
2578
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
2594
		0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
Lines 4651-4658 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4651
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4667
				BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
4652
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4668
				BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
4653
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4669
				BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
4654
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4655
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4670
				FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
4671
				FE1C0FFC1B193E9800B53FCA /* Exception.h */,
4656
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4672
				0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
4657
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4673
				0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
4658
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
4674
				1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
Lines 4686-4691 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
4686
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4702
				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
4687
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4703
				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
4688
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4704
				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
4705
				0F0A75201B94BFA900110660 /* InferredType.cpp */,
4706
				0F0A75211B94BFA900110660 /* InferredType.h */,
4707
				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
4708
				0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
4689
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4709
				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
4690
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4710
				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
4691
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
4711
				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
Lines 4736-4745 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
4736
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4756
				0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
4737
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4757
				A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
4738
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4758
				A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
4739
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4740
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4741
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4759
				8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
4742
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4760
				8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
4761
				86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
4762
				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
4743
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4763
				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
4744
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4764
				657CF45719BF6662004ACBF2 /* JSCallee.h */,
4745
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
4765
				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
Lines 5043-5051 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
5043
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5063
				0FE050241AA9095600D33B33 /* VarOffset.h */,
5044
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5064
				E18E3A570DF9278C00D90B34 /* VM.cpp */,
5045
				E18E3A560DF9278C00D90B34 /* VM.h */,
5065
				E18E3A560DF9278C00D90B34 /* VM.h */,
5046
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5047
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5066
				FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
5048
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5067
				FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
5068
				FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
5049
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5069
				FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
5050
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5070
				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
5051
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
5071
				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
Lines 5197-5202 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5197
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5217
				0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
5198
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5218
				0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
5199
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5219
				0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
5220
				0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
5200
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5221
				C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
5201
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5222
				C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
5202
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
5223
				0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
Lines 5241-5246 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
5241
				0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
5262
				0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
5242
				0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
5263
				0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
5243
				0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
5264
				0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
5265
				0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */,
5266
				0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */,
5244
				0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
5267
				0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
5245
				0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
5268
				0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
5246
				A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
5269
				A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
Lines 5273-5282 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
5273
				0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
5296
				0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
5274
				A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
5297
				A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
5275
				A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
5298
				A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
5276
				0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
5277
				0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
5278
				79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */,
5299
				79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */,
5279
				79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */,
5300
				79F8FC1D1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h */,
5301
				0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
5302
				0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
5280
				0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */,
5303
				0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */,
5281
				0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
5304
				0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
5282
				0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
5305
				0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
Lines 5344-5349 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
5344
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5367
				0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
5345
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5368
				0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
5346
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5369
				0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
5370
				0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
5347
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5371
				0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
5348
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5372
				0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
5349
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
5373
				0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
Lines 5934-5939 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
5934
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5958
				FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
5935
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5959
				C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
5936
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5960
				FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
5961
				0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
5937
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5962
				79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
5938
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5963
				52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
5939
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
5964
				52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
Lines 6047-6052 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
6047
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6072
				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
6048
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6073
				7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
6049
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6074
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
6075
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
6050
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6076
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
6051
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6077
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
6052
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
6078
				709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
Lines 6326-6337 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec17
6326
				0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
6352
				0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
6327
				0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */,
6353
				0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */,
6328
				0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
6354
				0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
6355
				0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */,
6329
				A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
6356
				A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
6330
				0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
6357
				0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
6331
				0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
6358
				0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
6332
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6359
				0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
6333
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6360
				0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
6334
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6361
				0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
6362
				0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
6335
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6363
				0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
6336
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6364
				0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
6337
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
6365
				0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
Lines 6497-6502 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec18
6497
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6525
				BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
6498
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6526
				A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
6499
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6527
				0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
6528
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
6500
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6529
				0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
6501
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6530
				0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
6502
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
6531
				0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
Lines 7439-7444 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec19
7439
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7468
				1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
7440
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7469
				A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
7441
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7470
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
7471
				0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
7442
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7472
				2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
7443
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7473
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
7444
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
7474
				0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
Lines 7819-7824 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec20
7819
				0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
7849
				0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
7820
				86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
7850
				86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
7821
				0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
7851
				0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
7852
				0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
7822
				0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
7853
				0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
7823
				14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
7854
				14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
7824
				147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */,
7855
				147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */,
Lines 7853-7858 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec21
7853
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7884
				86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
7854
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7885
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
7855
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7886
				A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
7887
				0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
7856
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7888
				A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
7857
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7889
				A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
7858
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
7890
				A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
- Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp +14 lines
Lines 686-691 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec1
686
    }
686
    }
687
687
688
    case Replace: {
688
    case Replace: {
689
        if (InferredType* type = structure()->inferredTypeFor(ident.impl())) {
690
            if (verbose)
691
                dataLog("Have type: ", type->descriptor(), "\n");
692
            state.failAndRepatch.append(jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor()));
693
        } else if (verbose)
694
            dataLog("Don't have type.\n");
695
        
689
        if (isInlineOffset(m_offset)) {
696
        if (isInlineOffset(m_offset)) {
690
            jit.storeValue(
697
            jit.storeValue(
691
                valueRegs,
698
                valueRegs,
Lines 709-714 void AccessCase::generate(AccessGenerati Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp_sec2
709
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
716
        RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity());
710
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
717
        RELEASE_ASSERT(!structure()->couldHaveIndexingHeader());
711
718
719
        if (InferredType* type = newStructure()->inferredTypeFor(ident.impl())) {
720
            if (verbose)
721
                dataLog("Have type: ", type->descriptor(), "\n");
722
            state.failAndRepatch.append(jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor()));
723
        } else if (verbose)
724
            dataLog("Don't have type.\n");
725
        
712
        CCallHelpers::JumpList slowPath;
726
        CCallHelpers::JumpList slowPath;
713
727
714
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
728
        ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
- Source/JavaScriptCore/bytecode/PutByIdFlags.cpp -7 / +6 lines
Lines 26-31 Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "PutByIdFlags.h"
27
#include "PutByIdFlags.h"
28
28
29
#include "InferredType.h"
29
#include <wtf/CommaPrinter.h>
30
#include <wtf/CommaPrinter.h>
30
#include <wtf/PrintStream.h>
31
#include <wtf/PrintStream.h>
31
#include <wtf/StringPrintStream.h>
32
#include <wtf/StringPrintStream.h>
Lines 35-50 namespace WTF { Source/JavaScriptCore/bytecode/PutByIdFlags.cpp_sec2
35
using namespace JSC;
36
using namespace JSC;
36
37
37
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
void printInternal(PrintStream& out, PutByIdFlags flags) {
38
    StringPrintStream stringOut;
39
    CommaPrinter comma("|");
39
    CommaPrinter comma("|");
40
    if (flags & PutByIdIsDirect)
40
    if (flags & PutByIdIsDirect)
41
        stringOut.print(comma, "IsDirect");
41
        out.print(comma, "IsDirect");
42
42
43
    CString string = stringOut.toCString();
43
    InferredType::Kind kind = InferredType::kindForFlags(flags);
44
    if (!string.length())
44
    out.print(comma, kind);
45
        out.print("None");
45
    if (InferredType::hasStructure(kind))
46
    else
46
        out.print(":", bitwise_cast<int32_t>(decodeStructureID(flags)));
47
        out.print(string);
48
}
47
}
49
48
50
} // namespace WTF
49
} // namespace WTF
- Source/JavaScriptCore/bytecode/PutByIdFlags.h -2 / +59 lines
Lines 26-38 Source/JavaScriptCore/bytecode/PutByIdFlags.h_sec1
26
#ifndef PutByIdFlags_h
26
#ifndef PutByIdFlags_h
27
#define PutByIdFlags_h
27
#define PutByIdFlags_h
28
28
29
#include "StructureIDTable.h"
30
29
namespace JSC {
31
namespace JSC {
30
32
31
enum PutByIdFlags {
33
enum PutByIdFlags : intptr_t {
32
    PutByIdNone = 0,
34
    PutByIdNone = 0,
33
    PutByIdIsDirect = 1
35
36
    // This flag indicates that the put_by_id is direct. That means that we store the property without
37
    // checking if the prototype chain has a setter.
38
    PutByIdIsDirect = 0x1,
39
    PutByIdPersistentFlagsMask = 0x1,
40
41
    // NOTE: The values below must be in sync with what is in LowLevelInterpreter.asm.
42
43
    // Determining the required inferred type involves first checking the primary type mask, and then
44
    // using that to figure out the meaning of the secondary mask:
45
    // switch (flags & PutByIdPrimaryTypeMask) {
46
    // case PutByIdPrimaryTypeSecondary:
47
    //     switch (flags & PutByIdSecondaryTypeMask) {
48
    //     ...
49
    //     }
50
    //     break;
51
    // case PutByIdPrimaryTypeObjectWithStructure:
52
    // case PutByIdPrimaryTypeObjectWithStructureOrOther:
53
    //     StructureID structureID = decodeStructureID(flags);
54
    //     break;
55
    // }
56
    PutByIdPrimaryTypeMask = 0x6,
57
    PutByIdPrimaryTypeSecondary = 0x0, // Need to check the secondary type mask for the type.
58
    PutByIdPrimaryTypeObjectWithStructure = 0x2, // Secondary type has structure ID.
59
    PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4, // Secondary type has structure ID.
60
61
    PutByIdSecondaryTypeMask = -0x8,
62
    PutByIdSecondaryTypeBottom = 0x0,
63
    PutByIdSecondaryTypeBoolean = 0x8,
64
    PutByIdSecondaryTypeOther = 0x10,
65
    PutByIdSecondaryTypeInt32 = 0x18,
66
    PutByIdSecondaryTypeNumber = 0x20,
67
    PutByIdSecondaryTypeString = 0x28,
68
    PutByIdSecondaryTypeObject = 0x30,
69
    PutByIdSecondaryTypeObjectOrOther = 0x38,
70
    PutByIdSecondaryTypeTop = 0x40
34
};
71
};
35
72
73
inline PutByIdFlags encodeStructureID(StructureID id)
74
{
75
#if USE(JSVALUE64)
76
    return static_cast<PutByIdFlags>(static_cast<PutByIdFlags>(id) << 3);
77
#else
78
    PutByIdFlags result = bitwise_cast<PutByIdFlags>(id);
79
    ASSERT(!(result & ~PutByIdSecondaryTypeMask));
80
    return result;
81
#endif
82
}
83
84
inline StructureID decodeStructureID(PutByIdFlags flags)
85
{
86
#if USE(JSVALUE64)
87
    return static_cast<StructureID>(flags >> 3);
88
#else
89
    return bitwise_cast<StructureID>(flags & PutByIdSecondaryTypeMask);
90
#endif
91
}
92
36
} // namespace JSC
93
} // namespace JSC
37
94
38
namespace WTF {
95
namespace WTF {
- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp -9 / +17 lines
Lines 83-89 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec1
83
        if (!isValidOffset(offset))
83
        if (!isValidOffset(offset))
84
            return PutByIdStatus(NoInformation);
84
            return PutByIdStatus(NoInformation);
85
        
85
        
86
        return PutByIdVariant::replace(structure, offset);
86
        return PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
87
    }
87
    }
88
88
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
89
    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
Lines 103-109 PutByIdStatus PutByIdStatus::computeFrom Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec2
103
            return PutByIdStatus(NoInformation);
103
            return PutByIdStatus(NoInformation);
104
    }
104
    }
105
    
105
    
106
    return PutByIdVariant::transition(structure, newStructure, conditionSet, offset);
106
    return PutByIdVariant::transition(
107
        structure, newStructure, conditionSet, offset, newStructure->inferredTypeDescriptorFor(uid));
107
}
108
}
108
109
109
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
110
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, UniquedStringImpl* uid)
Lines 162-168 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec3
162
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
            stubInfo->u.byIdSelf.baseObjectStructure->getConcurrently(uid);
163
        if (isValidOffset(offset)) {
164
        if (isValidOffset(offset)) {
164
            return PutByIdVariant::replace(
165
            return PutByIdVariant::replace(
165
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset);
166
                stubInfo->u.byIdSelf.baseObjectStructure.get(), offset, InferredType::Top);
166
        }
167
        }
167
        return PutByIdStatus(TakesSlowPath);
168
        return PutByIdStatus(TakesSlowPath);
168
    }
169
    }
Lines 193-199 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec4
193
                PropertyOffset offset = structure->getConcurrently(uid);
194
                PropertyOffset offset = structure->getConcurrently(uid);
194
                if (!isValidOffset(offset))
195
                if (!isValidOffset(offset))
195
                    return PutByIdStatus(slowPathState);
196
                    return PutByIdStatus(slowPathState);
196
                variant = PutByIdVariant::replace(structure, offset);
197
                variant = PutByIdVariant::replace(
198
                    structure, offset, structure->inferredTypeDescriptorFor(uid));
197
                break;
199
                break;
198
            }
200
            }
199
                
201
                
Lines 206-212 PutByIdStatus PutByIdStatus::computeForS Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec5
206
                if (!conditionSet.structuresEnsureValidity())
208
                if (!conditionSet.structuresEnsureValidity())
207
                    return PutByIdStatus(slowPathState);
209
                    return PutByIdStatus(slowPathState);
208
                variant = PutByIdVariant::transition(
210
                variant = PutByIdVariant::transition(
209
                    access.structure(), access.newStructure(), conditionSet, offset);
211
                    access.structure(), access.newStructure(), conditionSet, offset,
212
                    access.newStructure()->inferredTypeDescriptorFor(uid));
210
                break;
213
                break;
211
            }
214
            }
212
                
215
                
Lines 329-336 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec6
329
                // So, better leave this alone and take slow path.
332
                // So, better leave this alone and take slow path.
330
                return PutByIdStatus(TakesSlowPath);
333
                return PutByIdStatus(TakesSlowPath);
331
            }
334
            }
332
            
335
333
            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
336
            PutByIdVariant variant =
337
                PutByIdVariant::replace(structure, offset, structure->inferredTypeDescriptorFor(uid));
338
            if (!result.appendVariant(variant))
334
                return PutByIdStatus(TakesSlowPath);
339
                return PutByIdStatus(TakesSlowPath);
335
            continue;
340
            continue;
336
        }
341
        }
Lines 356-368 PutByIdStatus PutByIdStatus::computeFor( Source/JavaScriptCore/bytecode/PutByIdStatus.cpp_sec7
356
        }
361
        }
357
    
362
    
358
        // We only optimize if there is already a structure that the transition is cached to.
363
        // We only optimize if there is already a structure that the transition is cached to.
359
        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
364
        Structure* transition =
365
            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
360
        if (!transition)
366
        if (!transition)
361
            return PutByIdStatus(TakesSlowPath);
367
            return PutByIdStatus(TakesSlowPath);
362
        ASSERT(isValidOffset(offset));
368
        ASSERT(isValidOffset(offset));
363
    
369
    
364
        bool didAppend = result.appendVariant(
370
        bool didAppend = result.appendVariant(
365
            PutByIdVariant::transition(structure, transition, conditionSet, offset));
371
            PutByIdVariant::transition(
372
                structure, transition, conditionSet, offset,
373
                transition->inferredTypeDescriptorFor(uid)));
366
        if (!didAppend)
374
        if (!didAppend)
367
            return PutByIdStatus(TakesSlowPath);
375
            return PutByIdStatus(TakesSlowPath);
368
    }
376
    }
- Source/JavaScriptCore/bytecode/PutByIdVariant.cpp -5 / +16 lines
Lines 45-50 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec1
45
    m_newStructure = other.m_newStructure;
45
    m_newStructure = other.m_newStructure;
46
    m_conditionSet = other.m_conditionSet;
46
    m_conditionSet = other.m_conditionSet;
47
    m_offset = other.m_offset;
47
    m_offset = other.m_offset;
48
    m_requiredType = other.m_requiredType;
48
    if (other.m_callLinkStatus)
49
    if (other.m_callLinkStatus)
49
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
50
    else
51
    else
Lines 52-69 PutByIdVariant& PutByIdVariant::operator Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec2
52
    return *this;
53
    return *this;
53
}
54
}
54
55
55
PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset)
56
PutByIdVariant PutByIdVariant::replace(
57
    const StructureSet& structure, PropertyOffset offset, const InferredType::Descriptor& requiredType)
56
{
58
{
57
    PutByIdVariant result;
59
    PutByIdVariant result;
58
    result.m_kind = Replace;
60
    result.m_kind = Replace;
59
    result.m_oldStructure = structure;
61
    result.m_oldStructure = structure;
60
    result.m_offset = offset;
62
    result.m_offset = offset;
63
    result.m_requiredType = requiredType;
61
    return result;
64
    return result;
62
}
65
}
63
66
64
PutByIdVariant PutByIdVariant::transition(
67
PutByIdVariant PutByIdVariant::transition(
65
    const StructureSet& oldStructure, Structure* newStructure,
68
    const StructureSet& oldStructure, Structure* newStructure,
66
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset)
69
    const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset,
70
    const InferredType::Descriptor& requiredType)
67
{
71
{
68
    PutByIdVariant result;
72
    PutByIdVariant result;
69
    result.m_kind = Transition;
73
    result.m_kind = Transition;
Lines 71-76 PutByIdVariant PutByIdVariant::transitio Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec3
71
    result.m_newStructure = newStructure;
75
    result.m_newStructure = newStructure;
72
    result.m_conditionSet = conditionSet;
76
    result.m_conditionSet = conditionSet;
73
    result.m_offset = offset;
77
    result.m_offset = offset;
78
    result.m_requiredType = requiredType;
74
    return result;
79
    return result;
75
}
80
}
76
81
Lines 85-90 PutByIdVariant PutByIdVariant::setter( Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec4
85
    result.m_conditionSet = conditionSet;
90
    result.m_conditionSet = conditionSet;
86
    result.m_offset = offset;
91
    result.m_offset = offset;
87
    result.m_callLinkStatus = WTF::move(callLinkStatus);
92
    result.m_callLinkStatus = WTF::move(callLinkStatus);
93
    result.m_requiredType = InferredType::Top;
88
    return result;
94
    return result;
89
}
95
}
90
96
Lines 134-142 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec5
134
{
140
{
135
    if (m_offset != other.m_offset)
141
    if (m_offset != other.m_offset)
136
        return false;
142
        return false;
143
144
    if (m_requiredType != other.m_requiredType)
145
        return false;
137
    
146
    
138
    switch (m_kind) {
147
    switch (m_kind) {
139
    case Replace:
148
    case Replace: {
140
        switch (other.m_kind) {
149
        switch (other.m_kind) {
141
        case Replace: {
150
        case Replace: {
142
            ASSERT(m_conditionSet.isEmpty());
151
            ASSERT(m_conditionSet.isEmpty());
Lines 158-163 bool PutByIdVariant::attemptToMerge(cons Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec6
158
        default:
167
        default:
159
            return false;
168
            return false;
160
        }
169
        }
170
    }
161
        
171
        
162
    case Transition:
172
    case Transition:
163
        switch (other.m_kind) {
173
        switch (other.m_kind) {
Lines 210-223 void PutByIdVariant::dumpInContext(Print Source/JavaScriptCore/bytecode/PutByIdVariant.cpp_sec7
210
        
220
        
211
    case Replace:
221
    case Replace:
212
        out.print(
222
        out.print(
213
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">");
223
            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ", ", requiredType(),
224
            ">");
214
        return;
225
        return;
215
        
226
        
216
    case Transition:
227
    case Transition:
217
        out.print(
228
        out.print(
218
            "<Transition: ", inContext(oldStructure(), context), " -> ",
229
            "<Transition: ", inContext(oldStructure(), context), " -> ",
219
            pointerDumpInContext(newStructure(), context), ", [",
230
            pointerDumpInContext(newStructure(), context), ", [",
220
            inContext(m_conditionSet, context), "], offset = ", offset(), ">");
231
            inContext(m_conditionSet, context), "], offset = ", offset(), ", ", requiredType(), ">");
221
        return;
232
        return;
222
        
233
        
223
    case Setter:
234
    case Setter:
- Source/JavaScriptCore/bytecode/PutByIdVariant.h -2 / +8 lines
Lines 53-63 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec1
53
    PutByIdVariant(const PutByIdVariant&);
53
    PutByIdVariant(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
54
    PutByIdVariant& operator=(const PutByIdVariant&);
55
55
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset);
56
    static PutByIdVariant replace(const StructureSet&, PropertyOffset, const InferredType::Descriptor&);
57
    
57
    
58
    static PutByIdVariant transition(
58
    static PutByIdVariant transition(
59
        const StructureSet& oldStructure, Structure* newStructure,
59
        const StructureSet& oldStructure, Structure* newStructure,
60
        const ObjectPropertyConditionSet&, PropertyOffset);
60
        const ObjectPropertyConditionSet&, PropertyOffset, const InferredType::Descriptor&);
61
    
61
    
62
    static PutByIdVariant setter(
62
    static PutByIdVariant setter(
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
63
        const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
Lines 99-104 public: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec2
99
        return m_newStructure;
99
        return m_newStructure;
100
    }
100
    }
101
101
102
    InferredType::Descriptor requiredType() const
103
    {
104
        return m_requiredType;
105
    }
106
102
    bool writesStructures() const;
107
    bool writesStructures() const;
103
    bool reallocatesStorage() const;
108
    bool reallocatesStorage() const;
104
    bool makesCalls() const;
109
    bool makesCalls() const;
Lines 130-135 private: Source/JavaScriptCore/bytecode/PutByIdVariant.h_sec3
130
    Structure* m_newStructure;
135
    Structure* m_newStructure;
131
    ObjectPropertyConditionSet m_conditionSet;
136
    ObjectPropertyConditionSet m_conditionSet;
132
    PropertyOffset m_offset;
137
    PropertyOffset m_offset;
138
    InferredType::Descriptor m_requiredType;
133
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
139
    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
134
};
140
};
135
141
- Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h -3 lines
Lines 36-42 Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec1
36
#include "JSCell.h"
36
#include "JSCell.h"
37
#include "JSString.h"
37
#include "JSString.h"
38
#include "ParserModes.h"
38
#include "ParserModes.h"
39
#include "PutByIdFlags.h"
40
#include "RegExp.h"
39
#include "RegExp.h"
41
#include "SpecialPointer.h"
40
#include "SpecialPointer.h"
42
#include "UnlinkedFunctionExecutable.h"
41
#include "UnlinkedFunctionExecutable.h"
Lines 98-109 struct UnlinkedInstruction { Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h_sec2
98
    UnlinkedInstruction() { u.operand = 0; }
97
    UnlinkedInstruction() { u.operand = 0; }
99
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
98
    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
100
    UnlinkedInstruction(int operand) { u.operand = operand; }
99
    UnlinkedInstruction(int operand) { u.operand = operand; }
101
    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
102
    union {
100
    union {
103
        OpcodeID opcode;
101
        OpcodeID opcode;
104
        int32_t operand;
102
        int32_t operand;
105
        unsigned index;
103
        unsigned index;
106
        PutByIdFlags putByIdFlags;
107
    } u;
104
    } u;
108
};
105
};
109
106
- Source/JavaScriptCore/bytecode/Watchpoint.h -1 / +33 lines
Lines 336-342 public: Source/JavaScriptCore/bytecode/Watchpoint.h_sec1
336
    {
336
    {
337
        touch(StringFireDetail(reason));
337
        touch(StringFireDetail(reason));
338
    }
338
    }
339
    
339
340
    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
341
    //
342
    // if (w.isBeingWatched())
343
    //     w.fireAll()
344
    //
345
    // Concurrently to this, the DFG could do:
346
    //
347
    // if (w.isStillValid())
348
    //     perform optimizations;
349
    // if (!w.isStillValid())
350
    //     retry compilation;
351
    //
352
    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
353
    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
354
    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
355
    // compilation later.
356
    //
357
    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
358
    // watchpoint by doing:
359
    //
360
    // if (w.isBeingWatched())
361
    //     w.fireAll()
362
    //
363
    // then the DFG would never know that you invalidated state between the two checks.
364
    //
365
    // There are two ways to work around this:
366
    //
367
    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
368
    //   been invalidated when it does its second check.
369
    //
370
    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
371
    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
340
    bool isBeingWatched() const
372
    bool isBeingWatched() const
341
    {
373
    {
342
        if (isFat())
374
        if (isFat())
- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp -2 / +2 lines
Lines 2112-2118 RegisterID* BytecodeGenerator::emitPutBy Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec1
2112
    instructions().append(0); // offset
2112
    instructions().append(0); // offset
2113
    instructions().append(0); // new structure
2113
    instructions().append(0); // new structure
2114
    instructions().append(0); // structure chain
2114
    instructions().append(0); // structure chain
2115
    instructions().append(PutByIdNone); // is not direct
2115
    instructions().append(static_cast<int>(PutByIdNone)); // is not direct
2116
2116
2117
    return value;
2117
    return value;
2118
}
2118
}
Lines 2134-2140 RegisterID* BytecodeGenerator::emitDirec Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp_sec2
2134
    instructions().append(0); // offset
2134
    instructions().append(0); // offset
2135
    instructions().append(0); // new structure
2135
    instructions().append(0); // new structure
2136
    instructions().append(0); // structure chain (unused if direct)
2136
    instructions().append(0); // structure chain (unused if direct)
2137
    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone);
2137
    instructions().append(static_cast<int>((putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone));
2138
    return value;
2138
    return value;
2139
}
2139
}
2140
2140
- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h -3 / +3 lines
Lines 116-124 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec1
116
    void dump(PrintStream& out);
116
    void dump(PrintStream& out);
117
    
117
    
118
    template<typename T>
118
    template<typename T>
119
    FiltrationResult filter(T node, const StructureSet& set)
119
    FiltrationResult filter(T node, const StructureSet& set, SpeculatedType admittedTypes = SpecNone)
120
    {
120
    {
121
        return filter(forNode(node), set);
121
        return filter(forNode(node), set, admittedTypes);
122
    }
122
    }
123
    
123
    
124
    template<typename T>
124
    template<typename T>
Lines 139-145 public: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h_sec2
139
        return filterByValue(forNode(node), value);
139
        return filterByValue(forNode(node), value);
140
    }
140
    }
141
    
141
    
142
    FiltrationResult filter(AbstractValue&, const StructureSet&);
142
    FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
143
    FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
144
    FiltrationResult filter(AbstractValue&, SpeculatedType);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
145
    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h -44 / +83 lines
Lines 1829-1838 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec1
1829
        }
1829
        }
1830
        
1830
        
1831
        AbstractValue& value = forNode(node->child1());
1831
        AbstractValue& value = forNode(node->child1());
1832
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
1832
        if (value.m_structure.isFinite()
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1833
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
1834
            GetByIdStatus status = GetByIdStatus::computeFor(
1834
            UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
1835
                value.m_structure.set(), m_graph.identifiers()[node->identifierNumber()]);
1835
            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
1836
            if (status.isSimple()) {
1836
            if (status.isSimple()) {
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1837
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
1838
                // something more subtle?
1838
                // something more subtle?
Lines 1841-1862 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec2
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1841
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
1842
                    // have more work to do here.
1842
                    // have more work to do here.
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1843
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
1844
                    
1844
1845
                    JSValue constantResult =
1845
                    result.merge(
1846
                        m_graph.tryGetConstantProperty(value, status[i].offset());
1846
                        m_graph.inferredValueForProperty(
1847
                    if (!constantResult) {
1847
                            value, uid, status[i].offset(), m_state.structureClobberState()));
1848
                        result.makeHeapTop();
1849
                        break;
1850
                    }
1851
                    
1852
                    AbstractValue thisResult;
1853
                    thisResult.set(
1854
                        m_graph, *m_graph.freeze(constantResult),
1855
                        m_state.structureClobberState());
1856
                    result.merge(thisResult);
1857
                }
1848
                }
1858
                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
1849
                m_state.setFoundConstants(true);
1859
                    m_state.setFoundConstants(true);
1860
                forNode(node) = result;
1850
                forNode(node) = result;
1861
                break;
1851
                break;
1862
            }
1852
            }
Lines 1880-1886 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec3
1880
        
1870
        
1881
    case CheckStructure: {
1871
    case CheckStructure: {
1882
        AbstractValue& value = forNode(node->child1());
1872
        AbstractValue& value = forNode(node->child1());
1883
        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
1884
1873
1885
        StructureSet& set = node->structureSet();
1874
        StructureSet& set = node->structureSet();
1886
        
1875
        
Lines 1888-1899 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec4
1888
        // that includes the set we're testing. In that case we could make the structure check
1877
        // that includes the set we're testing. In that case we could make the structure check
1889
        // more efficient. We currently don't.
1878
        // more efficient. We currently don't.
1890
        
1879
        
1891
        if (value.m_structure.isSubsetOf(set)) {
1880
        if (value.m_structure.isSubsetOf(set))
1892
            m_state.setFoundConstants(true);
1881
            m_state.setFoundConstants(true);
1882
1883
        SpeculatedType admittedTypes = SpecNone;
1884
        switch (node->child1().useKind()) {
1885
        case CellUse:
1886
            admittedTypes = SpecNone;
1887
            break;
1888
        case CellOrOtherUse:
1889
            admittedTypes = SpecOther;
1890
            break;
1891
        default:
1892
            DFG_CRASH(m_graph, node, "Bad use kind");
1893
            break;
1893
            break;
1894
        }
1894
        }
1895
1895
        
1896
        filter(value, set);
1896
        filter(value, set, admittedTypes);
1897
        break;
1897
        break;
1898
    }
1898
    }
1899
        
1899
        
Lines 2084-2096 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec5
2084
        
2084
        
2085
    case GetByOffset: {
2085
    case GetByOffset: {
2086
        StorageAccessData& data = node->storageAccessData();
2086
        StorageAccessData& data = node->storageAccessData();
2087
        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
2087
        UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
2088
        if (result) {
2088
2089
            setConstant(node, *m_graph.freeze(result));
2089
        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
2090
            break;
2090
        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
2091
        }
2091
        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
2092
        
2092
        // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
2093
        forNode(node).makeHeapTop();
2093
        // on the type that ByteCodeParser was able to prove.
2094
        AbstractValue value = m_graph.inferredValueForProperty(
2095
            forNode(node->child2()), uid, data.offset, m_state.structureClobberState());
2096
2097
        // It's possible that the type that ByteCodeParser came up with is better.
2098
        AbstractValue typeFromParsing;
2099
        typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
2100
        value.filter(typeFromParsing);
2101
2102
        // If we decide that there does not exist any value that this can return, then it's probably
2103
        // because the compilation was already invalidated.
2104
        if (value.isClear())
2105
            m_state.setIsValid(false);
2106
2107
        forNode(node) = value;
2108
        if (value.m_value)
2109
            m_state.setFoundConstants(true);
2094
        break;
2110
        break;
2095
    }
2111
    }
2096
        
2112
        
Lines 2120-2125 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec6
2120
        // because of the effect on compile times, but this node is FTL-only.
2136
        // because of the effect on compile times, but this node is FTL-only.
2121
        m_state.setFoundConstants(true);
2137
        m_state.setFoundConstants(true);
2122
        
2138
        
2139
        UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];
2140
2123
        AbstractValue base = forNode(node->child1());
2141
        AbstractValue base = forNode(node->child1());
2124
        StructureSet baseSet;
2142
        StructureSet baseSet;
2125
        AbstractValue result;
2143
        AbstractValue result;
Lines 2129-2146 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec7
2129
            if (set.isEmpty())
2147
            if (set.isEmpty())
2130
                continue;
2148
                continue;
2131
            baseSet.merge(set);
2149
            baseSet.merge(set);
2132
            
2150
2133
            if (getCase.method().kind() != GetByOffsetMethod::Constant) {
2151
            switch (getCase.method().kind()) {
2134
                result.makeHeapTop();
2152
            case GetByOffsetMethod::Constant: {
2135
                continue;
2153
                AbstractValue thisResult;
2154
                thisResult.set(
2155
                    m_graph,
2156
                    *getCase.method().constant(),
2157
                    m_state.structureClobberState());
2158
                result.merge(thisResult);
2159
                break;
2136
            }
2160
            }
2137
            
2161
2138
            AbstractValue thisResult;
2162
            case GetByOffsetMethod::Load: {
2139
            thisResult.set(
2163
                result.merge(
2140
                m_graph,
2164
                    m_graph.inferredValueForProperty(
2141
                *getCase.method().constant(),
2165
                        set, uid, m_state.structureClobberState()));
2142
                m_state.structureClobberState());
2166
                break;
2143
            result.merge(thisResult);
2167
            }
2168
2169
            default: {
2170
                result.makeHeapTop();
2171
                break;
2172
            } }
2144
        }
2173
        }
2145
        
2174
        
2146
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
2175
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
Lines 2163-2168 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec8
2163
        m_state.setFoundConstants(true);
2192
        m_state.setFoundConstants(true);
2164
        
2193
        
2165
        AbstractValue base = forNode(node->child1());
2194
        AbstractValue base = forNode(node->child1());
2195
        AbstractValue originalValue = forNode(node->child2());
2196
        AbstractValue resultingValue;
2166
        
2197
        
2167
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2198
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
2168
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
2199
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
Lines 2170-2175 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec9
2170
            thisSet.filter(base);
2201
            thisSet.filter(base);
2171
            if (thisSet.isEmpty())
2202
            if (thisSet.isEmpty())
2172
                continue;
2203
                continue;
2204
2205
            AbstractValue thisValue = originalValue;
2206
            thisValue.filter(m_graph, variant.requiredType());
2207
            resultingValue.merge(thisValue);
2208
            
2173
            if (variant.kind() == PutByIdVariant::Transition) {
2209
            if (variant.kind() == PutByIdVariant::Transition) {
2174
                if (thisSet.onlyStructure() != variant.newStructure()) {
2210
                if (thisSet.onlyStructure() != variant.newStructure()) {
2175
                    transitions.append(
2211
                    transitions.append(
Lines 2185-2190 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec10
2185
        observeTransitions(clobberLimit, transitions);
2221
        observeTransitions(clobberLimit, transitions);
2186
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2222
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
2187
            m_state.setIsValid(false);
2223
            m_state.setIsValid(false);
2224
        forNode(node->child2()) = resultingValue;
2225
        if (!!originalValue && !resultingValue)
2226
            m_state.setIsValid(false);
2188
        break;
2227
        break;
2189
    }
2228
    }
2190
        
2229
        
Lines 2264-2276 bool AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec11
2264
    case PutByIdFlush:
2303
    case PutByIdFlush:
2265
    case PutByIdDirect: {
2304
    case PutByIdDirect: {
2266
        AbstractValue& value = forNode(node->child1());
2305
        AbstractValue& value = forNode(node->child1());
2267
        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
2306
        if (value.m_structure.isFinite()) {
2268
            PutByIdStatus status = PutByIdStatus::computeFor(
2307
            PutByIdStatus status = PutByIdStatus::computeFor(
2269
                m_graph.globalObjectFor(node->origin.semantic),
2308
                m_graph.globalObjectFor(node->origin.semantic),
2270
                value.m_structure.set(),
2309
                value.m_structure.set(),
2271
                m_graph.identifiers()[node->identifierNumber()],
2310
                m_graph.identifiers()[node->identifierNumber()],
2272
                node->op() == PutByIdDirect);
2311
                node->op() == PutByIdDirect);
2273
            
2312
2274
            if (status.isSimple()) {
2313
            if (status.isSimple()) {
2275
                StructureSet newSet;
2314
                StructureSet newSet;
2276
                TransitionVector transitions;
2315
                TransitionVector transitions;
Lines 2615-2623 void AbstractInterpreter<AbstractStateTy Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h_sec12
2615
2654
2616
template<typename AbstractStateType>
2655
template<typename AbstractStateType>
2617
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2656
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
2618
    AbstractValue& value, const StructureSet& set)
2657
    AbstractValue& value, const StructureSet& set, SpeculatedType admittedTypes)
2619
{
2658
{
2620
    if (value.filter(m_graph, set) == FiltrationOK)
2659
    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
2621
        return FiltrationOK;
2660
        return FiltrationOK;
2622
    m_state.setIsValid(false);
2661
    m_state.setIsValid(false);
2623
    return Contradiction;
2662
    return Contradiction;
- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp -2 / +73 lines
Lines 117-122 void AbstractValue::setType(Graph& graph Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec1
117
    checkConsistency();
117
    checkConsistency();
118
}
118
}
119
119
120
void AbstractValue::set(Graph& graph, const InferredType::Descriptor& descriptor)
121
{
122
    switch (descriptor.kind()) {
123
    case InferredType::Bottom:
124
        clear();
125
        return;
126
    case InferredType::Boolean:
127
        setType(SpecBoolean);
128
        return;
129
    case InferredType::Other:
130
        setType(SpecOther);
131
        return;
132
    case InferredType::Int32:
133
        setType(SpecInt32);
134
        return;
135
    case InferredType::Number:
136
        setType(SpecBytecodeNumber);
137
        return;
138
    case InferredType::String:
139
        set(graph, graph.m_vm.stringStructure.get());
140
        return;
141
    case InferredType::ObjectWithStructure:
142
        set(graph, descriptor.structure());
143
        return;
144
    case InferredType::ObjectWithStructureOrOther:
145
        set(graph, descriptor.structure());
146
        merge(SpecOther);
147
        return;
148
    case InferredType::Object:
149
        setType(graph, SpecObject);
150
        return;
151
    case InferredType::ObjectOrOther:
152
        setType(graph, SpecObject | SpecOther);
153
        return;
154
    case InferredType::Top:
155
        makeHeapTop();
156
        return;
157
    }
158
159
    RELEASE_ASSERT_NOT_REACHED();
160
}
161
162
void AbstractValue::set(
163
    Graph& graph, const InferredType::Descriptor& descriptor, StructureClobberState clobberState)
164
{
165
    set(graph, descriptor);
166
    if (clobberState == StructuresAreClobbered)
167
        clobberStructures();
168
}
169
120
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
170
void AbstractValue::fixTypeForRepresentation(Graph& graph, NodeFlags representation, Node* node)
121
{
171
{
122
    if (representation == NodeResultDouble) {
172
    if (representation == NodeResultDouble) {
Lines 189-196 bool AbstractValue::mergeOSREntryValue(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec2
189
    return oldMe != *this;
239
    return oldMe != *this;
190
}
240
}
191
241
192
FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
242
bool AbstractValue::isType(Graph& graph, const InferredType::Descriptor& inferredType) const
193
{
243
{
244
    AbstractValue typeValue;
245
    typeValue.set(graph, inferredType);
246
247
    AbstractValue mergedValue = *this;
248
    mergedValue.merge(typeValue);
249
250
    return mergedValue == typeValue;
251
}
252
253
FiltrationResult AbstractValue::filter(
254
    Graph& graph, const StructureSet& other, SpeculatedType admittedTypes)
255
{
256
    ASSERT(!(admittedTypes & SpecCell));
257
    
194
    if (isClear())
258
    if (isClear())
195
        return FiltrationOK;
259
        return FiltrationOK;
196
    
260
    
Lines 198-204 FiltrationResult AbstractValue::filter(G Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec3
198
    // having structures, array modes, or a specific value.
262
    // having structures, array modes, or a specific value.
199
    // https://bugs.webkit.org/show_bug.cgi?id=109663
263
    // https://bugs.webkit.org/show_bug.cgi?id=109663
200
    
264
    
201
    m_type &= other.speculationFromStructures();
265
    m_type &= other.speculationFromStructures() | admittedTypes;
202
    m_arrayModes &= other.arrayModesFromStructures();
266
    m_arrayModes &= other.arrayModesFromStructures();
203
    m_structure.filter(other);
267
    m_structure.filter(other);
204
    
268
    
Lines 315-320 FiltrationResult AbstractValue::filter(c Source/JavaScriptCore/dfg/DFGAbstractValue.cpp_sec4
315
    return Contradiction;
379
    return Contradiction;
316
}
380
}
317
381
382
FiltrationResult AbstractValue::filter(Graph& graph, const InferredType::Descriptor& descriptor)
383
{
384
    AbstractValue filterValue;
385
    filterValue.set(graph, descriptor);
386
    return filter(filterValue);
387
}
388
318
void AbstractValue::filterValueByType()
389
void AbstractValue::filterValueByType()
319
{
390
{
320
    // We could go further, and ensure that if the futurePossibleStructure contravenes
391
    // We could go further, and ensure that if the futurePossibleStructure contravenes
- Source/JavaScriptCore/dfg/DFGAbstractValue.h -3 / +17 lines
Lines 34-39 Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec1
34
#include "DFGNodeFlags.h"
34
#include "DFGNodeFlags.h"
35
#include "DFGStructureAbstractValue.h"
35
#include "DFGStructureAbstractValue.h"
36
#include "DFGStructureClobberState.h"
36
#include "DFGStructureClobberState.h"
37
#include "InferredType.h"
37
#include "JSCell.h"
38
#include "JSCell.h"
38
#include "SpeculatedType.h"
39
#include "SpeculatedType.h"
39
#include "DumpContext.h"
40
#include "DumpContext.h"
Lines 214-220 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec2
214
        m_value = JSValue();
215
        m_value = JSValue();
215
        checkConsistency();
216
        checkConsistency();
216
    }
217
    }
217
    
218
219
    void set(Graph&, const InferredType::Descriptor&);
220
    void set(Graph&, const InferredType::Descriptor&, StructureClobberState);
221
218
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
222
    void fixTypeForRepresentation(Graph&, NodeFlags representation, Node* = nullptr);
219
    void fixTypeForRepresentation(Graph&, Node*);
223
    void fixTypeForRepresentation(Graph&, Node*);
220
    
224
    
Lines 280-296 struct AbstractValue { Source/JavaScriptCore/dfg/DFGAbstractValue.h_sec3
280
    {
284
    {
281
        return !(m_type & ~desiredType);
285
        return !(m_type & ~desiredType);
282
    }
286
    }
287
288
    bool isType(Graph&, const InferredType::Descriptor&) const;
289
290
    // Filters the value using the given structure set. If the admittedTypes argument is not passed, this
291
    // implicitly filters by the types implied by the structure set, which are usually a subset of
292
    // SpecCell. Hence, after this call, the value will no longer have any non-cell members. But, you can
293
    // use admittedTypes to preserve some non-cell types. Note that it's wrong for admittedTypes to overlap
294
    // with SpecCell.
295
    FiltrationResult filter(Graph&, const StructureSet&, SpeculatedType admittedTypes = SpecNone);
283
    
296
    
284
    FiltrationResult filter(Graph&, const StructureSet&);
285
    FiltrationResult filterArrayModes(ArrayModes);
297
    FiltrationResult filterArrayModes(ArrayModes);
286
    FiltrationResult filter(SpeculatedType);
298
    FiltrationResult filter(SpeculatedType);
287
    FiltrationResult filterByValue(const FrozenValue& value);
299
    FiltrationResult filterByValue(const FrozenValue& value);
288
    FiltrationResult filter(const AbstractValue&);
300
    FiltrationResult filter(const AbstractValue&);
301
302
    FiltrationResult filter(Graph&, const InferredType::Descriptor&);
289
    
303
    
290
    FiltrationResult changeStructure(Graph&, const StructureSet&);
304
    FiltrationResult changeStructure(Graph&, const StructureSet&);
291
    
305
    
292
    bool contains(Structure*) const;
306
    bool contains(Structure*) const;
293
    
307
294
    bool validate(JSValue value) const
308
    bool validate(JSValue value) const
295
    {
309
    {
296
        if (isHeapTop())
310
        if (isHeapTop())
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -10 / +26 lines
Lines 206-214 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
206
    bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
207
    template<typename ChecksFunctor>
207
    template<typename ChecksFunctor>
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
208
    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
209
    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
210
    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
211
    Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
212
211
213
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
212
    // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
214
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
213
    // check the validity of the condition, but it may return a null one if it encounters a contradiction.
Lines 2307-2313 bool ByteCodeParser::handleConstantInter Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
2307
    return false;
2306
    return false;
2308
}
2307
}
2309
2308
2310
Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
2309
Node* ByteCodeParser::handleGetByOffset(
2310
    SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
2311
    const InferredType::Descriptor& inferredType, NodeType op)
2311
{
2312
{
2312
    Node* propertyStorage;
2313
    Node* propertyStorage;
2313
    if (isInlineOffset(offset))
2314
    if (isInlineOffset(offset))
Lines 2318-2330 Node* ByteCodeParser::handleGetByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
2318
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2319
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2319
    data->offset = offset;
2320
    data->offset = offset;
2320
    data->identifierNumber = identifierNumber;
2321
    data->identifierNumber = identifierNumber;
2322
    data->inferredType = inferredType;
2321
    
2323
    
2322
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2324
    Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
2323
2325
2324
    return getByOffset;
2326
    return getByOffset;
2325
}
2327
}
2326
2328
2327
Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
2329
Node* ByteCodeParser::handlePutByOffset(
2330
    Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
2331
    Node* value)
2328
{
2332
{
2329
    Node* propertyStorage;
2333
    Node* propertyStorage;
2330
    if (isInlineOffset(offset))
2334
    if (isInlineOffset(offset))
Lines 2335-2340 Node* ByteCodeParser::handlePutByOffset( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
2335
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2339
    StorageAccessData* data = m_graph.m_storageAccessData.add();
2336
    data->offset = offset;
2340
    data->offset = offset;
2337
    data->identifierNumber = identifier;
2341
    data->identifierNumber = identifier;
2342
    data->inferredType = inferredType;
2338
    
2343
    
2339
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2344
    Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
2340
    
2345
    
Lines 2449-2455 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
2449
        return addToGraph(JSConstant, OpInfo(method.constant()));
2454
        return addToGraph(JSConstant, OpInfo(method.constant()));
2450
    case GetByOffsetMethod::LoadFromPrototype: {
2455
    case GetByOffsetMethod::LoadFromPrototype: {
2451
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2456
        Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
2452
        return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
2457
        return handleGetByOffset(
2458
            prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
2453
    }
2459
    }
2454
    case GetByOffsetMethod::Load:
2460
    case GetByOffsetMethod::Load:
2455
        // Will never see this from planLoad().
2461
        // Will never see this from planLoad().
Lines 2555-2567 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
2555
    
2561
    
2556
    bool needStructureCheck = true;
2562
    bool needStructureCheck = true;
2557
    
2563
    
2564
    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2565
    
2558
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2566
    if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>()) {
2559
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2567
        // Try to optimize away the structure check. Note that it's not worth doing anything about this
2560
        // if the base's structure is watched.
2568
        // if the base's structure is watched.
2561
        Structure* structure = base->constant()->structure();
2569
        Structure* structure = base->constant()->structure();
2562
        if (!structure->dfgShouldWatch()) {
2570
        if (!structure->dfgShouldWatch()) {
2563
            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
2564
            
2565
            if (!variant.conditionSet().isEmpty()) {
2571
            if (!variant.conditionSet().isEmpty()) {
2566
                // This means that we're loading from a prototype. We expect the base not to have the
2572
                // This means that we're loading from a prototype. We expect the base not to have the
2567
                // property. We can only use ObjectPropertyCondition if all of the structures in the
2573
                // property. We can only use ObjectPropertyCondition if all of the structures in the
Lines 2626-2634 Node* ByteCodeParser::load( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
2626
            if (constant)
2632
            if (constant)
2627
                return weakJSConstant(constant);
2633
                return weakJSConstant(constant);
2628
        }
2634
        }
2635
2636
        InferredType::Descriptor inferredType;
2637
        if (needStructureCheck) {
2638
            for (Structure* structure : variant.structureSet()) {
2639
                InferredType::Descriptor thisType = m_graph.inferredTypeForProperty(structure, uid);
2640
                inferredType.merge(thisType);
2641
            }
2642
        } else
2643
            inferredType = InferredType::Top;
2629
        
2644
        
2630
        loadedValue = handleGetByOffset(
2645
        loadedValue = handleGetByOffset(
2631
            loadPrediction, base, identifierNumber, variant.offset(), loadOp);
2646
            loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
2632
    }
2647
    }
2633
2648
2634
    return loadedValue;
2649
    return loadedValue;
Lines 2639-2645 Node* ByteCodeParser::store(Node* base, Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec8
2639
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2654
    RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
2640
2655
2641
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2656
    checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
2642
    return handlePutByOffset(base, identifier, variant.offset(), value);
2657
    return handlePutByOffset(base, identifier, variant.offset(), variant.requiredType(), value);
2643
}
2658
}
2644
2659
2645
void ByteCodeParser::handleGetById(
2660
void ByteCodeParser::handleGetById(
Lines 2854-2859 void ByteCodeParser::handlePutById( Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec9
2854
        StorageAccessData* data = m_graph.m_storageAccessData.add();
2869
        StorageAccessData* data = m_graph.m_storageAccessData.add();
2855
        data->offset = variant.offset();
2870
        data->offset = variant.offset();
2856
        data->identifierNumber = identifierNumber;
2871
        data->identifierNumber = identifierNumber;
2872
        data->inferredType = variant.requiredType();
2857
        
2873
        
2858
        addToGraph(
2874
        addToGraph(
2859
            PutByOffset,
2875
            PutByOffset,
- Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp +2 lines
Lines 64-69 bool clobbersExitState(Graph& graph, Nod Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp_sec1
64
    case PhantomCreateActivation:
64
    case PhantomCreateActivation:
65
    case MaterializeCreateActivation:
65
    case MaterializeCreateActivation:
66
    case CountExecution:
66
    case CountExecution:
67
    case AllocatePropertyStorage:
68
    case ReallocatePropertyStorage:
67
        // These do clobber memory, but nothing that is observable. It may be nice to separate the
69
        // These do clobber memory, but nothing that is observable. It may be nice to separate the
68
        // heaps into those that are observable and those that aren't, but we don't do that right now.
70
        // heaps into those that are observable and those that aren't, but we don't do that right now.
69
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=148440
71
        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=148440
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp -4 / +13 lines
Lines 33-38 Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
33
#include "DFGBasicBlock.h"
33
#include "DFGBasicBlock.h"
34
#include "DFGGraph.h"
34
#include "DFGGraph.h"
35
#include "DFGInPlaceAbstractState.h"
35
#include "DFGInPlaceAbstractState.h"
36
#include "DFGInferredTypeCheck.h"
36
#include "DFGInsertionSet.h"
37
#include "DFGInsertionSet.h"
37
#include "DFGPhase.h"
38
#include "DFGPhase.h"
38
#include "GetByIdStatus.h"
39
#include "GetByIdStatus.h"
Lines 373-379 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec2
373
                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
374
                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
374
                        variant = PutByIdVariant::replace(
375
                        variant = PutByIdVariant::replace(
375
                            variant.oldStructure(),
376
                            variant.oldStructure(),
376
                            variant.offset());
377
                            variant.offset(),
378
                            variant.requiredType());
377
                        changed = true;
379
                        changed = true;
378
                    }
380
                    }
379
                }
381
                }
Lines 448-453 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec3
448
                ASSERT(childEdge.useKind() == CellUse);
450
                ASSERT(childEdge.useKind() == CellUse);
449
                
451
                
450
                AbstractValue baseValue = m_state.forNode(child);
452
                AbstractValue baseValue = m_state.forNode(child);
453
                AbstractValue valueValue = m_state.forNode(node->child2());
451
454
452
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
455
                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
453
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
456
                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
Lines 463-469 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec4
463
                
466
                
464
                if (!status.isSimple())
467
                if (!status.isSimple())
465
                    break;
468
                    break;
466
                
469
467
                ASSERT(status.numVariants());
470
                ASSERT(status.numVariants());
468
                
471
                
469
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
472
                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
Lines 640-646 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec5
640
        emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
643
        emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
641
    }
644
    }
642
    
645
    
643
    void emitGetByOffset(unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber, PropertyOffset offset)
646
    void emitGetByOffset(
647
        unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber,
648
        PropertyOffset offset, const InferredType::Descriptor& inferredType = InferredType::Top)
644
    {
649
    {
645
        childEdge.setUseKind(KnownCellUse);
650
        childEdge.setUseKind(KnownCellUse);
646
        
651
        
Lines 656-661 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec6
656
        StorageAccessData& data = *m_graph.m_storageAccessData.add();
661
        StorageAccessData& data = *m_graph.m_storageAccessData.add();
657
        data.offset = offset;
662
        data.offset = offset;
658
        data.identifierNumber = identifierNumber;
663
        data.identifierNumber = identifierNumber;
664
        data.inferredType = inferredType;
659
        
665
        
660
        node->convertToGetByOffset(data, propertyStorage);
666
        node->convertToGetByOffset(data, propertyStorage);
661
    }
667
    }
Lines 664-671 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec7
664
    {
670
    {
665
        NodeOrigin origin = node->origin;
671
        NodeOrigin origin = node->origin;
666
        Edge childEdge = node->child1();
672
        Edge childEdge = node->child1();
667
        
673
668
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
674
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
675
        insertInferredTypeCheck(
676
            m_insertionSet, indexInBlock, origin, node->child2().node(), variant.requiredType());
669
677
670
        node->child1().setUseKind(KnownCellUse);
678
        node->child1().setUseKind(KnownCellUse);
671
        childEdge.setUseKind(KnownCellUse);
679
        childEdge.setUseKind(KnownCellUse);
Lines 730-735 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec8
730
            // Arises when we prune MultiGetByOffset. We could have a
738
            // Arises when we prune MultiGetByOffset. We could have a
731
            // MultiGetByOffset with a single variant that checks for structure S,
739
            // MultiGetByOffset with a single variant that checks for structure S,
732
            // and the input has structures S and T, for example.
740
            // and the input has structures S and T, for example.
741
            ASSERT(node->child1());
733
            m_insertionSet.insertNode(
742
            m_insertionSet.insertNode(
734
                indexInBlock, SpecNone, CheckStructure, node->origin,
743
                indexInBlock, SpecNone, CheckStructure, node->origin,
735
                OpInfo(m_graph.addStructureSet(set)), node->child1());
744
                OpInfo(m_graph.addStructureSet(set)), node->child1());
- 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(InferredType::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 == InferredType::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, nullptr);
102
    }
103
104
private:
105
    InferredType* m_object;
106
    InferredType::Descriptor m_expected;
107
};
108
109
struct DesiredInferredTypeHash {
110
    static unsigned hash(const DesiredInferredType& key) { return key.hash(); }
111
    static bool equal(const DesiredInferredType& a, const DesiredInferredType& b) { return a == b; }
112
    static const bool safeToCompareToEmptyOrDeleted = true;
113
};
114
115
} } // namespace JSC::DFG
116
117
namespace WTF {
118
119
template<typename T> struct DefaultHash;
120
template<> struct DefaultHash<JSC::DFG::DesiredInferredType> {
121
    typedef JSC::DFG::DesiredInferredTypeHash Hash;
122
};
123
124
template<typename T> struct HashTraits;
125
template<> struct HashTraits<JSC::DFG::DesiredInferredType> : SimpleClassHashTraits<JSC::DFG::DesiredInferredType> { };
126
127
} // namespace WTF
128
129
#endif // ENABLE(DFG_JIT)
130
131
#endif // DFGDesiredInferredType_h
132
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp -1 / +14 lines
Lines 65-70 void AdaptiveStructureWatchpointAdaptor: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec1
65
    }
65
    }
66
}
66
}
67
67
68
void InferredTypeAdaptor::add(CodeBlock* codeBlock, const DesiredInferredType& key, CommonData& common)
69
{
70
    key.add(common.watchpoints.add(codeBlock));
71
}
72
68
DesiredWatchpoints::DesiredWatchpoints() { }
73
DesiredWatchpoints::DesiredWatchpoints() { }
69
DesiredWatchpoints::~DesiredWatchpoints() { }
74
DesiredWatchpoints::~DesiredWatchpoints() { }
70
75
Lines 93-98 void DesiredWatchpoints::addLazily(const Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec2
93
    m_adaptiveStructureSets.addLazily(key);
98
    m_adaptiveStructureSets.addLazily(key);
94
}
99
}
95
100
101
void DesiredWatchpoints::addLazily(const DesiredInferredType& key)
102
{
103
    m_inferredTypes.addLazily(key);
104
}
105
96
bool DesiredWatchpoints::consider(Structure* structure)
106
bool DesiredWatchpoints::consider(Structure* structure)
97
{
107
{
98
    if (!structure->dfgShouldWatch())
108
    if (!structure->dfgShouldWatch())
Lines 108-113 void DesiredWatchpoints::reallyAdd(CodeB Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec3
108
    m_inferredValues.reallyAdd(codeBlock, commonData);
118
    m_inferredValues.reallyAdd(codeBlock, commonData);
109
    m_bufferViews.reallyAdd(codeBlock, commonData);
119
    m_bufferViews.reallyAdd(codeBlock, commonData);
110
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
120
    m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
121
    m_inferredTypes.reallyAdd(codeBlock, commonData);
111
}
122
}
112
123
113
bool DesiredWatchpoints::areStillValid() const
124
bool DesiredWatchpoints::areStillValid() const
Lines 116-122 bool DesiredWatchpoints::areStillValid() Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec4
116
        && m_inlineSets.areStillValid()
127
        && m_inlineSets.areStillValid()
117
        && m_inferredValues.areStillValid()
128
        && m_inferredValues.areStillValid()
118
        && m_bufferViews.areStillValid()
129
        && m_bufferViews.areStillValid()
119
        && m_adaptiveStructureSets.areStillValid();
130
        && m_adaptiveStructureSets.areStillValid()
131
        && m_inferredTypes.areStillValid();
120
}
132
}
121
133
122
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
134
void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
Lines 127-132 void DesiredWatchpoints::dumpInContext(P Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp_sec5
127
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
139
    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
128
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
140
    out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
129
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
141
    out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
142
    out.print("    Inferred types: ", inContext(m_inferredTypes, context), "\n");
130
}
143
}
131
144
132
} } // namespace JSC::DFG
145
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h +22 lines
Lines 30-35 Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec1
30
30
31
#include "CodeOrigin.h"
31
#include "CodeOrigin.h"
32
#include "DFGCommonData.h"
32
#include "DFGCommonData.h"
33
#include "DFGDesiredInferredType.h"
33
#include "InferredValue.h"
34
#include "InferredValue.h"
34
#include "JSArrayBufferView.h"
35
#include "JSArrayBufferView.h"
35
#include "ObjectPropertyCondition.h"
36
#include "ObjectPropertyCondition.h"
Lines 91-96 struct AdaptiveStructureWatchpointAdapto Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec2
91
    }
92
    }
92
};
93
};
93
94
95
struct InferredTypeAdaptor {
96
    static void add(CodeBlock*, const DesiredInferredType&, CommonData&);
97
    static bool hasBeenInvalidated(const DesiredInferredType& key)
98
    {
99
        return !key.isStillValid();
100
    }
101
    static void dumpInContext(PrintStream& out, const DesiredInferredType& key, DumpContext* context)
102
    {
103
        out.print(inContext(key, context));
104
    }
105
};
106
94
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
107
template<typename WatchpointSetType, typename Adaptor = SetPointerAdaptor<WatchpointSetType>>
95
class GenericDesiredWatchpoints {
108
class GenericDesiredWatchpoints {
96
#if !ASSERT_DISABLED
109
#if !ASSERT_DISABLED
Lines 159-164 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec3
159
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
172
    // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
160
    // the required GC magic as well as some other bookkeeping.
173
    // the required GC magic as well as some other bookkeeping.
161
    void addLazily(const ObjectPropertyCondition&);
174
    void addLazily(const ObjectPropertyCondition&);
175
176
    // It's recommended that you don't call this directly. Use Graph::inferredTypeFor(), which does
177
    // the required GC magic.
178
    void addLazily(const DesiredInferredType&);
162
    
179
    
163
    bool consider(Structure*);
180
    bool consider(Structure*);
164
    
181
    
Lines 186-191 public: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec4
186
    {
203
    {
187
        return m_adaptiveStructureSets.isWatched(key);
204
        return m_adaptiveStructureSets.isWatched(key);
188
    }
205
    }
206
    bool isWatched(const DesiredInferredType& key)
207
    {
208
        return m_inferredTypes.isWatched(key);
209
    }
189
210
190
    void dumpInContext(PrintStream&, DumpContext*) const;
211
    void dumpInContext(PrintStream&, DumpContext*) const;
191
    void dump(PrintStream&) const;
212
    void dump(PrintStream&) const;
Lines 196-201 private: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h_sec5
196
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
217
    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
197
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
218
    GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
198
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
219
    GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
220
    GenericDesiredWatchpoints<DesiredInferredType, InferredTypeAdaptor> m_inferredTypes;
199
};
221
};
200
222
201
} } // namespace JSC::DFG
223
} } // namespace JSC::DFG
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +4 lines
Lines 30-35 Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
30
30
31
#include "ArrayPrototype.h"
31
#include "ArrayPrototype.h"
32
#include "DFGGraph.h"
32
#include "DFGGraph.h"
33
#include "DFGInferredTypeCheck.h"
33
#include "DFGInsertionSet.h"
34
#include "DFGInsertionSet.h"
34
#include "DFGPhase.h"
35
#include "DFGPhase.h"
35
#include "DFGPredictionPropagationPhase.h"
36
#include "DFGPredictionPropagationPhase.h"
Lines 1092-1097 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec2
1092
            if (!node->child1()->hasStorageResult())
1093
            if (!node->child1()->hasStorageResult())
1093
                fixEdge<KnownCellUse>(node->child1());
1094
                fixEdge<KnownCellUse>(node->child1());
1094
            fixEdge<KnownCellUse>(node->child2());
1095
            fixEdge<KnownCellUse>(node->child2());
1096
            insertInferredTypeCheck(
1097
                m_insertionSet, m_indexInBlock, node->origin, node->child3().node(),
1098
                node->storageAccessData().inferredType);
1095
            speculateForBarrier(node->child3());
1099
            speculateForBarrier(node->child3());
1096
            break;
1100
            break;
1097
        }
1101
        }
- Source/JavaScriptCore/dfg/DFGGraph.cpp -2 / +70 lines
Lines 261-272 void Graph::dump(PrintStream& out, const Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
261
        StorageAccessData& storageAccessData = node->storageAccessData();
261
        StorageAccessData& storageAccessData = node->storageAccessData();
262
        out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
262
        out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
263
        out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
263
        out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
264
        out.print(", inferredType = ", inContext(storageAccessData.inferredType, context));
264
    }
265
    }
265
    if (node->hasMultiGetByOffsetData()) {
266
    if (node->hasMultiGetByOffsetData()) {
266
        MultiGetByOffsetData& data = node->multiGetByOffsetData();
267
        MultiGetByOffsetData& data = node->multiGetByOffsetData();
267
        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
268
        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
268
        for (unsigned i = 0; i < data.cases.size(); ++i)
269
        for (unsigned i = 0; i < data.cases.size(); ++i) {
269
            out.print(comma, inContext(data.cases[i], context));
270
            out.print(comma, inContext(data.cases[i], context));
271
            if (data.cases[i].method().kind() == GetByOffsetMethod::Load)
272
                out.print(" (inferred value = ", inContext(inferredValueForProperty(data.cases[i].set(), identifiers()[data.identifierNumber]), context), ")");
273
        }
270
    }
274
    }
271
    if (node->hasMultiPutByOffsetData()) {
275
    if (node->hasMultiPutByOffsetData()) {
272
        MultiPutByOffsetData& data = node->multiPutByOffsetData();
276
        MultiPutByOffsetData& data = node->multiPutByOffsetData();
Lines 887-892 bool Graph::isSafeToLoad(JSObject* base, Source/JavaScriptCore/dfg/DFGGraph.cpp_sec2
887
    return m_safeToLoad.contains(std::make_pair(base, offset));
891
    return m_safeToLoad.contains(std::make_pair(base, offset));
888
}
892
}
889
893
894
InferredType::Descriptor Graph::inferredTypeFor(const PropertyTypeKey& key)
895
{
896
    assertIsRegistered(key.structure());
897
    
898
    auto iter = m_inferredTypes.find(key);
899
    if (iter != m_inferredTypes.end())
900
        return iter->value;
901
902
    InferredType* typeObject = key.structure()->inferredTypeFor(key.uid());
903
    if (!typeObject) {
904
        m_inferredTypes.add(key, InferredType::Top);
905
        return InferredType::Top;
906
    }
907
908
    InferredType::Descriptor typeDescriptor = typeObject->descriptor();
909
    if (typeDescriptor.kind() == InferredType::Top) {
910
        m_inferredTypes.add(key, InferredType::Top);
911
        return InferredType::Top;
912
    }
913
    
914
    m_inferredTypes.add(key, typeDescriptor);
915
916
    m_plan.weakReferences.addLazily(typeObject);
917
    if (typeDescriptor.structure())
918
        registerStructure(typeDescriptor.structure());
919
920
    // Note that we may already be watching this desired inferred type, because multiple structures may
921
    // point to the same InferredType instance.
922
    m_plan.watchpoints.addLazily(DesiredInferredType(typeObject, typeDescriptor));
923
924
    return typeDescriptor;
925
}
926
890
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
927
FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
891
{
928
{
892
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
929
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
Lines 1061-1067 JSValue Graph::tryGetConstantProperty(JS Source/JavaScriptCore/dfg/DFGGraph.cpp_sec3
1061
JSValue Graph::tryGetConstantProperty(
1098
JSValue Graph::tryGetConstantProperty(
1062
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1099
    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
1063
{
1100
{
1064
    if (structure.isTop() || structure.isClobbered()) {
1101
    if (structure.isInfinite()) {
1065
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1102
        // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
1066
        // watching to constant-fold the property.
1103
        // watching to constant-fold the property.
1067
        // https://bugs.webkit.org/show_bug.cgi?id=147271
1104
        // https://bugs.webkit.org/show_bug.cgi?id=147271
Lines 1076-1081 JSValue Graph::tryGetConstantProperty(co Source/JavaScriptCore/dfg/DFGGraph.cpp_sec4
1076
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1113
    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1077
}
1114
}
1078
1115
1116
AbstractValue Graph::inferredValueForProperty(
1117
    const StructureSet& base, UniquedStringImpl* uid, StructureClobberState clobberState)
1118
{
1119
    AbstractValue result;
1120
    base.forEach(
1121
        [&] (Structure* structure) {
1122
            AbstractValue value;
1123
            value.set(*this, inferredTypeForProperty(structure, uid));
1124
            result.merge(value);
1125
        });
1126
    if (clobberState == StructuresAreClobbered)
1127
        result.clobberStructures();
1128
    return result;
1129
}
1130
1131
AbstractValue Graph::inferredValueForProperty(
1132
    const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset offset,
1133
    StructureClobberState clobberState)
1134
{
1135
    if (JSValue value = tryGetConstantProperty(base, offset)) {
1136
        AbstractValue result;
1137
        result.set(*this, *freeze(value), clobberState);
1138
        return result;
1139
    }
1140
1141
    if (base.m_structure.isFinite())
1142
        return inferredValueForProperty(base.m_structure.set(), uid, clobberState);
1143
1144
    return AbstractValue::heapTop();
1145
}
1146
1079
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1147
JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
1080
{
1148
{
1081
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
1149
    // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
- Source/JavaScriptCore/dfg/DFGGraph.h +17 lines
Lines 41-46 Source/JavaScriptCore/dfg/DFGGraph.h_sec1
41
#include "DFGNodeAllocator.h"
41
#include "DFGNodeAllocator.h"
42
#include "DFGPlan.h"
42
#include "DFGPlan.h"
43
#include "DFGPrePostNumbering.h"
43
#include "DFGPrePostNumbering.h"
44
#include "DFGPropertyTypeKey.h"
44
#include "DFGScannable.h"
45
#include "DFGScannable.h"
45
#include "FullBytecodeLiveness.h"
46
#include "FullBytecodeLiveness.h"
46
#include "JSStack.h"
47
#include "JSStack.h"
Lines 675-680 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec2
675
    // Checks if it's known that loading from the given object at the given offset is fine. This is
676
    // 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().
677
    // computed by tracking which conditions we track with watchCondition().
677
    bool isSafeToLoad(JSObject* base, PropertyOffset);
678
    bool isSafeToLoad(JSObject* base, PropertyOffset);
679
680
    // Tells us what inferred type we are able to prove the property to have now and in the future.
681
    InferredType::Descriptor inferredTypeFor(const PropertyTypeKey&);
682
    InferredType::Descriptor inferredTypeForProperty(Structure* structure, UniquedStringImpl* uid)
683
    {
684
        return inferredTypeFor(PropertyTypeKey(structure, uid));
685
    }
686
687
    AbstractValue inferredValueForProperty(
688
        const StructureSet& base, UniquedStringImpl* uid, StructureClobberState = StructuresAreWatched);
689
690
    // This uses either constant property inference or property type inference to derive a good abstract
691
    // value for some property accessed with the given abstract value base.
692
    AbstractValue inferredValueForProperty(
693
        const AbstractValue& base, UniquedStringImpl* uid, PropertyOffset, StructureClobberState);
678
    
694
    
679
    FullBytecodeLiveness& livenessFor(CodeBlock*);
695
    FullBytecodeLiveness& livenessFor(CodeBlock*);
680
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
696
    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
Lines 856-861 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec3
856
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
872
    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
857
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
873
    HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
858
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
874
    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
875
    HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes;
859
    Dominators m_dominators;
876
    Dominators m_dominators;
860
    PrePostNumbering m_prePostNumbering;
877
    PrePostNumbering m_prePostNumbering;
861
    NaturalLoops m_naturalLoops;
878
    NaturalLoops m_naturalLoops;
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp +96 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "DFGInferredTypeCheck.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include "JSCInlines.h"
32
33
namespace JSC { namespace DFG {
34
35
void insertInferredTypeCheck(
36
    InsertionSet& insertionSet, unsigned nodeIndex, NodeOrigin origin, Node* baseNode,
37
    const InferredType::Descriptor& type)
38
{
39
    switch (type.kind()) {
40
    case InferredType::Bottom:
41
        insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, origin);
42
        return;
43
44
    case InferredType::Boolean:
45
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, BooleanUse));
46
        return;
47
48
    case InferredType::Other:
49
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, OtherUse));
50
        return;
51
52
    case InferredType::Int32:
53
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, Int32Use));
54
        return;
55
56
    case InferredType::Number:
57
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, NumberUse));
58
        return;
59
60
    case InferredType::String:
61
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, StringUse));
62
        return;
63
64
    case InferredType::ObjectWithStructure:
65
        insertionSet.insertNode(
66
            nodeIndex, SpecNone, CheckStructure, origin,
67
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
68
            Edge(baseNode, CellUse));
69
        return;
70
71
    case InferredType::ObjectWithStructureOrOther:
72
        insertionSet.insertNode(
73
            nodeIndex, SpecNone, CheckStructure, origin,
74
            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
75
            Edge(baseNode, CellOrOtherUse));
76
        return;
77
78
    case InferredType::Object:
79
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectUse));
80
        return;
81
82
    case InferredType::ObjectOrOther:
83
        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectOrOtherUse));
84
        return;
85
86
    case InferredType::Top:
87
        return;
88
    }
89
90
    DFG_CRASH(insertionSet.graph(), baseNode, "Bad inferred type");
91
}
92
93
} } // namespace JSC::DFG
94
95
#endif // ENABLE(DFG_JIT)
96
- Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h +45 lines
Line 0 Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef DFGInferredTypeCheck_h
27
#define DFGInferredTypeCheck_h
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGInsertionSet.h"
32
#include "InferredType.h"
33
34
namespace JSC { namespace DFG {
35
36
// Inserts a type check that ensures that baseNode has the given inferred type.
37
void insertInferredTypeCheck(
38
    InsertionSet&, unsigned nodeIndex, NodeOrigin, Node* baseNode, const InferredType::Descriptor&);
39
40
} } // namespace JSC::DFG
41
42
#endif // ENABLE(DFG_JIT)
43
44
#endif // DFGInferredTypeCheck_h
45
- Source/JavaScriptCore/dfg/DFGNode.h +5 lines
Lines 64-69 struct BasicBlock; Source/JavaScriptCore/dfg/DFGNode.h_sec1
64
struct StorageAccessData {
64
struct StorageAccessData {
65
    PropertyOffset offset;
65
    PropertyOffset offset;
66
    unsigned identifierNumber;
66
    unsigned identifierNumber;
67
68
    // This needs to know the inferred type. For puts, this is necessary because we need to remember
69
    // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
70
    // guaranteed.
71
    InferredType::Descriptor inferredType;
67
};
72
};
68
73
69
struct MultiPutByOffsetData {
74
struct MultiPutByOffsetData {
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp -2 / +8 lines
Lines 2135-2148 private: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec1
2135
                for (Structure* structure : structures) {
2135
                for (Structure* structure : structures) {
2136
                    PropertyOffset offset = structure->getConcurrently(uid);
2136
                    PropertyOffset offset = structure->getConcurrently(uid);
2137
                    if (offset != currentOffset) {
2137
                    if (offset != currentOffset) {
2138
                        // Because our analysis treats MultiPutByOffset like an escape, we only have to
2139
                        // deal with storing results that would have been previously stored by PutByOffset
2140
                        // nodes. Those nodes were guarded by the appropriate type checks. This means that
2141
                        // at this point, we can simply trust that the incoming value has the right type
2142
                        // for whatever structure we are using.
2138
                        data->variants.append(
2143
                        data->variants.append(
2139
                            PutByIdVariant::replace(currentSet, currentOffset));
2144
                            PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
2140
                        currentOffset = offset;
2145
                        currentOffset = offset;
2141
                        currentSet.clear();
2146
                        currentSet.clear();
2142
                    }
2147
                    }
2143
                    currentSet.add(structure);
2148
                    currentSet.add(structure);
2144
                }
2149
                }
2145
                data->variants.append(PutByIdVariant::replace(currentSet, currentOffset));
2150
                data->variants.append(
2151
                    PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
2146
            }
2152
            }
2147
2153
2148
            return m_graph.addNode(
2154
            return m_graph.addNode(
- Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h +129 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 "Structure.h"
32
#include <wtf/HashMap.h>
33
34
namespace JSC { namespace DFG {
35
36
// This object is a key for finding a property's type. It's a tuple of Structure* and UniquedStringImpl*.
37
38
class PropertyTypeKey {
39
public:
40
    PropertyTypeKey()
41
        : m_structure(nullptr)
42
        , m_uid(nullptr)
43
    {
44
    }
45
46
    PropertyTypeKey(Structure* structure, UniquedStringImpl* uid)
47
        : m_structure(structure)
48
        , m_uid(uid)
49
    {
50
    }
51
52
    PropertyTypeKey(WTF::HashTableDeletedValueType)
53
        : m_structure(nullptr)
54
        , m_uid(deletedUID())
55
    {
56
    }
57
58
    explicit operator bool() const { return m_structure && m_uid; }
59
60
    Structure* structure() const { return m_structure; }
61
    UniquedStringImpl* uid() const { return m_uid; }
62
63
    bool operator==(const PropertyTypeKey& other) const
64
    {
65
        return m_structure == other.m_structure
66
            && m_uid == other.m_uid;
67
    }
68
69
    bool operator!=(const PropertyTypeKey& other) const
70
    {
71
        return !(*this == other);
72
    }
73
74
    unsigned hash() const
75
    {
76
        return WTF::PtrHash<Structure*>::hash(m_structure) + WTF::PtrHash<UniquedStringImpl*>::hash(m_uid);
77
    }
78
79
    bool isHashTableDeletedValue() const
80
    {
81
        return !m_structure && m_uid == deletedUID();
82
    }
83
84
    void dumpInContext(PrintStream& out, DumpContext* context) const
85
    {
86
        out.print(pointerDumpInContext(m_structure, context), "+", m_uid);
87
    }
88
89
    void dump(PrintStream& out) const
90
    {
91
        dumpInContext(out, nullptr);
92
    }
93
94
private:
95
    static UniquedStringImpl* deletedUID()
96
    {
97
        return bitwise_cast<UniquedStringImpl*>(static_cast<intptr_t>(1));
98
    }
99
    
100
    Structure* m_structure;
101
    UniquedStringImpl* m_uid;
102
};
103
104
struct PropertyTypeKeyHash {
105
    static unsigned hash(const PropertyTypeKey& key) { return key.hash(); }
106
    static bool equal(const PropertyTypeKey& a, const PropertyTypeKey& b) { return a == b; }
107
    static const bool safeToCompareToEmptyOrDeleted = true;
108
};
109
110
} } // namespace JSC::DFG
111
112
namespace WTF {
113
114
template<typename T> struct DefaultHash;
115
template<> struct DefaultHash<JSC::DFG::PropertyTypeKey> {
116
    typedef JSC::DFG::PropertyTypeKeyHash Hash;
117
};
118
119
template<typename T> struct HashTraits;
120
template<> struct HashTraits<JSC::DFG::PropertyTypeKey> : SimpleClassHashTraits<JSC::DFG::PropertyTypeKey> {
121
    static const bool emptyValueIsZero = false;
122
};
123
124
} // namespace WTF
125
126
#endif // ENABLE(DFG_JIT)
127
128
#endif // DFGPropertyTypeKey_h
129
- Source/JavaScriptCore/dfg/DFGSafeToExecute.h +4 lines
Lines 53-58 public: Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec1
53
        case RealNumberUse:
53
        case RealNumberUse:
54
        case BooleanUse:
54
        case BooleanUse:
55
        case CellUse:
55
        case CellUse:
56
        case CellOrOtherUse:
56
        case ObjectUse:
57
        case ObjectUse:
57
        case FunctionUse:
58
        case FunctionUse:
58
        case FinalObjectUse:
59
        case FinalObjectUse:
Lines 127-132 bool safeToExecute(AbstractStateType& st Source/JavaScriptCore/dfg/DFGSafeToExecute.h_sec2
127
    if (!safeToExecuteEdge.result())
128
    if (!safeToExecuteEdge.result())
128
        return false;
129
        return false;
129
130
131
    // NOTE: This tends to lie when it comes to effectful nodes, because it knows that they aren't going to
132
    // get hoisted anyway.
133
130
    switch (node->op()) {
134
    switch (node->op()) {
131
    case JSConstant:
135
    case JSConstant:
132
    case DoubleConstant:
136
    case DoubleConstant:
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp -30 / +1 lines
Lines 3898-3933 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp_sec1
3898
    }
3898
    }
3899
        
3899
        
3900
    case CheckStructure: {
3900
    case CheckStructure: {
3901
        SpeculateCellOperand base(this, node->child1());
3901
        compileCheckStructure(node);
3902
        
3903
        ASSERT(node->structureSet().size());
3904
        
3905
        if (node->structureSet().size() == 1) {
3906
            speculationCheck(
3907
                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3908
                m_jit.branchWeakPtr(
3909
                    JITCompiler::NotEqual,
3910
                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
3911
                    node->structureSet()[0]));
3912
        } else {
3913
            GPRTemporary structure(this);
3914
            
3915
            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), structure.gpr());
3916
            
3917
            JITCompiler::JumpList done;
3918
            
3919
            for (size_t i = 0; i < node->structureSet().size() - 1; ++i)
3920
                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node->structureSet()[i]));
3921
            
3922
            speculationCheck(
3923
                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3924
                m_jit.branchWeakPtr(
3925
                    JITCompiler::NotEqual, structure.gpr(), node->structureSet().last()));
3926
            
3927
            done.link(&m_jit);
3928
        }
3929
        
3930
        noResult(node);
3931
        break;
3902
        break;
3932
    }
3903
    }
3933
        
3904
        
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp -32 / +1 lines
Lines 3911-3948 void SpeculativeJIT::compile(Node* node) Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp_sec1
3911
    }
3911
    }
3912
        
3912
        
3913
    case CheckStructure: {
3913
    case CheckStructure: {
3914
        SpeculateCellOperand base(this, node->child1());
3914
        compileCheckStructure(node);
3915
        
3916
        ASSERT(node->structureSet().size());
3917
        
3918
        ExitKind exitKind;
3919
        if (node->child1()->hasConstant())
3920
            exitKind = BadConstantCache;
3921
        else
3922
            exitKind = BadCache;
3923
        
3924
        if (node->structureSet().size() == 1) {
3925
            speculationCheck(
3926
                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
3927
                m_jit.branchWeakStructure(
3928
                    JITCompiler::NotEqual,
3929
                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
3930
                    node->structureSet()[0]));
3931
        } else {
3932
            JITCompiler::JumpList done;
3933
            
3934
            for (size_t i = 0; i < node->structureSet().size() - 1; ++i)
3935
                done.append(m_jit.branchWeakStructure(JITCompiler::Equal, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node->structureSet()[i]));
3936
            
3937
            speculationCheck(
3938
                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
3939
                m_jit.branchWeakStructure(
3940
                    JITCompiler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node->structureSet().last()));
3941
            
3942
            done.link(&m_jit);
3943
        }
3944
        
3945
        noResult(node);
3946
        break;
3915
        break;
3947
    }
3916
    }
3948
        
3917
        
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +93 lines
Lines 5232-5237 void SpeculativeJIT::compileTypeOf(Node* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
5232
    cellResult(resultGPR, node);
5232
    cellResult(resultGPR, node);
5233
}
5233
}
5234
5234
5235
void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
5236
{
5237
    ASSERT(node->structureSet().size());
5238
    
5239
    if (node->structureSet().size() == 1) {
5240
        speculationCheck(
5241
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5242
            m_jit.branchWeakStructure(
5243
                JITCompiler::NotEqual,
5244
                JITCompiler::Address(cellGPR, JSCell::structureIDOffset()),
5245
                node->structureSet()[0]));
5246
    } else {
5247
        std::unique_ptr<GPRTemporary> structure;
5248
        GPRReg structureGPR;
5249
        
5250
        if (tempGPR == InvalidGPRReg) {
5251
            structure = std::make_unique<GPRTemporary>(this);
5252
            structureGPR = structure->gpr();
5253
        } else
5254
            structureGPR = tempGPR;
5255
        
5256
        m_jit.load32(JITCompiler::Address(cellGPR, JSCell::structureIDOffset()), structureGPR);
5257
        
5258
        JITCompiler::JumpList done;
5259
        
5260
        for (size_t i = 0; i < node->structureSet().size() - 1; ++i) {
5261
            done.append(
5262
                m_jit.branchWeakStructure(JITCompiler::Equal, structureGPR, node->structureSet()[i]));
5263
        }
5264
        
5265
        speculationCheck(
5266
            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
5267
            m_jit.branchWeakStructure(
5268
                JITCompiler::NotEqual, structureGPR, node->structureSet().last()));
5269
        
5270
        done.link(&m_jit);
5271
    }
5272
}
5273
5274
void SpeculativeJIT::compileCheckStructure(Node* node)
5275
{
5276
    switch (node->child1().useKind()) {
5277
    case CellUse: {
5278
        SpeculateCellOperand cell(this, node->child1());
5279
        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
5280
        noResult(node);
5281
        return;
5282
    }
5283
5284
    case CellOrOtherUse: {
5285
        JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
5286
        GPRTemporary temp(this);
5287
5288
        JSValueRegs valueRegs = value.jsValueRegs();
5289
        GPRReg tempGPR = temp.gpr();
5290
5291
        JITCompiler::Jump cell = m_jit.branchIfCell(valueRegs);
5292
        DFG_TYPE_CHECK(
5293
            valueRegs, node->child1(), SpecCell | SpecOther,
5294
            m_jit.branchIfNotOther(valueRegs, tempGPR));
5295
        JITCompiler::Jump done = m_jit.jump();
5296
        cell.link(&m_jit);
5297
        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
5298
        done.link(&m_jit);
5299
        noResult(node);
5300
        return;
5301
    }
5302
5303
    default:
5304
        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
5305
        return;
5306
    }
5307
}
5308
5235
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5309
void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
5236
{
5310
{
5237
    if (node->transition()->previous->couldHaveIndexingHeader()) {
5311
    if (node->transition()->previous->couldHaveIndexingHeader()) {
Lines 5636-5641 void SpeculativeJIT::speculateCell(Edge Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
5636
    (SpeculateCellOperand(this, edge)).gpr();
5710
    (SpeculateCellOperand(this, edge)).gpr();
5637
}
5711
}
5638
5712
5713
void SpeculativeJIT::speculateCellOrOther(Edge edge)
5714
{
5715
    if (!needsTypeCheck(edge, SpecCell | SpecOther))
5716
        return;
5717
    
5718
    JSValueOperand operand(this, edge, ManualOperandSpeculation);
5719
    GPRTemporary temp(this);
5720
    GPRReg tempGPR = temp.gpr();
5721
5722
    MacroAssembler::Jump ok = m_jit.branchIfCell(operand.jsValueRegs());
5723
    DFG_TYPE_CHECK(
5724
        operand.jsValueRegs(), edge, SpecCell | SpecOther,
5725
        m_jit.branchIfNotOther(operand.jsValueRegs(), tempGPR));
5726
    ok.link(&m_jit);
5727
}
5728
5639
void SpeculativeJIT::speculateObject(Edge edge)
5729
void SpeculativeJIT::speculateObject(Edge edge)
5640
{
5730
{
5641
    if (!needsTypeCheck(edge, SpecObject))
5731
    if (!needsTypeCheck(edge, SpecObject))
Lines 5916-5921 void SpeculativeJIT::speculate(Node*, Ed Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
5916
    case CellUse:
6006
    case CellUse:
5917
        speculateCell(edge);
6007
        speculateCell(edge);
5918
        break;
6008
        break;
6009
    case CellOrOtherUse:
6010
        speculateCellOrOther(edge);
6011
        break;
5919
    case ObjectUse:
6012
    case ObjectUse:
5920
        speculateObject(edge);
6013
        speculateObject(edge);
5921
        break;
6014
        break;
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +3 lines
Lines 2215-2220 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec1
2215
    void compileIsObjectOrNull(Node*);
2215
    void compileIsObjectOrNull(Node*);
2216
    void compileIsFunction(Node*);
2216
    void compileIsFunction(Node*);
2217
    void compileTypeOf(Node*);
2217
    void compileTypeOf(Node*);
2218
    void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
2219
    void compileCheckStructure(Node*);
2218
    
2220
    
2219
    void moveTrueTo(GPRReg);
2221
    void moveTrueTo(GPRReg);
2220
    void moveFalseTo(GPRReg);
2222
    void moveFalseTo(GPRReg);
Lines 2374-2379 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec2
2374
    void speculateDoubleRepReal(Edge);
2376
    void speculateDoubleRepReal(Edge);
2375
    void speculateBoolean(Edge);
2377
    void speculateBoolean(Edge);
2376
    void speculateCell(Edge);
2378
    void speculateCell(Edge);
2379
    void speculateCellOrOther(Edge);
2377
    void speculateObject(Edge);
2380
    void speculateObject(Edge);
2378
    void speculateFunction(Edge);
2381
    void speculateFunction(Edge);
2379
    void speculateFinalObject(Edge);
2382
    void speculateFinalObject(Edge);
- Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp -6 / +1 lines
Lines 314-320 private: Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp_sec1
314
            case AllocatePropertyStorage:
314
            case AllocatePropertyStorage:
315
            case ReallocatePropertyStorage:
315
            case ReallocatePropertyStorage:
316
                // These allocate but then run their own barrier.
316
                // These allocate but then run their own barrier.
317
                insertBarrierWithInvalidExit(m_nodeIndex + 1, Edge(m_node->child1().node(), KnownCellUse));
317
                insertBarrier(m_nodeIndex + 1, Edge(m_node->child1().node(), KnownCellUse));
318
                m_node->setEpoch(Epoch());
318
                m_node->setEpoch(Epoch());
319
                break;
319
                break;
320
                
320
                
Lines 481-491 private: Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp_sec2
481
        insertBarrier(m_nodeIndex, base);
481
        insertBarrier(m_nodeIndex, base);
482
    }
482
    }
483
483
484
    void insertBarrierWithInvalidExit(unsigned nodeIndex, Edge base)
485
    {
486
        insertBarrier(nodeIndex, base, false);
487
    }
488
489
    void insertBarrier(unsigned nodeIndex, Edge base, bool exitOK = true)
484
    void insertBarrier(unsigned nodeIndex, Edge base, bool exitOK = true)
490
    {
485
    {
491
        // If we're in global mode, we should only insert the barriers once we have converged.
486
        // If we're in global mode, we should only insert the barriers once we have converged.
- Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h -1 / +8 lines
Lines 192-198 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec1
192
    }
192
    }
193
    
193
    
194
    Structure* operator[](size_t i) const { return at(i); }
194
    Structure* operator[](size_t i) const { return at(i); }
195
    
195
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
196
    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
197
    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
198
    // meaningfully special, like for transitions.
198
    // meaningfully special, like for transitions.
Lines 202-207 public: Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h_sec2
202
            return nullptr;
202
            return nullptr;
203
        return m_set.onlyStructure();
203
        return m_set.onlyStructure();
204
    }
204
    }
205
206
    template<typename Functor>
207
    void forEach(const Functor& functor) const
208
    {
209
        ASSERT(!isTop());
210
        m_set.forEach(functor);
211
    }
205
    
212
    
206
    void dumpInContext(PrintStream&, DumpContext*) const;
213
    void dumpInContext(PrintStream&, DumpContext*) const;
207
    void dump(PrintStream&) const;
214
    void dump(PrintStream&) const;
- Source/JavaScriptCore/dfg/DFGUseKind.cpp +3 lines
Lines 79-84 void printInternal(PrintStream& out, Use Source/JavaScriptCore/dfg/DFGUseKind.cpp_sec1
79
    case KnownCellUse:
79
    case KnownCellUse:
80
        out.print("KnownCell");
80
        out.print("KnownCell");
81
        return;
81
        return;
82
    case CellOrOtherUse:
83
        out.print("CellOrOther");
84
        return;
82
    case ObjectUse:
85
    case ObjectUse:
83
        out.print("Object");
86
        out.print("Object");
84
        return;
87
        return;
- Source/JavaScriptCore/dfg/DFGUseKind.h +3 lines
Lines 51-56 enum UseKind { Source/JavaScriptCore/dfg/DFGUseKind.h_sec1
51
    KnownBooleanUse,
51
    KnownBooleanUse,
52
    CellUse,
52
    CellUse,
53
    KnownCellUse,
53
    KnownCellUse,
54
    CellOrOtherUse,
54
    ObjectUse,
55
    ObjectUse,
55
    FunctionUse,
56
    FunctionUse,
56
    FinalObjectUse,
57
    FinalObjectUse,
Lines 108-113 inline SpeculatedType typeFilterFor(UseK Source/JavaScriptCore/dfg/DFGUseKind.h_sec2
108
    case CellUse:
109
    case CellUse:
109
    case KnownCellUse:
110
    case KnownCellUse:
110
        return SpecCell;
111
        return SpecCell;
112
    case CellOrOtherUse:
113
        return SpecCell | SpecOther;
111
    case ObjectUse:
114
    case ObjectUse:
112
        return SpecObject;
115
        return SpecObject;
113
    case FunctionUse:
116
    case FunctionUse:
- Source/JavaScriptCore/dfg/DFGValidate.cpp +3 lines
Lines 263-268 public: Source/JavaScriptCore/dfg/DFGValidate.cpp_sec1
263
                    VALIDATE((node), !!node->child1());
263
                    VALIDATE((node), !!node->child1());
264
                    VALIDATE((node), !!node->child2());
264
                    VALIDATE((node), !!node->child2());
265
                    break;
265
                    break;
266
                case CheckStructure:
267
                    VALIDATE((node), !!node->child1());
268
                    break;
266
                case PutStructure:
269
                case PutStructure:
267
                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
270
                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
268
                    break;
271
                    break;
- Source/JavaScriptCore/ftl/FTLCapabilities.cpp +1 lines
Lines 418-423 CapabilityLevel canCompile(Graph& graph) Source/JavaScriptCore/ftl/FTLCapabilities.cpp_sec1
418
                case KnownBooleanUse:
418
                case KnownBooleanUse:
419
                case CellUse:
419
                case CellUse:
420
                case KnownCellUse:
420
                case KnownCellUse:
421
                case CellOrOtherUse:
421
                case ObjectUse:
422
                case ObjectUse:
422
                case FunctionUse:
423
                case FunctionUse:
423
                case ObjectOrOtherUse:
424
                case ObjectOrOtherUse:
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -11 / +204 lines
Lines 2026-2046 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
2026
    
2026
    
2027
    void compileCheckStructure()
2027
    void compileCheckStructure()
2028
    {
2028
    {
2029
        LValue cell = lowCell(m_node->child1());
2030
        
2031
        ExitKind exitKind;
2029
        ExitKind exitKind;
2032
        if (m_node->child1()->hasConstant())
2030
        if (m_node->child1()->hasConstant())
2033
            exitKind = BadConstantCache;
2031
            exitKind = BadConstantCache;
2034
        else
2032
        else
2035
            exitKind = BadCache;
2033
            exitKind = BadCache;
2036
        
2034
2037
        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2035
        switch (m_node->child1().useKind()) {
2038
        
2036
        case CellUse: {
2039
        checkStructure(
2037
            LValue cell = lowCell(m_node->child1());
2040
            structureID, jsValueValue(cell), exitKind, m_node->structureSet(),
2038
            
2041
            [this] (Structure* structure) {
2039
            checkStructure(
2042
                return weakStructureID(structure);
2040
                m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2043
            });
2041
                exitKind, m_node->structureSet(),
2042
                [&] (Structure* structure) {
2043
                    return weakStructureID(structure);
2044
                });
2045
            return;
2046
        }
2047
2048
        case CellOrOtherUse: {
2049
            LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
2050
2051
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse cell case"));
2052
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse not cell case"));
2053
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse continuation"));
2054
2055
            m_out.branch(
2056
                isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2057
2058
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2059
            checkStructure(
2060
                m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
2061
                exitKind, m_node->structureSet(),
2062
                [&] (Structure* structure) {
2063
                    return weakStructureID(structure);
2064
                });
2065
            m_out.jump(continuation);
2066
2067
            m_out.appendTo(notCellCase, continuation);
2068
            FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecCell | SpecOther, isNotOther(value));
2069
            m_out.jump(continuation);
2070
2071
            m_out.appendTo(continuation, lastNext);
2072
            return;
2073
        }
2074
2075
        default:
2076
            DFG_CRASH(m_graph, m_node, "Bad use kind");
2077
            return;
2078
        }
2044
    }
2079
    }
2045
    
2080
    
2046
    void compileCheckCell()
2081
    void compileCheckCell()
Lines 4022-4027 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
4022
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4057
            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
4023
            
4058
            
4024
            PutByIdVariant variant = data.variants[i];
4059
            PutByIdVariant variant = data.variants[i];
4060
4061
            checkInferredType(m_node->child2(), value, variant.requiredType());
4025
            
4062
            
4026
            LValue storage;
4063
            LValue storage;
4027
            if (variant.kind() == PutByIdVariant::Replace) {
4064
            if (variant.kind() == PutByIdVariant::Replace) {
Lines 5674-5679 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
5674
        m_out.appendTo(continuation, lastNext);
5711
        m_out.appendTo(continuation, lastNext);
5675
        return m_out.phi(m_out.int32, results);
5712
        return m_out.phi(m_out.int32, results);
5676
    }
5713
    }
5714
5715
    void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor& type)
5716
    {
5717
        // This cannot use FTL_TYPE_CHECK or typeCheck() because it is called partially, as in a node like:
5718
        //
5719
        //     MultiPutByOffset(...)
5720
        //
5721
        // may be lowered to:
5722
        //
5723
        //     switch (object->structure) {
5724
        //     case 42:
5725
        //         checkInferredType(..., type1);
5726
        //         ...
5727
        //         break;
5728
        //     case 43:
5729
        //         checkInferredType(..., type2);
5730
        //         ...
5731
        //         break;
5732
        //     }
5733
        //
5734
        // where type1 and type2 are different. Using typeCheck() would mean that the edge would be
5735
        // filtered by type1 & type2, instead of type1 | type2.
5736
        
5737
        switch (type.kind()) {
5738
        case InferredType::Bottom:
5739
            speculate(BadType, jsValueValue(value), edge.node(), m_out.booleanTrue);
5740
            return;
5741
5742
        case InferredType::Boolean:
5743
            speculate(BadType, jsValueValue(value), edge.node(), isNotBoolean(value, provenType(edge)));
5744
            return;
5745
5746
        case InferredType::Other:
5747
            speculate(BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType(edge)));
5748
            return;
5749
5750
        case InferredType::Int32:
5751
            speculate(BadType, jsValueValue(value), edge.node(), isNotInt32(value, provenType(edge)));
5752
            return;
5753
5754
        case InferredType::Number:
5755
            speculate(BadType, jsValueValue(value), edge.node(), isNotNumber(value, provenType(edge)));
5756
            return;
5757
5758
        case InferredType::String:
5759
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5760
            speculate(BadType, jsValueValue(value), edge.node(), isNotString(value, provenType(edge)));
5761
            return;
5762
5763
        case InferredType::ObjectWithStructure:
5764
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5765
            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
5766
                speculate(
5767
                    BadType, jsValueValue(value), edge.node(),
5768
                    m_out.notEqual(
5769
                        m_out.load32(value, m_heaps.JSCell_structureID),
5770
                        weakStructureID(type.structure())));
5771
            }
5772
            return;
5773
5774
        case InferredType::ObjectWithStructureOrOther: {
5775
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther cell case"));
5776
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther not cell case"));
5777
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectWithStructureOrOther continuation"));
5778
5779
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5780
5781
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5782
5783
            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
5784
                speculate(
5785
                    BadType, jsValueValue(value), edge.node(),
5786
                    m_out.notEqual(
5787
                        m_out.load32(value, m_heaps.JSCell_structureID),
5788
                        weakStructureID(type.structure())));
5789
            }
5790
5791
            m_out.jump(continuation);
5792
5793
            m_out.appendTo(notCellCase, continuation);
5794
5795
            speculate(
5796
                BadType, jsValueValue(value), edge.node(),
5797
                isNotOther(value, provenType(edge) & ~SpecCell));
5798
5799
            m_out.jump(continuation);
5800
5801
            m_out.appendTo(continuation, lastNext);
5802
            return;
5803
        }
5804
5805
        case InferredType::Object:
5806
            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
5807
            speculate(BadType, jsValueValue(value), edge.node(), isNotObject(value, provenType(edge)));
5808
            return;
5809
5810
        case InferredType::ObjectOrOther: {
5811
            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther cell case"));
5812
            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther not cell case"));
5813
            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("checkInferredType ObjectOrOther continuation"));
5814
5815
            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
5816
5817
            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
5818
5819
            speculate(
5820
                BadType, jsValueValue(value), edge.node(),
5821
                isNotObject(value, provenType(edge) & SpecCell));
5822
5823
            m_out.jump(continuation);
5824
5825
            m_out.appendTo(notCellCase, continuation);
5826
5827
            speculate(
5828
                BadType, jsValueValue(value), edge.node(),
5829
                isNotOther(value, provenType(edge) & ~SpecCell));
5830
5831
            m_out.jump(continuation);
5832
5833
            m_out.appendTo(continuation, lastNext);
5834
            return;
5835
        }
5836
5837
        case InferredType::Top:
5838
            return;
5839
        }
5840
5841
        DFG_CRASH(m_graph, m_node, "Bad inferred type");
5842
    }
5677
    
5843
    
5678
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5844
    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
5679
    {
5845
    {
Lines 7514-7519 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
7514
        case CellUse:
7680
        case CellUse:
7515
            speculateCell(edge);
7681
            speculateCell(edge);
7516
            break;
7682
            break;
7683
        case CellOrOtherUse:
7684
            speculateCellOrOther(edge);
7685
            break;
7517
        case KnownCellUse:
7686
        case KnownCellUse:
7518
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7687
            ASSERT(!m_interpreter.needsTypeCheck(edge));
7519
            break;
7688
            break;
Lines 7594-7599 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
7594
        lowCell(edge);
7763
        lowCell(edge);
7595
    }
7764
    }
7596
    
7765
    
7766
    void speculateCellOrOther(Edge edge)
7767
    {
7768
        LValue value = lowJSValue(edge, ManualOperandSpeculation);
7769
7770
        LBasicBlock isNotCell = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther not cell"));
7771
        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate CellOrOther continuation"));
7772
7773
        m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
7774
7775
        LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
7776
        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
7777
        m_out.jump(continuation);
7778
7779
        m_out.appendTo(continuation, lastNext);
7780
    }
7781
    
7597
    void speculateMachineInt(Edge edge)
7782
    void speculateMachineInt(Edge edge)
7598
    {
7783
    {
7599
        if (!m_interpreter.needsTypeCheck(edge))
7784
        if (!m_interpreter.needsTypeCheck(edge))
Lines 8127-8132 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
8127
            }
8312
            }
8128
        }
8313
        }
8129
8314
8315
        if (failCondition == m_out.booleanFalse)
8316
            return;
8317
8130
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8318
        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
8131
        
8319
        
8132
        m_ftlState.jitCode->osrExit.append(OSRExit(
8320
        m_ftlState.jitCode->osrExit.append(OSRExit(
Lines 8135-8143 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
8135
            availabilityMap().m_locals.numberOfArguments(),
8323
            availabilityMap().m_locals.numberOfArguments(),
8136
            availabilityMap().m_locals.numberOfLocals()));
8324
            availabilityMap().m_locals.numberOfLocals()));
8137
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8325
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8138
        
8326
8139
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8327
        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
8140
8328
8329
        if (failCondition == m_out.booleanTrue) {
8330
            emitOSRExitCall(exit, lowValue);
8331
            return;
8332
        }
8333
8141
        LBasicBlock lastNext = nullptr;
8334
        LBasicBlock lastNext = nullptr;
8142
        LBasicBlock continuation = nullptr;
8335
        LBasicBlock continuation = nullptr;
8143
        
8336
        
- Source/JavaScriptCore/jit/AssemblyHelpers.cpp +64 lines
Lines 55-60 Vector<BytecodeAndMachineOffset>& Assemb Source/JavaScriptCore/jit/AssemblyHelpers.cpp_sec1
55
    return result.iterator->value;
55
    return result.iterator->value;
56
}
56
}
57
57
58
AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType(
59
    JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor& descriptor)
60
{
61
    AssemblyHelpers::JumpList result;
62
63
    switch (descriptor.kind()) {
64
    case InferredType::Bottom:
65
        result.append(jump());
66
        break;
67
68
    case InferredType::Boolean:
69
        result.append(branchIfNotBoolean(regs, tempGPR));
70
        break;
71
72
    case InferredType::Other:
73
        result.append(branchIfNotOther(regs, tempGPR));
74
        break;
75
76
    case InferredType::Int32:
77
        result.append(branchIfNotInt32(regs));
78
        break;
79
80
    case InferredType::Number:
81
        result.append(branchIfNotNumber(regs, tempGPR));
82
        break;
83
84
    case InferredType::String:
85
        result.append(branchIfNotCell(regs));
86
        result.append(branchIfNotString(regs.payloadGPR()));
87
        break;
88
89
    case InferredType::ObjectWithStructure:
90
        result.append(branchIfNotCell(regs));
91
        result.append(branchStructure(NotEqual, regs.payloadGPR(), descriptor.structure()));
92
        break;
93
94
    case InferredType::ObjectWithStructureOrOther: {
95
        Jump ok = branchIfOther(regs, tempGPR);
96
        result.append(branchIfNotCell(regs));
97
        result.append(branchStructure(NotEqual, regs.payloadGPR(), descriptor.structure()));
98
        ok.link(this);
99
        break;
100
    }
101
102
    case InferredType::Object:
103
        result.append(branchIfNotCell(regs));
104
        result.append(branchIfNotObject(regs.payloadGPR()));
105
        break;
106
107
    case InferredType::ObjectOrOther: {
108
        Jump ok = branchIfOther(regs, tempGPR);
109
        result.append(branchIfNotCell(regs));
110
        result.append(branchIfNotObject(regs.payloadGPR()));
111
        ok.link(this);
112
        break;
113
    }
114
115
    case InferredType::Top:
116
        break;
117
    }
118
119
    return result;
120
}
121
58
void AssemblyHelpers::purifyNaN(FPRReg fpr)
122
void AssemblyHelpers::purifyNaN(FPRReg fpr)
59
{
123
{
60
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
124
    MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
- Source/JavaScriptCore/jit/AssemblyHelpers.h +2 lines
Lines 719-724 public: Source/JavaScriptCore/jit/AssemblyHelpers.h_sec1
719
#endif
719
#endif
720
    }
720
    }
721
721
722
    JumpList branchIfNotType(JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor&);
723
722
    template<typename T>
724
    template<typename T>
723
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
725
    Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
724
    {
726
    {
- Source/JavaScriptCore/jit/Repatch.cpp -1 / +2 lines
Lines 377-383 static InlineCacheAction tryCachePutByID Source/JavaScriptCore/jit/Repatch.cpp_sec1
377
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
377
            ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
378
            if (stubInfo.cacheType == CacheType::Unset
378
            if (stubInfo.cacheType == CacheType::Unset
379
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
379
                && MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
380
                && !structure->needImpurePropertyWatchpoint()) {
380
                && !structure->needImpurePropertyWatchpoint()
381
                && !structure->inferredTypeFor(ident.impl())) {
381
382
382
                repatchByIdSelfAccess(
383
                repatchByIdSelfAccess(
383
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
384
                    codeBlock, stubInfo, structure, slot.cachedOffset(),
- Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +8 lines
Lines 633-638 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec1
633
        pc[5].u.pointer = nullptr; // offset
633
        pc[5].u.pointer = nullptr; // offset
634
        pc[6].u.pointer = nullptr; // new structure
634
        pc[6].u.pointer = nullptr; // new structure
635
        pc[7].u.pointer = nullptr; // structure chain
635
        pc[7].u.pointer = nullptr; // structure chain
636
        pc[8].u.putByIdFlags =
637
            static_cast<PutByIdFlags>(pc[8].u.putByIdFlags & PutByIdPersistentFlagsMask);
636
        
638
        
637
        JSCell* baseCell = baseValue.asCell();
639
        JSCell* baseCell = baseValue.asCell();
638
        Structure* structure = baseCell->structure();
640
        Structure* structure = baseCell->structure();
Lines 660-671 LLINT_SLOW_PATH_DECL(slow_path_put_by_id Source/JavaScriptCore/llint/LLIntSlowPaths.cpp_sec2
660
                            pc[7].u.structureChain.set(
662
                            pc[7].u.structureChain.set(
661
                                vm, codeBlock->ownerExecutable(), chain);
663
                                vm, codeBlock->ownerExecutable(), chain);
662
                        }
664
                        }
665
                        pc[8].u.putByIdFlags = static_cast<PutByIdFlags>(
666
                            pc[8].u.putByIdFlags |
667
                            structure->inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
663
                    }
668
                    }
664
                }
669
                }
665
            } else {
670
            } else {
666
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
671
                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
667
                pc[4].u.structureID = structure->id();
672
                pc[4].u.structureID = structure->id();
668
                pc[5].u.operand = slot.cachedOffset();
673
                pc[5].u.operand = slot.cachedOffset();
674
                pc[8].u.putByIdFlags = static_cast<PutByIdFlags>(
675
                    pc[8].u.putByIdFlags |
676
                    structure->inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
669
            }
677
            }
670
        }
678
        }
671
    }
679
    }
- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm -4 / +77 lines
Lines 1265-1278 _llint_op_put_by_id: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec1
1265
    writeBarrierOnOperands(1, 3)
1265
    writeBarrierOnOperands(1, 3)
1266
    loadisFromInstruction(1, t3)
1266
    loadisFromInstruction(1, t3)
1267
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1267
    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1268
    loadi JSCell::m_structureID[t0], t2
1268
    loadisFromInstruction(4, t2)
1269
    loadisFromInstruction(4, t1)
1269
    bineq t2, JSCell::m_structureID[t0], .opPutByIdSlow
1270
    bineq t2, t1, .opPutByIdSlow
1271
1270
1272
    # At this point, we have:
1271
    # At this point, we have:
1273
    # t1, t2 -> current structure ID
1272
    # t2 -> current structure ID
1274
    # t0 -> object base
1273
    # t0 -> object base
1275
1274
1275
    loadisFromInstruction(3, t1)
1276
    loadConstantOrVariable(t1, t3)
1277
1278
    loadpFromInstruction(8, t1)
1279
1280
    # At this point, we have:
1281
    # t0 -> object base
1282
    # t1 -> put by id flags
1283
    # t2 -> current structure ID
1284
    # t3 -> value to put
1285
1286
    btpnz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1287
1288
    # We have one of the non-structure type checks. Find out which one.
1289
    andp PutByIdSecondaryTypeMask, t1
1290
    bplt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1291
1292
    # We are one of the following: String, Object, ObjectOrOther, Top
1293
    bplt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1294
1295
    # We are either ObjectOrOther or Top.
1296
    bpeq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1297
1298
    # Check if we are ObjectOrOther.
1299
    btqz t3, tagMask, .opPutByIdTypeCheckObject
1300
.opPutByIdTypeCheckOther:
1301
    andq ~TagBitUndefined, t3
1302
    bqeq t3, ValueNull, .opPutByIdDoneCheckingTypes
1303
    jmp .opPutByIdSlow
1304
1305
.opPutByIdTypeCheckLessThanObjectOrOther:
1306
    # We are either String or Object.
1307
    btqnz t3, tagMask, .opPutByIdSlow
1308
    bpeq t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckObject
1309
    bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1310
    jmp .opPutByIdSlow
1311
.opPutByIdTypeCheckObject:
1312
    bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1313
    jmp .opPutByIdSlow
1314
1315
.opPutByIdTypeCheckLessThanString:
1316
    # We are one of the following: Bottom, Boolean, Other, Int32, Number
1317
    bplt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1318
1319
    # We are either Int32 or Number.
1320
    bpeq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1321
1322
    bqaeq t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1323
    jmp .opPutByIdSlow
1324
1325
.opPutByIdTypeCheckNumber:
1326
    btqnz t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1327
    jmp .opPutByIdSlow
1328
1329
.opPutByIdTypeCheckLessThanInt32:
1330
    # We are one of the following: Bottom, Boolean, Other.
1331
    bpneq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1332
    xorq ValueFalse, t3
1333
    btqz t3, ~1, .opPutByIdDoneCheckingTypes
1334
    jmp .opPutByIdSlow
1335
1336
.opPutByIdTypeCheckBottomOrOther:
1337
    bpeq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1338
    jmp .opPutByIdSlow
1339
1340
.opPutByIdTypeCheckObjectWithStructureOrOther:
1341
    btpnz t1, PutByIdPrimaryTypeObjectWithStructure, .opPutByIdTypeCheckObjectWithStructure
1342
    btqnz t3, tagMask, .opPutByIdTypeCheckOther
1343
1344
.opPutByIdTypeCheckObjectWithStructure:
1345
    urshiftp 3, t1
1346
    bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1347
1348
.opPutByIdDoneCheckingTypes:
1276
    loadisFromInstruction(6, t1)
1349
    loadisFromInstruction(6, t1)
1277
    
1350
    
1278
    btiz t1, .opPutByIdNotTransition
1351
    btiz t1, .opPutByIdNotTransition
- Source/JavaScriptCore/llint/LowLevelInterpreter.asm +16 lines
Lines 204-209 else Source/JavaScriptCore/llint/LowLevelInterpreter.asm_sec1
204
    const LowestTag = DeletedValueTag
204
    const LowestTag = DeletedValueTag
205
end
205
end
206
206
207
# NOTE: The values below must be in sync with what is in PutByIdFlags.h.
208
const PutByIdPrimaryTypeMask = 0x6
209
const PutByIdPrimaryTypeSecondary = 0x0
210
const PutByIdPrimaryTypeObjectWithStructure = 0x2
211
const PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4
212
const PutByIdSecondaryTypeMask = -0x8
213
const PutByIdSecondaryTypeBottom = 0x0
214
const PutByIdSecondaryTypeBoolean = 0x8
215
const PutByIdSecondaryTypeOther = 0x10
216
const PutByIdSecondaryTypeInt32 = 0x18
217
const PutByIdSecondaryTypeNumber = 0x20
218
const PutByIdSecondaryTypeString = 0x28
219
const PutByIdSecondaryTypeObject = 0x30
220
const PutByIdSecondaryTypeObjectOrOther = 0x38
221
const PutByIdSecondaryTypeTop = 0x40
222
207
const CallOpCodeSize = 9
223
const CallOpCodeSize = 9
208
224
209
if X86_64 or ARM64 or C_LOOP
225
if X86_64 or ARM64 or C_LOOP
- Source/JavaScriptCore/runtime/InferredType.cpp +521 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->m_finalizer);
59
}
60
61
InferredType::Kind InferredType::kindForFlags(PutByIdFlags flags)
62
{
63
    switch (flags & PutByIdPrimaryTypeMask) {
64
    case PutByIdPrimaryTypeSecondary:
65
        switch (flags & PutByIdSecondaryTypeMask) {
66
        case PutByIdSecondaryTypeBottom:
67
            return Bottom;
68
        case PutByIdSecondaryTypeBoolean:
69
            return Boolean;
70
        case PutByIdSecondaryTypeOther:
71
            return Other;
72
        case PutByIdSecondaryTypeInt32:
73
            return Int32;
74
        case PutByIdSecondaryTypeNumber:
75
            return Number;
76
        case PutByIdSecondaryTypeString:
77
            return String;
78
        case PutByIdSecondaryTypeObject:
79
            return Object;
80
        case PutByIdSecondaryTypeObjectOrOther:
81
            return ObjectOrOther;
82
        case PutByIdSecondaryTypeTop:
83
            return Top;
84
        default:
85
            RELEASE_ASSERT_NOT_REACHED();
86
            return Bottom;
87
        }
88
    case PutByIdPrimaryTypeObjectWithStructure:
89
        return ObjectWithStructure;
90
    case PutByIdPrimaryTypeObjectWithStructureOrOther:
91
        return ObjectWithStructureOrOther;
92
    default:
93
        RELEASE_ASSERT_NOT_REACHED();
94
        return Bottom;
95
    }
96
}
97
98
InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
99
{
100
    if (value.isBoolean())
101
        return Boolean;
102
    if (value.isUndefinedOrNull())
103
        return Other;
104
    if (value.isInt32())
105
        return Int32;
106
    if (value.isNumber())
107
        return Number;
108
    if (value.isCell()) {
109
        JSCell* cell = value.asCell();
110
        if (cell->isString())
111
            return String;
112
        if (cell->isObject()) {
113
            if (cell->structure()->transitionWatchpointSetIsStillValid())
114
                return Descriptor(ObjectWithStructure, cell->structure());
115
            return Object;
116
        }
117
    }
118
    return Top;
119
}
120
121
InferredType::Descriptor InferredType::Descriptor::forFlags(VM& vm, PutByIdFlags flags)
122
{
123
    Kind kind = kindForFlags(flags);
124
    Structure* structure;
125
    if (hasStructure(kind))
126
        structure = vm.heap.structureIDTable().get(decodeStructureID(flags));
127
    else
128
        structure = nullptr;
129
    return Descriptor(kind, structure);
130
}
131
132
PutByIdFlags InferredType::Descriptor::putByIdFlags() const
133
{
134
    switch (m_kind) {
135
    case Bottom:
136
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBottom);
137
    case Boolean:
138
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBoolean);
139
    case Other:
140
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeOther);
141
    case Int32:
142
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeInt32);
143
    case Number:
144
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeNumber);
145
    case String:
146
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeString);
147
    case Object:
148
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObject);
149
    case ObjectOrOther:
150
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObjectOrOther);
151
    case Top:
152
        return static_cast<PutByIdFlags>(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeTop);
153
    case ObjectWithStructure:
154
        return static_cast<PutByIdFlags>(
155
            PutByIdPrimaryTypeObjectWithStructure | encodeStructureID(m_structure->id()));
156
    case ObjectWithStructureOrOther:
157
        return static_cast<PutByIdFlags>(
158
            PutByIdPrimaryTypeObjectWithStructureOrOther | encodeStructureID(m_structure->id()));
159
    }
160
    RELEASE_ASSERT_NOT_REACHED();
161
    return PutByIdNone;
162
}
163
164
void InferredType::Descriptor::merge(const Descriptor& other)
165
{
166
    // Filter out common things to simplify the switch statement below.
167
    if (*this == other)
168
        return;
169
    if (other.m_kind == Bottom)
170
        return;
171
172
    switch (m_kind) {
173
    case Bottom:
174
        *this = other;
175
        return;
176
    case Boolean:
177
    case String:
178
        *this = Top;
179
        return;
180
    case Other:
181
        switch (other.m_kind) {
182
        case ObjectWithStructure:
183
        case ObjectWithStructureOrOther:
184
            *this = Descriptor(ObjectWithStructureOrOther, other.structure());
185
            return;
186
        case Object:
187
        case ObjectOrOther:
188
            *this = ObjectOrOther;
189
            return;
190
        default:
191
            *this = Top;
192
            return;
193
        }
194
    case Int32:
195
        switch (other.m_kind) {
196
        case Number:
197
            *this = Number;
198
            return;
199
        default:
200
            *this = Top;
201
            return;
202
        }
203
    case Number:
204
        switch (other.m_kind) {
205
        case Int32:
206
            return;
207
        default:
208
            *this = Top;
209
            return;
210
        }
211
    case ObjectWithStructure:
212
        switch (other.m_kind) {
213
        case ObjectWithStructure: // If we see this here, then we know that the structures didn't match.
214
        case Object:
215
            *this = Object;
216
            return;
217
        case ObjectWithStructureOrOther:
218
            if (m_structure == other.m_structure) {
219
                *this = other;
220
                return;
221
            }
222
            *this = ObjectOrOther;
223
            return;
224
        case ObjectOrOther:
225
            *this = ObjectOrOther;
226
            return;
227
        case Other:
228
            m_kind = ObjectWithStructureOrOther;
229
            return;
230
        default:
231
            *this = Top;
232
            return;
233
        }
234
    case ObjectWithStructureOrOther:
235
        switch (other.m_kind) {
236
        case ObjectWithStructure:
237
            if (m_structure == other.m_structure)
238
                return;
239
            *this = ObjectOrOther;
240
            return;
241
        case Object:
242
        case ObjectWithStructureOrOther: // If we see this here, then we know that the structures didn't match.
243
        case ObjectOrOther:
244
            *this = ObjectOrOther;
245
            return;
246
        case Other:
247
            return;
248
        default:
249
            *this = Top;
250
            return;
251
        }
252
    case Object:
253
        switch (other.m_kind) {
254
        case ObjectWithStructure:
255
            return;
256
        case ObjectWithStructureOrOther:
257
        case ObjectOrOther:
258
        case Other:
259
            *this = ObjectOrOther;
260
            return;
261
        default:
262
            *this = Top;
263
            return;
264
        }
265
    case ObjectOrOther:
266
        switch (other.m_kind) {
267
        case ObjectWithStructure:
268
        case ObjectWithStructureOrOther:
269
        case Object:
270
        case Other:
271
            return;
272
        default:
273
            *this = Top;
274
            return;
275
        }
276
    case Top:
277
        return;
278
    }
279
280
    RELEASE_ASSERT_NOT_REACHED();
281
}
282
283
void InferredType::Descriptor::removeStructure()
284
{
285
    switch (m_kind) {
286
    case ObjectWithStructure:
287
        *this = Object;
288
        return;
289
    case ObjectWithStructureOrOther:
290
        *this = ObjectOrOther;
291
        return;
292
    default:
293
        return;
294
    }
295
}
296
297
bool InferredType::Descriptor::subsumes(const Descriptor& other) const
298
{
299
    Descriptor merged = *this;
300
    merged.merge(other);
301
    return *this == merged;
302
}
303
304
void InferredType::Descriptor::dumpInContext(PrintStream& out, DumpContext* context) const
305
{
306
    out.print(m_kind);
307
    if (m_structure)
308
        out.print(":", inContext(*m_structure, context));
309
}
310
311
void InferredType::Descriptor::dump(PrintStream& out) const
312
{
313
    dumpInContext(out, nullptr);
314
}
315
316
InferredType::InferredType(VM& vm)
317
    : Base(vm, vm.inferredTypeStructure.get())
318
    , m_watchpointSet(ClearWatchpoint)
319
{
320
}
321
322
InferredType::~InferredType()
323
{
324
}
325
326
bool InferredType::canWatch(const ConcurrentJITLocker& locker, const Descriptor& expected)
327
{
328
    if (expected.kind() == Top)
329
        return false;
330
    
331
    return descriptor(locker) == expected;
332
}
333
334
bool InferredType::canWatch(const Descriptor& expected)
335
{
336
    ConcurrentJITLocker locker(m_lock);
337
    return canWatch(locker, expected);
338
}
339
340
void InferredType::addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint* watchpoint)
341
{
342
    RELEASE_ASSERT(descriptor(locker).kind() != Top);
343
344
    m_watchpointSet.add(watchpoint);
345
}
346
347
void InferredType::addWatchpoint(Watchpoint* watchpoint)
348
{
349
    ConcurrentJITLocker locker(m_lock);
350
    addWatchpoint(locker, watchpoint);
351
}
352
353
void InferredType::dump(PrintStream& out) const
354
{
355
    out.print(RawPointer(this), ":", descriptor());
356
}
357
358
bool InferredType::willStoreValueSlow(VM& vm, JSValue value)
359
{
360
    ConcurrentJITLocker locker(m_lock);
361
    Descriptor myType = descriptor(locker);
362
    Descriptor otherType = Descriptor::forValue(value);
363
364
    myType.merge(otherType);
365
366
    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
367
368
    set(locker, vm, myType);
369
370
    return kind(locker) != Top;
371
}
372
373
void InferredType::makeTopSlow(VM& vm)
374
{
375
    ConcurrentJITLocker locker(m_lock);
376
    set(locker, vm, Top);
377
}
378
379
void InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
380
{
381
    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
382
    // could change. If it does, we don't want to deadlock. Note that we could have used
383
    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
384
    // a good idea.
385
    DeferGCForAWhile deferGC(vm.heap);
386
    
387
    // Be defensive: if we're not really changing the type, then we don't have to do anything.
388
    if (descriptor(locker) == newDescriptor)
389
        return;
390
391
    // The new descriptor must be more general than the previous one.
392
    ASSERT(newDescriptor.subsumes(descriptor(locker)));
393
394
    // If the new descriptors have different structures, then it can only be because one is null.
395
    if (descriptor(locker).structure() != newDescriptor.structure())
396
        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
397
398
    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
399
    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
400
    if (m_watchpointSet.state() != ClearWatchpoint) {
401
        // We cannot have been invalidated, since if we were, then we'd already be at Top.
402
        ASSERT(m_watchpointSet.state() != IsInvalidated);
403
404
        // We're about to do expensive things because some compiler thread decided to watch this type and
405
        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
406
        // it.
407
        newDescriptor = Top;
408
409
        m_watchpointSet.fireAll("Inferred type changed");
410
    }
411
412
    // Remove the old InferredStructure object if we no longer need it.
413
    if (!newDescriptor.structure())
414
        m_structure = nullptr;
415
416
    // Add a new InferredStructure object if we need one now.
417
    if (newDescriptor.structure()) {
418
        if (m_structure) {
419
            // We should agree on the structures if we get here.
420
            ASSERT(newDescriptor.structure() == m_structure->structure());
421
        } else {
422
            m_structure = std::make_unique<InferredStructure>(vm, this, newDescriptor.structure());
423
            newDescriptor.structure()->addTransitionWatchpoint(&m_structure->m_watchpoint);
424
        }
425
    }
426
427
    // Finally, set the descriptor kind.
428
    m_kind = newDescriptor.kind();
429
430
    // Assert that we did things.
431
    ASSERT(descriptor(locker) == newDescriptor);
432
}
433
434
void InferredType::removeStructure()
435
{
436
    VM& vm = *Heap::heap(this)->vm();
437
438
    ConcurrentJITLocker locker(m_lock);
439
    
440
    Descriptor newDescriptor = descriptor(locker);
441
    newDescriptor.removeStructure();
442
    
443
    set(locker, vm, newDescriptor);
444
}
445
446
void InferredType::InferredStructureWatchpoint::fireInternal(const FireDetail&)
447
{
448
    InferredStructure* inferredStructure =
449
        bitwise_cast<InferredStructure*>(
450
            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(InferredStructure, m_watchpoint));
451
452
    inferredStructure->m_parent->removeStructure();
453
}
454
455
void InferredType::InferredStructureFinalizer::finalizeUnconditionally()
456
{
457
    InferredStructure* inferredStructure =
458
        bitwise_cast<InferredStructure*>(
459
            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(InferredStructure, m_finalizer));
460
461
    ASSERT(Heap::isMarked(inferredStructure->m_parent));
462
    
463
    if (!Heap::isMarked(inferredStructure->m_structure.get()))
464
        inferredStructure->m_parent->removeStructure();
465
}
466
467
InferredType::InferredStructure::InferredStructure(VM& vm, InferredType* parent, Structure* structure)
468
    : m_parent(parent)
469
    , m_structure(vm, parent, structure)
470
{
471
}
472
473
} // namespace JSC
474
475
namespace WTF {
476
477
using namespace JSC;
478
479
void printInternal(PrintStream& out, InferredType::Kind kind)
480
{
481
    switch (kind) {
482
    case InferredType::Bottom:
483
        out.print("Bottom");
484
        return;
485
    case InferredType::Boolean:
486
        out.print("Boolean");
487
        return;
488
    case InferredType::Other:
489
        out.print("Other");
490
        return;
491
    case InferredType::Int32:
492
        out.print("Int32");
493
        return;
494
    case InferredType::Number:
495
        out.print("Number");
496
        return;
497
    case InferredType::String:
498
        out.print("String");
499
        return;
500
    case InferredType::ObjectWithStructure:
501
        out.print("ObjectWithStructure");
502
        return;
503
    case InferredType::ObjectWithStructureOrOther:
504
        out.print("ObjectWithStructureOrOther");
505
        return;
506
    case InferredType::Object:
507
        out.print("Object");
508
        return;
509
    case InferredType::ObjectOrOther:
510
        out.print("ObjectOrOther");
511
        return;
512
    case InferredType::Top:
513
        out.print("Top");
514
        return;
515
    }
516
517
    RELEASE_ASSERT_NOT_REACHED();
518
}
519
520
} // namespace WTF
521
- Source/JavaScriptCore/runtime/InferredType.h +285 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
#ifndef InferredType_h
27
#define InferredType_h
28
29
#include "ConcurrentJITLock.h"
30
#include "JSCell.h"
31
#include "PutByIdFlags.h"
32
#include "Watchpoint.h"
33
34
namespace JSC {
35
36
// This is an object used for the inference of the types of object properties.
37
38
class InferredType final : public JSCell {
39
public:
40
    typedef JSCell Base;
41
42
    static InferredType* create(VM&);
43
44
    static const bool needsDestruction = true;
45
    static void destroy(JSCell*);
46
47
    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
48
    
49
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
50
51
    static void visitChildren(JSCell*, SlotVisitor&);
52
53
    DECLARE_INFO;
54
55
    enum Kind : uint8_t {
56
        Bottom,
57
        Boolean,
58
        Other,
59
        Int32,
60
        Number,
61
        String,
62
        ObjectWithStructure,
63
        ObjectWithStructureOrOther,
64
        Object,
65
        ObjectOrOther,
66
        Top
67
    };
68
69
    static Kind kindForFlags(PutByIdFlags);
70
    
71
    static bool hasStructure(Kind kind)
72
    {
73
        switch (kind) {
74
        case ObjectWithStructure:
75
        case ObjectWithStructureOrOther:
76
            return true;
77
        default:
78
            return false;
79
        }
80
    }
81
82
    class Descriptor {
83
    public:
84
        Descriptor()
85
            : m_kind(Bottom)
86
            , m_structure(nullptr)
87
        {
88
        }
89
90
        Descriptor(Kind kind, Structure* structure = nullptr)
91
            : m_kind(kind)
92
            , m_structure(structure)
93
        {
94
            if (hasStructure(kind))
95
                ASSERT(structure);
96
        }
97
98
        static Descriptor forValue(JSValue);
99
100
        static Descriptor forFlags(VM&, PutByIdFlags);
101
102
        explicit operator bool() const
103
        {
104
            return m_kind == Bottom && !m_structure;
105
        }
106
107
        Kind kind() const { return m_kind; }
108
        Structure* structure() const { return m_structure; }
109
110
        PutByIdFlags putByIdFlags() const;
111
112
        ALWAYS_INLINE bool includesValue(JSValue value)
113
        {
114
            switch (m_kind) {
115
            case Bottom:
116
                return false;
117
            case Boolean:
118
                return value.isBoolean();
119
            case Other:
120
                return value.isUndefinedOrNull();
121
            case Int32:
122
                return value.isInt32();
123
            case Number:
124
                return value.isNumber();
125
            case String:
126
                return value.isString();
127
            case ObjectWithStructure:
128
                return value.isCell() && value.asCell()->structure() == m_structure;
129
            case ObjectWithStructureOrOther:
130
                return value.isUndefinedOrNull()
131
                    || (value.isCell() && value.asCell()->structure() == m_structure);
132
            case Object:
133
                return value.isObject();
134
            case ObjectOrOther:
135
                return value.isUndefinedOrNull() || value.isObject();
136
            case Top:
137
                return true;
138
            }
139
140
            RELEASE_ASSERT_NOT_REACHED();
141
        }
142
143
        bool operator==(const Descriptor& other) const
144
        {
145
            return m_kind == other.m_kind
146
                && m_structure == other.m_structure;
147
        }
148
149
        bool operator!=(const Descriptor& other) const
150
        {
151
            return !(*this == other);
152
        }
153
154
        unsigned hash() const
155
        {
156
            return WTF::PtrHash<Structure*>::hash(m_structure) ^ static_cast<unsigned>(m_kind);
157
        }
158
    
159
        void merge(const Descriptor&);
160
        void removeStructure();
161
162
        // Returns true if this descriptor is more general than the other one.
163
        bool subsumes(const Descriptor&) const;
164
165
        void dumpInContext(PrintStream&, DumpContext*) const;
166
        void dump(PrintStream&) const;
167
168
    private:
169
        Kind m_kind;
170
        Structure* m_structure;
171
    };
172
173
    ConcurrentJITLock& lock() const { return m_lock; }
174
175
    Descriptor descriptorMainThread() const
176
    {
177
        return Descriptor(m_kind, m_structure ? m_structure->structure() : nullptr);
178
    }
179
    
180
    Descriptor descriptor(const ConcurrentJITLocker&) const
181
    {
182
        return descriptorMainThread();
183
    }
184
    Descriptor descriptor() const
185
    {
186
        ConcurrentJITLocker locker(m_lock);
187
        return descriptor(locker);
188
    }
189
    
190
    Kind kind(const ConcurrentJITLocker& locker) const { return descriptor(locker).kind(); }
191
192
    bool isTop() const { return m_kind == Top; }
193
    bool isRelevant() const { return m_kind != Top; }
194
195
    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
196
    ALWAYS_INLINE bool willStoreValue(VM& vm, JSValue value)
197
    {
198
        Descriptor currentDescriptor = descriptorMainThread();
199
        if (currentDescriptor.includesValue(value))
200
            return currentDescriptor.kind() != Top;
201
        return willStoreValueSlow(vm, value);
202
    }
203
204
    // Immediately makes this type irrelevant.
205
    void makeTop(VM& vm)
206
    {
207
        if (isTop())
208
            return;
209
        makeTopSlow(vm);
210
    }
211
212
    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
213
    // this will always return false for Top.
214
    bool canWatch(const ConcurrentJITLocker& locker, const Descriptor&);
215
    bool canWatch(const Descriptor&);
216
    
217
    void addWatchpoint(const ConcurrentJITLocker& locker, Watchpoint*);
218
    void addWatchpoint(Watchpoint*);
219
220
    void dump(PrintStream&) const;
221
222
private:
223
    InferredType(VM&);
224
    ~InferredType();
225
226
    bool willStoreValueSlow(VM&, JSValue);
227
    void makeTopSlow(VM&);
228
    void set(const ConcurrentJITLocker&, VM&, Descriptor);
229
    void removeStructure();
230
231
    mutable ConcurrentJITLock m_lock;
232
    
233
    Kind m_kind { Bottom };
234
235
    class InferredStructureWatchpoint : public Watchpoint {
236
    public:
237
        InferredStructureWatchpoint() { }
238
    protected:
239
        void fireInternal(const FireDetail&) override;
240
    };
241
242
    class InferredStructureFinalizer : public UnconditionalFinalizer {
243
    public:
244
        InferredStructureFinalizer() { }
245
    protected:
246
        void finalizeUnconditionally() override;
247
    };
248
249
    class InferredStructure {
250
        WTF_MAKE_FAST_ALLOCATED;
251
    public:
252
        InferredStructure(VM&, InferredType* parent, Structure*);
253
254
        Structure* structure() const { return m_structure.get(); };
255
256
    private:
257
        friend class InferredType;
258
        friend class InferredStructureWatchpoint;
259
        friend class InferredStructureFinalizer;
260
        
261
        InferredType* m_parent;
262
        WriteBarrier<Structure> m_structure;
263
264
        InferredStructureWatchpoint m_watchpoint;
265
        InferredStructureFinalizer m_finalizer;
266
    };
267
268
    std::unique_ptr<InferredStructure> m_structure;
269
270
    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
271
    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
272
    // thread. The DFG will use the InferredType as the thing that it watches.
273
    InlineWatchpointSet m_watchpointSet;
274
};
275
276
} // namespace JSC
277
278
namespace WTF {
279
280
void printInternal(PrintStream&, JSC::InferredType::Kind);
281
282
} // namespace WTF
283
284
#endif // InferredType_h
285
- Source/JavaScriptCore/runtime/InferredTypeTable.cpp +166 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(inferredTypeTable->m_lock);
58
    
59
    for (auto& entry : inferredTypeTable->m_table) {
60
        if (!entry.value)
61
            continue;
62
        if (entry.value->isRelevant())
63
            visitor.append(&entry.value);
64
        else
65
            entry.value.clear();
66
    }
67
}
68
69
InferredType* InferredTypeTable::get(const ConcurrentJITLocker&, UniquedStringImpl* uid)
70
{
71
    auto iter = m_table.find(uid);
72
    if (iter == m_table.end() || !iter->value)
73
        return nullptr;
74
75
    // Take this opportunity to prune invalidated types.
76
    if (!iter->value->isRelevant()) {
77
        iter->value.clear();
78
        return nullptr;
79
    }
80
81
    return iter->value.get();
82
}
83
84
InferredType* InferredTypeTable::get(UniquedStringImpl* uid)
85
{
86
    ConcurrentJITLocker locker(m_lock);
87
    return get(locker, uid);
88
}
89
90
InferredType* InferredTypeTable::get(PropertyName propertyName)
91
{
92
    return get(propertyName.uid());
93
}
94
95
bool InferredTypeTable::willStoreValue(
96
    VM& vm, PropertyName propertyName, JSValue value, StoredPropertyAge age)
97
{
98
    // The algorithm here relies on the fact that only one thread modifies the hash map.
99
    
100
    if (age == OldProperty) {
101
        TableType::iterator iter = m_table.find(propertyName.uid());
102
        if (iter == m_table.end() || !iter->value)
103
            return false; // Absence on replace => top.
104
        
105
        if (iter->value->willStoreValue(vm, value))
106
            return true;
107
        
108
        iter->value.clear();
109
        return false;
110
    }
111
112
    TableType::AddResult result;
113
    {
114
        ConcurrentJITLocker locker(m_lock);
115
        result = m_table.add(propertyName.uid(), WriteBarrier<InferredType>());
116
    }
117
    if (result.isNewEntry) {
118
        InferredType* inferredType = InferredType::create(vm);
119
        WTF::storeStoreFence();
120
        result.iterator->value.set(vm, this, inferredType);
121
    } else if (!result.iterator->value)
122
        return false;
123
    
124
    if (result.iterator->value->willStoreValue(vm, value))
125
        return true;
126
    
127
    result.iterator->value.clear();
128
    return false;
129
}
130
131
void InferredTypeTable::makeTop(VM& vm, PropertyName propertyName, StoredPropertyAge age)
132
{
133
    // The algorithm here relies on the fact that only one thread modifies the hash map.
134
    if (age == OldProperty) {
135
        TableType::iterator iter = m_table.find(propertyName.uid());
136
        if (iter == m_table.end() || !iter->value)
137
            return; // Absence on replace => top.
138
139
        iter->value->makeTop(vm);
140
        iter->value.clear();
141
        return;
142
    }
143
144
    TableType::AddResult result;
145
    {
146
        ConcurrentJITLocker locker(m_lock);
147
        result = m_table.add(propertyName.uid(), WriteBarrier<InferredType>());
148
    }
149
    if (!result.iterator->value)
150
        return;
151
    
152
    result.iterator->value->makeTop(vm);
153
    result.iterator->value.clear();
154
}
155
156
InferredTypeTable::InferredTypeTable(VM& vm)
157
    : Base(vm, vm.inferredTypeTableStructure.get())
158
{
159
}
160
161
InferredTypeTable::~InferredTypeTable()
162
{
163
}
164
165
} // namespace JSC
166
- Source/JavaScriptCore/runtime/InferredTypeTable.h +114 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 "Identifier.h"
30
#include "InferredType.h"
31
#include "JSCell.h"
32
33
namespace JSC {
34
35
// A table of inferred types for some structure. This is a JSCell because that simplifies the Structure
36
// destructor and makes lifetype easier to manage. For example, since it's a cell, we know that this thing
37
// cannot be deleted while the DFG is running. This is separate from PropertyTable because most properties
38
// will not have an InferredType, since most properties are in dictionaries (if you think of "a property"
39
// as being "a property in some Structure"). Also, this will happily conflate the types of properties from
40
// different structures even if the structures represent disjoint sets of objects.
41
42
class InferredTypeTable final : public JSCell {
43
public:
44
    typedef JSCell Base;
45
46
    static InferredTypeTable* create(VM&);
47
48
    static const bool needsDestruction = true;
49
    static void destroy(JSCell*);
50
51
    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
52
    
53
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
54
55
    static void visitChildren(JSCell*, SlotVisitor&);
56
57
    DECLARE_INFO;
58
59
    ConcurrentJITLock& lock() { return m_lock; }
60
61
    bool isEmpty() const { return m_table.isEmpty(); }
62
63
    // Get the current inferred type. Returns nullptr for both Top and Bottom. Null means Bottom if the
64
    // owning Structure doesn't know about the property.
65
    InferredType* get(const ConcurrentJITLocker&, UniquedStringImpl*);
66
    InferredType* get(UniquedStringImpl*);
67
    InferredType* get(PropertyName);
68
69
    enum StoredPropertyAge {
70
        NewProperty,
71
        OldProperty
72
    };
73
    
74
    // Returns true if the InferredType for this property is still relevant after the store. It's not
75
    // relevant if it's Top. Note that this table will internally prune Top entries.
76
    bool willStoreValue(VM&, PropertyName, JSValue, StoredPropertyAge);
77
78
    // Invalidates the type for the property. Useful if we detect a store in a reflective context.
79
    void makeTop(VM&, PropertyName, StoredPropertyAge);
80
81
private:
82
    InferredTypeTable(VM&);
83
    ~InferredTypeTable();
84
85
    // Bottom: absence from table.
86
    // Top: null value in table, !value->isRelevant(), or absence from table.
87
    //
88
    // We know how to determine if absence from the table is bottom or top depending on whether the
89
    // property is present in the owning structure. Hence, depending on the structure, absence may have
90
    // different meanings. The way that this class determines if the owning structure knows of the property
91
    // is that we differentiate between actions: replace or transition. If we're adding a new property
92
    // (transition), then absence means bottom. If we're storing to an existing property (replace, then
93
    // absence means top. To make this work, we have to watch out for the case where two structures, S1 and
94
    // S2, share the same InferredTypeTable and neither of them initially know about property P. S1 may
95
    // want to add P without a type, while S2 may want to add P with a type. If S1 added P and used absence
96
    // to indicate Top, then S2 would use that absence to mean Bottom and would end up creating a non-Top
97
    // entry in the table. Then S1 would forget that it wanted Top, and would use S2's type. Clearly,
98
    // that's bad. We avoid such confusion by ensuring that a transition always adds an entry. Hence,
99
    // absence-means-bottom only comes into play for properties added before the InferredTypeTable was
100
    // created.
101
    typedef HashMap<RefPtr<UniquedStringImpl>, WriteBarrier<InferredType>, IdentifierRepHash, HashTraits<UniquedStringImpl*>> TableType;
102
    
103
    TableType m_table;
104
105
    // We only grab this lock when we're doing modifications on the main thread, or reads on the compiler
106
    // thread. The compiler thread is not allowed to do modifications.
107
    ConcurrentJITLock m_lock;
108
};
109
110
} // namespace JSC
111
112
#endif // InferredTypeTable_h
113
114
- Source/JavaScriptCore/runtime/JSObject.h -13 / +32 lines
Lines 1189-1194 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec1
1189
1189
1190
    Structure* structure = this->structure(vm);
1190
    Structure* structure = this->structure(vm);
1191
    if (structure->isDictionary()) {
1191
    if (structure->isDictionary()) {
1192
        ASSERT(!structure->hasInferredTypes());
1193
        
1192
        unsigned currentAttributes;
1194
        unsigned currentAttributes;
1193
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1195
        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
1194
        if (offset != invalidOffset) {
1196
        if (offset != invalidOffset) {
Lines 1227-1255 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec2
1227
1229
1228
    PropertyOffset offset;
1230
    PropertyOffset offset;
1229
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1231
    size_t currentCapacity = this->structure()->outOfLineCapacity();
1230
    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
1232
    Structure* newStructure = Structure::addPropertyTransitionToExistingStructure(
1233
        structure, propertyName, attributes, offset);
1234
    if (newStructure) {
1235
        newStructure->willStoreValueForTransition(
1236
            vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1237
        
1231
        DeferGC deferGC(vm.heap);
1238
        DeferGC deferGC(vm.heap);
1232
        Butterfly* newButterfly = butterfly();
1239
        Butterfly* newButterfly = butterfly();
1233
        if (currentCapacity != structure->outOfLineCapacity()) {
1240
        if (currentCapacity != newStructure->outOfLineCapacity()) {
1234
            ASSERT(structure != this->structure());
1241
            ASSERT(newStructure != this->structure());
1235
            newButterfly = growOutOfLineStorage(vm, currentCapacity, structure->outOfLineCapacity());
1242
            newButterfly = growOutOfLineStorage(vm, currentCapacity, newStructure->outOfLineCapacity());
1236
        }
1243
        }
1237
1244
1238
        validateOffset(offset);
1245
        validateOffset(offset);
1239
        ASSERT(structure->isValidOffset(offset));
1246
        ASSERT(newStructure->isValidOffset(offset));
1240
        setStructureAndButterfly(vm, structure, newButterfly);
1247
        setStructureAndButterfly(vm, newStructure, newButterfly);
1241
        putDirect(vm, offset, value);
1248
        putDirect(vm, offset, value);
1242
        slot.setNewProperty(this, offset);
1249
        slot.setNewProperty(this, offset);
1243
        return true;
1250
        return true;
1244
    }
1251
    }
1245
1252
1246
    unsigned currentAttributes;
1253
    unsigned currentAttributes;
1247
    offset = structure->get(vm, propertyName, currentAttributes);
1254
    bool hasInferredType;
1255
    offset = structure->get(vm, propertyName, currentAttributes, hasInferredType);
1248
    if (offset != invalidOffset) {
1256
    if (offset != invalidOffset) {
1249
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1257
        if ((mode == PutModePut) && currentAttributes & ReadOnly)
1250
            return false;
1258
            return false;
1251
1259
1252
        structure->didReplaceProperty(offset);
1260
        structure->didReplaceProperty(offset);
1261
        if (UNLIKELY(hasInferredType)) {
1262
            structure->willStoreValueForReplace(
1263
                vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1264
        }
1265
1253
        slot.setExistingProperty(this, offset);
1266
        slot.setExistingProperty(this, offset);
1254
        putDirect(vm, offset, value);
1267
        putDirect(vm, offset, value);
1255
1268
Lines 1268-1283 inline bool JSObject::putDirectInternal( Source/JavaScriptCore/runtime/JSObject.h_sec3
1268
    // we want.
1281
    // we want.
1269
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1282
    DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
1270
    
1283
    
1271
    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1284
    newStructure = Structure::addPropertyTransition(
1285
        vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
1286
    newStructure->willStoreValueForTransition(
1287
        vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
1272
    
1288
    
1273
    validateOffset(offset);
1289
    validateOffset(offset);
1274
    ASSERT(structure->isValidOffset(offset));
1290
    ASSERT(newStructure->isValidOffset(offset));
1275
    setStructureAndReallocateStorageIfNecessary(vm, structure);
1291
    setStructureAndReallocateStorageIfNecessary(vm, newStructure);
1276
1292
1277
    putDirect(vm, offset, value);
1293
    putDirect(vm, offset, value);
1278
    slot.setNewProperty(this, offset);
1294
    slot.setNewProperty(this, offset);
1279
    if (attributes & ReadOnly)
1295
    if (attributes & ReadOnly)
1280
        structure->setContainsReadOnlyProperties();
1296
        newStructure->setContainsReadOnlyProperties();
1281
    return true;
1297
    return true;
1282
}
1298
}
1283
1299
Lines 1335-1342 inline void JSObject::putDirectWithoutTr Source/JavaScriptCore/runtime/JSObject.h_sec4
1335
    Butterfly* newButterfly = m_butterfly.get();
1351
    Butterfly* newButterfly = m_butterfly.get();
1336
    if (structure()->putWillGrowOutOfLineStorage())
1352
    if (structure()->putWillGrowOutOfLineStorage())
1337
        newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
1353
        newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
1338
    PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes);
1354
    Structure* structure = this->structure();
1339
    setStructureAndButterfly(vm, structure(), newButterfly);
1355
    PropertyOffset offset = structure->addPropertyWithoutTransition(vm, propertyName, attributes);
1356
    bool shouldOptimize = false;
1357
    structure->willStoreValueForTransition(vm, propertyName, value, shouldOptimize);
1358
    setStructureAndButterfly(vm, structure, newButterfly);
1340
    putDirect(vm, offset, value);
1359
    putDirect(vm, offset, value);
1341
}
1360
}
1342
1361
- Source/JavaScriptCore/runtime/Structure.cpp +62 lines
Lines 350-360 void Structure::materializePropertyMap(V Source/JavaScriptCore/runtime/Structure.cpp_sec1
350
    else
350
    else
351
        propertyTable().set(vm, this, table);
351
        propertyTable().set(vm, this, table);
352
352
353
    InferredTypeTable* typeTable = m_inferredTypeTable.get();
354
353
    for (size_t i = structures.size(); i--;) {
355
    for (size_t i = structures.size(); i--;) {
354
        structure = structures[i];
356
        structure = structures[i];
355
        if (!structure->m_nameInPrevious)
357
        if (!structure->m_nameInPrevious)
356
            continue;
358
            continue;
357
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
359
        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
360
        if (typeTable && typeTable->get(structure->m_nameInPrevious.get()))
361
            entry.hasInferredType = true;
358
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
362
        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
359
    }
363
    }
360
    
364
    
Lines 464-469 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec2
464
    transition->setAttributesInPrevious(attributes);
468
    transition->setAttributesInPrevious(attributes);
465
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
469
    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
466
    transition->m_offset = structure->m_offset;
470
    transition->m_offset = structure->m_offset;
471
    transition->m_inferredTypeTable.setMayBeNull(vm, transition, structure->m_inferredTypeTable.get());
467
472
468
    offset = transition->add(vm, propertyName, attributes);
473
    offset = transition->add(vm, propertyName, attributes);
469
474
Lines 479-484 Structure* Structure::addPropertyTransit Source/JavaScriptCore/runtime/Structure.cpp_sec3
479
484
480
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
485
Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
481
{
486
{
487
    // NOTE: There are some good reasons why this goes directly to uncacheable dictionary rather than
488
    // caching the removal. We can fix all of these things, but we must remember to do so, if we ever try
489
    // to optimize this case.
490
    //
491
    // - Cached transitions usually steal the property table, and assume that this is possible because they
492
    //   can just rebuild the table by looking at past transitions. That code assumes that the table only
493
    //   grew and never shrank. To support removals, we'd have to change the property table materialization
494
    //   code to handle deletions. Also, we have logic to get the list of properties on a structure that
495
    //   lacks a property table by just looking back through the set of transitions since the last
496
    //   structure that had a pinned table. That logic would also have to be changed to handle cached
497
    //   removals.
498
    //
499
    // - InferredTypeTable assumes that removal has never happened. This is important since if we could
500
    //   remove a property and then re-add it later, then the "absence means top" optimization wouldn't
501
    //   work anymore, unless removal also either poisoned type inference (by doing something equivalent to
502
    //   hasBeenDictionary) or by strongly marking the entry as Top by ensuring that it is not absent, but
503
    //   instead, has a null entry.
504
    
482
    ASSERT(!structure->isUncacheableDictionary());
505
    ASSERT(!structure->isUncacheableDictionary());
483
506
484
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
507
    Structure* transition = toUncacheableDictionaryTransition(vm, structure);
Lines 841-846 void Structure::startWatchingInternalPro Source/JavaScriptCore/runtime/Structure.cpp_sec4
841
    setDidWatchInternalProperties(true);
864
    setDidWatchInternalProperties(true);
842
}
865
}
843
866
867
void Structure::willStoreValueSlow(
868
    VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize,
869
    InferredTypeTable::StoredPropertyAge age)
870
{
871
    ASSERT(!isCompilationThread());
872
    ASSERT(structure()->classInfo() == info());
873
    ASSERT(!hasBeenDictionary());
874
875
    // Create the inferred type table before doing anything else, so that we don't GC after we have already
876
    // grabbed a pointer into the property map.
877
    InferredTypeTable* table = m_inferredTypeTable.get();
878
    if (!table) {
879
        table = InferredTypeTable::create(vm);
880
        WTF::storeStoreFence();
881
        m_inferredTypeTable.set(vm, this, table);
882
    }
883
884
    // This only works if we've got a property table.
885
    PropertyTable* propertyTable;
886
    materializePropertyMapIfNecessary(vm, propertyTable);
887
888
    // We must be calling this after having created the given property or confirmed that it was present
889
    // already, so we must have a property table now.
890
    ASSERT(propertyTable);
891
892
    // ... and the property must be present.
893
    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
894
    ASSERT(entry);
895
896
    if (shouldOptimize)
897
        entry->hasInferredType = table->willStoreValue(vm, propertyName, value, age);
898
    else {
899
        table->makeTop(vm, propertyName, age);
900
        entry->hasInferredType = false;
901
    }
902
}
903
844
#if DUMP_PROPERTYMAP_STATS
904
#if DUMP_PROPERTYMAP_STATS
845
905
846
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
906
PropertyMapHashTableStats* propertyMapHashTableStats = 0;
Lines 1058-1063 void Structure::visitChildren(JSCell* ce Source/JavaScriptCore/runtime/Structure.cpp_sec5
1058
        visitor.append(&thisObject->m_propertyTableUnsafe);
1118
        visitor.append(&thisObject->m_propertyTableUnsafe);
1059
    } else if (thisObject->m_propertyTableUnsafe)
1119
    } else if (thisObject->m_propertyTableUnsafe)
1060
        thisObject->m_propertyTableUnsafe.clear();
1120
        thisObject->m_propertyTableUnsafe.clear();
1121
1122
    visitor.append(&thisObject->m_inferredTypeTable);
1061
}
1123
}
1062
1124
1063
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
1125
bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
- Source/JavaScriptCore/runtime/Structure.h +44 lines
Lines 29-34 Source/JavaScriptCore/runtime/Structure.h_sec1
29
#include "ClassInfo.h"
29
#include "ClassInfo.h"
30
#include "ConcurrentJITLock.h"
30
#include "ConcurrentJITLock.h"
31
#include "IndexingType.h"
31
#include "IndexingType.h"
32
#include "InferredTypeTable.h"
32
#include "JSCJSValue.h"
33
#include "JSCJSValue.h"
33
#include "JSCell.h"
34
#include "JSCell.h"
34
#include "JSType.h"
35
#include "JSType.h"
Lines 81-91 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec2
81
    UniquedStringImpl* key;
82
    UniquedStringImpl* key;
82
    PropertyOffset offset;
83
    PropertyOffset offset;
83
    uint8_t attributes;
84
    uint8_t attributes;
85
    bool hasInferredType; // This caches whether or not a property has an inferred type in the inferred type table, and is used for a fast check in JSObject::putDirectInternal().
84
86
85
    PropertyMapEntry()
87
    PropertyMapEntry()
86
        : key(nullptr)
88
        : key(nullptr)
87
        , offset(invalidOffset)
89
        , offset(invalidOffset)
88
        , attributes(0)
90
        , attributes(0)
91
        , hasInferredType(false)
89
    {
92
    {
90
    }
93
    }
91
    
94
    
Lines 93-98 struct PropertyMapEntry { Source/JavaScriptCore/runtime/Structure.h_sec3
93
        : key(key)
96
        : key(key)
94
        , offset(offset)
97
        , offset(offset)
95
        , attributes(attributes)
98
        , attributes(attributes)
99
        , hasInferredType(false)
96
    {
100
    {
97
        ASSERT(this->attributes == attributes);
101
        ASSERT(this->attributes == attributes);
98
    }
102
    }
Lines 323-328 public: Source/JavaScriptCore/runtime/Structure.h_sec4
323
327
324
    PropertyOffset get(VM&, PropertyName);
328
    PropertyOffset get(VM&, PropertyName);
325
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
329
    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
330
    PropertyOffset get(VM&, PropertyName, unsigned& attributes, bool& hasInferredType);
326
331
327
    // This is a somewhat internalish method. It will call your functor while possibly holding the
332
    // This is a somewhat internalish method. It will call your functor while possibly holding the
328
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
333
    // Structure's lock. There is no guarantee whether the lock is held or not in any particular
Lines 481-486 public: Source/JavaScriptCore/runtime/Structure.h_sec5
481
            structure->startWatchingInternalPropertiesIfNecessary(vm);
486
            structure->startWatchingInternalPropertiesIfNecessary(vm);
482
    }
487
    }
483
488
489
    bool hasInferredTypes() const
490
    {
491
        return !!m_inferredTypeTable;
492
    }
493
494
    InferredType* inferredTypeFor(UniquedStringImpl* uid)
495
    {
496
        if (InferredTypeTable* table = m_inferredTypeTable.get())
497
            return table->get(uid);
498
        return nullptr;
499
    }
500
501
    InferredType::Descriptor inferredTypeDescriptorFor(UniquedStringImpl* uid)
502
    {
503
        if (InferredType* result = inferredTypeFor(uid))
504
            return result->descriptor();
505
        return InferredType::Top;
506
    }
507
508
    ALWAYS_INLINE void willStoreValueForTransition(
509
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
510
    {
511
        if (hasBeenDictionary() || (!shouldOptimize && !m_inferredTypeTable))
512
            return;
513
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::NewProperty);
514
    }
515
    ALWAYS_INLINE void willStoreValueForReplace(
516
        VM& vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
517
    {
518
        if (hasBeenDictionary())
519
            return;
520
        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::OldProperty);
521
    }
522
484
    PassRefPtr<StructureShape> toStructureShape(JSValue);
523
    PassRefPtr<StructureShape> toStructureShape(JSValue);
485
    
524
    
486
    // Determines if the two structures match enough that this one could be used for allocations
525
    // Determines if the two structures match enough that this one could be used for allocations
Lines 632-637 private: Source/JavaScriptCore/runtime/Structure.h_sec6
632
    
671
    
633
    void startWatchingInternalProperties(VM&);
672
    void startWatchingInternalProperties(VM&);
634
673
674
    JS_EXPORT_PRIVATE void willStoreValueSlow(
675
        VM&, PropertyName, JSValue, bool, InferredTypeTable::StoredPropertyAge);
676
635
    static const int s_maxTransitionLength = 64;
677
    static const int s_maxTransitionLength = 64;
636
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
678
    static const int s_maxTransitionLengthForNonEvalPutById = 512;
637
679
Lines 655-660 private: Source/JavaScriptCore/runtime/Structure.h_sec7
655
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
697
    // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
656
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
698
    WriteBarrier<PropertyTable> m_propertyTableUnsafe;
657
699
700
    WriteBarrier<InferredTypeTable> m_inferredTypeTable;
701
658
    mutable InlineWatchpointSet m_transitionWatchpointSet;
702
    mutable InlineWatchpointSet m_transitionWatchpointSet;
659
703
660
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
704
    COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
- Source/JavaScriptCore/runtime/StructureInlines.h -10 / +11 lines
Lines 1-5 Source/JavaScriptCore/runtime/StructureInlines.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 75-93 inline Structure* Structure::storedProto Source/JavaScriptCore/runtime/StructureInlines.h_sec2
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_sec3
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
- Source/JavaScriptCore/runtime/VM.cpp +3 lines
Lines 51-56 Source/JavaScriptCore/runtime/VM.cpp_sec1
51
#include "HostCallReturnValue.h"
51
#include "HostCallReturnValue.h"
52
#include "Identifier.h"
52
#include "Identifier.h"
53
#include "IncrementalSweeper.h"
53
#include "IncrementalSweeper.h"
54
#include "InferredTypeTable.h"
54
#include "Interpreter.h"
55
#include "Interpreter.h"
55
#include "JITCode.h"
56
#include "JITCode.h"
56
#include "JSAPIValueWrapper.h"
57
#include "JSAPIValueWrapper.h"
Lines 241-246 VM::VM(VMType vmType, HeapType heapType) Source/JavaScriptCore/runtime/VM.cpp_sec2
241
    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
242
    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
242
    weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull()));
243
    weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull()));
243
    inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
244
    inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
245
    inferredTypeStructure.set(*this, InferredType::createStructure(*this, 0, jsNull()));
246
    inferredTypeTableStructure.set(*this, InferredTypeTable::createStructure(*this, 0, jsNull()));
244
    functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
247
    functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
245
    exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
248
    exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
246
    promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
249
    promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
- Source/JavaScriptCore/runtime/VM.h +2 lines
Lines 302-307 public: Source/JavaScriptCore/runtime/VM.h_sec1
302
    Strong<Structure> propertyTableStructure;
302
    Strong<Structure> propertyTableStructure;
303
    Strong<Structure> weakMapDataStructure;
303
    Strong<Structure> weakMapDataStructure;
304
    Strong<Structure> inferredValueStructure;
304
    Strong<Structure> inferredValueStructure;
305
    Strong<Structure> inferredTypeStructure;
306
    Strong<Structure> inferredTypeTableStructure;
305
    Strong<Structure> functionRareDataStructure;
307
    Strong<Structure> functionRareDataStructure;
306
    Strong<Structure> exceptionStructure;
308
    Strong<Structure> exceptionStructure;
307
    Strong<Structure> promiseDeferredStructure;
309
    Strong<Structure> promiseDeferredStructure;
- Source/WTF/wtf/HashTable.h +1 lines
Lines 286-291 namespace WTF { Source/WTF/wtf/HashTable.h_sec1
286
    };
286
    };
287
287
288
    template<typename IteratorType> struct HashTableAddResult {
288
    template<typename IteratorType> struct HashTableAddResult {
289
        HashTableAddResult() : isNewEntry(false) { }
289
        HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { }
290
        HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { }
290
        IteratorType iterator;
291
        IteratorType iterator;
291
        bool isNewEntry;
292
        bool isNewEntry;

Return to Bug 148610