- a/Source/JavaScriptCore/ChangeLog +14 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2018-01-25  Commit Queue  <commit-queue@webkit.org>
2
3
        Unreviewed, rolling out r227592.
4
        https://bugs.webkit.org/show_bug.cgi?id=182110
5
6
        it made ARM64 (Linux and iOS) crash (Requested by pizlo-mbp on
7
        #webkit).
8
9
        Reverted changeset:
10
11
        "JSC GC should support TLCs (thread local caches)"
12
        https://bugs.webkit.org/show_bug.cgi?id=181559
13
        https://trac.webkit.org/changeset/227592
14
1
2018-01-25  Alejandro G. Castro  <alex@igalia.com>
15
2018-01-25  Alejandro G. Castro  <alex@igalia.com>
2
16
3
        undefined reference to 'JSC::B3::BasicBlock::fallThrough() const
17
        undefined reference to 'JSC::B3::BasicBlock::fallThrough() const
- a/Source/WTF/ChangeLog +14 lines
Lines 1-3 a/Source/WTF/ChangeLog_sec1
1
2018-01-25  Commit Queue  <commit-queue@webkit.org>
2
3
        Unreviewed, rolling out r227592.
4
        https://bugs.webkit.org/show_bug.cgi?id=182110
5
6
        it made ARM64 (Linux and iOS) crash (Requested by pizlo-mbp on
7
        #webkit).
8
9
        Reverted changeset:
10
11
        "JSC GC should support TLCs (thread local caches)"
12
        https://bugs.webkit.org/show_bug.cgi?id=181559
13
        https://trac.webkit.org/changeset/227592
14
1
2018-01-20  Filip Pizlo  <fpizlo@apple.com>
15
2018-01-20  Filip Pizlo  <fpizlo@apple.com>
2
16
3
        JSC GC should support TLCs (thread local caches)
17
        JSC GC should support TLCs (thread local caches)
- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -36 lines
Lines 389-401 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
389
		0F725CAA1C503DED00AD943A /* B3PureCSE.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CA61C503DED00AD943A /* B3PureCSE.h */; };
389
		0F725CAA1C503DED00AD943A /* B3PureCSE.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CA61C503DED00AD943A /* B3PureCSE.h */; };
390
		0F725CB01C506D3B00AD943A /* B3FoldPathConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */; };
390
		0F725CB01C506D3B00AD943A /* B3FoldPathConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */; };
391
		0F74B93B1F89614800B935D3 /* PrototypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F74B93A1F89614500B935D3 /* PrototypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
391
		0F74B93B1F89614800B935D3 /* PrototypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F74B93A1F89614500B935D3 /* PrototypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
392
		0F75A05E200D25F60038E2CF /* ThreadLocalCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A055200D25EF0038E2CF /* ThreadLocalCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
393
		0F75A060200D260B0038E2CF /* LocalAllocatorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A05A200D25F00038E2CF /* LocalAllocatorInlines.h */; };
394
		0F75A061200D26180038E2CF /* LocalAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A057200D25F00038E2CF /* LocalAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
395
		0F75A062200D261D0038E2CF /* AllocatorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A05D200D25F10038E2CF /* AllocatorInlines.h */; };
396
		0F75A063200D261F0038E2CF /* Allocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A054200D25EF0038E2CF /* Allocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
397
		0F75A064200D26280038E2CF /* ThreadLocalCacheLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A05C200D25F10038E2CF /* ThreadLocalCacheLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
398
		0F75A0662013E4F10038E2CF /* JITAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F75A0652013E4EF0038E2CF /* JITAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
399
		0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
392
		0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
400
		0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
393
		0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
401
		0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D1C15A5028D008F363E /* JITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
394
		0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D1C15A5028D008F363E /* JITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 2426-2442 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
2426
		0F725CAD1C506D3B00AD943A /* B3FoldPathConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3FoldPathConstants.cpp; path = b3/B3FoldPathConstants.cpp; sourceTree = "<group>"; };
2419
		0F725CAD1C506D3B00AD943A /* B3FoldPathConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3FoldPathConstants.cpp; path = b3/B3FoldPathConstants.cpp; sourceTree = "<group>"; };
2427
		0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3FoldPathConstants.h; path = b3/B3FoldPathConstants.h; sourceTree = "<group>"; };
2420
		0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3FoldPathConstants.h; path = b3/B3FoldPathConstants.h; sourceTree = "<group>"; };
2428
		0F74B93A1F89614500B935D3 /* PrototypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeKey.h; sourceTree = "<group>"; };
2421
		0F74B93A1F89614500B935D3 /* PrototypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeKey.h; sourceTree = "<group>"; };
2429
		0F75A054200D25EF0038E2CF /* Allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Allocator.h; sourceTree = "<group>"; };
2430
		0F75A055200D25EF0038E2CF /* ThreadLocalCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocalCache.h; sourceTree = "<group>"; };
2431
		0F75A056200D25EF0038E2CF /* ThreadLocalCacheInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocalCacheInlines.h; sourceTree = "<group>"; };
2432
		0F75A057200D25F00038E2CF /* LocalAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalAllocator.h; sourceTree = "<group>"; };
2433
		0F75A058200D25F00038E2CF /* ThreadLocalCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadLocalCache.cpp; sourceTree = "<group>"; };
2434
		0F75A059200D25F00038E2CF /* LocalAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalAllocator.cpp; sourceTree = "<group>"; };
2435
		0F75A05A200D25F00038E2CF /* LocalAllocatorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalAllocatorInlines.h; sourceTree = "<group>"; };
2436
		0F75A05B200D25F10038E2CF /* ThreadLocalCacheLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadLocalCacheLayout.cpp; sourceTree = "<group>"; };
2437
		0F75A05C200D25F10038E2CF /* ThreadLocalCacheLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocalCacheLayout.h; sourceTree = "<group>"; };
2438
		0F75A05D200D25F10038E2CF /* AllocatorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocatorInlines.h; sourceTree = "<group>"; };
2439
		0F75A0652013E4EF0038E2CF /* JITAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITAllocator.h; sourceTree = "<group>"; };
2440
		0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
2422
		0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
2441
		0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutine.cpp; sourceTree = "<group>"; };
2423
		0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutine.cpp; sourceTree = "<group>"; };
2442
		0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutineSet.cpp; sourceTree = "<group>"; };
2424
		0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutineSet.cpp; sourceTree = "<group>"; };
Lines 5465-5471 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
5465
				1429D92E0ED22D7000B89619 /* JIT.h */,
5447
				1429D92E0ED22D7000B89619 /* JIT.h */,
5466
				FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */,
5448
				FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */,
5467
				FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */,
5449
				FE1220261BE7F5640039E6F2 /* JITAddGenerator.h */,
5468
				0F75A0652013E4EF0038E2CF /* JITAllocator.h */,
5469
				86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */,
5450
				86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */,
5470
				A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */,
5451
				A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */,
5471
				FE3A06AD1C10CB6F00390FDD /* JITBitAndGenerator.cpp */,
5452
				FE3A06AD1C10CB6F00390FDD /* JITBitAndGenerator.cpp */,
Lines 5559-5574 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
5559
		142E312A134FF0A600AFADB5 /* heap */ = {
5540
		142E312A134FF0A600AFADB5 /* heap */ = {
5560
			isa = PBXGroup;
5541
			isa = PBXGroup;
5561
			children = (
5542
			children = (
5562
				0F75A054200D25EF0038E2CF /* Allocator.h */,
5563
				0F75A05D200D25F10038E2CF /* AllocatorInlines.h */,
5564
				0F75A059200D25F00038E2CF /* LocalAllocator.cpp */,
5565
				0F75A057200D25F00038E2CF /* LocalAllocator.h */,
5566
				0F75A05A200D25F00038E2CF /* LocalAllocatorInlines.h */,
5567
				0F75A058200D25F00038E2CF /* ThreadLocalCache.cpp */,
5568
				0F75A055200D25EF0038E2CF /* ThreadLocalCache.h */,
5569
				0F75A056200D25EF0038E2CF /* ThreadLocalCacheInlines.h */,
5570
				0F75A05B200D25F10038E2CF /* ThreadLocalCacheLayout.cpp */,
5571
				0F75A05C200D25F10038E2CF /* ThreadLocalCacheLayout.h */,
5572
				0FEC3C501F33A41600F59B6C /* AlignedMemoryAllocator.cpp */,
5543
				0FEC3C501F33A41600F59B6C /* AlignedMemoryAllocator.cpp */,
5573
				0FEC3C511F33A41600F59B6C /* AlignedMemoryAllocator.h */,
5544
				0FEC3C511F33A41600F59B6C /* AlignedMemoryAllocator.h */,
5574
				0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */,
5545
				0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */,
Lines 8077-8083 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
8077
				0F2AC5711E8EE4540001EE3F /* AirFormTable.h in Headers */,
8048
				0F2AC5711E8EE4540001EE3F /* AirFormTable.h in Headers */,
8078
				0FEC85771BDACDC70080FF74 /* AirFrequentedBlock.h in Headers */,
8049
				0FEC85771BDACDC70080FF74 /* AirFrequentedBlock.h in Headers */,
8079
				0FEC85791BDACDC70080FF74 /* AirGenerate.h in Headers */,
8050
				0FEC85791BDACDC70080FF74 /* AirGenerate.h in Headers */,
8080
				0F75A061200D26180038E2CF /* LocalAllocator.h in Headers */,
8081
				0FEC857A1BDACDC70080FF74 /* AirGenerationContext.h in Headers */,
8051
				0FEC857A1BDACDC70080FF74 /* AirGenerationContext.h in Headers */,
8082
				0FEC857C1BDACDC70080FF74 /* AirHandleCalleeSaves.h in Headers */,
8052
				0FEC857C1BDACDC70080FF74 /* AirHandleCalleeSaves.h in Headers */,
8083
				0FEC857E1BDACDC70080FF74 /* AirInsertionSet.h in Headers */,
8053
				0FEC857E1BDACDC70080FF74 /* AirInsertionSet.h in Headers */,
Lines 8243-8249 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
8243
				0F6B8ADD1C4EFAC300969052 /* B3SSACalculator.h in Headers */,
8213
				0F6B8ADD1C4EFAC300969052 /* B3SSACalculator.h in Headers */,
8244
				0F33FCF81C136E2500323F67 /* B3StackmapGenerationParams.h in Headers */,
8214
				0F33FCF81C136E2500323F67 /* B3StackmapGenerationParams.h in Headers */,
8245
				0FEC85311BDACDAC0080FF74 /* B3StackmapSpecial.h in Headers */,
8215
				0FEC85311BDACDAC0080FF74 /* B3StackmapSpecial.h in Headers */,
8246
				0F75A064200D26280038E2CF /* ThreadLocalCacheLayout.h in Headers */,
8247
				0F338DF21BE93AD10013C88F /* B3StackmapValue.h in Headers */,
8216
				0F338DF21BE93AD10013C88F /* B3StackmapValue.h in Headers */,
8248
				0F9495881C57F47500413A48 /* B3StackSlot.h in Headers */,
8217
				0F9495881C57F47500413A48 /* B3StackSlot.h in Headers */,
8249
				0FEC85361BDACDAC0080FF74 /* B3SuccessorCollection.h in Headers */,
8218
				0FEC85361BDACDAC0080FF74 /* B3SuccessorCollection.h in Headers */,
Lines 8413-8419 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
8413
				0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */,
8382
				0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */,
8414
				0F2DD8121AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h in Headers */,
8383
				0F2DD8121AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h in Headers */,
8415
				0F2DD8141AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h in Headers */,
8384
				0F2DD8141AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h in Headers */,
8416
				0F75A063200D261F0038E2CF /* Allocator.h in Headers */,
8417
				0F485322187750560083B687 /* DFGArithMode.h in Headers */,
8385
				0F485322187750560083B687 /* DFGArithMode.h in Headers */,
8418
				0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */,
8386
				0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */,
8419
				0F63948515E4811B006A597C /* DFGArrayMode.h in Headers */,
8387
				0F63948515E4811B006A597C /* DFGArrayMode.h in Headers */,
Lines 8694-8700 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
8694
				FEA0C4031CDD7D1D00481991 /* FunctionWhitelist.h in Headers */,
8662
				FEA0C4031CDD7D1D00481991 /* FunctionWhitelist.h in Headers */,
8695
				2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */,
8663
				2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */,
8696
				BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */,
8664
				BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */,
8697
				0F75A060200D260B0038E2CF /* LocalAllocatorInlines.h in Headers */,
8698
				0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
8665
				0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */,
8699
				0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */,
8666
				0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */,
8700
				0FB4767E1D99AEA9008EA6CB /* GCDeferralContext.h in Headers */,
8667
				0FB4767E1D99AEA9008EA6CB /* GCDeferralContext.h in Headers */,
Lines 8779-8785 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
8779
				0FB7F39A15ED8E4600F167B2 /* IndexingHeaderInlines.h in Headers */,
8746
				0FB7F39A15ED8E4600F167B2 /* IndexingHeaderInlines.h in Headers */,
8780
				0FB7F39B15ED8E4600F167B2 /* IndexingType.h in Headers */,
8747
				0FB7F39B15ED8E4600F167B2 /* IndexingType.h in Headers */,
8781
				14386A791DD6989C008652C4 /* IndirectEvalExecutable.h in Headers */,
8748
				14386A791DD6989C008652C4 /* IndirectEvalExecutable.h in Headers */,
8782
				0F75A062200D261D0038E2CF /* AllocatorInlines.h in Headers */,
8783
				0FBF92B91FD76FFF00AC28A8 /* InferredStructure.h in Headers */,
8749
				0FBF92B91FD76FFF00AC28A8 /* InferredStructure.h in Headers */,
8784
				0FBF92BA1FD7700400AC28A8 /* InferredStructureWatchpoint.h in Headers */,
8750
				0FBF92BA1FD7700400AC28A8 /* InferredStructureWatchpoint.h in Headers */,
8785
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
8751
				0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
Lines 8965-8971 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
8965
				E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */,
8931
				E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */,
8966
				E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */,
8932
				E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */,
8967
				E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */,
8933
				E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */,
8968
				0F75A05E200D25F60038E2CF /* ThreadLocalCache.h in Headers */,
8969
				E33F50751B8421C000413856 /* JSInternalPromisePrototype.h in Headers */,
8934
				E33F50751B8421C000413856 /* JSInternalPromisePrototype.h in Headers */,
8970
				A503FA1E188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h in Headers */,
8935
				A503FA1E188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h in Headers */,
8971
				7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */,
8936
				7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */,
Lines 9465-9471 a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
9465
				14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
9430
				14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
9466
				14BE7D3317135CF400D1807A /* WeakInlines.h in Headers */,
9431
				14BE7D3317135CF400D1807A /* WeakInlines.h in Headers */,
9467
				A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */,
9432
				A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */,
9468
				0F75A0662013E4F10038E2CF /* JITAllocator.h in Headers */,
9469
				E3A32BC71FC83147007D7E76 /* WeakMapImpl.h in Headers */,
9433
				E3A32BC71FC83147007D7E76 /* WeakMapImpl.h in Headers */,
9470
				E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */,
9434
				E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */,
9471
				A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
9435
				A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
- a/Source/JavaScriptCore/Sources.txt -4 lines
Lines 466-472 ftl/FTLThunks.cpp a/Source/JavaScriptCore/Sources.txt_sec1
466
ftl/FTLValueRange.cpp
466
ftl/FTLValueRange.cpp
467
467
468
heap/AlignedMemoryAllocator.cpp
468
heap/AlignedMemoryAllocator.cpp
469
heap/Allocator.cpp
470
heap/BlockDirectory.cpp
469
heap/BlockDirectory.cpp
471
heap/CellAttributes.cpp
470
heap/CellAttributes.cpp
472
heap/CellContainer.cpp
471
heap/CellContainer.cpp
Lines 501-507 heap/IsoCellSet.cpp a/Source/JavaScriptCore/Sources.txt_sec2
501
heap/IsoSubspace.cpp
500
heap/IsoSubspace.cpp
502
heap/JITStubRoutineSet.cpp
501
heap/JITStubRoutineSet.cpp
503
heap/LargeAllocation.cpp
502
heap/LargeAllocation.cpp
504
heap/LocalAllocator.cpp
505
heap/MachineStackMarker.cpp
503
heap/MachineStackMarker.cpp
506
heap/MarkStack.cpp
504
heap/MarkStack.cpp
507
heap/MarkStackMergingConstraint.cpp
505
heap/MarkStackMergingConstraint.cpp
Lines 520-527 heap/StopIfNecessaryTimer.cpp a/Source/JavaScriptCore/Sources.txt_sec3
520
heap/Subspace.cpp
518
heap/Subspace.cpp
521
heap/SynchronousStopTheWorldMutatorScheduler.cpp
519
heap/SynchronousStopTheWorldMutatorScheduler.cpp
522
heap/Synchronousness.cpp
520
heap/Synchronousness.cpp
523
heap/ThreadLocalCache.cpp
524
heap/ThreadLocalCacheLayout.cpp
525
heap/VisitRaceKey.cpp
521
heap/VisitRaceKey.cpp
526
heap/Weak.cpp
522
heap/Weak.cpp
527
heap/WeakBlock.cpp
523
heap/WeakBlock.cpp
- a/Source/JavaScriptCore/b3/B3LowerToAir.cpp -6 lines
Lines 1277-1288 private: a/Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec1
1277
            case ValueRep::SomeRegister:
1277
            case ValueRep::SomeRegister:
1278
                arg = tmp(value.value());
1278
                arg = tmp(value.value());
1279
                break;
1279
                break;
1280
            case ValueRep::SomeRegisterWithClobber: {
1281
                Tmp dstTmp = m_code.newTmp(value.value()->resultBank());
1282
                append(relaxedMoveForType(value.value()->type()), immOrTmp(value.value()), dstTmp);
1283
                arg = dstTmp;
1284
                break;
1285
            }
1286
            case ValueRep::LateRegister:
1280
            case ValueRep::LateRegister:
1287
            case ValueRep::Register:
1281
            case ValueRep::Register:
1288
                stackmap->earlyClobbered().clear(value.rep().reg());
1282
                stackmap->earlyClobbered().clear(value.rep().reg());
- a/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp -1 lines
Lines 118-124 bool PatchpointSpecial::admitsStack(Inst& inst, unsigned argIndex) a/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp_sec1
118
        case ValueRep::StackArgument:
118
        case ValueRep::StackArgument:
119
            return true;
119
            return true;
120
        case ValueRep::SomeRegister:
120
        case ValueRep::SomeRegister:
121
        case ValueRep::SomeRegisterWithClobber:
122
        case ValueRep::SomeEarlyRegister:
121
        case ValueRep::SomeEarlyRegister:
123
        case ValueRep::Register:
122
        case ValueRep::Register:
124
        case ValueRep::LateRegister:
123
        case ValueRep::LateRegister:
- a/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp -9 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2017 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 110-118 void StackmapSpecial::forEachArgImpl( a/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec2
110
            case ValueRep::Constant:
110
            case ValueRep::Constant:
111
                role = Arg::Use;
111
                role = Arg::Use;
112
                break;
112
                break;
113
            case ValueRep::SomeRegisterWithClobber:
114
                role = Arg::UseDef;
115
                break;
116
            case ValueRep::LateRegister:
113
            case ValueRep::LateRegister:
117
                role = Arg::LateUse;
114
                role = Arg::LateUse;
118
                break;
115
                break;
Lines 131-140 void StackmapSpecial::forEachArgImpl( a/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec3
131
            // be able to recover the stackmap value. So, force LateColdUse to preserve the
128
            // be able to recover the stackmap value. So, force LateColdUse to preserve the
132
            // original stackmap value across the Special operation.
129
            // original stackmap value across the Special operation.
133
            if (!Arg::isLateUse(role) && optionalDefArgWidth && *optionalDefArgWidth < child.value()->resultWidth()) {
130
            if (!Arg::isLateUse(role) && optionalDefArgWidth && *optionalDefArgWidth < child.value()->resultWidth()) {
134
                // The role can only be some kind of def if we did SomeRegisterWithClobber, which is
135
                // only allowed for patchpoints. Patchpoints don't use the defArgWidth feature.
136
                RELEASE_ASSERT(!Arg::isAnyDef(role));
137
                
138
                if (Arg::isWarmUse(role))
131
                if (Arg::isWarmUse(role))
139
                    role = Arg::LateUse;
132
                    role = Arg::LateUse;
140
                else
133
                else
Lines 252-258 bool StackmapSpecial::isArgValidForRep(Air::Code& code, const Air::Arg& arg, con a/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec4
252
        // We already verified by isArgValidForValue().
245
        // We already verified by isArgValidForValue().
253
        return true;
246
        return true;
254
    case ValueRep::SomeRegister:
247
    case ValueRep::SomeRegister:
255
    case ValueRep::SomeRegisterWithClobber:
256
    case ValueRep::SomeEarlyRegister:
248
    case ValueRep::SomeEarlyRegister:
257
        return arg.isTmp();
249
        return arg.isTmp();
258
    case ValueRep::LateRegister:
250
    case ValueRep::LateRegister:
- a/Source/JavaScriptCore/b3/B3StackmapValue.cpp -6 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/b3/B3StackmapValue.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 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 53-63 void StackmapValue::appendSomeRegister(Value* value) a/Source/JavaScriptCore/b3/B3StackmapValue.cpp_sec2
53
    append(ConstrainedValue(value, ValueRep::SomeRegister));
53
    append(ConstrainedValue(value, ValueRep::SomeRegister));
54
}
54
}
55
55
56
void StackmapValue::appendSomeRegisterWithClobber(Value* value)
57
{
58
    append(ConstrainedValue(value, ValueRep::SomeRegisterWithClobber));
59
}
60
61
void StackmapValue::setConstrainedChild(unsigned index, const ConstrainedValue& constrainedValue)
56
void StackmapValue::setConstrainedChild(unsigned index, const ConstrainedValue& constrainedValue)
62
{
57
{
63
    child(index) = constrainedValue.value();
58
    child(index) = constrainedValue.value();
- a/Source/JavaScriptCore/b3/B3StackmapValue.h -3 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/b3/B3StackmapValue.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2016 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 99-106 public: a/Source/JavaScriptCore/b3/B3StackmapValue.h_sec2
99
    // This is a helper for something you might do a lot of: append a value that should be constrained
99
    // This is a helper for something you might do a lot of: append a value that should be constrained
100
    // to SomeRegister.
100
    // to SomeRegister.
101
    void appendSomeRegister(Value*);
101
    void appendSomeRegister(Value*);
102
    void appendSomeRegisterWithClobber(Value*);
102
103
    
104
    const Vector<ValueRep>& reps() const { return m_reps; }
103
    const Vector<ValueRep>& reps() const { return m_reps; }
105
104
106
    // Stackmaps allow you to specify that the operation may clobber some registers. Clobbering a register
105
    // Stackmaps allow you to specify that the operation may clobber some registers. Clobbering a register
- a/Source/JavaScriptCore/b3/B3Validate.cpp -11 / +16 lines
Lines 432-439 public: a/Source/JavaScriptCore/b3/B3Validate.cpp_sec1
432
                VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
432
                VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
433
                if (value->type() == Void)
433
                if (value->type() == Void)
434
                    VALIDATE(value->as<PatchpointValue>()->resultConstraint == ValueRep::WarmAny, ("At ", *value));
434
                    VALIDATE(value->as<PatchpointValue>()->resultConstraint == ValueRep::WarmAny, ("At ", *value));
435
                else
435
                else {
436
                    switch (value->as<PatchpointValue>()->resultConstraint.kind()) {
437
                    case ValueRep::WarmAny:
438
                    case ValueRep::SomeRegister:
439
                    case ValueRep::SomeEarlyRegister:
440
                    case ValueRep::Register:
441
                    case ValueRep::StackArgument:
442
                        break;
443
                    default:
444
                        VALIDATE(false, ("At ", *value));
445
                        break;
446
                    }
447
                    
436
                    validateStackmapConstraint(value, ConstrainedValue(value, value->as<PatchpointValue>()->resultConstraint), ConstraintRole::Def);
448
                    validateStackmapConstraint(value, ConstrainedValue(value, value->as<PatchpointValue>()->resultConstraint), ConstraintRole::Def);
449
                }
437
                validateStackmap(value);
450
                validateStackmap(value);
438
                break;
451
                break;
439
            case CheckAdd:
452
            case CheckAdd:
Lines 558-581 private: a/Source/JavaScriptCore/b3/B3Validate.cpp_sec2
558
    {
571
    {
559
        switch (value.rep().kind()) {
572
        switch (value.rep().kind()) {
560
        case ValueRep::WarmAny:
573
        case ValueRep::WarmAny:
574
        case ValueRep::ColdAny:
575
        case ValueRep::LateColdAny:
561
        case ValueRep::SomeRegister:
576
        case ValueRep::SomeRegister:
562
        case ValueRep::StackArgument:
577
        case ValueRep::StackArgument:
563
            break;
578
            break;
564
        case ValueRep::LateColdAny:
565
        case ValueRep::ColdAny:
566
            VALIDATE(role == ConstraintRole::Use, ("At ", *context, ": ", value));
567
            break;
568
        case ValueRep::SomeRegisterWithClobber:
569
            VALIDATE(role == ConstraintRole::Use, ("At ", *context, ": ", value));
570
            VALIDATE(context->as<PatchpointValue>(), ("At ", *context));
571
            break;
572
        case ValueRep::SomeEarlyRegister:
579
        case ValueRep::SomeEarlyRegister:
573
            VALIDATE(role == ConstraintRole::Def, ("At ", *context, ": ", value));
580
            VALIDATE(role == ConstraintRole::Def, ("At ", *context, ": ", value));
574
            break;
581
            break;
575
        case ValueRep::Register:
582
        case ValueRep::Register:
576
        case ValueRep::LateRegister:
583
        case ValueRep::LateRegister:
577
            if (value.rep().kind() == ValueRep::LateRegister)
578
                VALIDATE(role == ConstraintRole::Use, ("At ", *context, ": ", value));
579
            if (value.rep().reg().isGPR())
584
            if (value.rep().reg().isGPR())
580
                VALIDATE(isInt(value.value()->type()), ("At ", *context, ": ", value));
585
                VALIDATE(isInt(value.value()->type()), ("At ", *context, ": ", value));
581
            else
586
            else
- a/Source/JavaScriptCore/b3/B3ValueRep.cpp -6 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/b3/B3ValueRep.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2016 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 40-46 void ValueRep::addUsedRegistersTo(RegisterSet& set) const a/Source/JavaScriptCore/b3/B3ValueRep.cpp_sec2
40
    case ColdAny:
40
    case ColdAny:
41
    case LateColdAny:
41
    case LateColdAny:
42
    case SomeRegister:
42
    case SomeRegister:
43
    case SomeRegisterWithClobber:
44
    case SomeEarlyRegister:
43
    case SomeEarlyRegister:
45
    case Constant:
44
    case Constant:
46
        return;
45
        return;
Lines 72-78 void ValueRep::dump(PrintStream& out) const a/Source/JavaScriptCore/b3/B3ValueRep.cpp_sec3
72
    case ColdAny:
71
    case ColdAny:
73
    case LateColdAny:
72
    case LateColdAny:
74
    case SomeRegister:
73
    case SomeRegister:
75
    case SomeRegisterWithClobber:
76
    case SomeEarlyRegister:
74
    case SomeEarlyRegister:
77
        return;
75
        return;
78
    case LateRegister:
76
    case LateRegister:
Lines 177-185 void printInternal(PrintStream& out, ValueRep::Kind kind) a/Source/JavaScriptCore/b3/B3ValueRep.cpp_sec4
177
    case ValueRep::SomeRegister:
175
    case ValueRep::SomeRegister:
178
        out.print("SomeRegister");
176
        out.print("SomeRegister");
179
        return;
177
        return;
180
    case ValueRep::SomeRegisterWithClobber:
181
        out.print("SomeRegisterWithClobber");
182
        return;
183
    case ValueRep::SomeEarlyRegister:
178
    case ValueRep::SomeEarlyRegister:
184
        out.print("SomeEarlyRegister");
179
        out.print("SomeEarlyRegister");
185
        return;
180
        return;
- a/Source/JavaScriptCore/b3/B3ValueRep.h -6 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/b3/B3ValueRep.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2016 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 65-74 public: a/Source/JavaScriptCore/b3/B3ValueRep.h_sec2
65
        // As an input representation, this means that B3 should pick some register. It could be a
65
        // As an input representation, this means that B3 should pick some register. It could be a
66
        // register that this claims to clobber!
66
        // register that this claims to clobber!
67
        SomeRegister,
67
        SomeRegister,
68
        
69
        // As an input representation, this means that B3 should pick some register but that this
70
        // register is then cobbered with garbage. This only works for patchpoints.
71
        SomeRegisterWithClobber,
72
68
73
        // As an input representation, this tells us that B3 should pick some register, but implies
69
        // As an input representation, this tells us that B3 should pick some register, but implies
74
        // that the def happens before any of the effects of the stackmap. This is only valid for
70
        // that the def happens before any of the effects of the stackmap. This is only valid for
Lines 111-117 public: a/Source/JavaScriptCore/b3/B3ValueRep.h_sec3
111
    ValueRep(Kind kind)
107
    ValueRep(Kind kind)
112
        : m_kind(kind)
108
        : m_kind(kind)
113
    {
109
    {
114
        ASSERT(kind == WarmAny || kind == ColdAny || kind == LateColdAny || kind == SomeRegister || kind == SomeRegisterWithClobber || kind == SomeEarlyRegister);
110
        ASSERT(kind == WarmAny || kind == ColdAny || kind == LateColdAny || kind == SomeRegister || kind == SomeEarlyRegister);
115
    }
111
    }
116
112
117
    static ValueRep reg(Reg reg)
113
    static ValueRep reg(Reg reg)
- a/Source/JavaScriptCore/bytecode/AccessCase.cpp -3 / +9 lines
Lines 1-5 a/Source/JavaScriptCore/bytecode/AccessCase.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2017 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 955-963 void AccessCase::generateImpl(AccessGenerationState& state) a/Source/JavaScriptCore/bytecode/AccessCase.cpp_sec2
955
            size_t newSize = newStructure()->outOfLineCapacity() * sizeof(JSValue);
955
            size_t newSize = newStructure()->outOfLineCapacity() * sizeof(JSValue);
956
956
957
            if (allocatingInline) {
957
            if (allocatingInline) {
958
                Allocator allocator = vm.jsValueGigacageAuxiliarySpace.allocatorFor(newSize, AllocatorForMode::AllocatorIfExists);
958
                BlockDirectory* allocator = vm.jsValueGigacageAuxiliarySpace.allocatorFor(newSize, AllocatorForMode::AllocatorIfExists);
959
959
960
                jit.emitAllocate(scratchGPR, JITAllocator::constant(allocator), scratchGPR2, scratchGPR3, slowPath);
960
                if (!allocator) {
961
                    // Yuck, this case would suck!
962
                    slowPath.append(jit.jump());
963
                }
964
965
                jit.move(CCallHelpers::TrustedImmPtr(allocator), scratchGPR2);
966
                jit.emitAllocate(scratchGPR, allocator, scratchGPR2, scratchGPR3, slowPath);
961
                jit.addPtr(CCallHelpers::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR);
967
                jit.addPtr(CCallHelpers::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR);
962
968
963
                size_t oldSize = structure()->outOfLineCapacity() * sizeof(JSValue);
969
                size_t oldSize = structure()->outOfLineCapacity() * sizeof(JSValue);
- a/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h -3 / +4 lines
Lines 43-49 public: a/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h_sec1
43
    static ptrdiff_t offsetOfInlineCapacity() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_inlineCapacity); }
43
    static ptrdiff_t offsetOfInlineCapacity() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_inlineCapacity); }
44
44
45
    ObjectAllocationProfile()
45
    ObjectAllocationProfile()
46
        : m_inlineCapacity(0)
46
        : m_allocator(0)
47
        , m_inlineCapacity(0)
47
    {
48
    {
48
    }
49
    }
49
50
Lines 62-68 public: a/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h_sec2
62
63
63
    void clear()
64
    void clear()
64
    {
65
    {
65
        m_allocator = Allocator();
66
        m_allocator = nullptr;
66
        m_structure.clear();
67
        m_structure.clear();
67
        m_inlineCapacity = 0;
68
        m_inlineCapacity = 0;
68
        ASSERT(isNull());
69
        ASSERT(isNull());
Lines 76-82 public: a/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h_sec3
76
private:
77
private:
77
    unsigned possibleDefaultPropertyCount(VM&, JSObject* prototype);
78
    unsigned possibleDefaultPropertyCount(VM&, JSObject* prototype);
78
79
79
    Allocator m_allocator; // Precomputed to make things easier for generated code.
80
    BlockDirectory* m_allocator; // Precomputed to make things easier for generated code.
80
    WriteBarrier<Structure> m_structure;
81
    WriteBarrier<Structure> m_structure;
81
    unsigned m_inlineCapacity;
82
    unsigned m_inlineCapacity;
82
};
83
};
- a/Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h -4 / +4 lines
Lines 53-59 ALWAYS_INLINE void ObjectAllocationProfile::initializeProfile(VM& vm, JSGlobalOb a/Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h_sec1
53
53
54
        if (Structure* structure = executable->cachedPolyProtoStructure()) {
54
        if (Structure* structure = executable->cachedPolyProtoStructure()) {
55
            RELEASE_ASSERT(structure->typeInfo().type() == FinalObjectType);
55
            RELEASE_ASSERT(structure->typeInfo().type() == FinalObjectType);
56
            m_allocator = Allocator();
56
            m_allocator = nullptr;
57
            m_structure.set(vm, owner, structure);
57
            m_structure.set(vm, owner, structure);
58
            m_inlineCapacity = structure->inlineCapacity();
58
            m_inlineCapacity = structure->inlineCapacity();
59
            return;
59
            return;
Lines 99-109 ALWAYS_INLINE void ObjectAllocationProfile::initializeProfile(VM& vm, JSGlobalOb a/Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h_sec2
99
    ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
99
    ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
100
100
101
    size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
101
    size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
102
    Allocator allocator = vm.cellSpace.allocatorForNonVirtual(allocationSize, AllocatorForMode::EnsureAllocator);
102
    BlockDirectory* allocator = vm.cellSpace.allocatorForNonVirtual(allocationSize, AllocatorForMode::EnsureAllocator);
103
103
104
    // Take advantage of extra inline capacity available in the size class.
104
    // Take advantage of extra inline capacity available in the size class.
105
    if (allocator) {
105
    if (allocator) {
106
        size_t slop = (allocator.cellSize(vm.heap) - allocationSize) / sizeof(WriteBarrier<Unknown>);
106
        size_t slop = (allocator->cellSize() - allocationSize) / sizeof(WriteBarrier<Unknown>);
107
        inlineCapacity += slop;
107
        inlineCapacity += slop;
108
        if (inlineCapacity > JSFinalObject::maxInlineCapacity())
108
        if (inlineCapacity > JSFinalObject::maxInlineCapacity())
109
            inlineCapacity = JSFinalObject::maxInlineCapacity();
109
            inlineCapacity = JSFinalObject::maxInlineCapacity();
Lines 113-119 ALWAYS_INLINE void ObjectAllocationProfile::initializeProfile(VM& vm, JSGlobalOb a/Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h_sec3
113
113
114
    if (isPolyProto) {
114
    if (isPolyProto) {
115
        ASSERT(structure->hasPolyProto());
115
        ASSERT(structure->hasPolyProto());
116
        m_allocator = Allocator();
116
        m_allocator = nullptr;
117
        executable->setCachedPolyProtoStructure(vm, structure);
117
        executable->setCachedPolyProtoStructure(vm, structure);
118
    } else {
118
    } else {
119
        if (executable) {
119
        if (executable) {
- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp -24 / +26 lines
Lines 113-120 void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
113
    m_jit.move(TrustedImmPtr(0), storageGPR);
113
    m_jit.move(TrustedImmPtr(0), storageGPR);
114
114
115
    if (size) {
115
    if (size) {
116
        if (Allocator allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists)) {
116
        if (BlockDirectory* allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists)) {
117
            m_jit.emitAllocate(storageGPR, JITAllocator::constant(allocator), scratchGPR, scratch2GPR, slowCases);
117
            m_jit.move(TrustedImmPtr(allocator), scratchGPR);
118
            m_jit.emitAllocate(storageGPR, allocator, scratchGPR, scratch2GPR, slowCases);
118
            
119
            
119
            m_jit.addPtr(
120
            m_jit.addPtr(
120
                TrustedImm32(outOfLineCapacity * sizeof(JSValue) + sizeof(IndexingHeader)),
121
                TrustedImm32(outOfLineCapacity * sizeof(JSValue) + sizeof(IndexingHeader)),
Lines 127-136 void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
127
    }
128
    }
128
129
129
    size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
130
    size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
130
    Allocator allocator = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
131
    BlockDirectory* allocatorPtr = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
131
    if (allocator) {
132
    if (allocatorPtr) {
133
        m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
132
        uint32_t mask = WTF::computeIndexingMask(vectorLength);
134
        uint32_t mask = WTF::computeIndexingMask(vectorLength);
133
        emitAllocateJSObject(resultGPR, JITAllocator::constant(allocator), scratchGPR, TrustedImmPtr(structure), storageGPR, TrustedImm32(mask), scratch2GPR, slowCases);
135
        emitAllocateJSObject(resultGPR, allocatorPtr, scratchGPR, TrustedImmPtr(structure), storageGPR, TrustedImm32(mask), scratch2GPR, slowCases);
134
        m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
136
        m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
135
    } else
137
    } else
136
        slowCases.append(m_jit.jump());
138
        slowCases.append(m_jit.jump());
Lines 4206-4213 void SpeculativeJIT::compileMakeRope(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
4206
    GPRReg scratchGPR = scratch.gpr();
4208
    GPRReg scratchGPR = scratch.gpr();
4207
    
4209
    
4208
    JITCompiler::JumpList slowPath;
4210
    JITCompiler::JumpList slowPath;
4209
    Allocator allocatorValue = subspaceFor<JSRopeString>(*m_jit.vm())->allocatorForNonVirtual(sizeof(JSRopeString), AllocatorForMode::AllocatorIfExists);
4211
    BlockDirectory* blockDirectory = subspaceFor<JSRopeString>(*m_jit.vm())->allocatorForNonVirtual(sizeof(JSRopeString), AllocatorForMode::AllocatorIfExists);
4210
    emitAllocateJSCell(resultGPR, JITAllocator::constant(allocatorValue), allocatorGPR, TrustedImmPtr(m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get())), scratchGPR, slowPath);
4212
    m_jit.move(TrustedImmPtr(blockDirectory), allocatorGPR);
4213
    emitAllocateJSCell(resultGPR, blockDirectory, allocatorGPR, TrustedImmPtr(m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get())), scratchGPR, slowPath);
4211
        
4214
        
4212
    m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSString::offsetOfValue()));
4215
    m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSString::offsetOfValue()));
4213
    for (unsigned i = 0; i < numOpGPRs; ++i)
4216
    for (unsigned i = 0; i < numOpGPRs; ++i)
Lines 8381-8387 void SpeculativeJIT::compileAllocatePropertyStorage(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec4
8381
    
8384
    
8382
    size_t size = initialOutOfLineCapacity * sizeof(JSValue);
8385
    size_t size = initialOutOfLineCapacity * sizeof(JSValue);
8383
8386
8384
    Allocator allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
8387
    BlockDirectory* allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
8385
8388
8386
    if (!allocator || node->transition()->previous->couldHaveIndexingHeader()) {
8389
    if (!allocator || node->transition()->previous->couldHaveIndexingHeader()) {
8387
        SpeculateCellOperand base(this, node->child1());
8390
        SpeculateCellOperand base(this, node->child1());
Lines 8406-8413 void SpeculativeJIT::compileAllocatePropertyStorage(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec5
8406
    GPRReg scratchGPR2 = scratch2.gpr();
8409
    GPRReg scratchGPR2 = scratch2.gpr();
8407
    GPRReg scratchGPR3 = scratch3.gpr();
8410
    GPRReg scratchGPR3 = scratch3.gpr();
8408
        
8411
        
8412
    m_jit.move(TrustedImmPtr(allocator), scratchGPR2);
8409
    JITCompiler::JumpList slowPath;
8413
    JITCompiler::JumpList slowPath;
8410
    m_jit.emitAllocate(scratchGPR1, JITAllocator::constant(allocator), scratchGPR2, scratchGPR3, slowPath);
8414
    m_jit.emitAllocate(scratchGPR1, allocator, scratchGPR2, scratchGPR3, slowPath);
8411
    m_jit.addPtr(JITCompiler::TrustedImm32(size + sizeof(IndexingHeader)), scratchGPR1);
8415
    m_jit.addPtr(JITCompiler::TrustedImm32(size + sizeof(IndexingHeader)), scratchGPR1);
8412
    
8416
    
8413
    for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(size); offset += sizeof(void*))
8417
    for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(size); offset += sizeof(void*))
Lines 8425-8431 void SpeculativeJIT::compileReallocatePropertyStorage(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec6
8425
    size_t newSize = oldSize * outOfLineGrowthFactor;
8429
    size_t newSize = oldSize * outOfLineGrowthFactor;
8426
    ASSERT(newSize == node->transition()->next->outOfLineCapacity() * sizeof(JSValue));
8430
    ASSERT(newSize == node->transition()->next->outOfLineCapacity() * sizeof(JSValue));
8427
    
8431
    
8428
    Allocator allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(newSize, AllocatorForMode::AllocatorIfExists);
8432
    BlockDirectory* allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(newSize, AllocatorForMode::AllocatorIfExists);
8429
8433
8430
    if (!allocator || node->transition()->previous->couldHaveIndexingHeader()) {
8434
    if (!allocator || node->transition()->previous->couldHaveIndexingHeader()) {
8431
        SpeculateCellOperand base(this, node->child1());
8435
        SpeculateCellOperand base(this, node->child1());
Lines 8453-8459 void SpeculativeJIT::compileReallocatePropertyStorage(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec7
8453
    GPRReg scratchGPR3 = scratch3.gpr();
8457
    GPRReg scratchGPR3 = scratch3.gpr();
8454
    
8458
    
8455
    JITCompiler::JumpList slowPath;
8459
    JITCompiler::JumpList slowPath;
8456
    m_jit.emitAllocate(scratchGPR1, JITAllocator::constant(allocator), scratchGPR2, scratchGPR3, slowPath);
8460
    m_jit.move(TrustedImmPtr(allocator), scratchGPR2);
8461
    m_jit.emitAllocate(scratchGPR1, allocator, scratchGPR2, scratchGPR3, slowPath);
8457
    
8462
    
8458
    m_jit.addPtr(JITCompiler::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR1);
8463
    m_jit.addPtr(JITCompiler::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR1);
8459
        
8464
        
Lines 11443-11456 void SpeculativeJIT::compileCreateThis(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec8
11443
        JITCompiler::Address(calleeGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
11448
        JITCompiler::Address(calleeGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
11444
    m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
11449
    m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
11445
    slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
11450
    slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
11446
    m_jit.load32(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
11451
    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
11447
    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
11452
    m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
11448
11453
11449
    slowPath.append(m_jit.branch32(MacroAssembler::Equal, allocatorGPR, TrustedImm32(Allocator().offset())));
11454
    slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, allocatorGPR));
11450
11455
11451
    auto butterfly = TrustedImmPtr(nullptr);
11456
    auto butterfly = TrustedImmPtr(nullptr);
11452
    auto mask = TrustedImm32(0);
11457
    auto mask = TrustedImm32(0);
11453
    emitAllocateJSObject(resultGPR, JITAllocator::variable(), allocatorGPR, structureGPR, butterfly, mask, scratchGPR, slowPath);
11458
    emitAllocateJSObject(resultGPR, nullptr, allocatorGPR, structureGPR, butterfly, mask, scratchGPR, slowPath);
11454
11459
11455
    m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
11460
    m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfRareData()), rareDataGPR);
11456
    m_jit.load32(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), inlineCapacityGPR);
11461
    m_jit.load32(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), inlineCapacityGPR);
Lines 11476-11492 void SpeculativeJIT::compileNewObject(Node* node) a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec9
11476
11481
11477
    RegisteredStructure structure = node->structure();
11482
    RegisteredStructure structure = node->structure();
11478
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
11483
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
11479
    Allocator allocatorValue = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
11484
    BlockDirectory* allocatorPtr = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
11480
11485
11481
    if (!allocatorValue)
11486
    m_jit.move(TrustedImmPtr(allocatorPtr), allocatorGPR);
11482
        slowPath.append(m_jit.jump());
11487
    auto butterfly = TrustedImmPtr(nullptr);
11483
    else {
11488
    auto mask = TrustedImm32(0);
11484
        auto butterfly = TrustedImmPtr(nullptr);
11489
    emitAllocateJSObject(resultGPR, allocatorPtr, allocatorGPR, TrustedImmPtr(structure), butterfly, mask, scratchGPR, slowPath);
11485
        auto mask = TrustedImm32(0);
11490
    m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
11486
        emitAllocateJSObject(resultGPR, JITAllocator::constant(allocatorValue), allocatorGPR, TrustedImmPtr(structure), butterfly, mask, scratchGPR, slowPath);
11491
    m_jit.mutatorFence(*m_jit.vm());
11487
        m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
11488
        m_jit.mutatorFence(*m_jit.vm());
11489
    }
11490
11492
11491
    addSlowPathGenerator(slowPathCall(slowPath, this, operationNewObject, resultGPR, structure));
11493
    addSlowPathGenerator(slowPathCall(slowPath, this, operationNewObject, resultGPR, structure));
11492
11494
- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h -3 / +3 lines
Lines 1-5 a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2011-2017 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 3142-3148 public: a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec2
3142
    // Allocator for a cell of a specific size.
3142
    // Allocator for a cell of a specific size.
3143
    template <typename StructureType> // StructureType can be GPR or ImmPtr.
3143
    template <typename StructureType> // StructureType can be GPR or ImmPtr.
3144
    void emitAllocateJSCell(
3144
    void emitAllocateJSCell(
3145
        GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
3145
        GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, StructureType structure,
3146
        GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
3146
        GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
3147
    {
3147
    {
3148
        m_jit.emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
3148
        m_jit.emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
Lines 3151-3157 public: a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec3
3151
    // Allocator for an object of a specific size.
3151
    // Allocator for an object of a specific size.
3152
    template <typename StructureType, typename StorageType, typename MaskType> // StructureType, StorageType and, MaskType can be GPR or ImmPtr.
3152
    template <typename StructureType, typename StorageType, typename MaskType> // StructureType, StorageType and, MaskType can be GPR or ImmPtr.
3153
    void emitAllocateJSObject(
3153
    void emitAllocateJSObject(
3154
        GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
3154
        GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, StructureType structure,
3155
        StorageType storage, MaskType mask, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
3155
        StorageType storage, MaskType mask, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
3156
    {
3156
    {
3157
        m_jit.emitAllocateJSObject(
3157
        m_jit.emitAllocateJSObject(
- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h -2 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013-2017 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 131-137 namespace JSC { namespace FTL { a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h_sec2
131
131
132
#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
132
#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
133
    macro(ArrayStorage_vector, ArrayStorage::vectorOffset(), sizeof(WriteBarrier<Unknown>)) \
133
    macro(ArrayStorage_vector, ArrayStorage::vectorOffset(), sizeof(WriteBarrier<Unknown>)) \
134
    macro(CompleteSubspace_allocatorForSizeStep, CompleteSubspace::offsetOfAllocatorForSizeStep(), sizeof(Allocator)) \
134
    macro(CompleteSubspace_allocatorForSizeStep, CompleteSubspace::offsetOfAllocatorForSizeStep(), sizeof(BlockDirectory*)) \
135
    macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \
135
    macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \
136
    macro(JSLexicalEnvironment_variables, JSLexicalEnvironment::offsetOfVariables(), sizeof(EncodedJSValue)) \
136
    macro(JSLexicalEnvironment_variables, JSLexicalEnvironment::offsetOfVariables(), sizeof(EncodedJSValue)) \
137
    macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \
137
    macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \
- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp -44 / +25 lines
Lines 5876-5885 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec1
5876
        
5876
        
5877
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
5877
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
5878
        
5878
        
5879
        Allocator allocator = subspaceFor<JSRopeString>(vm())->allocatorForNonVirtual(sizeof(JSRopeString), AllocatorForMode::AllocatorIfExists);
5879
        BlockDirectory* allocator = subspaceFor<JSRopeString>(vm())->allocatorForNonVirtual(sizeof(JSRopeString), AllocatorForMode::AllocatorIfExists);
5880
        
5880
        
5881
        LValue result = allocateCell(
5881
        LValue result = allocateCell(
5882
            m_out.constInt32(allocator.offset()), vm().stringStructure.get(), slowPath);
5882
            m_out.constIntPtr(allocator), vm().stringStructure.get(), slowPath);
5883
        
5883
        
5884
        m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
5884
        m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
5885
        for (unsigned i = 0; i < numKids; ++i)
5885
        for (unsigned i = 0; i < numKids; ++i)
Lines 9909-9915 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec2
9909
            
9909
            
9910
            if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
9910
            if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
9911
                size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
9911
                size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
9912
                Allocator cellAllocator = subspaceFor<JSFinalObject>(vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
9912
                BlockDirectory* cellAllocator = subspaceFor<JSFinalObject>(vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
9913
9913
9914
                bool hasIndexingHeader = hasIndexedProperties(structure->indexingType());
9914
                bool hasIndexingHeader = hasIndexedProperties(structure->indexingType());
9915
                unsigned indexingHeaderSize = 0;
9915
                unsigned indexingHeaderSize = 0;
Lines 9968-9974 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec3
9968
9968
9969
                LValue mask = computeButterflyIndexingMask(vectorLength);
9969
                LValue mask = computeButterflyIndexingMask(vectorLength);
9970
                LValue fastObjectValue = allocateObject(
9970
                LValue fastObjectValue = allocateObject(
9971
                    m_out.constInt32(cellAllocator.offset()), structure, fastButterflyValue, mask, slowPath);
9971
                    m_out.constIntPtr(cellAllocator), structure, fastButterflyValue, mask, slowPath);
9972
9972
9973
                ValueFromBlock fastObject = m_out.anchor(fastObjectValue);
9973
                ValueFromBlock fastObject = m_out.anchor(fastObjectValue);
9974
                ValueFromBlock fastButterfly = m_out.anchor(fastButterflyValue);
9974
                ValueFromBlock fastButterfly = m_out.anchor(fastButterflyValue);
Lines 10955-10962 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec4
10955
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
10955
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
10956
10956
10957
        size_t sizeInBytes = sizeInValues * sizeof(JSValue);
10957
        size_t sizeInBytes = sizeInValues * sizeof(JSValue);
10958
        Allocator allocator = vm().jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(sizeInBytes, AllocatorForMode::AllocatorIfExists);
10958
        BlockDirectory* allocator = vm().jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(sizeInBytes, AllocatorForMode::AllocatorIfExists);
10959
        LValue startOfStorage = allocateHeapCell(m_out.constInt32(allocator.offset()), slowPath);
10959
        LValue startOfStorage = allocateHeapCell(m_out.constIntPtr(allocator), slowPath);
10960
        ValueFromBlock fastButterfly = m_out.anchor(
10960
        ValueFromBlock fastButterfly = m_out.anchor(
10961
            m_out.add(m_out.constIntPtr(sizeInBytes + sizeof(IndexingHeader)), startOfStorage));
10961
            m_out.add(m_out.constIntPtr(sizeInBytes + sizeof(IndexingHeader)), startOfStorage));
10962
        m_out.jump(continuation);
10962
        m_out.jump(continuation);
Lines 11988-12015 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec5
11988
11988
11989
    LValue allocateHeapCell(LValue allocator, LBasicBlock slowPath)
11989
    LValue allocateHeapCell(LValue allocator, LBasicBlock slowPath)
11990
    {
11990
    {
11991
        JITAllocator actualAllocator;
11991
        BlockDirectory* actualAllocator = nullptr;
11992
        if (allocator->hasInt32())
11992
        if (allocator->hasIntPtr())
11993
            actualAllocator = JITAllocator::constant(Allocator(allocator->asInt32()));
11993
            actualAllocator = bitwise_cast<BlockDirectory*>(allocator->asIntPtr());
11994
        else
11995
            actualAllocator = JITAllocator::variable();
11996
        
11994
        
11997
        if (actualAllocator.isConstant()) {
11995
        if (!actualAllocator) {
11998
            if (!actualAllocator.allocator()) {
11999
                LBasicBlock haveAllocator = m_out.newBlock();
12000
                LBasicBlock lastNext = m_out.insertNewBlocksBefore(haveAllocator);
12001
                m_out.jump(slowPath);
12002
                m_out.appendTo(haveAllocator, lastNext);
12003
                return m_out.intPtrZero;
12004
            }
12005
        } else {
12006
            // This means that either we know that the allocator is null or we don't know what the
11996
            // This means that either we know that the allocator is null or we don't know what the
12007
            // allocator is. In either case, we need the null check.
11997
            // allocator is. In either case, we need the null check.
12008
            LBasicBlock haveAllocator = m_out.newBlock();
11998
            LBasicBlock haveAllocator = m_out.newBlock();
12009
            LBasicBlock lastNext = m_out.insertNewBlocksBefore(haveAllocator);
11999
            LBasicBlock lastNext = m_out.insertNewBlocksBefore(haveAllocator);
12010
            m_out.branch(
12000
            m_out.branch(allocator, usually(haveAllocator), rarely(slowPath));
12011
                m_out.notEqual(allocator, m_out.constInt32(Allocator().offset())),
12012
                usually(haveAllocator), rarely(slowPath));
12013
            m_out.appendTo(haveAllocator, lastNext);
12001
            m_out.appendTo(haveAllocator, lastNext);
12014
        }
12002
        }
12015
        
12003
        
Lines 12019-12028 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec6
12019
        
12007
        
12020
        PatchpointValue* patchpoint = m_out.patchpoint(pointerType());
12008
        PatchpointValue* patchpoint = m_out.patchpoint(pointerType());
12021
        patchpoint->effects.terminal = true;
12009
        patchpoint->effects.terminal = true;
12022
        if (actualAllocator.isConstant())
12010
        patchpoint->appendSomeRegister(allocator);
12023
            patchpoint->numGPScratchRegisters++;
12024
        else
12025
            patchpoint->appendSomeRegisterWithClobber(allocator);
12026
        patchpoint->numGPScratchRegisters++;
12011
        patchpoint->numGPScratchRegisters++;
12027
        patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
12012
        patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
12028
        
12013
        
Lines 12033-12044 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec7
12033
            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
12018
            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
12034
                CCallHelpers::JumpList jumpToSlowPath;
12019
                CCallHelpers::JumpList jumpToSlowPath;
12035
                
12020
                
12036
                GPRReg allocatorGPR;
12037
                if (actualAllocator.isConstant())
12038
                    allocatorGPR = params.gpScratch(1);
12039
                else
12040
                    allocatorGPR = params[1].gpr();
12041
                
12042
                // We use a patchpoint to emit the allocation path because whenever we mess with
12021
                // We use a patchpoint to emit the allocation path because whenever we mess with
12043
                // allocation paths, we already reason about them at the machine code level. We know
12022
                // allocation paths, we already reason about them at the machine code level. We know
12044
                // exactly what instruction sequence we want. We're confident that no compiler
12023
                // exactly what instruction sequence we want. We're confident that no compiler
Lines 12046-12052 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec8
12046
                // AssemblyHelpers::emitAllocate(). That way, the same optimized path is shared by
12025
                // AssemblyHelpers::emitAllocate(). That way, the same optimized path is shared by
12047
                // all of the compiler tiers.
12026
                // all of the compiler tiers.
12048
                jit.emitAllocateWithNonNullAllocator(
12027
                jit.emitAllocateWithNonNullAllocator(
12049
                    params[0].gpr(), actualAllocator, allocatorGPR, params.gpScratch(0),
12028
                    params[0].gpr(), actualAllocator, params[1].gpr(), params.gpScratch(0),
12050
                    jumpToSlowPath);
12029
                    jumpToSlowPath);
12051
                
12030
                
12052
                CCallHelpers::Jump jumpToSuccess;
12031
                CCallHelpers::Jump jumpToSuccess;
Lines 12138-12145 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec9
12138
    LValue allocateObject(
12117
    LValue allocateObject(
12139
        size_t size, StructureType structure, LValue butterfly, LValue indexingMask, LBasicBlock slowPath)
12118
        size_t size, StructureType structure, LValue butterfly, LValue indexingMask, LBasicBlock slowPath)
12140
    {
12119
    {
12141
        Allocator allocator = subspaceFor<ClassType>(vm())->allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
12120
        BlockDirectory* allocator = subspaceFor<ClassType>(vm())->allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
12142
        return allocateObject(m_out.constInt32(allocator.offset()), structure, butterfly, indexingMask, slowPath);
12121
        return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, indexingMask, slowPath);
12143
    }
12122
    }
12144
    
12123
    
12145
    template<typename ClassType, typename StructureType>
12124
    template<typename ClassType, typename StructureType>
Lines 12158-12173 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec10
12158
            CompleteSubspace* actualSubspace = bitwise_cast<CompleteSubspace*>(subspace->asIntPtr());
12137
            CompleteSubspace* actualSubspace = bitwise_cast<CompleteSubspace*>(subspace->asIntPtr());
12159
            size_t actualSize = size->asIntPtr();
12138
            size_t actualSize = size->asIntPtr();
12160
            
12139
            
12161
            Allocator actualAllocator = actualSubspace->allocatorForNonVirtual(actualSize, AllocatorForMode::AllocatorIfExists);
12140
            BlockDirectory* actualAllocator = actualSubspace->allocatorForNonVirtual(actualSize, AllocatorForMode::AllocatorIfExists);
12162
            if (!actualAllocator) {
12141
            if (!actualAllocator) {
12163
                LBasicBlock continuation = m_out.newBlock();
12142
                LBasicBlock continuation = m_out.newBlock();
12164
                LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
12143
                LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
12165
                m_out.jump(slowPath);
12144
                m_out.jump(slowPath);
12166
                m_out.appendTo(continuation, lastNext);
12145
                m_out.appendTo(continuation, lastNext);
12167
                return m_out.int32Zero;
12146
                return m_out.intPtrZero;
12168
            }
12147
            }
12169
            
12148
            
12170
            return m_out.constInt32(actualAllocator.offset());
12149
            return m_out.constIntPtr(actualAllocator);
12171
        }
12150
        }
12172
        
12151
        
12173
        unsigned stepShift = getLSBSet(MarkedSpace::sizeStep);
12152
        unsigned stepShift = getLSBSet(MarkedSpace::sizeStep);
Lines 12186-12192 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec11
12186
        
12165
        
12187
        m_out.appendTo(continuation, lastNext);
12166
        m_out.appendTo(continuation, lastNext);
12188
        
12167
        
12189
        return m_out.load32(
12168
        return m_out.loadPtr(
12190
            m_out.baseIndex(
12169
            m_out.baseIndex(
12191
                m_heaps.CompleteSubspace_allocatorForSizeStep,
12170
                m_heaps.CompleteSubspace_allocatorForSizeStep,
12192
                subspace, m_out.sub(sizeClassIndex, m_out.intPtrOne)));
12171
                subspace, m_out.sub(sizeClassIndex, m_out.intPtrOne)));
Lines 12201-12207 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec12
12201
    LValue allocateVariableSizedObject(
12180
    LValue allocateVariableSizedObject(
12202
        LValue size, RegisteredStructure structure, LValue butterfly, LValue butterflyIndexingMask, LBasicBlock slowPath)
12181
        LValue size, RegisteredStructure structure, LValue butterfly, LValue butterflyIndexingMask, LBasicBlock slowPath)
12203
    {
12182
    {
12204
        LValue allocator = allocatorForSize(*subspaceFor<ClassType>(vm()), size, slowPath);
12183
        LValue allocator = allocatorForSize(
12184
            *subspaceFor<ClassType>(vm()), size, slowPath);
12205
        return allocateObject(allocator, structure, butterfly, butterflyIndexingMask, slowPath);
12185
        return allocateObject(allocator, structure, butterfly, butterflyIndexingMask, slowPath);
12206
    }
12186
    }
12207
12187
Lines 12209-12222 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec13
12209
    LValue allocateVariableSizedCell(
12189
    LValue allocateVariableSizedCell(
12210
        LValue size, Structure* structure, LBasicBlock slowPath)
12190
        LValue size, Structure* structure, LBasicBlock slowPath)
12211
    {
12191
    {
12212
        LValue allocator = allocatorForSize(*subspaceFor<ClassType>(vm()), size, slowPath);
12192
        LValue allocator = allocatorForSize(
12193
            *subspaceFor<ClassType>(vm()), size, slowPath);
12213
        return allocateCell(allocator, structure, slowPath);
12194
        return allocateCell(allocator, structure, slowPath);
12214
    }
12195
    }
12215
    
12196
    
12216
    LValue allocateObject(RegisteredStructure structure)
12197
    LValue allocateObject(RegisteredStructure structure)
12217
    {
12198
    {
12218
        size_t allocationSize = JSFinalObject::allocationSize(structure.get()->inlineCapacity());
12199
        size_t allocationSize = JSFinalObject::allocationSize(structure.get()->inlineCapacity());
12219
        Allocator allocator = subspaceFor<JSFinalObject>(vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
12200
        BlockDirectory* allocator = subspaceFor<JSFinalObject>(vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
12220
        
12201
        
12221
        // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator
12202
        // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator
12222
        // instead of putting it on the slow path.
12203
        // instead of putting it on the slow path.
Lines 12228-12234 private: a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp_sec14
12228
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
12209
        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
12229
        
12210
        
12230
        ValueFromBlock fastResult = m_out.anchor(allocateObject(
12211
        ValueFromBlock fastResult = m_out.anchor(allocateObject(
12231
            m_out.constInt32(allocator.offset()), structure, m_out.intPtrZero, m_out.int32Zero, slowPath));
12212
            m_out.constIntPtr(allocator), structure, m_out.intPtrZero, m_out.int32Zero, slowPath));
12232
        
12213
        
12233
        m_out.jump(continuation);
12214
        m_out.jump(continuation);
12234
        
12215
        
- a/Source/JavaScriptCore/heap/Allocator.cpp -40 lines
Lines 1-40 a/Source/JavaScriptCore/heap/Allocator.cpp_sec1
1
/*
2
 * Copyright (C) 2018 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 "Allocator.h"
28
29
#include "Heap.h"
30
#include "ThreadLocalCacheLayout.h"
31
32
namespace JSC {
33
34
unsigned Allocator::cellSize(Heap& heap) const
35
{
36
    return heap.threadLocalCacheLayout().directory(m_offset)->cellSize();
37
}
38
39
} // namespace JSC
40
- a/Source/JavaScriptCore/heap/Allocator.h -66 lines
Lines 1-66 a/Source/JavaScriptCore/heap/Allocator.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "AllocationFailureMode.h"
29
#include <climits>
30
31
namespace JSC {
32
33
class GCDeferralContext;
34
class Heap;
35
class VM;
36
37
class Allocator {
38
public:
39
    Allocator() { }
40
    
41
    explicit Allocator(unsigned offset)
42
        : m_offset(offset)
43
    {
44
    }
45
    
46
    void* allocate(VM&, GCDeferralContext*, AllocationFailureMode) const;
47
    
48
    // This version calls FailureFunc if we have a null allocator or if the TLC hasn't been resized
49
    // to include this allocator.
50
    template<typename FailureFunc>
51
    void* tryAllocate(VM&, GCDeferralContext*, AllocationFailureMode, const FailureFunc&) const;
52
    
53
    unsigned cellSize(Heap&) const;
54
    
55
    unsigned offset() const { return m_offset; }
56
    
57
    bool operator==(const Allocator& other) const { return m_offset == other.offset(); }
58
    bool operator!=(const Allocator& other) const { return !(*this == other); }
59
    explicit operator bool() const { return *this != Allocator(); }
60
    
61
private:
62
    unsigned m_offset { UINT_MAX };
63
};
64
65
} // namespace JSC
66
- a/Source/JavaScriptCore/heap/AllocatorInlines.h -54 lines
Lines 1-54 a/Source/JavaScriptCore/heap/AllocatorInlines.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "Allocator.h"
29
#include "ThreadLocalCache.h"
30
31
namespace JSC {
32
33
inline void* Allocator::allocate(VM& vm, GCDeferralContext* context, AllocationFailureMode mode) const
34
{
35
    return ThreadLocalCache::allocator(vm, m_offset).allocate(context, mode);
36
}
37
38
template<typename FailureFunc>
39
void* Allocator::tryAllocate(VM& vm, GCDeferralContext* context, AllocationFailureMode mode, const FailureFunc& failureFunc) const
40
{
41
    void* result;
42
    ThreadLocalCache::tryGetAllocator(
43
        vm, m_offset,
44
        [&] (LocalAllocator& allocator) {
45
            result = allocator.allocate(context, mode);
46
        },
47
        [&] () {
48
            result = failureFunc();
49
        });
50
    return result;
51
}
52
53
} // namespace JSC
54
- a/Source/JavaScriptCore/heap/BlockDirectory.cpp -46 / +162 lines
Lines 26-31 a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "BlockDirectory.h"
27
#include "BlockDirectory.h"
28
28
29
#include "AllocatingScope.h"
29
#include "BlockDirectoryInlines.h"
30
#include "BlockDirectoryInlines.h"
30
#include "GCActivityCallback.h"
31
#include "GCActivityCallback.h"
31
#include "Heap.h"
32
#include "Heap.h"
Lines 38-48 a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec2
38
39
39
namespace JSC {
40
namespace JSC {
40
41
42
static constexpr bool tradeDestructorBlocks = true;
43
41
BlockDirectory::BlockDirectory(Heap* heap, size_t cellSize)
44
BlockDirectory::BlockDirectory(Heap* heap, size_t cellSize)
42
    : m_cellSize(static_cast<unsigned>(cellSize))
45
    : m_freeList(cellSize)
46
    , m_currentBlock(0)
47
    , m_lastActiveBlock(0)
48
    , m_cellSize(static_cast<unsigned>(cellSize))
43
    , m_heap(heap)
49
    , m_heap(heap)
44
{
50
{
45
    heap->threadLocalCacheLayout().allocateOffset(this);
46
}
51
}
47
52
48
void BlockDirectory::setSubspace(Subspace* subspace)
53
void BlockDirectory::setSubspace(Subspace* subspace)
Lines 76-89 MarkedBlock::Handle* BlockDirectory::findEmptyBlockToSteal() a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec3
76
    return m_blocks[m_emptyCursor];
81
    return m_blocks[m_emptyCursor];
77
}
82
}
78
83
79
MarkedBlock::Handle* BlockDirectory::findBlockForAllocation()
84
void BlockDirectory::didConsumeFreeList()
85
{
86
    if (m_currentBlock)
87
        m_currentBlock->didConsumeFreeList();
88
    
89
    m_freeList.clear();
90
    m_currentBlock = nullptr;
91
}
92
93
void* BlockDirectory::tryAllocateWithoutCollecting()
80
{
94
{
81
    m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(m_allocationCursor, true);
95
    SuperSamplerScope superSamplerScope(false);
82
    if (m_allocationCursor >= m_blocks.size())
96
    
97
    ASSERT(!m_currentBlock);
98
    ASSERT(m_freeList.allocationWillFail());
99
    
100
    for (;;) {
101
        m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(m_allocationCursor, true);
102
        if (m_allocationCursor >= m_blocks.size())
103
            break;
104
        
105
        setIsCanAllocateButNotEmpty(NoLockingNecessary, m_allocationCursor, false);
106
107
        if (void* result = tryAllocateIn(m_blocks[m_allocationCursor]))
108
            return result;
109
    }
110
    
111
    if (Options::stealEmptyBlocksFromOtherAllocators()
112
        && (tradeDestructorBlocks || !needsDestruction())) {
113
        if (MarkedBlock::Handle* block = m_subspace->findEmptyBlockToSteal()) {
114
            RELEASE_ASSERT(block->alignedMemoryAllocator() == m_subspace->alignedMemoryAllocator());
115
            
116
            block->sweep(nullptr);
117
            
118
            // It's good that this clears canAllocateButNotEmpty as well as all other bits,
119
            // because there is a remote chance that a block may have both canAllocateButNotEmpty
120
            // and empty set at the same time.
121
            block->removeFromDirectory();
122
            addBlock(block);
123
            return allocateIn(block);
124
        }
125
    }
126
    
127
    return nullptr;
128
}
129
130
void* BlockDirectory::allocateIn(MarkedBlock::Handle* block)
131
{
132
    void* result = tryAllocateIn(block);
133
    RELEASE_ASSERT(result);
134
    return result;
135
}
136
137
void* BlockDirectory::tryAllocateIn(MarkedBlock::Handle* block)
138
{
139
    ASSERT(block);
140
    ASSERT(!block->isFreeListed());
141
    
142
    block->sweep(&m_freeList);
143
    
144
    // It's possible to stumble on a completely full block. Marking tries to retire these, but
145
    // that algorithm is racy and may forget to do it sometimes.
146
    if (m_freeList.allocationWillFail()) {
147
        ASSERT(block->isFreeListed());
148
        block->unsweepWithNoNewlyAllocated();
149
        ASSERT(!block->isFreeListed());
150
        ASSERT(!isEmpty(NoLockingNecessary, block));
151
        ASSERT(!isCanAllocateButNotEmpty(NoLockingNecessary, block));
83
        return nullptr;
152
        return nullptr;
153
    }
154
    
155
    m_currentBlock = block;
156
    
157
    void* result = m_freeList.allocate(
158
        [] () -> HeapCell* {
159
            RELEASE_ASSERT_NOT_REACHED();
160
            return nullptr;
161
        });
162
    setIsEden(NoLockingNecessary, m_currentBlock, true);
163
    markedSpace().didAllocateInBlock(m_currentBlock);
164
    return result;
165
}
166
167
ALWAYS_INLINE void BlockDirectory::doTestCollectionsIfNeeded(GCDeferralContext* deferralContext)
168
{
169
    if (!Options::slowPathAllocsBetweenGCs())
170
        return;
171
172
    static unsigned allocationCount = 0;
173
    if (!allocationCount) {
174
        if (!m_heap->isDeferred()) {
175
            if (deferralContext)
176
                deferralContext->m_shouldGC = true;
177
            else
178
                m_heap->collectNow(Sync, CollectionScope::Full);
179
        }
180
    }
181
    if (++allocationCount >= Options::slowPathAllocsBetweenGCs())
182
        allocationCount = 0;
183
}
184
185
void* BlockDirectory::allocateSlowCase(GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
186
{
187
    SuperSamplerScope superSamplerScope(false);
188
    ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock());
189
    doTestCollectionsIfNeeded(deferralContext);
190
191
    ASSERT(!markedSpace().isIterating());
192
    m_heap->didAllocate(m_freeList.originalSize());
193
    
194
    didConsumeFreeList();
195
    
196
    AllocatingScope helpingHeap(*m_heap);
197
198
    m_heap->collectIfNecessaryOrDefer(deferralContext);
84
    
199
    
85
    setIsCanAllocateButNotEmpty(NoLockingNecessary, m_allocationCursor, false);
200
    // Goofy corner case: the GC called a callback and now this directory has a currentBlock. This only
86
    return m_blocks[m_allocationCursor];
201
    // happens when running WebKit tests, which inject a callback into the GC's finalization.
202
    if (UNLIKELY(m_currentBlock))
203
        return allocate(deferralContext, failureMode);
204
    
205
    void* result = tryAllocateWithoutCollecting();
206
    
207
    if (LIKELY(result != 0))
208
        return result;
209
    
210
    MarkedBlock::Handle* block = tryAllocateBlock();
211
    if (!block) {
212
        if (failureMode == AllocationFailureMode::Assert)
213
            RELEASE_ASSERT_NOT_REACHED();
214
        else
215
            return nullptr;
216
    }
217
    addBlock(block);
218
    result = allocateIn(block);
219
    ASSERT(result);
220
    return result;
87
}
221
}
88
222
89
static size_t blockHeaderSize()
223
static size_t blockHeaderSize()
Lines 179-197 void BlockDirectory::stopAllocating() a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec4
179
{
313
{
180
    if (false)
314
    if (false)
181
        dataLog(RawPointer(this), ": BlockDirectory::stopAllocating!\n");
315
        dataLog(RawPointer(this), ": BlockDirectory::stopAllocating!\n");
182
    m_localAllocators.forEach(
316
    ASSERT(!m_lastActiveBlock);
183
        [&] (LocalAllocator* allocator) {
317
    if (!m_currentBlock) {
184
            allocator->stopAllocating();
318
        ASSERT(m_freeList.allocationWillFail());
185
        });
319
        return;
320
    }
321
    
322
    m_currentBlock->stopAllocating(m_freeList);
323
    m_lastActiveBlock = m_currentBlock;
324
    m_currentBlock = 0;
325
    m_freeList.clear();
186
}
326
}
187
327
188
void BlockDirectory::prepareForAllocation()
328
void BlockDirectory::prepareForAllocation()
189
{
329
{
190
    m_localAllocators.forEach(
330
    m_lastActiveBlock = nullptr;
191
        [&] (LocalAllocator* allocator) {
331
    m_currentBlock = nullptr;
192
            allocator->prepareForAllocation();
332
    m_freeList.clear();
193
        });
333
194
    
195
    m_allocationCursor = 0;
334
    m_allocationCursor = 0;
196
    m_emptyCursor = 0;
335
    m_emptyCursor = 0;
197
    m_unsweptCursor = 0;
336
    m_unsweptCursor = 0;
Lines 205-225 void BlockDirectory::prepareForAllocation() a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec5
205
    }
344
    }
206
}
345
}
207
346
208
void BlockDirectory::stopAllocatingForGood()
209
{
210
    if (false)
211
        dataLog(RawPointer(this), ": BlockDirectory::stopAllocatingForGood!\n");
212
    
213
    m_localAllocators.forEach(
214
        [&] (LocalAllocator* allocator) {
215
            allocator->stopAllocatingForGood();
216
        });
217
218
    auto locker = holdLock(m_localAllocatorsLock);
219
    while (!m_localAllocators.isEmpty())
220
        m_localAllocators.begin()->remove();
221
}
222
223
void BlockDirectory::lastChanceToFinalize()
347
void BlockDirectory::lastChanceToFinalize()
224
{
348
{
225
    forEachBlock(
349
    forEachBlock(
Lines 230-239 void BlockDirectory::lastChanceToFinalize() a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec6
230
354
231
void BlockDirectory::resumeAllocating()
355
void BlockDirectory::resumeAllocating()
232
{
356
{
233
    m_localAllocators.forEach(
357
    if (!m_lastActiveBlock)
234
        [&] (LocalAllocator* allocator) {
358
        return;
235
            allocator->resumeAllocating();
359
236
        });
360
    m_lastActiveBlock->resumeAllocating(m_freeList);
361
    m_currentBlock = m_lastActiveBlock;
362
    m_lastActiveBlock = nullptr;
237
}
363
}
238
364
239
void BlockDirectory::beginMarkingForFullCollection()
365
void BlockDirectory::beginMarkingForFullCollection()
Lines 253-259 void BlockDirectory::endMarking() a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec7
253
    // know what kind of collection it is. That knowledge is already encoded in the m_markingXYZ
379
    // know what kind of collection it is. That knowledge is already encoded in the m_markingXYZ
254
    // vectors.
380
    // vectors.
255
    
381
    
256
    if (!Options::tradeDestructorBlocks() && needsDestruction()) {
382
    if (!tradeDestructorBlocks && needsDestruction()) {
257
        ASSERT(m_empty.isEmpty());
383
        ASSERT(m_empty.isEmpty());
258
        m_canAllocateButNotEmpty = m_live & ~m_markingRetired;
384
        m_canAllocateButNotEmpty = m_live & ~m_markingRetired;
259
    } else {
385
    } else {
Lines 386-400 MarkedSpace& BlockDirectory::markedSpace() const a/Source/JavaScriptCore/heap/BlockDirectory.cpp_sec8
386
    return m_subspace->space();
512
    return m_subspace->space();
387
}
513
}
388
514
389
bool BlockDirectory::isFreeListedCell(const void* target)
390
{
391
    bool result = false;
392
    m_localAllocators.forEach(
393
        [&] (LocalAllocator* allocator) {
394
            result |= allocator->isFreeListedCell(target);
395
        });
396
    return result;
397
}
398
399
} // namespace JSC
515
} // namespace JSC
400
516
- a/Source/JavaScriptCore/heap/BlockDirectory.h -14 / +28 lines
Lines 26-35 a/Source/JavaScriptCore/heap/BlockDirectory.h_sec1
26
#pragma once
26
#pragma once
27
27
28
#include "AllocationFailureMode.h"
28
#include "AllocationFailureMode.h"
29
#include "Allocator.h"
30
#include "CellAttributes.h"
29
#include "CellAttributes.h"
31
#include "FreeList.h"
30
#include "FreeList.h"
32
#include "LocalAllocator.h"
33
#include "MarkedBlock.h"
31
#include "MarkedBlock.h"
34
#include <wtf/DataLog.h>
32
#include <wtf/DataLog.h>
35
#include <wtf/FastBitVector.h>
33
#include <wtf/FastBitVector.h>
Lines 43-49 class Heap; a/Source/JavaScriptCore/heap/BlockDirectory.h_sec2
43
class IsoCellSet;
41
class IsoCellSet;
44
class MarkedSpace;
42
class MarkedSpace;
45
class LLIntOffsetsExtractor;
43
class LLIntOffsetsExtractor;
46
class ThreadLocalCacheLayout;
47
44
48
#define FOR_EACH_BLOCK_DIRECTORY_BIT(macro) \
45
#define FOR_EACH_BLOCK_DIRECTORY_BIT(macro) \
49
    macro(live, Live) /* The set of block indices that have actual blocks. */\
46
    macro(live, Live) /* The set of block indices that have actual blocks. */\
Lines 79-90 class BlockDirectory { a/Source/JavaScriptCore/heap/BlockDirectory.h_sec3
79
    friend class LLIntOffsetsExtractor;
76
    friend class LLIntOffsetsExtractor;
80
77
81
public:
78
public:
79
    static ptrdiff_t offsetOfFreeList();
80
    static ptrdiff_t offsetOfCellSize();
81
82
    BlockDirectory(Heap*, size_t cellSize);
82
    BlockDirectory(Heap*, size_t cellSize);
83
    void setSubspace(Subspace*);
83
    void setSubspace(Subspace*);
84
    void lastChanceToFinalize();
84
    void lastChanceToFinalize();
85
    void prepareForAllocation();
85
    void prepareForAllocation();
86
    void stopAllocating();
86
    void stopAllocating();
87
    void stopAllocatingForGood();
88
    void resumeAllocating();
87
    void resumeAllocating();
89
    void beginMarkingForFullCollection();
88
    void beginMarkingForFullCollection();
90
    void endMarking();
89
    void endMarking();
Lines 98-106 public: a/Source/JavaScriptCore/heap/BlockDirectory.h_sec4
98
    bool needsDestruction() const { return m_attributes.destruction == NeedsDestruction; }
97
    bool needsDestruction() const { return m_attributes.destruction == NeedsDestruction; }
99
    DestructionMode destruction() const { return m_attributes.destruction; }
98
    DestructionMode destruction() const { return m_attributes.destruction; }
100
    HeapCell::Kind cellKind() const { return m_attributes.cellKind; }
99
    HeapCell::Kind cellKind() const { return m_attributes.cellKind; }
100
    void* allocate(GCDeferralContext*, AllocationFailureMode);
101
    Heap* heap() { return m_heap; }
101
    Heap* heap() { return m_heap; }
102
102
103
    bool isFreeListedCell(const void* target);
103
    bool isFreeListedCell(const void* target) const;
104
104
105
    template<typename Functor> void forEachBlock(const Functor&);
105
    template<typename Functor> void forEachBlock(const Functor&);
106
    template<typename Functor> void forEachNotEmptyBlock(const Functor&);
106
    template<typename Functor> void forEachNotEmptyBlock(const Functor&);
Lines 157-176 public: a/Source/JavaScriptCore/heap/BlockDirectory.h_sec5
157
    Subspace* subspace() const { return m_subspace; }
157
    Subspace* subspace() const { return m_subspace; }
158
    MarkedSpace& markedSpace() const;
158
    MarkedSpace& markedSpace() const;
159
    
159
    
160
    Allocator allocator() const { return Allocator(m_tlcOffset); }
160
    const FreeList& freeList() const { return m_freeList; }
161
    
161
    
162
    void dump(PrintStream&) const;
162
    void dump(PrintStream&) const;
163
    void dumpBits(PrintStream& = WTF::dataFile());
163
    void dumpBits(PrintStream& = WTF::dataFile());
164
    
164
    
165
private:
165
private:
166
    friend class LocalAllocator;
167
    friend class IsoCellSet;
166
    friend class IsoCellSet;
168
    friend class MarkedBlock;
167
    friend class MarkedBlock;
169
    friend class ThreadLocalCacheLayout;
170
    
171
    MarkedBlock::Handle* findBlockForAllocation();
172
    
168
    
169
    JS_EXPORT_PRIVATE void* allocateSlowCase(GCDeferralContext*, AllocationFailureMode failureMode);
170
    void didConsumeFreeList();
171
    void* tryAllocateWithoutCollecting();
173
    MarkedBlock::Handle* tryAllocateBlock();
172
    MarkedBlock::Handle* tryAllocateBlock();
173
    void* tryAllocateIn(MarkedBlock::Handle*);
174
    void* allocateIn(MarkedBlock::Handle*);
175
    ALWAYS_INLINE void doTestCollectionsIfNeeded(GCDeferralContext*);
176
    
177
    FreeList m_freeList;
174
    
178
    
175
    Vector<MarkedBlock::Handle*> m_blocks;
179
    Vector<MarkedBlock::Handle*> m_blocks;
176
    Vector<unsigned> m_freeBlockIndices;
180
    Vector<unsigned> m_freeBlockIndices;
Lines 189-194 private: a/Source/JavaScriptCore/heap/BlockDirectory.h_sec6
189
    size_t m_emptyCursor { 0 }; // Points to the next block that is a candidate for empty allocation (allocating in empty blocks).
193
    size_t m_emptyCursor { 0 }; // Points to the next block that is a candidate for empty allocation (allocating in empty blocks).
190
    size_t m_unsweptCursor { 0 }; // Points to the next block that is a candidate for incremental sweeping.
194
    size_t m_unsweptCursor { 0 }; // Points to the next block that is a candidate for incremental sweeping.
191
    
195
    
196
    MarkedBlock::Handle* m_currentBlock;
197
    MarkedBlock::Handle* m_lastActiveBlock;
198
199
    Lock m_lock;
192
    unsigned m_cellSize;
200
    unsigned m_cellSize;
193
    CellAttributes m_attributes;
201
    CellAttributes m_attributes;
194
    // FIXME: All of these should probably be references.
202
    // FIXME: All of these should probably be references.
Lines 198-207 private: a/Source/JavaScriptCore/heap/BlockDirectory.h_sec7
198
    BlockDirectory* m_nextDirectory { nullptr };
206
    BlockDirectory* m_nextDirectory { nullptr };
199
    BlockDirectory* m_nextDirectoryInSubspace { nullptr };
207
    BlockDirectory* m_nextDirectoryInSubspace { nullptr };
200
    BlockDirectory* m_nextDirectoryInAlignedMemoryAllocator { nullptr };
208
    BlockDirectory* m_nextDirectoryInAlignedMemoryAllocator { nullptr };
201
    
202
    Lock m_localAllocatorsLock;
203
    size_t m_tlcOffset;
204
    SentinelLinkedList<LocalAllocator, BasicRawSentinelNode<LocalAllocator>> m_localAllocators;
205
};
209
};
206
210
211
inline ptrdiff_t BlockDirectory::offsetOfFreeList()
212
{
213
    return OBJECT_OFFSETOF(BlockDirectory, m_freeList);
214
}
215
216
inline ptrdiff_t BlockDirectory::offsetOfCellSize()
217
{
218
    return OBJECT_OFFSETOF(BlockDirectory, m_cellSize);
219
}
220
207
} // namespace JSC
221
} // namespace JSC
- a/Source/JavaScriptCore/heap/BlockDirectoryInlines.h +14 lines
Lines 31-36 a/Source/JavaScriptCore/heap/BlockDirectoryInlines.h_sec1
31
31
32
namespace JSC {
32
namespace JSC {
33
33
34
inline bool BlockDirectory::isFreeListedCell(const void* target) const
35
{
36
    return m_freeList.contains(bitwise_cast<HeapCell*>(target));
37
}
38
39
ALWAYS_INLINE void* BlockDirectory::allocate(GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
40
{
41
    return m_freeList.allocate(
42
        [&] () -> HeapCell* {
43
            sanitizeStackForVM(heap()->vm());
44
            return static_cast<HeapCell*>(allocateSlowCase(deferralContext, failureMode));
45
        });
46
}
47
34
template <typename Functor> inline void BlockDirectory::forEachBlock(const Functor& functor)
48
template <typename Functor> inline void BlockDirectory::forEachBlock(const Functor& functor)
35
{
49
{
36
    m_live.forEachSetBit(
50
    m_live.forEachSetBit(
- a/Source/JavaScriptCore/heap/CompleteSubspace.cpp -29 / +27 lines
Lines 1-5 a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2017 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 26-40 a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec2
26
#include "config.h"
26
#include "config.h"
27
#include "Subspace.h"
27
#include "Subspace.h"
28
28
29
#include "AlignedMemoryAllocator.h"
30
#include "AllocatorInlines.h"
31
#include "BlockDirectoryInlines.h"
29
#include "BlockDirectoryInlines.h"
32
#include "JSCInlines.h"
30
#include "JSCInlines.h"
33
#include "LocalAllocatorInlines.h"
34
#include "MarkedBlockInlines.h"
31
#include "MarkedBlockInlines.h"
35
#include "PreventCollectionScope.h"
32
#include "PreventCollectionScope.h"
36
#include "SubspaceInlines.h"
33
#include "SubspaceInlines.h"
37
#include "ThreadLocalCacheInlines.h"
38
34
39
namespace JSC {
35
namespace JSC {
40
36
Lines 42-79 CompleteSubspace::CompleteSubspace(CString name, Heap& heap, HeapCellType* heapC a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec3
42
    : Subspace(name, heap)
38
    : Subspace(name, heap)
43
{
39
{
44
    initialize(heapCellType, alignedMemoryAllocator);
40
    initialize(heapCellType, alignedMemoryAllocator);
41
    for (size_t i = MarkedSpace::numSizeClasses; i--;)
42
        m_allocatorForSizeStep[i] = nullptr;
45
}
43
}
46
44
47
CompleteSubspace::~CompleteSubspace()
45
CompleteSubspace::~CompleteSubspace()
48
{
46
{
49
}
47
}
50
48
51
Allocator CompleteSubspace::allocatorFor(size_t size, AllocatorForMode mode)
49
BlockDirectory* CompleteSubspace::allocatorFor(size_t size, AllocatorForMode mode)
52
{
50
{
53
    return allocatorForNonVirtual(size, mode);
51
    return allocatorForNonVirtual(size, mode);
54
}
52
}
55
53
56
void* CompleteSubspace::allocate(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
54
void* CompleteSubspace::allocate(size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
57
{
55
{
58
    return allocateNonVirtual(vm, size, deferralContext, failureMode);
56
    return allocateNonVirtual(size, deferralContext, failureMode);
59
}
57
}
60
58
61
void* CompleteSubspace::allocateNonVirtual(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
59
void* CompleteSubspace::allocateNonVirtual(size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
62
{
60
{
63
    Allocator allocator = allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
61
    void *result;
64
    return allocator.tryAllocate(
62
    if (BlockDirectory* allocator = allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists))
65
        vm, deferralContext, failureMode,
63
        result = allocator->allocate(deferralContext, failureMode);
66
        [&] () {
64
    else
67
            return allocateSlow(vm, size, deferralContext, failureMode);
65
        result = allocateSlow(size, deferralContext, failureMode);
68
        });
66
    return result;
69
}
67
}
70
68
71
Allocator CompleteSubspace::allocatorForSlow(size_t size)
69
BlockDirectory* CompleteSubspace::allocatorForSlow(size_t size)
72
{
70
{
73
    size_t index = MarkedSpace::sizeClassToIndex(size);
71
    size_t index = MarkedSpace::sizeClassToIndex(size);
74
    size_t sizeClass = MarkedSpace::s_sizeClassForSizeStep[index];
72
    size_t sizeClass = MarkedSpace::s_sizeClassForSizeStep[index];
75
    if (!sizeClass)
73
    if (!sizeClass)
76
        return Allocator();
74
        return nullptr;
77
    
75
    
78
    // This is written in such a way that it's OK for the JIT threads to end up here if they want
76
    // This is written in such a way that it's OK for the JIT threads to end up here if they want
79
    // to generate code that uses some allocator that hadn't been used yet. Note that a possibly-
77
    // to generate code that uses some allocator that hadn't been used yet. Note that a possibly-
Lines 84-90 Allocator CompleteSubspace::allocatorForSlow(size_t size) a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec4
84
    // that any "forEachAllocator" traversals will only see this allocator after it's initialized
82
    // that any "forEachAllocator" traversals will only see this allocator after it's initialized
85
    // enough: it will have 
83
    // enough: it will have 
86
    auto locker = holdLock(m_space.directoryLock());
84
    auto locker = holdLock(m_space.directoryLock());
87
    if (Allocator allocator = m_allocatorForSizeStep[index])
85
    if (BlockDirectory* allocator = m_allocatorForSizeStep[index])
88
        return allocator;
86
        return allocator;
89
87
90
    if (false)
88
    if (false)
Lines 100-106 Allocator CompleteSubspace::allocatorForSlow(size_t size) a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec5
100
        if (MarkedSpace::s_sizeClassForSizeStep[index] != sizeClass)
98
        if (MarkedSpace::s_sizeClassForSizeStep[index] != sizeClass)
101
            break;
99
            break;
102
100
103
        m_allocatorForSizeStep[index] = directory->allocator();
101
        m_allocatorForSizeStep[index] = directory;
104
        
102
        
105
        if (!index--)
103
        if (!index--)
106
            break;
104
            break;
Lines 109-131 Allocator CompleteSubspace::allocatorForSlow(size_t size) a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec6
109
    m_alignedMemoryAllocator->registerDirectory(directory);
107
    m_alignedMemoryAllocator->registerDirectory(directory);
110
    WTF::storeStoreFence();
108
    WTF::storeStoreFence();
111
    m_firstDirectory = directory;
109
    m_firstDirectory = directory;
112
    return directory->allocator();
110
    return directory;
113
}
111
}
114
112
115
void* CompleteSubspace::allocateSlow(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
113
void* CompleteSubspace::allocateSlow(size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
116
{
114
{
117
    void* result = tryAllocateSlow(vm, size, deferralContext);
115
    void* result = tryAllocateSlow(size, deferralContext);
118
    if (failureMode == AllocationFailureMode::Assert)
116
    if (failureMode == AllocationFailureMode::Assert)
119
        RELEASE_ASSERT(result);
117
        RELEASE_ASSERT(result);
120
    return result;
118
    return result;
121
}
119
}
122
120
123
void* CompleteSubspace::tryAllocateSlow(VM& vm, size_t size, GCDeferralContext* deferralContext)
121
void* CompleteSubspace::tryAllocateSlow(size_t size, GCDeferralContext* deferralContext)
124
{
122
{
125
    sanitizeStackForVM(&vm);
123
    sanitizeStackForVM(m_space.heap()->vm());
126
    
124
    
127
    if (Allocator allocator = allocatorFor(size, AllocatorForMode::EnsureAllocator))
125
    if (BlockDirectory* allocator = allocatorFor(size, AllocatorForMode::EnsureAllocator))
128
        return allocator.allocate(vm, deferralContext, AllocationFailureMode::ReturnNull);
126
        return allocator->allocate(deferralContext, AllocationFailureMode::ReturnNull);
129
    
127
    
130
    if (size <= Options::largeAllocationCutoff()
128
    if (size <= Options::largeAllocationCutoff()
131
        && size <= MarkedSpace::largeCutoff) {
129
        && size <= MarkedSpace::largeCutoff) {
Lines 134-148 void* CompleteSubspace::tryAllocateSlow(VM& vm, size_t size, GCDeferralContext* a/Source/JavaScriptCore/heap/CompleteSubspace.cpp_sec7
134
        RELEASE_ASSERT_NOT_REACHED();
132
        RELEASE_ASSERT_NOT_REACHED();
135
    }
133
    }
136
    
134
    
137
    vm.heap.collectIfNecessaryOrDefer(deferralContext);
135
    m_space.heap()->collectIfNecessaryOrDefer(deferralContext);
138
    
136
    
139
    size = WTF::roundUpToMultipleOf<MarkedSpace::sizeStep>(size);
137
    size = WTF::roundUpToMultipleOf<MarkedSpace::sizeStep>(size);
140
    LargeAllocation* allocation = LargeAllocation::tryCreate(vm.heap, size, this);
138
    LargeAllocation* allocation = LargeAllocation::tryCreate(*m_space.m_heap, size, this);
141
    if (!allocation)
139
    if (!allocation)
142
        return nullptr;
140
        return nullptr;
143
    
141
    
144
    m_space.m_largeAllocations.append(allocation);
142
    m_space.m_largeAllocations.append(allocation);
145
    vm.heap.didAllocate(size);
143
    m_space.m_heap->didAllocate(size);
146
    m_space.m_capacity += size;
144
    m_space.m_capacity += size;
147
    
145
    
148
    m_largeAllocations.append(allocation);
146
    m_largeAllocations.append(allocation);
- a/Source/JavaScriptCore/heap/CompleteSubspace.h -12 / +12 lines
Lines 39-69 public: a/Source/JavaScriptCore/heap/CompleteSubspace.h_sec1
39
    
39
    
40
    // FIXME: Currently subspaces speak of BlockDirectories as "allocators", but that's temporary.
40
    // FIXME: Currently subspaces speak of BlockDirectories as "allocators", but that's temporary.
41
    // https://bugs.webkit.org/show_bug.cgi?id=181559
41
    // https://bugs.webkit.org/show_bug.cgi?id=181559
42
    Allocator allocatorFor(size_t, AllocatorForMode) override;
42
    BlockDirectory* allocatorFor(size_t, AllocatorForMode) override;
43
    Allocator allocatorForNonVirtual(size_t, AllocatorForMode);
43
    BlockDirectory* allocatorForNonVirtual(size_t, AllocatorForMode);
44
    
44
    
45
    void* allocate(VM&, size_t, GCDeferralContext*, AllocationFailureMode) override;
45
    void* allocate(size_t, GCDeferralContext*, AllocationFailureMode) override;
46
    JS_EXPORT_PRIVATE void* allocateNonVirtual(VM&, size_t, GCDeferralContext*, AllocationFailureMode);
46
    JS_EXPORT_PRIVATE void* allocateNonVirtual(size_t, GCDeferralContext*, AllocationFailureMode);
47
    
47
    
48
    static ptrdiff_t offsetOfAllocatorForSizeStep() { return OBJECT_OFFSETOF(CompleteSubspace, m_allocatorForSizeStep); }
48
    static ptrdiff_t offsetOfAllocatorForSizeStep() { return OBJECT_OFFSETOF(CompleteSubspace, m_allocatorForSizeStep); }
49
    
49
    
50
    Allocator* allocatorForSizeStep() { return &m_allocatorForSizeStep[0]; }
50
    BlockDirectory** allocatorForSizeStep() { return &m_allocatorForSizeStep[0]; }
51
51
52
private:
52
private:
53
    Allocator allocatorForSlow(size_t);
53
    BlockDirectory* allocatorForSlow(size_t);
54
    
54
    
55
    // These slow paths are concerned with large allocations and allocator creation.
55
    // These slow paths are concerned with large allocations and allocator creation.
56
    void* allocateSlow(VM&, size_t, GCDeferralContext*, AllocationFailureMode);
56
    void* allocateSlow(size_t, GCDeferralContext*, AllocationFailureMode);
57
    void* tryAllocateSlow(VM&, size_t, GCDeferralContext*);
57
    void* tryAllocateSlow(size_t, GCDeferralContext*);
58
    
58
    
59
    std::array<Allocator, MarkedSpace::numSizeClasses> m_allocatorForSizeStep;
59
    std::array<BlockDirectory*, MarkedSpace::numSizeClasses> m_allocatorForSizeStep;
60
    Vector<std::unique_ptr<BlockDirectory>> m_directories;
60
    Vector<std::unique_ptr<BlockDirectory>> m_directories;
61
};
61
};
62
62
63
ALWAYS_INLINE Allocator CompleteSubspace::allocatorForNonVirtual(size_t size, AllocatorForMode mode)
63
ALWAYS_INLINE BlockDirectory* CompleteSubspace::allocatorForNonVirtual(size_t size, AllocatorForMode mode)
64
{
64
{
65
    if (size <= MarkedSpace::largeCutoff) {
65
    if (size <= MarkedSpace::largeCutoff) {
66
        Allocator result = m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)];
66
        BlockDirectory* result = m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)];
67
        switch (mode) {
67
        switch (mode) {
68
        case AllocatorForMode::MustAlreadyHaveAllocator:
68
        case AllocatorForMode::MustAlreadyHaveAllocator:
69
            RELEASE_ASSERT(result);
69
            RELEASE_ASSERT(result);
Lines 78-84 ALWAYS_INLINE Allocator CompleteSubspace::allocatorForNonVirtual(size_t size, Al a/Source/JavaScriptCore/heap/CompleteSubspace.h_sec2
78
        return result;
78
        return result;
79
    }
79
    }
80
    RELEASE_ASSERT(mode != AllocatorForMode::MustAlreadyHaveAllocator);
80
    RELEASE_ASSERT(mode != AllocatorForMode::MustAlreadyHaveAllocator);
81
    return Allocator();
81
    return nullptr;
82
}
82
}
83
83
84
} // namespace JSC
84
} // namespace JSC
- a/Source/JavaScriptCore/heap/FreeList.h +2 lines
Lines 57-62 struct FreeCell { a/Source/JavaScriptCore/heap/FreeList.h_sec1
57
};
57
};
58
58
59
class FreeList {
59
class FreeList {
60
    WTF_MAKE_NONCOPYABLE(FreeList);
61
    
60
public:
62
public:
61
    FreeList(unsigned cellSize);
63
    FreeList(unsigned cellSize);
62
    ~FreeList();
64
    ~FreeList();
- a/Source/JavaScriptCore/heap/GCDeferralContext.h -3 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/heap/GCDeferralContext.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2016 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 29-40 namespace JSC { a/Source/JavaScriptCore/heap/GCDeferralContext.h_sec2
29
29
30
class Heap;
30
class Heap;
31
class BlockDirectory;
31
class BlockDirectory;
32
class LocalAllocator;
33
32
34
class GCDeferralContext {
33
class GCDeferralContext {
35
    friend class Heap;
34
    friend class Heap;
36
    friend class BlockDirectory;
35
    friend class BlockDirectory;
37
    friend class LocalAllocator;
38
public:
36
public:
39
    inline GCDeferralContext(Heap&);
37
    inline GCDeferralContext(Heap&);
40
    inline ~GCDeferralContext();
38
    inline ~GCDeferralContext();
- a/Source/JavaScriptCore/heap/Heap.cpp -3 / +1 lines
Lines 68-74 a/Source/JavaScriptCore/heap/Heap.cpp_sec1
68
#include "StopIfNecessaryTimer.h"
68
#include "StopIfNecessaryTimer.h"
69
#include "SweepingScope.h"
69
#include "SweepingScope.h"
70
#include "SynchronousStopTheWorldMutatorScheduler.h"
70
#include "SynchronousStopTheWorldMutatorScheduler.h"
71
#include "ThreadLocalCacheLayout.h"
72
#include "TypeProfiler.h"
71
#include "TypeProfiler.h"
73
#include "TypeProfilerLog.h"
72
#include "TypeProfilerLog.h"
74
#include "UnlinkedCodeBlock.h"
73
#include "UnlinkedCodeBlock.h"
Lines 313-319 Heap::Heap(VM* vm, HeapType heapType) a/Source/JavaScriptCore/heap/Heap.cpp_sec2
313
    , m_helperClient(&heapHelperPool())
312
    , m_helperClient(&heapHelperPool())
314
    , m_threadLock(Box<Lock>::create())
313
    , m_threadLock(Box<Lock>::create())
315
    , m_threadCondition(AutomaticThreadCondition::create())
314
    , m_threadCondition(AutomaticThreadCondition::create())
316
    , m_threadLocalCacheLayout(std::make_unique<ThreadLocalCacheLayout>())
317
{
315
{
318
    m_worldState.store(0);
316
    m_worldState.store(0);
319
317
Lines 448-454 void Heap::lastChanceToFinalize() a/Source/JavaScriptCore/heap/Heap.cpp_sec3
448
        dataLog("5 ");
446
        dataLog("5 ");
449
    
447
    
450
    m_arrayBuffers.lastChanceToFinalize();
448
    m_arrayBuffers.lastChanceToFinalize();
451
    m_objectSpace.stopAllocatingForGood();
449
    m_objectSpace.stopAllocating();
452
    m_objectSpace.lastChanceToFinalize();
450
    m_objectSpace.lastChanceToFinalize();
453
    releaseDelayedReleasedObjects();
451
    releaseDelayedReleasedObjects();
454
452
- a/Source/JavaScriptCore/heap/Heap.h -5 lines
Lines 84-90 class SlotVisitor; a/Source/JavaScriptCore/heap/Heap.h_sec1
84
class SpaceTimeMutatorScheduler;
84
class SpaceTimeMutatorScheduler;
85
class StopIfNecessaryTimer;
85
class StopIfNecessaryTimer;
86
class SweepingScope;
86
class SweepingScope;
87
class ThreadLocalCacheLayout;
88
class VM;
87
class VM;
89
class WeakGCMapBase;
88
class WeakGCMapBase;
90
struct CurrentThreadState;
89
struct CurrentThreadState;
Lines 373-380 public: a/Source/JavaScriptCore/heap/Heap.h_sec2
373
372
374
    template<typename Func>
373
    template<typename Func>
375
    void forEachSlotVisitor(const Func&);
374
    void forEachSlotVisitor(const Func&);
376
    
377
    ThreadLocalCacheLayout& threadLocalCacheLayout() { return *m_threadLocalCacheLayout; }
378
375
379
private:
376
private:
380
    friend class AllocatingScope;
377
    friend class AllocatingScope;
Lines 717-724 private: a/Source/JavaScriptCore/heap/Heap.h_sec3
717
    
714
    
718
    CurrentThreadState* m_currentThreadState { nullptr };
715
    CurrentThreadState* m_currentThreadState { nullptr };
719
    WTF::Thread* m_currentThread { nullptr }; // It's OK if this becomes a dangling pointer.
716
    WTF::Thread* m_currentThread { nullptr }; // It's OK if this becomes a dangling pointer.
720
    
721
    std::unique_ptr<ThreadLocalCacheLayout> m_threadLocalCacheLayout;
722
};
717
};
723
718
724
} // namespace JSC
719
} // namespace JSC
- a/Source/JavaScriptCore/heap/IsoCellSet.h -3 lines
Lines 25-36 a/Source/JavaScriptCore/heap/IsoCellSet.h_sec1
25
25
26
#pragma once
26
#pragma once
27
27
28
#include "MarkedBlock.h"
29
#include <wtf/Bitmap.h>
28
#include <wtf/Bitmap.h>
30
#include <wtf/ConcurrentVector.h>
29
#include <wtf/ConcurrentVector.h>
31
#include <wtf/FastBitVector.h>
30
#include <wtf/FastBitVector.h>
32
#include <wtf/SentinelLinkedList.h>
33
#include <wtf/SharedTask.h>
34
31
35
namespace JSC {
32
namespace JSC {
36
33
- a/Source/JavaScriptCore/heap/IsoSubspace.cpp -9 / +5 lines
Lines 26-36 a/Source/JavaScriptCore/heap/IsoSubspace.cpp_sec1
26
#include "config.h"
26
#include "config.h"
27
#include "IsoSubspace.h"
27
#include "IsoSubspace.h"
28
28
29
#include "AllocatorInlines.h"
30
#include "BlockDirectoryInlines.h"
29
#include "BlockDirectoryInlines.h"
31
#include "IsoAlignedMemoryAllocator.h"
30
#include "IsoAlignedMemoryAllocator.h"
32
#include "LocalAllocatorInlines.h"
33
#include "ThreadLocalCacheInlines.h"
34
31
35
namespace JSC {
32
namespace JSC {
36
33
Lines 38-44 IsoSubspace::IsoSubspace(CString name, Heap& heap, HeapCellType* heapCellType, s a/Source/JavaScriptCore/heap/IsoSubspace.cpp_sec2
38
    : Subspace(name, heap)
35
    : Subspace(name, heap)
39
    , m_size(size)
36
    , m_size(size)
40
    , m_directory(&heap, WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(size))
37
    , m_directory(&heap, WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(size))
41
    , m_allocator(m_directory.allocator())
42
    , m_isoAlignedMemoryAllocator(std::make_unique<IsoAlignedMemoryAllocator>())
38
    , m_isoAlignedMemoryAllocator(std::make_unique<IsoAlignedMemoryAllocator>())
43
{
39
{
44
    initialize(heapCellType, m_isoAlignedMemoryAllocator.get());
40
    initialize(heapCellType, m_isoAlignedMemoryAllocator.get());
Lines 54-73 IsoSubspace::~IsoSubspace() a/Source/JavaScriptCore/heap/IsoSubspace.cpp_sec3
54
{
50
{
55
}
51
}
56
52
57
Allocator IsoSubspace::allocatorFor(size_t size, AllocatorForMode mode)
53
BlockDirectory* IsoSubspace::allocatorFor(size_t size, AllocatorForMode mode)
58
{
54
{
59
    return allocatorForNonVirtual(size, mode);
55
    return allocatorForNonVirtual(size, mode);
60
}
56
}
61
57
62
void* IsoSubspace::allocate(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
58
void* IsoSubspace::allocate(size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
63
{
59
{
64
    return allocateNonVirtual(vm, size, deferralContext, failureMode);
60
    return allocateNonVirtual(size, deferralContext, failureMode);
65
}
61
}
66
62
67
void* IsoSubspace::allocateNonVirtual(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
63
void* IsoSubspace::allocateNonVirtual(size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
68
{
64
{
69
    RELEASE_ASSERT(size == this->size());
65
    RELEASE_ASSERT(size == this->size());
70
    void* result = m_allocator.allocate(vm, deferralContext, failureMode);
66
    void* result = m_directory.allocate(deferralContext, failureMode);
71
    return result;
67
    return result;
72
}
68
}
73
69
- a/Source/JavaScriptCore/heap/IsoSubspace.h -7 / +6 lines
Lines 41-51 public: a/Source/JavaScriptCore/heap/IsoSubspace.h_sec1
41
41
42
    size_t size() const { return m_size; }
42
    size_t size() const { return m_size; }
43
43
44
    Allocator allocatorFor(size_t, AllocatorForMode) override;
44
    BlockDirectory* allocatorFor(size_t, AllocatorForMode) override;
45
    Allocator allocatorForNonVirtual(size_t, AllocatorForMode);
45
    BlockDirectory* allocatorForNonVirtual(size_t, AllocatorForMode);
46
46
47
    void* allocate(VM&, size_t, GCDeferralContext*, AllocationFailureMode) override;
47
    void* allocate(size_t, GCDeferralContext*, AllocationFailureMode) override;
48
    JS_EXPORT_PRIVATE void* allocateNonVirtual(VM&, size_t, GCDeferralContext*, AllocationFailureMode);
48
    JS_EXPORT_PRIVATE void* allocateNonVirtual(size_t, GCDeferralContext*, AllocationFailureMode);
49
49
50
private:
50
private:
51
    friend class IsoCellSet;
51
    friend class IsoCellSet;
Lines 56-70 private: a/Source/JavaScriptCore/heap/IsoSubspace.h_sec2
56
    
56
    
57
    size_t m_size;
57
    size_t m_size;
58
    BlockDirectory m_directory;
58
    BlockDirectory m_directory;
59
    Allocator m_allocator;
60
    std::unique_ptr<IsoAlignedMemoryAllocator> m_isoAlignedMemoryAllocator;
59
    std::unique_ptr<IsoAlignedMemoryAllocator> m_isoAlignedMemoryAllocator;
61
    SentinelLinkedList<IsoCellSet, BasicRawSentinelNode<IsoCellSet>> m_cellSets;
60
    SentinelLinkedList<IsoCellSet, BasicRawSentinelNode<IsoCellSet>> m_cellSets;
62
};
61
};
63
62
64
inline Allocator IsoSubspace::allocatorForNonVirtual(size_t size, AllocatorForMode)
63
inline BlockDirectory* IsoSubspace::allocatorForNonVirtual(size_t size, AllocatorForMode)
65
{
64
{
66
    RELEASE_ASSERT(size == this->size());
65
    RELEASE_ASSERT(size == this->size());
67
    return m_allocator;
66
    return &m_directory;
68
}
67
}
69
68
70
#define ISO_SUBSPACE_INIT(heap, heapCellType, type) ("Isolated " #type " Space", (heap), (heapCellType), sizeof(type))
69
#define ISO_SUBSPACE_INIT(heap, heapCellType, type) ("Isolated " #type " Space", (heap), (heapCellType), sizeof(type))
- a/Source/JavaScriptCore/heap/LocalAllocator.cpp -297 lines
Lines 1-297 a/Source/JavaScriptCore/heap/LocalAllocator.cpp_sec1
1
/*
2
 * Copyright (C) 2018 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 "LocalAllocator.h"
28
29
#include "AllocatingScope.h"
30
#include "LocalAllocatorInlines.h"
31
#include "Options.h"
32
33
namespace JSC {
34
35
LocalAllocator::LocalAllocator(BlockDirectory* directory)
36
    : m_directory(directory)
37
    , m_cellSize(directory->m_cellSize)
38
    , m_freeList(m_cellSize)
39
{
40
    auto locker = holdLock(directory->m_localAllocatorsLock);
41
    directory->m_localAllocators.append(this);
42
}
43
44
LocalAllocator::LocalAllocator(LocalAllocator&& other)
45
    : m_directory(other.m_directory)
46
    , m_cellSize(other.m_cellSize)
47
    , m_freeList(WTFMove(other.m_freeList))
48
    , m_currentBlock(other.m_currentBlock)
49
    , m_lastActiveBlock(other.m_lastActiveBlock)
50
{
51
    other.reset();
52
    if (other.isOnList()) {
53
        auto locker = holdLock(m_directory->m_localAllocatorsLock);
54
        other.remove();
55
        m_directory->m_localAllocators.append(this);
56
    }
57
}
58
59
void LocalAllocator::reset()
60
{
61
    m_freeList.clear();
62
    m_currentBlock = nullptr;
63
    m_lastActiveBlock = nullptr;
64
}
65
66
LocalAllocator::~LocalAllocator()
67
{
68
    if (isOnList()) {
69
        auto locker = holdLock(m_directory->m_localAllocatorsLock);
70
        remove();
71
    }
72
    
73
    // Assert that this allocator isn't holding onto any memory. This is a valid assertion for the
74
    // following two use cases:
75
    // 
76
    // - Immortal TLC. Those destruct after the heap is done destructing, so they should not have
77
    //   any state left in them.
78
    //
79
    // - TLC owned by an object. Such a TLC gets destroyed after a GC flip during which we proved
80
    //   that it is not reachable. Therefore, the TLC should still be in a fully reset state at the
81
    //   time of destruction because for it to get into any other state, someone must have allocated
82
    //   in it (which is impossible because it's supposedly unreachable).
83
    bool ok = true;
84
    if (!m_freeList.allocationWillFail()) {
85
        dataLog("FATAL: ", RawPointer(this), "->~LocalAllocator has non-empty free-list.\n");
86
        ok = false;
87
    }
88
    if (m_currentBlock) {
89
        dataLog("FATAL: ", RawPointer(this), "->~LocalAllocator has non-null current block.\n");
90
        ok = false;
91
    }
92
    if (m_lastActiveBlock) {
93
        dataLog("FATAL: ", RawPointer(this), "->~LocalAllocator has non-null last active block.\n");
94
        ok = false;
95
    }
96
    RELEASE_ASSERT(ok);
97
}
98
99
void LocalAllocator::stopAllocating()
100
{
101
    ASSERT(!m_lastActiveBlock);
102
    if (!m_currentBlock) {
103
        ASSERT(m_freeList.allocationWillFail());
104
        return;
105
    }
106
    
107
    m_currentBlock->stopAllocating(m_freeList);
108
    m_lastActiveBlock = m_currentBlock;
109
    m_currentBlock = nullptr;
110
    m_freeList.clear();
111
}
112
113
void LocalAllocator::resumeAllocating()
114
{
115
    if (!m_lastActiveBlock)
116
        return;
117
118
    m_lastActiveBlock->resumeAllocating(m_freeList);
119
    m_currentBlock = m_lastActiveBlock;
120
    m_lastActiveBlock = nullptr;
121
}
122
123
void LocalAllocator::prepareForAllocation()
124
{
125
    reset();
126
}
127
128
void LocalAllocator::stopAllocatingForGood()
129
{
130
    stopAllocating();
131
    reset();
132
}
133
134
void* LocalAllocator::allocateSlowCase(GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
135
{
136
    SuperSamplerScope superSamplerScope(false);
137
    Heap& heap = *m_directory->m_heap;
138
    ASSERT(heap.vm()->currentThreadIsHoldingAPILock());
139
    doTestCollectionsIfNeeded(deferralContext);
140
141
    ASSERT(!m_directory->markedSpace().isIterating());
142
    heap.didAllocate(m_freeList.originalSize());
143
    
144
    didConsumeFreeList();
145
    
146
    AllocatingScope helpingHeap(heap);
147
148
    heap.collectIfNecessaryOrDefer(deferralContext);
149
    
150
    // Goofy corner case: the GC called a callback and now this directory has a currentBlock. This only
151
    // happens when running WebKit tests, which inject a callback into the GC's finalization.
152
    if (UNLIKELY(m_currentBlock))
153
        return allocate(deferralContext, failureMode);
154
    
155
    void* result = tryAllocateWithoutCollecting();
156
    
157
    if (LIKELY(result != 0))
158
        return result;
159
    
160
    MarkedBlock::Handle* block = m_directory->tryAllocateBlock();
161
    if (!block) {
162
        if (failureMode == AllocationFailureMode::Assert)
163
            RELEASE_ASSERT_NOT_REACHED();
164
        else
165
            return nullptr;
166
    }
167
    m_directory->addBlock(block);
168
    result = allocateIn(block);
169
    ASSERT(result);
170
    return result;
171
}
172
173
void LocalAllocator::didConsumeFreeList()
174
{
175
    if (m_currentBlock)
176
        m_currentBlock->didConsumeFreeList();
177
    
178
    m_freeList.clear();
179
    m_currentBlock = nullptr;
180
}
181
182
void* LocalAllocator::tryAllocateWithoutCollecting()
183
{
184
    // FIXME: If we wanted this to be used for real multi-threaded allocations then we would have to
185
    // come up with some concurrency protocol here. That protocol would need to be able to handle:
186
    //
187
    // - The basic case of multiple LocalAllocators trying to do an allocationCursor search on the
188
    //   same bitvector. That probably needs the bitvector lock at least.
189
    //
190
    // - The harder case of some LocalAllocator triggering a steal from a different BlockDirectory
191
    //   via a search in the AlignedMemoryAllocator's list. Who knows what locks that needs.
192
    // 
193
    // One way to make this work is to have a single per-Heap lock that protects all mutator lock
194
    // allocation slow paths. That would probably be scalable enough for years. It would certainly be
195
    // for using TLC allocation from JIT threads.
196
    // https://bugs.webkit.org/show_bug.cgi?id=181635
197
    
198
    SuperSamplerScope superSamplerScope(false);
199
    
200
    ASSERT(!m_currentBlock);
201
    ASSERT(m_freeList.allocationWillFail());
202
    
203
    for (;;) {
204
        MarkedBlock::Handle* block = m_directory->findBlockForAllocation();
205
        if (!block)
206
            break;
207
208
        if (void* result = tryAllocateIn(block))
209
            return result;
210
    }
211
    
212
    if (Options::stealEmptyBlocksFromOtherAllocators()
213
        && (Options::tradeDestructorBlocks() || !m_directory->needsDestruction())) {
214
        if (MarkedBlock::Handle* block = m_directory->m_subspace->findEmptyBlockToSteal()) {
215
            RELEASE_ASSERT(block->alignedMemoryAllocator() == m_directory->m_subspace->alignedMemoryAllocator());
216
            
217
            block->sweep(nullptr);
218
            
219
            // It's good that this clears canAllocateButNotEmpty as well as all other bits,
220
            // because there is a remote chance that a block may have both canAllocateButNotEmpty
221
            // and empty set at the same time.
222
            block->removeFromDirectory();
223
            m_directory->addBlock(block);
224
            return allocateIn(block);
225
        }
226
    }
227
    
228
    return nullptr;
229
}
230
231
void* LocalAllocator::allocateIn(MarkedBlock::Handle* block)
232
{
233
    void* result = tryAllocateIn(block);
234
    RELEASE_ASSERT(result);
235
    return result;
236
}
237
238
void* LocalAllocator::tryAllocateIn(MarkedBlock::Handle* block)
239
{
240
    ASSERT(block);
241
    ASSERT(!block->isFreeListed());
242
    
243
    block->sweep(&m_freeList);
244
    
245
    // It's possible to stumble on a completely full block. Marking tries to retire these, but
246
    // that algorithm is racy and may forget to do it sometimes.
247
    if (m_freeList.allocationWillFail()) {
248
        ASSERT(block->isFreeListed());
249
        block->unsweepWithNoNewlyAllocated();
250
        ASSERT(!block->isFreeListed());
251
        ASSERT(!m_directory->isEmpty(NoLockingNecessary, block));
252
        ASSERT(!m_directory->isCanAllocateButNotEmpty(NoLockingNecessary, block));
253
        return nullptr;
254
    }
255
    
256
    m_currentBlock = block;
257
    
258
    void* result = m_freeList.allocate(
259
        [] () -> HeapCell* {
260
            RELEASE_ASSERT_NOT_REACHED();
261
            return nullptr;
262
        });
263
    m_directory->setIsEden(NoLockingNecessary, m_currentBlock, true);
264
    m_directory->markedSpace().didAllocateInBlock(m_currentBlock);
265
    return result;
266
}
267
268
void LocalAllocator::doTestCollectionsIfNeeded(GCDeferralContext* deferralContext)
269
{
270
    if (!Options::slowPathAllocsBetweenGCs())
271
        return;
272
273
    static unsigned allocationCount = 0;
274
    if (!allocationCount) {
275
        if (!m_directory->m_heap->isDeferred()) {
276
            if (deferralContext)
277
                deferralContext->m_shouldGC = true;
278
            else
279
                m_directory->m_heap->collectNow(Sync, CollectionScope::Full);
280
        }
281
    }
282
    if (++allocationCount >= Options::slowPathAllocsBetweenGCs())
283
        allocationCount = 0;
284
}
285
286
bool LocalAllocator::isFreeListedCell(const void* target) const
287
{
288
    // This abomination exists to detect when an object is in the dead-but-not-destructed state.
289
    // Therefore, it's not even clear that this needs to do anything beyond returning "false", since
290
    // if we know that the block owning the object is free-listed, then it's impossible for any
291
    // objects to be in the dead-but-not-destructed state.
292
    // FIXME: Get rid of this abomination. https://bugs.webkit.org/show_bug.cgi?id=181655
293
    return m_freeList.contains(bitwise_cast<HeapCell*>(target));
294
}
295
296
} // namespace JSC
297
- a/Source/JavaScriptCore/heap/LocalAllocator.h -84 lines
Lines 1-84 a/Source/JavaScriptCore/heap/LocalAllocator.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "FreeList.h"
29
#include "MarkedBlock.h"
30
#include <wtf/Noncopyable.h>
31
32
namespace JSC {
33
34
class BlockDirectory;
35
class GCDeferralContext;
36
37
class LocalAllocator : public BasicRawSentinelNode<LocalAllocator> {
38
    WTF_MAKE_NONCOPYABLE(LocalAllocator);
39
    
40
public:
41
    LocalAllocator(BlockDirectory*);
42
    LocalAllocator(LocalAllocator&&);
43
    ~LocalAllocator();
44
    
45
    void* allocate(GCDeferralContext*, AllocationFailureMode);
46
47
    void stopAllocating();
48
    void prepareForAllocation();
49
    void resumeAllocating();
50
    void stopAllocatingForGood();
51
    
52
    static ptrdiff_t offsetOfFreeList();
53
    static ptrdiff_t offsetOfCellSize();
54
    
55
    bool isFreeListedCell(const void*) const;
56
57
private:
58
    void reset();
59
    JS_EXPORT_PRIVATE void* allocateSlowCase(GCDeferralContext*, AllocationFailureMode failureMode);
60
    void didConsumeFreeList();
61
    void* tryAllocateWithoutCollecting();
62
    void* tryAllocateIn(MarkedBlock::Handle*);
63
    void* allocateIn(MarkedBlock::Handle*);
64
    ALWAYS_INLINE void doTestCollectionsIfNeeded(GCDeferralContext*);
65
66
    BlockDirectory* m_directory;
67
    unsigned m_cellSize;
68
    FreeList m_freeList;
69
    MarkedBlock::Handle* m_currentBlock { nullptr };
70
    MarkedBlock::Handle* m_lastActiveBlock { nullptr };
71
};
72
73
inline ptrdiff_t LocalAllocator::offsetOfFreeList()
74
{
75
    return OBJECT_OFFSETOF(LocalAllocator, m_freeList);
76
}
77
78
inline ptrdiff_t LocalAllocator::offsetOfCellSize()
79
{
80
    return OBJECT_OFFSETOF(LocalAllocator, m_cellSize);
81
}
82
83
} // namespace JSC
84
- a/Source/JavaScriptCore/heap/LocalAllocatorInlines.h -42 lines
Lines 1-42 a/Source/JavaScriptCore/heap/LocalAllocatorInlines.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "LocalAllocator.h"
29
30
namespace JSC {
31
32
ALWAYS_INLINE void* LocalAllocator::allocate(GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
33
{
34
    return m_freeList.allocate(
35
        [&] () -> HeapCell* {
36
            sanitizeStackForVM(m_directory->heap()->vm());
37
            return static_cast<HeapCell*>(allocateSlowCase(deferralContext, failureMode));
38
        });
39
}
40
41
} // namespace JSC
42
- a/Source/JavaScriptCore/heap/MarkedBlock.cpp -9 / +2 lines
Lines 399-413 void MarkedBlock::Handle::sweep(FreeList* freeList) a/Source/JavaScriptCore/heap/MarkedBlock.cpp_sec1
399
    if (sweepMode == SweepOnly && !needsDestruction)
399
    if (sweepMode == SweepOnly && !needsDestruction)
400
        return;
400
        return;
401
401
402
    if (m_isFreeListed) {
402
    RELEASE_ASSERT(!m_isFreeListed);
403
        dataLog("FATAL: ", RawPointer(this), "->sweep: block is free-listed.\n");
403
    RELEASE_ASSERT(!isAllocated());
404
        RELEASE_ASSERT_NOT_REACHED();
405
    }
406
    
407
    if (isAllocated()) {
408
        dataLog("FATAL: ", RawPointer(this), "->sweep: block is allocated.\n");
409
        RELEASE_ASSERT_NOT_REACHED();
410
    }
411
    
404
    
412
    if (space()->isMarking())
405
    if (space()->isMarking())
413
        block().m_lock.lock();
406
        block().m_lock.lock();
- a/Source/JavaScriptCore/heap/MarkedSpace.cpp -10 lines
Lines 302-317 void MarkedSpace::stopAllocating() a/Source/JavaScriptCore/heap/MarkedSpace.cpp_sec1
302
        });
302
        });
303
}
303
}
304
304
305
void MarkedSpace::stopAllocatingForGood()
306
{
307
    ASSERT(!isIterating());
308
    forEachDirectory(
309
        [&] (BlockDirectory& directory) -> IterationStatus {
310
            directory.stopAllocatingForGood();
311
            return IterationStatus::Continue;
312
        });
313
}
314
315
void MarkedSpace::prepareForConservativeScan()
305
void MarkedSpace::prepareForConservativeScan()
316
{
306
{
317
    m_largeAllocationsForThisCollectionBegin = m_largeAllocations.begin() + m_largeAllocationsOffsetForThisCollection;
307
    m_largeAllocationsForThisCollectionBegin = m_largeAllocations.begin() + m_largeAllocationsOffsetForThisCollection;
- a/Source/JavaScriptCore/heap/MarkedSpace.h -2 / +1 lines
Lines 94-100 public: a/Source/JavaScriptCore/heap/MarkedSpace.h_sec1
94
    
94
    
95
    Heap* heap() const { return m_heap; }
95
    Heap* heap() const { return m_heap; }
96
    
96
    
97
    void lastChanceToFinalize(); // Must call stopAllocatingForGood first.
97
    void lastChanceToFinalize(); // You must call stopAllocating before you call this.
98
    void freeMemory();
98
    void freeMemory();
99
99
100
    static size_t optimalSizeFor(size_t);
100
    static size_t optimalSizeFor(size_t);
Lines 111-117 public: a/Source/JavaScriptCore/heap/MarkedSpace.h_sec2
111
    void didFinishIterating();
111
    void didFinishIterating();
112
112
113
    void stopAllocating();
113
    void stopAllocating();
114
    void stopAllocatingForGood();
115
    void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation.
114
    void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation.
116
    
115
    
117
    void prepareForMarking();
116
    void prepareForMarking();
- a/Source/JavaScriptCore/heap/SlotVisitor.cpp -1 lines
Lines 37-43 a/Source/JavaScriptCore/heap/SlotVisitor.cpp_sec1
37
#include "JSObject.h"
37
#include "JSObject.h"
38
#include "JSString.h"
38
#include "JSString.h"
39
#include "JSCInlines.h"
39
#include "JSCInlines.h"
40
#include "MarkingConstraintSolver.h"
41
#include "SlotVisitorInlines.h"
40
#include "SlotVisitorInlines.h"
42
#include "StopIfNecessaryTimer.h"
41
#include "StopIfNecessaryTimer.h"
43
#include "SuperSampler.h"
42
#include "SuperSampler.h"
- a/Source/JavaScriptCore/heap/SlotVisitor.h -2 lines
Lines 31-37 a/Source/JavaScriptCore/heap/SlotVisitor.h_sec1
31
#include "VisitRaceKey.h"
31
#include "VisitRaceKey.h"
32
#include <wtf/Forward.h>
32
#include <wtf/Forward.h>
33
#include <wtf/MonotonicTime.h>
33
#include <wtf/MonotonicTime.h>
34
#include <wtf/SharedTask.h>
35
#include <wtf/text/CString.h>
34
#include <wtf/text/CString.h>
36
35
37
namespace JSC {
36
namespace JSC {
Lines 42-48 class Heap; a/Source/JavaScriptCore/heap/SlotVisitor.h_sec2
42
class HeapCell;
41
class HeapCell;
43
class HeapSnapshotBuilder;
42
class HeapSnapshotBuilder;
44
class MarkedBlock;
43
class MarkedBlock;
45
class MarkingConstraint;
46
class MarkingConstraintSolver;
44
class MarkingConstraintSolver;
47
class UnconditionalFinalizer;
45
class UnconditionalFinalizer;
48
template<typename T> class Weak;
46
template<typename T> class Weak;
- a/Source/JavaScriptCore/heap/Subspace.h -3 / +2 lines
Lines 27-33 a/Source/JavaScriptCore/heap/Subspace.h_sec1
27
27
28
#include "AllocationFailureMode.h"
28
#include "AllocationFailureMode.h"
29
#include "AllocatorForMode.h"
29
#include "AllocatorForMode.h"
30
#include "Allocator.h"
31
#include "MarkedBlock.h"
30
#include "MarkedBlock.h"
32
#include "MarkedSpace.h"
31
#include "MarkedSpace.h"
33
#include <wtf/text/CString.h>
32
#include <wtf/text/CString.h>
Lines 57-64 public: a/Source/JavaScriptCore/heap/Subspace.h_sec2
57
    void finishSweep(MarkedBlock::Handle&, FreeList*);
56
    void finishSweep(MarkedBlock::Handle&, FreeList*);
58
    void destroy(VM&, JSCell*);
57
    void destroy(VM&, JSCell*);
59
58
60
    virtual Allocator allocatorFor(size_t, AllocatorForMode) = 0;
59
    virtual BlockDirectory* allocatorFor(size_t, AllocatorForMode) = 0;
61
    virtual void* allocate(VM&, size_t, GCDeferralContext*, AllocationFailureMode) = 0;
60
    virtual void* allocate(size_t, GCDeferralContext*, AllocationFailureMode) = 0;
62
    
61
    
63
    void prepareForAllocation();
62
    void prepareForAllocation();
64
    
63
    
- a/Source/JavaScriptCore/heap/ThreadLocalCache.cpp -121 lines
Lines 1-121 a/Source/JavaScriptCore/heap/ThreadLocalCache.cpp_sec1
1
/*
2
 * Copyright (C) 2018 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 "ThreadLocalCache.h"
28
29
#include "ThreadLocalCacheInlines.h"
30
#include "ThreadLocalCacheLayout.h"
31
#include <wtf/StdLibExtras.h>
32
33
namespace JSC {
34
35
RefPtr<ThreadLocalCache> ThreadLocalCache::create(Heap& heap)
36
{
37
    return adoptRef(new ThreadLocalCache(heap));
38
}
39
40
ThreadLocalCache::ThreadLocalCache(Heap& heap)
41
    : m_heap(heap)
42
{
43
    m_data = allocateData();
44
}
45
46
ThreadLocalCache::~ThreadLocalCache()
47
{
48
    destroyData(m_data);
49
}
50
51
ThreadLocalCache::Data* ThreadLocalCache::allocateData()
52
{
53
    size_t oldSize = m_data ? m_data->size : 0;
54
    ThreadLocalCacheLayout::Snapshot layout = m_heap.threadLocalCacheLayout().snapshot();
55
    
56
    Data* result = static_cast<Data*>(fastMalloc(OBJECT_OFFSETOF(Data, allocator) + layout.size));
57
    result->size = layout.size;
58
    result->cache = this;
59
    for (size_t offset = 0; offset < oldSize; offset += sizeof(LocalAllocator))
60
        new (&allocator(*result, offset)) LocalAllocator(WTFMove(allocator(*m_data, offset)));
61
    for (size_t offset = oldSize; offset < layout.size; offset += sizeof(LocalAllocator))
62
        new (&allocator(*result, offset)) LocalAllocator(layout.directories[offset / sizeof(LocalAllocator)]);
63
    return result;
64
}
65
66
void ThreadLocalCache::destroyData(Data* data)
67
{
68
    for (size_t offset = 0; offset < data->size; offset += sizeof(LocalAllocator))
69
        allocator(*data, offset).~LocalAllocator();
70
    fastFree(data);
71
}
72
73
void ThreadLocalCache::installSlow(VM& vm)
74
{
75
#if ENABLE(FAST_TLS_JIT)
76
    static std::once_flag onceFlag;
77
    std::call_once(
78
        onceFlag,
79
        [] () {
80
            pthread_key_init_np(tlsKey, destructor);
81
        });
82
#endif
83
    
84
    ref();
85
    
86
    if (RefPtr<ThreadLocalCache> oldCache = get(vm))
87
        oldCache->deref();
88
    
89
    installData(vm, m_data);
90
}
91
92
void ThreadLocalCache::installData(VM& vm, Data* data)
93
{
94
#if ENABLE(FAST_TLS_JIT)
95
    UNUSED_PARAM(vm);
96
    _pthread_setspecific_direct(tlsKey, data);
97
#else
98
    vm.threadLocalCacheData = data;
99
#endif
100
}
101
102
LocalAllocator& ThreadLocalCache::allocatorSlow(VM& vm, size_t offset)
103
{
104
    Data* oldData = m_data;
105
    m_data = allocateData();
106
    destroyData(oldData);
107
    installData(vm, m_data);
108
    RELEASE_ASSERT(offset < m_data->size);
109
    return allocator(*m_data, offset);
110
}
111
112
void ThreadLocalCache::destructor(void* arg)
113
{
114
    if (!arg)
115
        return;
116
    Data* data = static_cast<Data*>(arg);
117
    data->cache->deref();
118
}
119
120
} // namespace JSC
121
- a/Source/JavaScriptCore/heap/ThreadLocalCache.h -101 lines
Lines 1-101 a/Source/JavaScriptCore/heap/ThreadLocalCache.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include <wtf/FastMalloc.h>
29
#include <wtf/FastTLS.h>
30
#include <wtf/ThreadSafeRefCounted.h>
31
32
namespace JSC {
33
34
class Heap;
35
class VM;
36
37
class ThreadLocalCache : public ThreadSafeRefCounted<ThreadLocalCache> {
38
    WTF_MAKE_NONCOPYABLE(ThreadLocalCache);
39
    WTF_MAKE_FAST_ALLOCATED;
40
    
41
public:
42
    static RefPtr<ThreadLocalCache> create(Heap&);
43
    
44
    JS_EXPORT_PRIVATE ~ThreadLocalCache();
45
46
    static RefPtr<ThreadLocalCache> get(VM&);
47
    
48
    // This is designed to be fast enough that you could even call it before every allocation, by
49
    // optimizing for the case that you're just installing the cache that is already installed. This
50
    // assumes a relatively small number of caches or low chance of actual context switch combined
51
    // with possibly high rate of "I may have context switched" sites that call this out of paranoia.
52
    void install(VM&);
53
    
54
    static LocalAllocator& allocator(VM&, size_t offset);
55
    
56
    template<typename SuccessFunc, typename FailureFunc>
57
    static void tryGetAllocator(VM&, size_t offset, const SuccessFunc&, const FailureFunc&);
58
    
59
    static ptrdiff_t offsetOfSizeInData() { return OBJECT_OFFSETOF(Data, size); }
60
    static ptrdiff_t offsetOfFirstAllocatorInData() { return OBJECT_OFFSETOF(Data, allocator); }
61
    
62
private:
63
    friend class VM;
64
    
65
    ThreadLocalCache(Heap&);
66
    
67
    struct Data {
68
        size_t size;
69
        ThreadLocalCache* cache;
70
        LocalAllocator allocator[1];
71
    };
72
73
    static Data* getImpl(VM&);
74
    
75
    Data* allocateData();
76
    void destroyData(Data*);
77
    static LocalAllocator& allocator(Data& data, size_t offset);
78
79
    void installSlow(VM&);
80
    static void installData(VM&, Data*);
81
    
82
    LocalAllocator& allocatorSlow(VM&, size_t offset);
83
    
84
    static void destructor(void*);
85
    
86
    // When installed, we ref() the cache. Uninstalling deref()s the cache. TLS destruction deref()s
87
    // the cache. When the cache is destructed, it needs to return all of its state to the GC. I
88
    // think that just means stopAllocating(), but with some seriously heavy caveats having to do
89
    // with when it's valid to make that call. Alternatively, we could RELEASE_ASSERT that the cache
90
    // is empty when we destruct it. This is correct for caches that are kept live by GC objects and
91
    // it's correct for immortal caches.
92
    Heap& m_heap;
93
    Data* m_data { nullptr };
94
95
#if ENABLE(FAST_TLS_JIT)
96
    static const pthread_key_t tlsKey = WTF_GC_TLC_KEY;
97
#endif
98
};
99
100
} // namespace JSC
101
- a/Source/JavaScriptCore/heap/ThreadLocalCacheInlines.h -81 lines
Lines 1-81 a/Source/JavaScriptCore/heap/ThreadLocalCacheInlines.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "ThreadLocalCache.h"
29
30
namespace JSC {
31
32
inline ThreadLocalCache::Data* ThreadLocalCache::getImpl(VM& vm)
33
{
34
#if ENABLE(FAST_TLS_JIT)
35
    UNUSED_PARAM(vm);
36
    return static_cast<Data*>(_pthread_getspecific_direct(tlsKey));
37
#else
38
    return vm.threadLocalCacheData;
39
#endif
40
}
41
42
inline RefPtr<ThreadLocalCache> ThreadLocalCache::get(VM& vm)
43
{
44
    ThreadLocalCache::Data* data = getImpl(vm);
45
    if (LIKELY(data))
46
        return data->cache;
47
    return nullptr;
48
}
49
50
inline void ThreadLocalCache::install(VM& vm)
51
{
52
    if (getImpl(vm) == m_data)
53
        return;
54
    installSlow(vm);
55
}
56
57
inline LocalAllocator& ThreadLocalCache::allocator(VM& vm, size_t offset)
58
{
59
    ThreadLocalCache::Data* data = getImpl(vm);
60
    if (LIKELY(offset < data->size))
61
        return allocator(*data, offset);
62
    return data->cache->allocatorSlow(vm, offset);
63
}
64
65
template<typename SuccessFunc, typename FailureFunc>
66
void ThreadLocalCache::tryGetAllocator(VM& vm, size_t offset, const SuccessFunc& successFunc, const FailureFunc& failureFunc)
67
{
68
    ThreadLocalCache::Data* data = getImpl(vm);
69
    if (LIKELY(offset < data->size))
70
        successFunc(allocator(*data, offset));
71
    else
72
        failureFunc();
73
}
74
75
inline LocalAllocator& ThreadLocalCache::allocator(Data& data, size_t offset)
76
{
77
    return *bitwise_cast<LocalAllocator*>(bitwise_cast<char*>(&data.allocator[0]) + offset);
78
}
79
80
} // namespace JSC
81
- a/Source/JavaScriptCore/heap/ThreadLocalCacheLayout.cpp -65 lines
Lines 1-65 a/Source/JavaScriptCore/heap/ThreadLocalCacheLayout.cpp_sec1
1
/*
2
 * Copyright (C) 2018 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 "ThreadLocalCacheLayout.h"
28
29
#include "BlockDirectory.h"
30
31
namespace JSC {
32
33
ThreadLocalCacheLayout::ThreadLocalCacheLayout()
34
{
35
}
36
37
ThreadLocalCacheLayout::~ThreadLocalCacheLayout()
38
{
39
}
40
41
void ThreadLocalCacheLayout::allocateOffset(BlockDirectory* directory)
42
{
43
    auto locker = holdLock(m_lock);
44
    directory->m_tlcOffset = m_size;
45
    m_size += sizeof(LocalAllocator);
46
    m_directories.append(directory);
47
}
48
49
ThreadLocalCacheLayout::Snapshot ThreadLocalCacheLayout::snapshot()
50
{
51
    auto locker = holdLock(m_lock);
52
    Snapshot result;
53
    result.size = m_size;
54
    result.directories = m_directories;
55
    return result;
56
}
57
58
BlockDirectory* ThreadLocalCacheLayout::directory(unsigned offset)
59
{
60
    auto locker = holdLock(m_lock);
61
    return m_directories[offset / sizeof(LocalAllocator)];
62
}
63
64
} // namespace JSC
65
- a/Source/JavaScriptCore/heap/ThreadLocalCacheLayout.h -67 lines
Lines 1-67 a/Source/JavaScriptCore/heap/ThreadLocalCacheLayout.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include <wtf/FastMalloc.h>
29
#include <wtf/Lock.h>
30
#include <wtf/Noncopyable.h>
31
#include <wtf/Vector.h>
32
33
namespace JSC {
34
35
class BlockDirectory;
36
37
// Each Heap has a ThreadLocalCacheLayout that helps us figure out how to allocate a ThreadLocalCache
38
// for that Heap.
39
40
class ThreadLocalCacheLayout {
41
    WTF_MAKE_NONCOPYABLE(ThreadLocalCacheLayout);
42
    WTF_MAKE_FAST_ALLOCATED;
43
    
44
public:
45
    ThreadLocalCacheLayout();
46
    ~ThreadLocalCacheLayout();
47
48
    // BlockDirectory calls this during creation and this fills in BlockDirectory::offset.
49
    void allocateOffset(BlockDirectory*);
50
    
51
    struct Snapshot {
52
        size_t size;
53
        Vector<BlockDirectory*> directories;
54
    };
55
    
56
    Snapshot snapshot();
57
    
58
    BlockDirectory* directory(unsigned offset);
59
    
60
private:
61
    Lock m_lock;
62
    size_t m_size { 0 };
63
    Vector<BlockDirectory*> m_directories;
64
};
65
66
} // namespace JSC
67
- a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp -98 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2011-2017 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 582-684 void AssemblyHelpers::emitRandomThunk(VM& vm, GPRReg scratch0, GPRReg scratch1, a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp_sec2
582
}
582
}
583
#endif
583
#endif
584
584
585
void AssemblyHelpers::emitAllocateWithNonNullAllocator(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath)
586
{
587
    // NOTE: This is carefully written so that we can call it while we disallow scratch
588
    // register usage.
589
        
590
    if (Options::forceGCSlowPaths()) {
591
        slowPath.append(jump());
592
        return;
593
    }
594
    
595
    Jump popPath;
596
    Jump done;
597
    
598
#if ENABLE(FAST_TLS_JIT)
599
    loadFromTLSPtr(fastTLSOffsetForKey(WTF_GC_TLC_KEY), scratchGPR);
600
#else
601
    loadPtr(&vm().threadLocalCacheData, scratchGPR);
602
#endif
603
    if (allocator.isConstant()) {
604
        slowPath.append(branch32(BelowOrEqual, Address(scratchGPR, ThreadLocalCache::offsetOfSizeInData()), TrustedImm32(allocator.allocator().offset())));
605
        addPtr(TrustedImm32(ThreadLocalCache::offsetOfFirstAllocatorInData() + allocator.allocator().offset()), scratchGPR, allocatorGPR);
606
    } else {
607
        slowPath.append(branch32(BelowOrEqual, Address(scratchGPR, ThreadLocalCache::offsetOfSizeInData()), allocatorGPR));
608
        addPtr(TrustedImm32(ThreadLocalCache::offsetOfFirstAllocatorInData()), allocatorGPR);
609
        addPtr(scratchGPR, allocatorGPR);
610
    }
611
612
    load32(Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfRemaining()), resultGPR);
613
    popPath = branchTest32(Zero, resultGPR);
614
    if (allocator.isConstant())
615
        add32(TrustedImm32(-allocator.allocator().cellSize(vm().heap)), resultGPR, scratchGPR);
616
    else {
617
        if (isX86()) {
618
            move(resultGPR, scratchGPR);
619
            sub32(Address(allocatorGPR, LocalAllocator::offsetOfCellSize()), scratchGPR);
620
        } else {
621
            load32(Address(allocatorGPR, LocalAllocator::offsetOfCellSize()), scratchGPR);
622
            sub32(resultGPR, scratchGPR, scratchGPR);
623
        }
624
    }
625
    negPtr(resultGPR);
626
    store32(scratchGPR, Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfRemaining()));
627
    Address payloadEndAddr = Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfPayloadEnd());
628
    if (isX86())
629
        addPtr(payloadEndAddr, resultGPR);
630
    else {
631
        loadPtr(payloadEndAddr, scratchGPR);
632
        addPtr(scratchGPR, resultGPR);
633
    }
634
        
635
    done = jump();
636
        
637
    popPath.link(this);
638
        
639
    loadPtr(Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfScrambledHead()), resultGPR);
640
    if (isX86())
641
        xorPtr(Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfSecret()), resultGPR);
642
    else {
643
        loadPtr(Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfSecret()), scratchGPR);
644
        xorPtr(scratchGPR, resultGPR);
645
    }
646
    slowPath.append(branchTestPtr(Zero, resultGPR));
647
        
648
    // The object is half-allocated: we have what we know is a fresh object, but
649
    // it's still on the GC's free list.
650
    loadPtr(Address(resultGPR), scratchGPR);
651
    storePtr(scratchGPR, Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfScrambledHead()));
652
        
653
    done.link(this);
654
}
655
656
void AssemblyHelpers::emitAllocate(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath)
657
{
658
    if (allocator.isConstant()) {
659
        if (!allocator.allocator()) {
660
            slowPath.append(jump());
661
            return;
662
        }
663
    }
664
    emitAllocateWithNonNullAllocator(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath);
665
}
666
667
void AssemblyHelpers::emitAllocateVariableSized(GPRReg resultGPR, CompleteSubspace& subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath)
668
{
669
    static_assert(!(MarkedSpace::sizeStep & (MarkedSpace::sizeStep - 1)), "MarkedSpace::sizeStep must be a power of two.");
670
    
671
    unsigned stepShift = getLSBSet(MarkedSpace::sizeStep);
672
    
673
    add32(TrustedImm32(MarkedSpace::sizeStep - 1), allocationSize, scratchGPR1);
674
    urshift32(TrustedImm32(stepShift), scratchGPR1);
675
    slowPath.append(branch32(Above, scratchGPR1, TrustedImm32(MarkedSpace::largeCutoff >> stepShift)));
676
    move(TrustedImmPtr(subspace.allocatorForSizeStep() - 1), scratchGPR2);
677
    load32(BaseIndex(scratchGPR2, scratchGPR1, TimesFour), scratchGPR1);
678
    
679
    emitAllocate(resultGPR, JITAllocator::variable(), scratchGPR1, scratchGPR2, slowPath);
680
}
681
682
void AssemblyHelpers::restoreCalleeSavesFromEntryFrameCalleeSavesBuffer(EntryFrame*& topEntryFrame)
585
void AssemblyHelpers::restoreCalleeSavesFromEntryFrameCalleeSavesBuffer(EntryFrame*& topEntryFrame)
683
{
586
{
684
#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
587
#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
- a/Source/JavaScriptCore/jit/AssemblyHelpers.h -12 / +87 lines
Lines 1-5 a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2011-2017 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 32-38 a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec2
32
#include "GPRInfo.h"
32
#include "GPRInfo.h"
33
#include "Heap.h"
33
#include "Heap.h"
34
#include "InlineCallFrame.h"
34
#include "InlineCallFrame.h"
35
#include "JITAllocator.h"
36
#include "JITCode.h"
35
#include "JITCode.h"
37
#include "MacroAssembler.h"
36
#include "MacroAssembler.h"
38
#include "MarkedSpace.h"
37
#include "MarkedSpace.h"
Lines 60-66 public: a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec3
60
    }
59
    }
61
60
62
    CodeBlock* codeBlock() { return m_codeBlock; }
61
    CodeBlock* codeBlock() { return m_codeBlock; }
63
    VM& vm() { return *m_codeBlock->vm(); }
64
    AssemblerType_T& assembler() { return m_assembler; }
62
    AssemblerType_T& assembler() { return m_assembler; }
65
63
66
    void checkStackPointerAlignment()
64
    void checkStackPointerAlignment()
Lines 1493-1513 public: a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec4
1493
1491
1494
    // Call this if you know that the value held in allocatorGPR is non-null. This DOES NOT mean
1492
    // Call this if you know that the value held in allocatorGPR is non-null. This DOES NOT mean
1495
    // that allocator is non-null; allocator can be null as a signal that we don't know what the
1493
    // that allocator is non-null; allocator can be null as a signal that we don't know what the
1496
    // value of allocatorGPR is. Additionally, if the allocator is not null, then there is no need
1494
    // value of allocatorGPR is.
1497
    // to populate allocatorGPR - this code will ignore the contents of allocatorGPR.
1495
    void emitAllocateWithNonNullAllocator(GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath)
1498
    void emitAllocateWithNonNullAllocator(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath);
1496
    {
1497
        // NOTE: This is carefully written so that we can call it while we disallow scratch
1498
        // register usage.
1499
        
1500
        if (Options::forceGCSlowPaths()) {
1501
            slowPath.append(jump());
1502
            return;
1503
        }
1504
        
1505
        Jump popPath;
1506
        Jump done;
1507
        
1508
        load32(Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfRemaining()), resultGPR);
1509
        popPath = branchTest32(Zero, resultGPR);
1510
        if (allocator)
1511
            add32(TrustedImm32(-allocator->cellSize()), resultGPR, scratchGPR);
1512
        else {
1513
            if (isX86()) {
1514
                move(resultGPR, scratchGPR);
1515
                sub32(Address(allocatorGPR, BlockDirectory::offsetOfCellSize()), scratchGPR);
1516
            } else {
1517
                load32(Address(allocatorGPR, BlockDirectory::offsetOfCellSize()), scratchGPR);
1518
                sub32(resultGPR, scratchGPR, scratchGPR);
1519
            }
1520
        }
1521
        negPtr(resultGPR);
1522
        store32(scratchGPR, Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfRemaining()));
1523
        Address payloadEndAddr = Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfPayloadEnd());
1524
        if (isX86())
1525
            addPtr(payloadEndAddr, resultGPR);
1526
        else {
1527
            loadPtr(payloadEndAddr, scratchGPR);
1528
            addPtr(scratchGPR, resultGPR);
1529
        }
1530
        
1531
        done = jump();
1532
        
1533
        popPath.link(this);
1534
        
1535
        loadPtr(Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfScrambledHead()), resultGPR);
1536
        if (isX86())
1537
            xorPtr(Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfSecret()), resultGPR);
1538
        else {
1539
            loadPtr(Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfSecret()), scratchGPR);
1540
            xorPtr(scratchGPR, resultGPR);
1541
        }
1542
        slowPath.append(branchTestPtr(Zero, resultGPR));
1543
        
1544
        // The object is half-allocated: we have what we know is a fresh object, but
1545
        // it's still on the GC's free list.
1546
        loadPtr(Address(resultGPR), scratchGPR);
1547
        storePtr(scratchGPR, Address(allocatorGPR, BlockDirectory::offsetOfFreeList() + FreeList::offsetOfScrambledHead()));
1548
        
1549
        done.link(this);
1550
    }
1499
    
1551
    
1500
    void emitAllocate(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath);
1552
    void emitAllocate(GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath)
1553
    {
1554
        if (!allocator)
1555
            slowPath.append(branchTestPtr(Zero, allocatorGPR));
1556
        emitAllocateWithNonNullAllocator(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath);
1557
    }
1501
    
1558
    
1502
    template<typename StructureType>
1559
    template<typename StructureType>
1503
    void emitAllocateJSCell(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure, GPRReg scratchGPR, JumpList& slowPath)
1560
    void emitAllocateJSCell(GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, StructureType structure, GPRReg scratchGPR, JumpList& slowPath)
1504
    {
1561
    {
1505
        emitAllocate(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath);
1562
        emitAllocate(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath);
1506
        emitStoreStructureWithTypeInfo(structure, resultGPR, scratchGPR);
1563
        emitStoreStructureWithTypeInfo(structure, resultGPR, scratchGPR);
1507
    }
1564
    }
1508
    
1565
    
1509
    template<typename StructureType, typename StorageType, typename MaskType>
1566
    template<typename StructureType, typename StorageType, typename MaskType>
1510
    void emitAllocateJSObject(GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure, StorageType storage, MaskType mask, GPRReg scratchGPR, JumpList& slowPath)
1567
    void emitAllocateJSObject(GPRReg resultGPR, BlockDirectory* allocator, GPRReg allocatorGPR, StructureType structure, StorageType storage, MaskType mask, GPRReg scratchGPR, JumpList& slowPath)
1511
    {
1568
    {
1512
        emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
1569
        emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
1513
        storePtr(storage, Address(resultGPR, JSObject::butterflyOffset()));
1570
        storePtr(storage, Address(resultGPR, JSObject::butterflyOffset()));
Lines 1519-1526 public: a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec5
1519
        VM& vm, GPRReg resultGPR, StructureType structure, StorageType storage, MaskType mask, GPRReg scratchGPR1,
1576
        VM& vm, GPRReg resultGPR, StructureType structure, StorageType storage, MaskType mask, GPRReg scratchGPR1,
1520
        GPRReg scratchGPR2, JumpList& slowPath, size_t size)
1577
        GPRReg scratchGPR2, JumpList& slowPath, size_t size)
1521
    {
1578
    {
1522
        Allocator allocator = subspaceFor<ClassType>(vm)->allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
1579
        BlockDirectory* allocator = subspaceFor<ClassType>(vm)->allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists);
1523
        emitAllocateJSObject(resultGPR, JITAllocator::constant(allocator), scratchGPR1, structure, storage, mask, scratchGPR2, slowPath);
1580
        if (!allocator) {
1581
            slowPath.append(jump());
1582
            return;
1583
        }
1584
        move(TrustedImmPtr(allocator), scratchGPR1);
1585
        emitAllocateJSObject(resultGPR, allocator, scratchGPR1, structure, storage, mask, scratchGPR2, slowPath);
1524
    }
1586
    }
1525
    
1587
    
1526
    template<typename ClassType, typename StructureType, typename StorageType, typename MaskType>
1588
    template<typename ClassType, typename StructureType, typename StorageType, typename MaskType>
Lines 1531-1537 public: a/Source/JavaScriptCore/jit/AssemblyHelpers.h_sec6
1531
    
1593
    
1532
    // allocationSize can be aliased with any of the other input GPRs. If it's not aliased then it
1594
    // allocationSize can be aliased with any of the other input GPRs. If it's not aliased then it
1533
    // won't be clobbered.
1595
    // won't be clobbered.
1534
    void emitAllocateVariableSized(GPRReg resultGPR, CompleteSubspace& subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath);
1596
    void emitAllocateVariableSized(GPRReg resultGPR, CompleteSubspace& subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath)
1597
    {
1598
        static_assert(!(MarkedSpace::sizeStep & (MarkedSpace::sizeStep - 1)), "MarkedSpace::sizeStep must be a power of two.");
1599
        
1600
        unsigned stepShift = getLSBSet(MarkedSpace::sizeStep);
1601
        
1602
        add32(TrustedImm32(MarkedSpace::sizeStep - 1), allocationSize, scratchGPR1);
1603
        urshift32(TrustedImm32(stepShift), scratchGPR1);
1604
        slowPath.append(branch32(Above, scratchGPR1, TrustedImm32(MarkedSpace::largeCutoff >> stepShift)));
1605
        move(TrustedImmPtr(subspace.allocatorForSizeStep() - 1), scratchGPR2);
1606
        loadPtr(BaseIndex(scratchGPR2, scratchGPR1, timesPtr()), scratchGPR1);
1607
        
1608
        emitAllocate(resultGPR, nullptr, scratchGPR1, scratchGPR2, slowPath);
1609
    }
1535
    
1610
    
1536
    template<typename ClassType, typename StructureType>
1611
    template<typename ClassType, typename StructureType>
1537
    void emitAllocateVariableSizedCell(VM& vm, GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath)
1612
    void emitAllocateVariableSizedCell(VM& vm, GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath)
- a/Source/JavaScriptCore/jit/JITAllocator.h -88 lines
Lines 1-88 a/Source/JavaScriptCore/jit/JITAllocator.h_sec1
1
/*
2
 * Copyright (C) 2018 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
#pragma once
27
28
#include "Allocator.h"
29
30
namespace JSC {
31
32
class JITAllocator {
33
public:
34
    enum Kind {
35
        Constant,
36
        Variable
37
    };
38
    
39
    JITAllocator() { }
40
    
41
    static JITAllocator constant(Allocator allocator)
42
    {
43
        JITAllocator result;
44
        result.m_kind = Constant;
45
        result.m_allocator = allocator;
46
        return result;
47
    }
48
    
49
    static JITAllocator variable()
50
    {
51
        JITAllocator result;
52
        result.m_kind = Variable;
53
        return result;
54
    }
55
    
56
    bool operator==(const JITAllocator& other) const
57
    {
58
        return m_kind == other.m_kind
59
            && m_allocator == other.m_allocator;
60
    }
61
    
62
    bool operator!=(const JITAllocator& other) const
63
    {
64
        return !(*this == other);
65
    }
66
    
67
    explicit operator bool() const
68
    {
69
        return *this != JITAllocator();
70
    }
71
    
72
    Kind kind() const { return m_kind; }
73
    bool isConstant() const { return m_kind == Constant; }
74
    bool isVariable() const { return m_kind == Variable; }
75
    
76
    Allocator allocator() const
77
    {
78
        RELEASE_ASSERT(isConstant());
79
        return m_allocator;
80
    }
81
    
82
private:
83
    Kind m_kind { Constant };
84
    Allocator m_allocator;
85
};
86
87
} // namespace JSC
88
- a/Source/JavaScriptCore/jit/JITOpcodes.cpp -16 / +15 lines
Lines 1-5 a/Source/JavaScriptCore/jit/JITOpcodes.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
3
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
3
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
Lines 81-103 void JIT::emit_op_new_object(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes.cpp_sec2
81
{
81
{
82
    Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
82
    Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
83
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
83
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
84
    Allocator allocator = subspaceFor<JSFinalObject>(*m_vm)->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
84
    BlockDirectory* allocator = subspaceFor<JSFinalObject>(*m_vm)->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
85
85
86
    RegisterID resultReg = regT0;
86
    RegisterID resultReg = regT0;
87
    RegisterID allocatorReg = regT1;
87
    RegisterID allocatorReg = regT1;
88
    RegisterID scratchReg = regT2;
88
    RegisterID scratchReg = regT2;
89
89
90
    if (!allocator)
90
    move(TrustedImmPtr(allocator), allocatorReg);
91
        addSlowCase(jump());
91
    if (allocator)
92
    else {
92
        addSlowCase(Jump());
93
        JumpList slowCases;
93
    JumpList slowCases;
94
        auto butterfly = TrustedImmPtr(nullptr);
94
    auto butterfly = TrustedImmPtr(nullptr);
95
        auto mask = TrustedImm32(0);
95
    auto mask = TrustedImm32(0);
96
        emitAllocateJSObject(resultReg, JITAllocator::constant(allocator), allocatorReg, TrustedImmPtr(structure), butterfly, mask, scratchReg, slowCases);
96
    emitAllocateJSObject(resultReg, allocator, allocatorReg, TrustedImmPtr(structure), butterfly, mask, scratchReg, slowCases);
97
        emitInitializeInlineStorage(resultReg, structure->inlineCapacity());
97
    emitInitializeInlineStorage(resultReg, structure->inlineCapacity());
98
        addSlowCase(slowCases);
98
    addSlowCase(slowCases);
99
        emitPutVirtualRegister(currentInstruction[1].u.operand);
99
    emitPutVirtualRegister(currentInstruction[1].u.operand);
100
    }
101
}
100
}
102
101
103
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
102
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
Lines 767-775 void JIT::emit_op_create_this(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes.cpp_sec3
767
    addSlowCase(branch8(NotEqual, Address(calleeReg, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
766
    addSlowCase(branch8(NotEqual, Address(calleeReg, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
768
    loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
767
    loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
769
    addSlowCase(branchTestPtr(Zero, rareDataReg));
768
    addSlowCase(branchTestPtr(Zero, rareDataReg));
770
    load32(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
769
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
771
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
770
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
772
    addSlowCase(branch32(Equal, allocatorReg, TrustedImm32(Allocator().offset())));
771
    addSlowCase(branchTestPtr(Zero, allocatorReg));
773
772
774
    loadPtr(cachedFunction, cachedFunctionReg);
773
    loadPtr(cachedFunction, cachedFunctionReg);
775
    Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
774
    Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
Lines 779-785 void JIT::emit_op_create_this(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes.cpp_sec4
779
    JumpList slowCases;
778
    JumpList slowCases;
780
    auto butterfly = TrustedImmPtr(nullptr);
779
    auto butterfly = TrustedImmPtr(nullptr);
781
    auto mask = TrustedImm32(0);
780
    auto mask = TrustedImm32(0);
782
    emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, mask, scratchReg, slowCases);
781
    emitAllocateJSObject(resultReg, nullptr, allocatorReg, structureReg, butterfly, mask, scratchReg, slowCases);
783
    emitGetVirtualRegister(callee, scratchReg);
782
    emitGetVirtualRegister(callee, scratchReg);
784
    loadPtr(Address(scratchReg, JSFunction::offsetOfRareData()), scratchReg);
783
    loadPtr(Address(scratchReg, JSFunction::offsetOfRareData()), scratchReg);
785
    load32(Address(scratchReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), scratchReg);
784
    load32(Address(scratchReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfInlineCapacity()), scratchReg);
- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp -16 / +15 lines
Lines 1-5 a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
3
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
3
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
Lines 79-101 void JIT::emit_op_new_object(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp_sec2
79
{
79
{
80
    Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
80
    Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
81
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
81
    size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
82
    Allocator allocator = subspaceFor<JSFinalObject>(*m_vm)->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
82
    BlockDirectory* allocator = subspaceFor<JSFinalObject>(*m_vm)->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
83
83
84
    RegisterID resultReg = returnValueGPR;
84
    RegisterID resultReg = returnValueGPR;
85
    RegisterID allocatorReg = regT1;
85
    RegisterID allocatorReg = regT1;
86
    RegisterID scratchReg = regT3;
86
    RegisterID scratchReg = regT3;
87
87
88
    if (!allocator)
88
    move(TrustedImmPtr(allocator), allocatorReg);
89
        addSlowCase(jump());
89
    if (allocator)
90
    else {
90
        addSlowCase(Jump());
91
        JumpList slowCases;
91
    JumpList slowCases;
92
        auto butterfly = TrustedImmPtr(nullptr);
92
    auto butterfly = TrustedImmPtr(nullptr);
93
        auto mask = TrustedImm32(0);
93
    auto mask = TrustedImm32(0);
94
        emitAllocateJSObject(resultReg, JITAllocator::constant(allocator), allocatorReg, TrustedImmPtr(structure), butterfly, mask, scratchReg, slowCases);
94
    emitAllocateJSObject(resultReg, allocator, allocatorReg, TrustedImmPtr(structure), butterfly, mask, scratchReg, slowCases);
95
        emitInitializeInlineStorage(resultReg, structure->inlineCapacity());
95
    emitInitializeInlineStorage(resultReg, structure->inlineCapacity());
96
        addSlowCase(slowCases);
96
    addSlowCase(slowCases);
97
        emitStoreCell(currentInstruction[1].u.operand, resultReg);
97
    emitStoreCell(currentInstruction[1].u.operand, resultReg);
98
    }
99
}
98
}
100
99
101
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
100
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
Lines 857-865 void JIT::emit_op_create_this(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp_sec3
857
    addSlowCase(branch8(NotEqual, Address(calleeReg, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
856
    addSlowCase(branch8(NotEqual, Address(calleeReg, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
858
    loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
857
    loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
859
    addSlowCase(branchTestPtr(Zero, rareDataReg));
858
    addSlowCase(branchTestPtr(Zero, rareDataReg));
860
    load32(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
859
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
861
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
860
    loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
862
    addSlowCase(branch32(Equal, allocatorReg, TrustedImm32(Allocator().offset())));
861
    addSlowCase(branchTestPtr(Zero, allocatorReg));
863
862
864
    loadPtr(cachedFunction, cachedFunctionReg);
863
    loadPtr(cachedFunction, cachedFunctionReg);
865
    Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
864
    Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
Lines 869-875 void JIT::emit_op_create_this(Instruction* currentInstruction) a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp_sec4
869
    JumpList slowCases;
868
    JumpList slowCases;
870
    auto butterfly = TrustedImmPtr(nullptr);
869
    auto butterfly = TrustedImmPtr(nullptr);
871
    auto mask = TrustedImm32(0);
870
    auto mask = TrustedImm32(0);
872
    emitAllocateJSObject(resultReg, JITAllocator::variable(), allocatorReg, structureReg, butterfly, mask, scratchReg, slowCases);
871
    emitAllocateJSObject(resultReg, nullptr, allocatorReg, structureReg, butterfly, mask, scratchReg, slowCases);
873
    addSlowCase(slowCases);
872
    addSlowCase(slowCases);
874
    emitStoreCell(currentInstruction[1].u.operand, resultReg);
873
    emitStoreCell(currentInstruction[1].u.operand, resultReg);
875
}
874
}
- a/Source/JavaScriptCore/runtime/ButterflyInlines.h -3 / +3 lines
Lines 79-85 ALWAYS_INLINE unsigned Butterfly::optimalContiguousVectorLength(Structure* struc a/Source/JavaScriptCore/runtime/ButterflyInlines.h_sec1
79
inline Butterfly* Butterfly::createUninitialized(VM& vm, JSCell*, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
79
inline Butterfly* Butterfly::createUninitialized(VM& vm, JSCell*, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
80
{
80
{
81
    size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes);
81
    size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes);
82
    void* base = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, size, nullptr, AllocationFailureMode::Assert);
82
    void* base = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(size, nullptr, AllocationFailureMode::Assert);
83
    Butterfly* result = fromBase(base, preCapacity, propertyCapacity);
83
    Butterfly* result = fromBase(base, preCapacity, propertyCapacity);
84
    return result;
84
    return result;
85
}
85
}
Lines 87-93 inline Butterfly* Butterfly::createUninitialized(VM& vm, JSCell*, size_t preCapa a/Source/JavaScriptCore/runtime/ButterflyInlines.h_sec2
87
inline Butterfly* Butterfly::tryCreate(VM& vm, JSCell*, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes)
87
inline Butterfly* Butterfly::tryCreate(VM& vm, JSCell*, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes)
88
{
88
{
89
    size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes);
89
    size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes);
90
    void* base = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, size, nullptr, AllocationFailureMode::ReturnNull);
90
    void* base = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(size, nullptr, AllocationFailureMode::ReturnNull);
91
    if (!base)
91
    if (!base)
92
        return nullptr;
92
        return nullptr;
93
    Butterfly* result = fromBase(base, preCapacity, propertyCapacity);
93
    Butterfly* result = fromBase(base, preCapacity, propertyCapacity);
Lines 165-171 inline Butterfly* Butterfly::growArrayRight( a/Source/JavaScriptCore/runtime/ButterflyInlines.h_sec3
165
    void* theBase = base(0, propertyCapacity);
165
    void* theBase = base(0, propertyCapacity);
166
    size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes);
166
    size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes);
167
    size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes);
167
    size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes);
168
    void* newBase = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, newSize, nullptr, AllocationFailureMode::ReturnNull);
168
    void* newBase = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(newSize, nullptr, AllocationFailureMode::ReturnNull);
169
    if (!newBase)
169
    if (!newBase)
170
        return nullptr;
170
        return nullptr;
171
    // FIXME: This probably shouldn't be a memcpy.
171
    // FIXME: This probably shouldn't be a memcpy.
- a/Source/JavaScriptCore/runtime/DirectArguments.cpp -2 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/DirectArguments.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2017 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 118-124 void DirectArguments::overrideThings(VM& vm) a/Source/JavaScriptCore/runtime/DirectArguments.cpp_sec2
118
    putDirect(vm, vm.propertyNames->callee, m_callee.get(), static_cast<unsigned>(PropertyAttribute::DontEnum));
118
    putDirect(vm, vm.propertyNames->callee, m_callee.get(), static_cast<unsigned>(PropertyAttribute::DontEnum));
119
    putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
119
    putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
120
    
120
    
121
    void* backingStore = vm.gigacageAuxiliarySpace(m_mappedArguments.kind).allocateNonVirtual(vm, mappedArgumentsSize(), nullptr, AllocationFailureMode::Assert);
121
    void* backingStore = vm.gigacageAuxiliarySpace(m_mappedArguments.kind).allocateNonVirtual(mappedArgumentsSize(), nullptr, AllocationFailureMode::Assert);
122
    bool* overrides = static_cast<bool*>(backingStore);
122
    bool* overrides = static_cast<bool*>(backingStore);
123
    m_mappedArguments.set(vm, this, overrides);
123
    m_mappedArguments.set(vm, this, overrides);
124
    for (unsigned i = m_length; i--;)
124
    for (unsigned i = m_length; i--;)
- a/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h -2 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2015-2017 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 263-269 void GenericArguments<Type>::initModifiedArgumentsDescriptor(VM& vm, unsigned ar a/Source/JavaScriptCore/runtime/GenericArgumentsInlines.h_sec2
263
    RELEASE_ASSERT(!m_modifiedArgumentsDescriptor);
263
    RELEASE_ASSERT(!m_modifiedArgumentsDescriptor);
264
264
265
    if (argsLength) {
265
    if (argsLength) {
266
        void* backingStore = vm.gigacageAuxiliarySpace(m_modifiedArgumentsDescriptor.kind).allocateNonVirtual(vm, WTF::roundUpToMultipleOf<8>(argsLength), nullptr, AllocationFailureMode::Assert);
266
        void* backingStore = vm.gigacageAuxiliarySpace(m_modifiedArgumentsDescriptor.kind).allocateNonVirtual(WTF::roundUpToMultipleOf<8>(argsLength), nullptr, AllocationFailureMode::Assert);
267
        bool* modifiedArguments = static_cast<bool*>(backingStore);
267
        bool* modifiedArguments = static_cast<bool*>(backingStore);
268
        m_modifiedArgumentsDescriptor.set(vm, this, modifiedArguments);
268
        m_modifiedArgumentsDescriptor.set(vm, this, modifiedArguments);
269
        for (unsigned i = argsLength; i--;)
269
        for (unsigned i = argsLength; i--;)
- a/Source/JavaScriptCore/runtime/HashMapImpl.h -2 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/HashMapImpl.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2016-2017 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 207-213 public: a/Source/JavaScriptCore/runtime/HashMapImpl.h_sec2
207
    {
207
    {
208
        auto scope = DECLARE_THROW_SCOPE(vm);
208
        auto scope = DECLARE_THROW_SCOPE(vm);
209
        size_t allocationSize = HashMapBuffer::allocationSize(capacity);
209
        size_t allocationSize = HashMapBuffer::allocationSize(capacity);
210
        void* data = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, allocationSize, nullptr, AllocationFailureMode::ReturnNull);
210
        void* data = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(allocationSize, nullptr, AllocationFailureMode::ReturnNull);
211
        if (!data) {
211
        if (!data) {
212
            throwOutOfMemoryError(exec, scope);
212
            throwOutOfMemoryError(exec, scope);
213
            return nullptr;
213
            return nullptr;
- a/Source/JavaScriptCore/runtime/JSArray.cpp -11 / +4 lines
Lines 1-6 a/Source/JavaScriptCore/runtime/JSArray.cpp_sec1
1
/*
1
/*
2
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
2
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3
 *  Copyright (C) 2003-2018 Apple Inc. All rights reserved.
3
 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
4
 *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
4
 *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
5
 *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
5
 *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
6
 *
6
 *
Lines 81-90 JSArray* JSArray::tryCreateUninitializedRestricted(ObjectInitializationScope& sc a/Source/JavaScriptCore/runtime/JSArray.cpp_sec2
81
            || hasContiguous(indexingType));
81
            || hasContiguous(indexingType));
82
82
83
        unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
83
        unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
84
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
84
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)), deferralContext, AllocationFailureMode::ReturnNull);
85
            vm,
86
            Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)),
87
            deferralContext, AllocationFailureMode::ReturnNull);
88
        if (UNLIKELY(!temp))
85
        if (UNLIKELY(!temp))
89
            return nullptr;
86
            return nullptr;
90
        butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
87
        butterfly = Butterfly::fromBase(temp, 0, outOfLineStorage);
Lines 101-110 JSArray* JSArray::tryCreateUninitializedRestricted(ObjectInitializationScope& sc a/Source/JavaScriptCore/runtime/JSArray.cpp_sec3
101
    } else {
98
    } else {
102
        static const unsigned indexBias = 0;
99
        static const unsigned indexBias = 0;
103
        unsigned vectorLength = ArrayStorage::optimalVectorLength(indexBias, structure, initialLength);
100
        unsigned vectorLength = ArrayStorage::optimalVectorLength(indexBias, structure, initialLength);
104
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
101
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(Butterfly::totalSize(indexBias, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)), deferralContext, AllocationFailureMode::ReturnNull);
105
            vm,
106
            Butterfly::totalSize(indexBias, outOfLineStorage, true, ArrayStorage::sizeFor(vectorLength)),
107
            deferralContext, AllocationFailureMode::ReturnNull);
108
        if (UNLIKELY(!temp))
102
        if (UNLIKELY(!temp))
109
            return nullptr;
103
            return nullptr;
110
        butterfly = Butterfly::fromBase(temp, indexBias, outOfLineStorage);
104
        butterfly = Butterfly::fromBase(temp, indexBias, outOfLineStorage);
Lines 374-381 bool JSArray::unshiftCountSlowCase(const AbstractLocker&, VM& vm, DeferGC&, bool a/Source/JavaScriptCore/runtime/JSArray.cpp_sec4
374
        allocatedNewStorage = false;
368
        allocatedNewStorage = false;
375
    } else {
369
    } else {
376
        size_t newSize = Butterfly::totalSize(0, propertyCapacity, true, ArrayStorage::sizeFor(desiredCapacity));
370
        size_t newSize = Butterfly::totalSize(0, propertyCapacity, true, ArrayStorage::sizeFor(desiredCapacity));
377
        newAllocBase = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
371
        newAllocBase = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(newSize, nullptr, AllocationFailureMode::ReturnNull);
378
            vm, newSize, nullptr, AllocationFailureMode::ReturnNull);
379
        if (!newAllocBase)
372
        if (!newAllocBase)
380
            return false;
373
            return false;
381
        newStorageCapacity = desiredCapacity;
374
        newStorageCapacity = desiredCapacity;
- a/Source/JavaScriptCore/runtime/JSArray.h -2 / +1 lines
Lines 1-6 a/Source/JavaScriptCore/runtime/JSArray.h_sec1
1
/*
1
/*
2
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
2
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3
 *  Copyright (C) 2003-2018 Apple Inc. All rights reserved.
3
 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
4
 *
4
 *
5
 *  This library is free software; you can redistribute it and/or
5
 *  This library is free software; you can redistribute it and/or
6
 *  modify it under the terms of the GNU Lesser General Public
6
 *  modify it under the terms of the GNU Lesser General Public
Lines 238-244 inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initia a/Source/JavaScriptCore/runtime/JSArray.h_sec2
238
238
239
        unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLengthHint);
239
        unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLengthHint);
240
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
240
        void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
241
            vm,
242
            Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)),
241
            Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)),
243
            nullptr, AllocationFailureMode::ReturnNull);
242
            nullptr, AllocationFailureMode::ReturnNull);
244
        if (!temp)
243
        if (!temp)
- a/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp -1 / +1 lines
Lines 66-72 JSArrayBufferView::ConstructionContext::ConstructionContext( a/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp_sec1
66
        void* temp;
66
        void* temp;
67
        size_t size = sizeOf(length, elementSize);
67
        size_t size = sizeOf(length, elementSize);
68
        if (size) {
68
        if (size) {
69
            temp = vm.primitiveGigacageAuxiliarySpace.allocateNonVirtual(vm, size, nullptr, AllocationFailureMode::ReturnNull);
69
            temp = vm.primitiveGigacageAuxiliarySpace.allocateNonVirtual(size, nullptr, AllocationFailureMode::ReturnNull);
70
            if (!temp)
70
            if (!temp)
71
                return;
71
                return;
72
        } else
72
        } else
- a/Source/JavaScriptCore/runtime/JSCellInlines.h -5 / +4 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/JSCellInlines.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2012-2017 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 145-159 CompleteSubspace* JSCell::subspaceFor(VM& vm) a/Source/JavaScriptCore/runtime/JSCellInlines.h_sec2
145
template<typename T>
145
template<typename T>
146
ALWAYS_INLINE void* tryAllocateCellHelper(Heap& heap, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
146
ALWAYS_INLINE void* tryAllocateCellHelper(Heap& heap, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
147
{
147
{
148
    VM& vm = *heap.vm();
149
    ASSERT(deferralContext || !DisallowGC::isInEffectOnCurrentThread());
148
    ASSERT(deferralContext || !DisallowGC::isInEffectOnCurrentThread());
150
    ASSERT(size >= sizeof(T));
149
    ASSERT(size >= sizeof(T));
151
    JSCell* result = static_cast<JSCell*>(subspaceFor<T>(vm)->allocateNonVirtual(vm, size, deferralContext, failureMode));
150
    JSCell* result = static_cast<JSCell*>(subspaceFor<T>(*heap.vm())->allocateNonVirtual(size, deferralContext, failureMode));
152
    if (failureMode == AllocationFailureMode::ReturnNull && !result)
151
    if (failureMode == AllocationFailureMode::ReturnNull && !result)
153
        return nullptr;
152
        return nullptr;
154
#if ENABLE(GC_VALIDATION)
153
#if ENABLE(GC_VALIDATION)
155
    ASSERT(!vm.isInitializingObject());
154
    ASSERT(!heap.vm()->isInitializingObject());
156
    vm.setInitializingObjectClass(T::info());
155
    heap.vm()->setInitializingObjectClass(T::info());
157
#endif
156
#endif
158
    result->clearStructure();
157
    result->clearStructure();
159
    return result;
158
    return result;
- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp -2 / +1 lines
Lines 335-341 static EncodedJSValue JSC_HOST_CALL enqueueJob(ExecState* exec) a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec1
335
    return JSValue::encode(jsUndefined());
335
    return JSValue::encode(jsUndefined());
336
}
336
}
337
337
338
JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable, RefPtr<ThreadLocalCache> threadLocalCache)
338
JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
339
    : Base(vm, structure, 0)
339
    : Base(vm, structure, 0)
340
    , m_vm(vm)
340
    , m_vm(vm)
341
    , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
341
    , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
Lines 353-359 JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectM a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec2
353
    , m_templateRegistry(vm)
353
    , m_templateRegistry(vm)
354
    , m_runtimeFlags()
354
    , m_runtimeFlags()
355
    , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
355
    , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
356
    , m_threadLocalCache(threadLocalCache ? WTFMove(threadLocalCache) : vm.defaultThreadLocalCache)
357
{
356
{
358
}
357
}
359
358
- a/Source/JavaScriptCore/runtime/JSGlobalObject.h -5 / +1 lines
Lines 491-497 public: a/Source/JavaScriptCore/runtime/JSGlobalObject.h_sec1
491
    const RuntimeFlags& runtimeFlags() const { return m_runtimeFlags; }
491
    const RuntimeFlags& runtimeFlags() const { return m_runtimeFlags; }
492
492
493
protected:
493
protected:
494
    JS_EXPORT_PRIVATE explicit JSGlobalObject(VM&, Structure*, const GlobalObjectMethodTable* = 0, RefPtr<ThreadLocalCache> = nullptr);
494
    JS_EXPORT_PRIVATE explicit JSGlobalObject(VM&, Structure*, const GlobalObjectMethodTable* = 0);
495
495
496
    JS_EXPORT_PRIVATE void finishCreation(VM&);
496
    JS_EXPORT_PRIVATE void finishCreation(VM&);
497
497
Lines 893-900 public: a/Source/JavaScriptCore/runtime/JSGlobalObject.h_sec2
893
    JSWrapperMap* wrapperMap() const { return m_wrapperMap.get(); }
893
    JSWrapperMap* wrapperMap() const { return m_wrapperMap.get(); }
894
    void setWrapperMap(JSWrapperMap* map) { m_wrapperMap = map; }
894
    void setWrapperMap(JSWrapperMap* map) { m_wrapperMap = map; }
895
#endif
895
#endif
896
    
897
    ThreadLocalCache& threadLocalCache() const { return *m_threadLocalCache.get(); }
898
896
899
protected:
897
protected:
900
    struct GlobalPropertyInfo {
898
    struct GlobalPropertyInfo {
Lines 926-933 private: a/Source/JavaScriptCore/runtime/JSGlobalObject.h_sec3
926
#if JSC_OBJC_API_ENABLED
924
#if JSC_OBJC_API_ENABLED
927
    RetainPtr<JSWrapperMap> m_wrapperMap;
925
    RetainPtr<JSWrapperMap> m_wrapperMap;
928
#endif
926
#endif
929
    
930
    RefPtr<ThreadLocalCache> m_threadLocalCache;
931
};
927
};
932
928
933
JSGlobalObject* asGlobalObject(JSValue);
929
JSGlobalObject* asGlobalObject(JSValue);
- a/Source/JavaScriptCore/runtime/JSLock.cpp -5 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/JSLock.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2005-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * This library is free software; you can redistribute it and/or
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Library General Public
5
 * modify it under the terms of the GNU Library General Public
Lines 28-34 a/Source/JavaScriptCore/runtime/JSLock.cpp_sec2
28
#include "JSCInlines.h"
28
#include "JSCInlines.h"
29
#include "MachineStackMarker.h"
29
#include "MachineStackMarker.h"
30
#include "SamplingProfiler.h"
30
#include "SamplingProfiler.h"
31
#include "ThreadLocalCacheInlines.h"
32
#include "WasmMachineThreads.h"
31
#include "WasmMachineThreads.h"
33
#include <thread>
32
#include <thread>
34
#include <wtf/Threading.h>
33
#include <wtf/Threading.h>
Lines 148-156 void JSLock::didAcquireLock() a/Source/JavaScriptCore/runtime/JSLock.cpp_sec3
148
147
149
    m_vm->setLastStackTop(thread.savedLastStackTop());
148
    m_vm->setLastStackTop(thread.savedLastStackTop());
150
    ASSERT(thread.stack().contains(m_vm->lastStackTop()));
149
    ASSERT(thread.stack().contains(m_vm->lastStackTop()));
151
    
150
152
    m_vm->defaultThreadLocalCache->install(*m_vm);
153
    
154
    m_vm->heap.machineThreads().addCurrentThread();
151
    m_vm->heap.machineThreads().addCurrentThread();
155
#if ENABLE(WEBASSEMBLY)
152
#if ENABLE(WEBASSEMBLY)
156
    Wasm::startTrackingCurrentThread();
153
    Wasm::startTrackingCurrentThread();
- a/Source/JavaScriptCore/runtime/Options.h -1 lines
Lines 236-242 constexpr bool enableAsyncIteration = false; a/Source/JavaScriptCore/runtime/Options.h_sec1
236
    v(bool, dumpSizeClasses, false, Normal, nullptr) \
236
    v(bool, dumpSizeClasses, false, Normal, nullptr) \
237
    v(bool, useBumpAllocator, true, Normal, nullptr) \
237
    v(bool, useBumpAllocator, true, Normal, nullptr) \
238
    v(bool, stealEmptyBlocksFromOtherAllocators, true, Normal, nullptr) \
238
    v(bool, stealEmptyBlocksFromOtherAllocators, true, Normal, nullptr) \
239
    v(bool, tradeDestructorBlocks, true, Normal, nullptr) \
240
    v(bool, eagerlyUpdateTopCallFrame, false, Normal, nullptr) \
239
    v(bool, eagerlyUpdateTopCallFrame, false, Normal, nullptr) \
241
    \
240
    \
242
    v(bool, useOSREntryToDFG, true, Normal, nullptr) \
241
    v(bool, useOSREntryToDFG, true, Normal, nullptr) \
- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h -2 / +2 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h_sec1
1
/*
1
/*
2
 *  Copyright (C) 2008-2018 Apple Inc. All Rights Reserved.
2
 *  Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
3
 *
3
 *
4
 *  This library is free software; you can redistribute it and/or
4
 *  This library is free software; you can redistribute it and/or
5
 *  modify it under the terms of the GNU Lesser General Public
5
 *  modify it under the terms of the GNU Lesser General Public
Lines 42-48 ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializa a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h_sec2
42
42
43
    JSGlobalObject* globalObject = structure->globalObject();
43
    JSGlobalObject* globalObject = structure->globalObject();
44
    bool createUninitialized = globalObject->isOriginalArrayStructure(structure);
44
    bool createUninitialized = globalObject->isOriginalArrayStructure(structure);
45
    void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(vm, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), deferralContext, AllocationFailureMode::ReturnNull);
45
    void* temp = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), deferralContext, AllocationFailureMode::ReturnNull);
46
    if (UNLIKELY(!temp))
46
    if (UNLIKELY(!temp))
47
        return nullptr;
47
        return nullptr;
48
    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
48
    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
- a/Source/JavaScriptCore/runtime/VM.cpp -9 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/VM.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2008-2017 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 121-127 a/Source/JavaScriptCore/runtime/VM.cpp_sec2
121
#include "StrongInlines.h"
121
#include "StrongInlines.h"
122
#include "StructureInlines.h"
122
#include "StructureInlines.h"
123
#include "TestRunnerUtils.h"
123
#include "TestRunnerUtils.h"
124
#include "ThreadLocalCacheInlines.h"
125
#include "ThunkGenerators.h"
124
#include "ThunkGenerators.h"
126
#include "TypeProfiler.h"
125
#include "TypeProfiler.h"
127
#include "TypeProfilerLog.h"
126
#include "TypeProfilerLog.h"
Lines 307-315 VM::VM(VMType vmType, HeapType heapType) a/Source/JavaScriptCore/runtime/VM.cpp_sec3
307
    updateSoftReservedZoneSize(Options::softReservedZoneSize());
306
    updateSoftReservedZoneSize(Options::softReservedZoneSize());
308
    setLastStackTop(stack.origin());
307
    setLastStackTop(stack.origin());
309
308
310
    defaultThreadLocalCache = ThreadLocalCache::create(heap);
311
    defaultThreadLocalCache->install(*this);
312
313
    // Need to be careful to keep everything consistent here
309
    // Need to be careful to keep everything consistent here
314
    JSLockHolder lock(this);
310
    JSLockHolder lock(this);
315
    AtomicStringTable* existingEntryAtomicStringTable = Thread::current().setCurrentAtomicStringTable(m_atomicStringTable);
311
    AtomicStringTable* existingEntryAtomicStringTable = Thread::current().setCurrentAtomicStringTable(m_atomicStringTable);
Lines 498-507 VM::~VM() a/Source/JavaScriptCore/runtime/VM.cpp_sec4
498
    ASSERT(currentThreadIsHoldingAPILock());
494
    ASSERT(currentThreadIsHoldingAPILock());
499
    m_apiLock->willDestroyVM(this);
495
    m_apiLock->willDestroyVM(this);
500
    heap.lastChanceToFinalize();
496
    heap.lastChanceToFinalize();
501
    
502
#if !ENABLE(FAST_TLS_JIT)
503
    ThreadLocalCache::destructor(threadLocalCacheData);
504
#endif
505
497
506
    delete interpreter;
498
    delete interpreter;
507
#ifndef NDEBUG
499
#ifndef NDEBUG
- a/Source/JavaScriptCore/runtime/VM.h -6 lines
Lines 54-60 a/Source/JavaScriptCore/runtime/VM.h_sec1
54
#include "TemplateRegistryKeyTable.h"
54
#include "TemplateRegistryKeyTable.h"
55
#include "VMEntryRecord.h"
55
#include "VMEntryRecord.h"
56
#include "VMTraps.h"
56
#include "VMTraps.h"
57
#include "ThreadLocalCache.h"
58
#include "WasmContext.h"
57
#include "WasmContext.h"
59
#include "Watchpoint.h"
58
#include "Watchpoint.h"
60
#include <wtf/BumpPointerAllocator.h>
59
#include <wtf/BumpPointerAllocator.h>
Lines 657-667 public: a/Source/JavaScriptCore/runtime/VM.h_sec2
657
656
658
    JSObject* stringRecursionCheckFirstObject { nullptr };
657
    JSObject* stringRecursionCheckFirstObject { nullptr };
659
    HashSet<JSObject*> stringRecursionCheckVisitedObjects;
658
    HashSet<JSObject*> stringRecursionCheckVisitedObjects;
660
    
661
#if !ENABLE(FAST_TLS_JIT)
662
    ThreadLocalCache::Data* threadLocalCacheData { nullptr };
663
#endif
664
    RefPtr<ThreadLocalCache> defaultThreadLocalCache;
665
659
666
    LocalTimeOffsetCache localTimeOffsetCache;
660
    LocalTimeOffsetCache localTimeOffsetCache;
667
661
- a/Source/JavaScriptCore/runtime/VMEntryScope.cpp -3 / +1 lines
Lines 1-5 a/Source/JavaScriptCore/runtime/VMEntryScope.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013-2017 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 29-35 a/Source/JavaScriptCore/runtime/VMEntryScope.cpp_sec2
29
#include "DisallowVMReentry.h"
29
#include "DisallowVMReentry.h"
30
#include "Options.h"
30
#include "Options.h"
31
#include "SamplingProfiler.h"
31
#include "SamplingProfiler.h"
32
#include "ThreadLocalCacheInlines.h"
33
#include "VM.h"
32
#include "VM.h"
34
#include "Watchdog.h"
33
#include "Watchdog.h"
35
#include <wtf/StackBounds.h>
34
#include <wtf/StackBounds.h>
Lines 41-47 VMEntryScope::VMEntryScope(VM& vm, JSGlobalObject* globalObject) a/Source/JavaScriptCore/runtime/VMEntryScope.cpp_sec3
41
    : m_vm(vm)
40
    : m_vm(vm)
42
    , m_globalObject(globalObject)
41
    , m_globalObject(globalObject)
43
{
42
{
44
    globalObject->threadLocalCache().install(vm);
45
    ASSERT(!DisallowVMReentry::isInEffectOnCurrentThread());
43
    ASSERT(!DisallowVMReentry::isInEffectOnCurrentThread());
46
    ASSERT(Thread::current().stack().isGrowingDownward());
44
    ASSERT(Thread::current().stack().isGrowingDownward());
47
    if (!vm.entryScope) {
45
    if (!vm.entryScope) {
- a/Source/WTF/wtf/Bitmap.h -1 lines
Lines 21-27 a/Source/WTF/wtf/Bitmap.h_sec1
21
21
22
#include <array>
22
#include <array>
23
#include <wtf/Atomics.h>
23
#include <wtf/Atomics.h>
24
#include <wtf/HashFunctions.h>
25
#include <wtf/StdLibExtras.h>
24
#include <wtf/StdLibExtras.h>
26
#include <stdint.h>
25
#include <stdint.h>
27
#include <string.h>
26
#include <string.h>

Return to Bug 182110