| Differences between
and this patch
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj -2 / +151 lines
Lines 25-30 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
25
			buildPhases = (
25
			buildPhases = (
26
			);
26
			);
27
			dependencies = (
27
			dependencies = (
28
				0F6183471C45F67A0072450B /* PBXTargetDependency */,
28
				0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */,
29
				0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */,
29
				0FEC85B11BDB5D8F0080FF74 /* PBXTargetDependency */,
30
				0FEC85B11BDB5D8F0080FF74 /* PBXTargetDependency */,
30
				5D6B2A4F152B9E23005231DE /* PBXTargetDependency */,
31
				5D6B2A4F152B9E23005231DE /* PBXTargetDependency */,
Lines 400-405 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
400
		0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; };
401
		0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; };
401
		0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
402
		0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
402
		0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
403
		0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
404
		0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183201C45BF070072450B /* AirCCallingConvention.cpp */; };
405
		0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; };
406
		0F61832B1C45BF070072450B /* AirCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183221C45BF070072450B /* AirCustom.cpp */; };
407
		0F61832C1C45BF070072450B /* AirEmitShuffle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183231C45BF070072450B /* AirEmitShuffle.cpp */; };
408
		0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183241C45BF070072450B /* AirEmitShuffle.h */; };
409
		0F61832E1C45BF070072450B /* AirLowerAfterRegAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */; };
410
		0F61832F1C45BF070072450B /* AirLowerAfterRegAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */; };
411
		0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183271C45BF070072450B /* AirLowerMacros.cpp */; };
412
		0F6183311C45BF070072450B /* AirLowerMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183281C45BF070072450B /* AirLowerMacros.h */; };
413
		0F6183331C45F35C0072450B /* AirOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183321C45F35C0072450B /* AirOpcode.h */; };
414
		0F6183361C45F3B60072450B /* AirOpcodeGenerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183341C45F3B60072450B /* AirOpcodeGenerated.h */; };
415
		0F6183371C45F3B60072450B /* AirOpcodeUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183351C45F3B60072450B /* AirOpcodeUtils.h */; };
416
		0F61833C1C45F62A0072450B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
417
		0F61833D1C45F62A0072450B /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
418
		0F6183451C45F6600072450B /* testair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183441C45F6600072450B /* testair.cpp */; };
403
		0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; };
419
		0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; };
404
		0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; };
420
		0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; };
405
		0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; };
421
		0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; };
Lines 2078-2083 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
2078
/* End PBXBuildFile section */
2094
/* End PBXBuildFile section */
2079
2095
2080
/* Begin PBXContainerItemProxy section */
2096
/* Begin PBXContainerItemProxy section */
2097
		0F6183461C45F67A0072450B /* PBXContainerItemProxy */ = {
2098
			isa = PBXContainerItemProxy;
2099
			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
2100
			proxyType = 1;
2101
			remoteGlobalIDString = 0F6183381C45F62A0072450B;
2102
			remoteInfo = testair;
2103
		};
2081
		0F93275C1C20BF3A00CF6564 /* PBXContainerItemProxy */ = {
2104
		0F93275C1C20BF3A00CF6564 /* PBXContainerItemProxy */ = {
2082
			isa = PBXContainerItemProxy;
2105
			isa = PBXContainerItemProxy;
2083
			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
2106
			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
Lines 2541-2546 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
2541
		0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
2564
		0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
2542
		0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
2565
		0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
2543
		0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; };
2566
		0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; };
2567
		0F6183201C45BF070072450B /* AirCCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCCallingConvention.cpp; path = b3/air/AirCCallingConvention.cpp; sourceTree = "<group>"; };
2568
		0F6183211C45BF070072450B /* AirCCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirCCallingConvention.h; path = b3/air/AirCCallingConvention.h; sourceTree = "<group>"; };
2569
		0F6183221C45BF070072450B /* AirCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCustom.cpp; path = b3/air/AirCustom.cpp; sourceTree = "<group>"; };
2570
		0F6183231C45BF070072450B /* AirEmitShuffle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirEmitShuffle.cpp; path = b3/air/AirEmitShuffle.cpp; sourceTree = "<group>"; };
2571
		0F6183241C45BF070072450B /* AirEmitShuffle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirEmitShuffle.h; path = b3/air/AirEmitShuffle.h; sourceTree = "<group>"; };
2572
		0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerAfterRegAlloc.cpp; path = b3/air/AirLowerAfterRegAlloc.cpp; sourceTree = "<group>"; };
2573
		0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerAfterRegAlloc.h; path = b3/air/AirLowerAfterRegAlloc.h; sourceTree = "<group>"; };
2574
		0F6183271C45BF070072450B /* AirLowerMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerMacros.cpp; path = b3/air/AirLowerMacros.cpp; sourceTree = "<group>"; };
2575
		0F6183281C45BF070072450B /* AirLowerMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerMacros.h; path = b3/air/AirLowerMacros.h; sourceTree = "<group>"; };
2576
		0F6183321C45F35C0072450B /* AirOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirOpcode.h; sourceTree = "<group>"; };
2577
		0F6183341C45F3B60072450B /* AirOpcodeGenerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirOpcodeGenerated.h; sourceTree = "<group>"; };
2578
		0F6183351C45F3B60072450B /* AirOpcodeUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirOpcodeUtils.h; sourceTree = "<group>"; };
2579
		0F6183431C45F62A0072450B /* testair */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testair; sourceTree = BUILT_PRODUCTS_DIR; };
2580
		0F6183441C45F6600072450B /* testair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testair.cpp; path = b3/air/testair.cpp; sourceTree = "<group>"; };
2544
		0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; };
2581
		0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; };
2545
		0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; };
2582
		0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; };
2546
		0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
2583
		0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
Lines 3370-3377 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
3370
		7013CA8A1B491A9400CAE613 /* JSJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSJob.h; sourceTree = "<group>"; };
3407
		7013CA8A1B491A9400CAE613 /* JSJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSJob.h; sourceTree = "<group>"; };
3371
		7035587C1C418419004BD7BF /* MapPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = MapPrototype.js; sourceTree = "<group>"; };
3408
		7035587C1C418419004BD7BF /* MapPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = MapPrototype.js; sourceTree = "<group>"; };
3372
		7035587D1C418419004BD7BF /* SetPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SetPrototype.js; sourceTree = "<group>"; };
3409
		7035587D1C418419004BD7BF /* SetPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SetPrototype.js; sourceTree = "<group>"; };
3373
		7035587E1C418458004BD7BF /* MapPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapPrototype.lut.h; path = MapPrototype.lut.h; sourceTree = "<group>"; };
3410
		7035587E1C418458004BD7BF /* MapPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapPrototype.lut.h; sourceTree = "<group>"; };
3374
		7035587F1C418458004BD7BF /* SetPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SetPrototype.lut.h; path = SetPrototype.lut.h; sourceTree = "<group>"; };
3411
		7035587F1C418458004BD7BF /* SetPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetPrototype.lut.h; sourceTree = "<group>"; };
3375
		704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; };
3412
		704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; };
3376
		705B41A31A6E501E00716757 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbol.cpp; sourceTree = "<group>"; };
3413
		705B41A31A6E501E00716757 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbol.cpp; sourceTree = "<group>"; };
3377
		705B41A41A6E501E00716757 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = "<group>"; };
3414
		705B41A41A6E501E00716757 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = "<group>"; };
Lines 4304-4309 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec6
4304
/* End PBXFileReference section */
4341
/* End PBXFileReference section */
4305
4342
4306
/* Begin PBXFrameworksBuildPhase section */
4343
/* Begin PBXFrameworksBuildPhase section */
4344
		0F61833B1C45F62A0072450B /* Frameworks */ = {
4345
			isa = PBXFrameworksBuildPhase;
4346
			buildActionMask = 2147483647;
4347
			files = (
4348
				0F61833C1C45F62A0072450B /* Foundation.framework in Frameworks */,
4349
				0F61833D1C45F62A0072450B /* JavaScriptCore.framework in Frameworks */,
4350
			);
4351
			runOnlyForDeploymentPostprocessing = 0;
4352
		};
4307
		0F9327511C20BCBA00CF6564 /* Frameworks */ = {
4353
		0F9327511C20BCBA00CF6564 /* Frameworks */ = {
4308
			isa = PBXFrameworksBuildPhase;
4354
			isa = PBXFrameworksBuildPhase;
4309
			buildActionMask = 2147483647;
4355
			buildActionMask = 2147483647;
Lines 4401-4406 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec7
4401
				0FEC85AD1BDB5CF10080FF74 /* testb3 */,
4447
				0FEC85AD1BDB5CF10080FF74 /* testb3 */,
4402
				6511230514046A4C002B101D /* testRegExp */,
4448
				6511230514046A4C002B101D /* testRegExp */,
4403
				0F9327591C20BCBA00CF6564 /* dynbench */,
4449
				0F9327591C20BCBA00CF6564 /* dynbench */,
4450
				0F6183431C45F62A0072450B /* testair */,
4404
			);
4451
			);
4405
			name = Products;
4452
			name = Products;
4406
			sourceTree = "<group>";
4453
			sourceTree = "<group>";
Lines 4791-4803 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec8
4791
				0FEC854C1BDACDC70080FF74 /* AirBasicBlock.cpp */,
4838
				0FEC854C1BDACDC70080FF74 /* AirBasicBlock.cpp */,
4792
				0FEC854D1BDACDC70080FF74 /* AirBasicBlock.h */,
4839
				0FEC854D1BDACDC70080FF74 /* AirBasicBlock.h */,
4793
				0FB3878B1BFBC44D00E3AB1E /* AirBlockWorklist.h */,
4840
				0FB3878B1BFBC44D00E3AB1E /* AirBlockWorklist.h */,
4841
				0F6183201C45BF070072450B /* AirCCallingConvention.cpp */,
4842
				0F6183211C45BF070072450B /* AirCCallingConvention.h */,
4794
				0FEC854E1BDACDC70080FF74 /* AirCCallSpecial.cpp */,
4843
				0FEC854E1BDACDC70080FF74 /* AirCCallSpecial.cpp */,
4795
				0FEC854F1BDACDC70080FF74 /* AirCCallSpecial.h */,
4844
				0FEC854F1BDACDC70080FF74 /* AirCCallSpecial.h */,
4796
				0FEC85501BDACDC70080FF74 /* AirCode.cpp */,
4845
				0FEC85501BDACDC70080FF74 /* AirCode.cpp */,
4797
				0FEC85511BDACDC70080FF74 /* AirCode.h */,
4846
				0FEC85511BDACDC70080FF74 /* AirCode.h */,
4847
				0F6183221C45BF070072450B /* AirCustom.cpp */,
4798
				0F10F1A21C420BF0001C07D2 /* AirCustom.h */,
4848
				0F10F1A21C420BF0001C07D2 /* AirCustom.h */,
4799
				0F4570361BE44C910062A629 /* AirEliminateDeadCode.cpp */,
4849
				0F4570361BE44C910062A629 /* AirEliminateDeadCode.cpp */,
4800
				0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */,
4850
				0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */,
4851
				0F6183231C45BF070072450B /* AirEmitShuffle.cpp */,
4852
				0F6183241C45BF070072450B /* AirEmitShuffle.h */,
4801
				262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */,
4853
				262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */,
4802
				262D85B51C0D650F006ACB61 /* AirFixPartialRegisterStalls.h */,
4854
				262D85B51C0D650F006ACB61 /* AirFixPartialRegisterStalls.h */,
4803
				0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */,
4855
				0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */,
Lines 4816-4821 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec9
4816
				26718BA21BE99F780052017B /* AirIteratedRegisterCoalescing.cpp */,
4868
				26718BA21BE99F780052017B /* AirIteratedRegisterCoalescing.cpp */,
4817
				26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */,
4869
				26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */,
4818
				2684D4371C00161C0081D663 /* AirLiveness.h */,
4870
				2684D4371C00161C0081D663 /* AirLiveness.h */,
4871
				0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */,
4872
				0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */,
4873
				0F6183271C45BF070072450B /* AirLowerMacros.cpp */,
4874
				0F6183281C45BF070072450B /* AirLowerMacros.h */,
4819
				264091FA1BE2FD4100684DB2 /* AirOpcode.opcodes */,
4875
				264091FA1BE2FD4100684DB2 /* AirOpcode.opcodes */,
4820
				0FB3878C1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.cpp */,
4876
				0FB3878C1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.cpp */,
4821
				0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */,
4877
				0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */,
Lines 4841-4846 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec10
4841
				0F3730921C0D67EE00052BFA /* AirUseCounts.h */,
4897
				0F3730921C0D67EE00052BFA /* AirUseCounts.h */,
4842
				0FEC856B1BDACDC70080FF74 /* AirValidate.cpp */,
4898
				0FEC856B1BDACDC70080FF74 /* AirValidate.cpp */,
4843
				0FEC856C1BDACDC70080FF74 /* AirValidate.h */,
4899
				0FEC856C1BDACDC70080FF74 /* AirValidate.h */,
4900
				0F6183441C45F6600072450B /* testair.cpp */,
4844
			);
4901
			);
4845
			name = air;
4902
			name = air;
4846
			sourceTree = "<group>";
4903
			sourceTree = "<group>";
Lines 5298-5303 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec11
5298
		650FDF8D09D0FCA700769E54 /* Derived Sources */ = {
5355
		650FDF8D09D0FCA700769E54 /* Derived Sources */ = {
5299
			isa = PBXGroup;
5356
			isa = PBXGroup;
5300
			children = (
5357
			children = (
5358
				0F6183321C45F35C0072450B /* AirOpcode.h */,
5359
				0F6183341C45F3B60072450B /* AirOpcodeGenerated.h */,
5360
				0F6183351C45F3B60072450B /* AirOpcodeUtils.h */,
5301
				996B73151BDA05AA00331B84 /* ArrayConstructor.lut.h */,
5361
				996B73151BDA05AA00331B84 /* ArrayConstructor.lut.h */,
5302
				996B73161BDA05AA00331B84 /* ArrayIteratorPrototype.lut.h */,
5362
				996B73161BDA05AA00331B84 /* ArrayIteratorPrototype.lut.h */,
5303
				996B73071BD9FA2C00331B84 /* BooleanPrototype.lut.h */,
5363
				996B73071BD9FA2C00331B84 /* BooleanPrototype.lut.h */,
Lines 6896-6901 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec12
6896
				0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */,
6956
				0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */,
6897
				79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */,
6957
				79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */,
6898
				79D5CD5B1C1106A900CECA07 /* SamplingProfiler.h in Headers */,
6958
				79D5CD5B1C1106A900CECA07 /* SamplingProfiler.h in Headers */,
6959
				0F6183311C45BF070072450B /* AirLowerMacros.h in Headers */,
6899
				0FEC85771BDACDC70080FF74 /* AirFrequentedBlock.h in Headers */,
6960
				0FEC85771BDACDC70080FF74 /* AirFrequentedBlock.h in Headers */,
6900
				0FEC85791BDACDC70080FF74 /* AirGenerate.h in Headers */,
6961
				0FEC85791BDACDC70080FF74 /* AirGenerate.h in Headers */,
6901
				79DF66B11BF26A570001CF11 /* FTLExceptionHandlerManager.h in Headers */,
6962
				79DF66B11BF26A570001CF11 /* FTLExceptionHandlerManager.h in Headers */,
Lines 6958-6963 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec13
6958
				0FEC85141BDACDAC0080FF74 /* B3ControlValue.h in Headers */,
7019
				0FEC85141BDACDAC0080FF74 /* B3ControlValue.h in Headers */,
6959
				0FEC85C11BE167A00080FF74 /* B3Effects.h in Headers */,
7020
				0FEC85C11BE167A00080FF74 /* B3Effects.h in Headers */,
6960
				0FEC85161BDACDAC0080FF74 /* B3FrequencyClass.h in Headers */,
7021
				0FEC85161BDACDAC0080FF74 /* B3FrequencyClass.h in Headers */,
7022
				0F61832F1C45BF070072450B /* AirLowerAfterRegAlloc.h in Headers */,
6961
				0FEC85171BDACDAC0080FF74 /* B3FrequentedBlock.h in Headers */,
7023
				0FEC85171BDACDAC0080FF74 /* B3FrequentedBlock.h in Headers */,
6962
				0FEC85191BDACDAC0080FF74 /* B3Generate.h in Headers */,
7024
				0FEC85191BDACDAC0080FF74 /* B3Generate.h in Headers */,
6963
				0FEC851A1BDACDAC0080FF74 /* B3GenericFrequentedBlock.h in Headers */,
7025
				0FEC851A1BDACDAC0080FF74 /* B3GenericFrequentedBlock.h in Headers */,
Lines 7150-7155 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec14
7150
				A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
7212
				A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
7151
				0F37308D1C0BD29100052BFA /* B3PhiChildren.h in Headers */,
7213
				0F37308D1C0BD29100052BFA /* B3PhiChildren.h in Headers */,
7152
				A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
7214
				A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
7215
				0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */,
7153
				0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
7216
				0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
7154
				0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */,
7217
				0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */,
7155
				0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
7218
				0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
Lines 7254-7259 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec15
7254
				0F2B9CED19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h in Headers */,
7317
				0F2B9CED19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h in Headers */,
7255
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
7318
				0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
7256
				0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */,
7319
				0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */,
7320
				0F6183361C45F3B60072450B /* AirOpcodeGenerated.h in Headers */,
7257
				0F3730911C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h in Headers */,
7321
				0F3730911C0CD70C00052BFA /* AllowMacroScratchRegisterUsage.h in Headers */,
7258
				0F3A1BFA1A9ECB7D000DE01A /* DFGPutStackSinkingPhase.h in Headers */,
7322
				0F3A1BFA1A9ECB7D000DE01A /* DFGPutStackSinkingPhase.h in Headers */,
7259
				86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */,
7323
				86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */,
Lines 7270-7275 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec16
7270
				0FC20CBA18556A3500C9E954 /* DFGSSALoweringPhase.h in Headers */,
7334
				0FC20CBA18556A3500C9E954 /* DFGSSALoweringPhase.h in Headers */,
7271
				0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */,
7335
				0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */,
7272
				0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */,
7336
				0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */,
7337
				0F6183371C45F3B60072450B /* AirOpcodeUtils.h in Headers */,
7273
				0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */,
7338
				0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */,
7274
				0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
7339
				0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
7275
				0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
7340
				0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
Lines 7624-7629 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec17
7624
				0F2B66F717B6B5AB00A7AE3F /* JSInt8Array.h in Headers */,
7689
				0F2B66F717B6B5AB00A7AE3F /* JSInt8Array.h in Headers */,
7625
				A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */,
7690
				A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */,
7626
				E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */,
7691
				E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */,
7692
				0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
7627
				E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */,
7693
				E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */,
7628
				E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */,
7694
				E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */,
7629
				E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */,
7695
				E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */,
Lines 8014-8019 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec18
8014
				142E313C134FF0A600AFADB5 /* Weak.h in Headers */,
8080
				142E313C134FF0A600AFADB5 /* Weak.h in Headers */,
8015
				14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */,
8081
				14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */,
8016
				14BFCE6910CDB1FC00364CCE /* WeakGCMap.h in Headers */,
8082
				14BFCE6910CDB1FC00364CCE /* WeakGCMap.h in Headers */,
8083
				0F6183331C45F35C0072450B /* AirOpcode.h in Headers */,
8017
				AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */,
8084
				AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */,
8018
				14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */,
8085
				14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */,
8019
				14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
8086
				14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
Lines 8046-8051 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec19
8046
/* End PBXHeadersBuildPhase section */
8113
/* End PBXHeadersBuildPhase section */
8047
8114
8048
/* Begin PBXNativeTarget section */
8115
/* Begin PBXNativeTarget section */
8116
		0F6183381C45F62A0072450B /* testair */ = {
8117
			isa = PBXNativeTarget;
8118
			buildConfigurationList = 0F61833E1C45F62A0072450B /* Build configuration list for PBXNativeTarget "testair" */;
8119
			buildPhases = (
8120
				0F6183391C45F62A0072450B /* Sources */,
8121
				0F61833B1C45F62A0072450B /* Frameworks */,
8122
			);
8123
			buildRules = (
8124
			);
8125
			dependencies = (
8126
			);
8127
			name = testair;
8128
			productName = testapi;
8129
			productReference = 0F6183431C45F62A0072450B /* testair */;
8130
			productType = "com.apple.product-type.tool";
8131
		};
8049
		0F93274E1C20BCBA00CF6564 /* dynbench */ = {
8132
		0F93274E1C20BCBA00CF6564 /* dynbench */ = {
8050
			isa = PBXNativeTarget;
8133
			isa = PBXNativeTarget;
8051
			buildConfigurationList = 0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */;
8134
			buildConfigurationList = 0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */;
Lines 8253-8258 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec20
8253
				0FEC85941BDB5CF10080FF74 /* testb3 */,
8336
				0FEC85941BDB5CF10080FF74 /* testb3 */,
8254
				5D6B2A47152B9E17005231DE /* Test Tools */,
8337
				5D6B2A47152B9E17005231DE /* Test Tools */,
8255
				0F93274E1C20BCBA00CF6564 /* dynbench */,
8338
				0F93274E1C20BCBA00CF6564 /* dynbench */,
8339
				0F6183381C45F62A0072450B /* testair */,
8256
			);
8340
			);
8257
		};
8341
		};
8258
/* End PBXProject section */
8342
/* End PBXProject section */
Lines 8489-8494 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec21
8489
/* End PBXShellScriptBuildPhase section */
8573
/* End PBXShellScriptBuildPhase section */
8490
8574
8491
/* Begin PBXSourcesBuildPhase section */
8575
/* Begin PBXSourcesBuildPhase section */
8576
		0F6183391C45F62A0072450B /* Sources */ = {
8577
			isa = PBXSourcesBuildPhase;
8578
			buildActionMask = 2147483647;
8579
			files = (
8580
				0F6183451C45F6600072450B /* testair.cpp in Sources */,
8581
			);
8582
			runOnlyForDeploymentPostprocessing = 0;
8583
		};
8492
		0F93274F1C20BCBA00CF6564 /* Sources */ = {
8584
		0F93274F1C20BCBA00CF6564 /* Sources */ = {
8493
			isa = PBXSourcesBuildPhase;
8585
			isa = PBXSourcesBuildPhase;
8494
			buildActionMask = 2147483647;
8586
			buildActionMask = 2147483647;
Lines 8693-8698 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec22
8693
				52B717B51A0597E1007AF4F3 /* ControlFlowProfiler.cpp in Sources */,
8785
				52B717B51A0597E1007AF4F3 /* ControlFlowProfiler.cpp in Sources */,
8694
				0FBADF541BD1F4B800E073C1 /* CopiedBlock.cpp in Sources */,
8786
				0FBADF541BD1F4B800E073C1 /* CopiedBlock.cpp in Sources */,
8695
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
8787
				C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
8788
				0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */,
8696
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
8789
				C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
8697
				2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */,
8790
				2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */,
8698
				62E3D5F01B8D0B7300B868BB /* DataFormat.cpp in Sources */,
8791
				62E3D5F01B8D0B7300B868BB /* DataFormat.cpp in Sources */,
Lines 8741-8746 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec23
8741
				0F0981F71BC5E565004814F8 /* DFGCopyBarrierOptimizationPhase.cpp in Sources */,
8834
				0F0981F71BC5E565004814F8 /* DFGCopyBarrierOptimizationPhase.cpp in Sources */,
8742
				0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */,
8835
				0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */,
8743
				A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */,
8836
				A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */,
8837
				0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */,
8744
				0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
8838
				0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
8745
				0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
8839
				0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
8746
				0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */,
8840
				0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */,
Lines 8757-8762 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec24
8757
				A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */,
8851
				A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */,
8758
				A78A9776179738B8009DF744 /* DFGFinalizer.cpp in Sources */,
8852
				A78A9776179738B8009DF744 /* DFGFinalizer.cpp in Sources */,
8759
				0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */,
8853
				0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */,
8854
				0F61832C1C45BF070072450B /* AirEmitShuffle.cpp in Sources */,
8760
				0F9D339617FFC4E60073C2BC /* DFGFlushedAt.cpp in Sources */,
8855
				0F9D339617FFC4E60073C2BC /* DFGFlushedAt.cpp in Sources */,
8761
				A7D89CF717A0B8CC00773AD8 /* DFGFlushFormat.cpp in Sources */,
8856
				A7D89CF717A0B8CC00773AD8 /* DFGFlushFormat.cpp in Sources */,
8762
				0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */,
8857
				0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */,
Lines 9068-9073 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec25
9068
				E33F50841B8437A000413856 /* JSInternalPromiseDeferred.cpp in Sources */,
9163
				E33F50841B8437A000413856 /* JSInternalPromiseDeferred.cpp in Sources */,
9069
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
9164
				E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
9070
				A503FA1B188E0FB000110F14 /* JSJavaScriptCallFrame.cpp in Sources */,
9165
				A503FA1B188E0FB000110F14 /* JSJavaScriptCallFrame.cpp in Sources */,
9166
				0F61832E1C45BF070072450B /* AirLowerAfterRegAlloc.cpp in Sources */,
9071
				A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */,
9167
				A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */,
9072
				7013CA8B1B491A9400CAE613 /* JSJob.cpp in Sources */,
9168
				7013CA8B1B491A9400CAE613 /* JSJob.cpp in Sources */,
9073
				140B7D1D0DC69AF7009C42B8 /* JSLexicalEnvironment.cpp in Sources */,
9169
				140B7D1D0DC69AF7009C42B8 /* JSLexicalEnvironment.cpp in Sources */,
Lines 9210-9215 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec26
9210
				0F9D4C0C1C3E1C11006CD984 /* FTLExceptionTarget.cpp in Sources */,
9306
				0F9D4C0C1C3E1C11006CD984 /* FTLExceptionTarget.cpp in Sources */,
9211
				0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
9307
				0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
9212
				0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
9308
				0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
9309
				0F61832B1C45BF070072450B /* AirCustom.cpp in Sources */,
9213
				0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
9310
				0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
9214
				0FD3E40D1B618B6600C80E1E /* PropertyCondition.cpp in Sources */,
9311
				0FD3E40D1B618B6600C80E1E /* PropertyCondition.cpp in Sources */,
9215
				A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
9312
				A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
Lines 9362-9367 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec27
9362
/* End PBXSourcesBuildPhase section */
9459
/* End PBXSourcesBuildPhase section */
9363
9460
9364
/* Begin PBXTargetDependency section */
9461
/* Begin PBXTargetDependency section */
9462
		0F6183471C45F67A0072450B /* PBXTargetDependency */ = {
9463
			isa = PBXTargetDependency;
9464
			target = 0F6183381C45F62A0072450B /* testair */;
9465
			targetProxy = 0F6183461C45F67A0072450B /* PBXContainerItemProxy */;
9466
		};
9365
		0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */ = {
9467
		0F93275D1C20BF3A00CF6564 /* PBXTargetDependency */ = {
9366
			isa = PBXTargetDependency;
9468
			isa = PBXTargetDependency;
9367
			target = 0F93274E1C20BCBA00CF6564 /* dynbench */;
9469
			target = 0F93274E1C20BCBA00CF6564 /* dynbench */;
Lines 9473-9478 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec28
9473
			};
9575
			};
9474
			name = Production;
9576
			name = Production;
9475
		};
9577
		};
9578
		0F61833F1C45F62A0072450B /* Debug */ = {
9579
			isa = XCBuildConfiguration;
9580
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
9581
			buildSettings = {
9582
				CODE_SIGN_ENTITLEMENTS_ios_testair = entitlements.plist;
9583
				PRODUCT_NAME = testair;
9584
			};
9585
			name = Debug;
9586
		};
9587
		0F6183401C45F62A0072450B /* Release */ = {
9588
			isa = XCBuildConfiguration;
9589
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
9590
			buildSettings = {
9591
				CODE_SIGN_ENTITLEMENTS_ios_testair = entitlements.plist;
9592
				PRODUCT_NAME = testair;
9593
			};
9594
			name = Release;
9595
		};
9596
		0F6183411C45F62A0072450B /* Profiling */ = {
9597
			isa = XCBuildConfiguration;
9598
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
9599
			buildSettings = {
9600
				CODE_SIGN_ENTITLEMENTS_ios_testair = entitlements.plist;
9601
				PRODUCT_NAME = testair;
9602
			};
9603
			name = Profiling;
9604
		};
9605
		0F6183421C45F62A0072450B /* Production */ = {
9606
			isa = XCBuildConfiguration;
9607
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
9608
			buildSettings = {
9609
				CODE_SIGN_ENTITLEMENTS_ios_testair = entitlements.plist;
9610
				PRODUCT_NAME = testair;
9611
			};
9612
			name = Production;
9613
		};
9476
		0F9327551C20BCBA00CF6564 /* Debug */ = {
9614
		0F9327551C20BCBA00CF6564 /* Debug */ = {
9477
			isa = XCBuildConfiguration;
9615
			isa = XCBuildConfiguration;
9478
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
9616
			baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */;
Lines 9902-9907 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec29
9902
			defaultConfigurationIsVisible = 0;
10040
			defaultConfigurationIsVisible = 0;
9903
			defaultConfigurationName = Production;
10041
			defaultConfigurationName = Production;
9904
		};
10042
		};
10043
		0F61833E1C45F62A0072450B /* Build configuration list for PBXNativeTarget "testair" */ = {
10044
			isa = XCConfigurationList;
10045
			buildConfigurations = (
10046
				0F61833F1C45F62A0072450B /* Debug */,
10047
				0F6183401C45F62A0072450B /* Release */,
10048
				0F6183411C45F62A0072450B /* Profiling */,
10049
				0F6183421C45F62A0072450B /* Production */,
10050
			);
10051
			defaultConfigurationIsVisible = 0;
10052
			defaultConfigurationName = Production;
10053
		};
9905
		0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */ = {
10054
		0F9327541C20BCBA00CF6564 /* Build configuration list for PBXNativeTarget "dynbench" */ = {
9906
			isa = XCConfigurationList;
10055
			isa = XCConfigurationList;
9907
			buildConfigurations = (
10056
			buildConfigurations = (
- Source/JavaScriptCore/assembler/AbstractMacroAssembler.h -1 / +10 lines
Lines 1-5 Source/JavaScriptCore/assembler/AbstractMacroAssembler.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2008, 2012, 2014, 2015 Apple Inc. All rights reserved.
2
 * Copyright (C) 2008, 2012, 2014-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 76-81 inline bool isX86_64() Source/JavaScriptCore/assembler/AbstractMacroAssembler.h_sec2
76
#endif
76
#endif
77
}
77
}
78
78
79
inline bool isIOS()
80
{
81
#if PLATFORM(IOS)
82
    return true;
83
#else
84
    return false;
85
#endif
86
}
87
79
inline bool optimizeForARMv7IDIVSupported()
88
inline bool optimizeForARMv7IDIVSupported()
80
{
89
{
81
    return isARMv7IDIVSupported() && Options::useArchitectureSpecificOptimizations();
90
    return isARMv7IDIVSupported() && Options::useArchitectureSpecificOptimizations();
- Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +10 lines
Lines 1411-1416 public: Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h_sec1
1411
    }
1411
    }
1412
#endif
1412
#endif
1413
1413
1414
    void swap32(RegisterID src, RegisterID dest)
1415
    {
1416
        m_assembler.xchgl_rr(src, dest);
1417
    }
1418
1419
    void swap32(RegisterID src, Address dest)
1420
    {
1421
        m_assembler.xchgl_rm(src, dest.offset, dest.base);
1422
    }
1423
1414
    void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID src, RegisterID dest)
1424
    void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID src, RegisterID dest)
1415
    {
1425
    {
1416
        m_assembler.cmpl_rr(right, left);
1426
        m_assembler.cmpl_rr(right, left);
- Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h -1 / +11 lines
Lines 1-5 Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2008, 2012, 2014, 2015 Apple Inc. All rights reserved.
2
 * Copyright (C) 2008, 2012, 2014-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 655-660 public: Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h_sec2
655
        return DataLabel32(this);
655
        return DataLabel32(this);
656
    }
656
    }
657
657
658
    void swap64(RegisterID src, RegisterID dest)
659
    {
660
        m_assembler.xchgq_rr(src, dest);
661
    }
662
663
    void swap64(RegisterID src, Address dest)
664
    {
665
        m_assembler.xchgq_rm(src, dest.offset, dest.base);
666
    }
667
658
    void move64ToDouble(RegisterID src, FPRegisterID dest)
668
    void move64ToDouble(RegisterID src, FPRegisterID dest)
659
    {
669
    {
660
        m_assembler.movq_rr(src, dest);
670
        m_assembler.movq_rr(src, dest);
- Source/JavaScriptCore/assembler/X86Assembler.h -1 / +11 lines
Lines 1-5 Source/JavaScriptCore/assembler/X86Assembler.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved.
2
 * Copyright (C) 2008, 2012-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 1431-1436 public: Source/JavaScriptCore/assembler/X86Assembler.h_sec2
1431
            m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
1431
            m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
1432
    }
1432
    }
1433
1433
1434
    void xchgl_rm(RegisterID src, int offset, RegisterID base)
1435
    {
1436
        m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, offset);
1437
    }
1438
1434
#if CPU(X86_64)
1439
#if CPU(X86_64)
1435
    void xchgq_rr(RegisterID src, RegisterID dst)
1440
    void xchgq_rr(RegisterID src, RegisterID dst)
1436
    {
1441
    {
Lines 1441-1446 public: Source/JavaScriptCore/assembler/X86Assembler.h_sec3
1441
        else
1446
        else
1442
            m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
1447
            m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
1443
    }
1448
    }
1449
1450
    void xchgq_rm(RegisterID src, int offset, RegisterID base)
1451
    {
1452
        m_formatter.oneByteOp64(OP_XCHG_EvGv, src, base, offset);
1453
    }
1444
#endif
1454
#endif
1445
1455
1446
    void movl_rr(RegisterID src, RegisterID dst)
1456
    void movl_rr(RegisterID src, RegisterID dst)
- Source/JavaScriptCore/b3/B3CCallValue.h -3 / +2 lines
Lines 1-5 Source/JavaScriptCore/b3/B3CCallValue.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 39-45 public: Source/JavaScriptCore/b3/B3CCallValue.h_sec2
39
39
40
    ~CCallValue();
40
    ~CCallValue();
41
41
42
    Effects effects;
42
    Effects effects { Effects::forCall() };
43
43
44
private:
44
private:
45
    friend class Procedure;
45
    friend class Procedure;
Lines 47-53 private: Source/JavaScriptCore/b3/B3CCallValue.h_sec3
47
    template<typename... Arguments>
47
    template<typename... Arguments>
48
    CCallValue(unsigned index, Type type, Origin origin, Arguments... arguments)
48
    CCallValue(unsigned index, Type type, Origin origin, Arguments... arguments)
49
        : Value(index, CheckedOpcode, CCall, type, origin, arguments...)
49
        : Value(index, CheckedOpcode, CCall, type, origin, arguments...)
50
        , effects(Effects::forCall())
51
    {
50
    {
52
        RELEASE_ASSERT(numChildren() >= 1);
51
        RELEASE_ASSERT(numChildren() >= 1);
53
    }
52
    }
- Source/JavaScriptCore/b3/B3Compilation.cpp -1 / +7 lines
Lines 1-5 Source/JavaScriptCore/b3/B3Compilation.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 52-57 Compilation::Compilation(VM& vm, Procedu Source/JavaScriptCore/b3/B3Compilation.cpp_sec2
52
    m_byproducts = proc.releaseByproducts();
52
    m_byproducts = proc.releaseByproducts();
53
}
53
}
54
54
55
Compilation::Compilation(MacroAssemblerCodeRef codeRef, std::unique_ptr<OpaqueByproducts> byproducts)
56
    : m_codeRef(codeRef)
57
    , m_byproducts(WTFMove(byproducts))
58
{
59
}
60
55
Compilation::~Compilation()
61
Compilation::~Compilation()
56
{
62
{
57
}
63
}
- Source/JavaScriptCore/b3/B3Compilation.h -1 / +6 lines
Lines 1-5 Source/JavaScriptCore/b3/B3Compilation.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 55-60 class Compilation { Source/JavaScriptCore/b3/B3Compilation.h_sec2
55
55
56
public:
56
public:
57
    JS_EXPORT_PRIVATE Compilation(VM&, Procedure&, unsigned optLevel = 1);
57
    JS_EXPORT_PRIVATE Compilation(VM&, Procedure&, unsigned optLevel = 1);
58
59
    // This constructor allows you to manually create a Compilation. It's currently only used by test
60
    // code. Probably best to keep it that way.
61
    JS_EXPORT_PRIVATE Compilation(MacroAssemblerCodeRef, std::unique_ptr<OpaqueByproducts>);
62
    
58
    JS_EXPORT_PRIVATE ~Compilation();
63
    JS_EXPORT_PRIVATE ~Compilation();
59
64
60
    MacroAssemblerCodePtr code() const { return m_codeRef.code(); }
65
    MacroAssemblerCodePtr code() const { return m_codeRef.code(); }
- Source/JavaScriptCore/b3/B3LowerToAir.cpp -77 / +20 lines
Lines 35-40 Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec1
35
#include "AirStackSlot.h"
35
#include "AirStackSlot.h"
36
#include "B3ArgumentRegValue.h"
36
#include "B3ArgumentRegValue.h"
37
#include "B3BasicBlockInlines.h"
37
#include "B3BasicBlockInlines.h"
38
#include "B3BlockWorklist.h"
38
#include "B3CCallValue.h"
39
#include "B3CCallValue.h"
39
#include "B3CheckSpecial.h"
40
#include "B3CheckSpecial.h"
40
#include "B3Commutativity.h"
41
#include "B3Commutativity.h"
Lines 94-99 public: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec2
94
            }
95
            }
95
        }
96
        }
96
97
98
        // Figure out which blocks are not rare.
99
        m_fastWorklist.push(m_procedure[0]);
100
        while (B3::BasicBlock* block = m_fastWorklist.pop()) {
101
            for (B3::FrequentedBlock& successor : block->successors()) {
102
                if (!successor.isRare())
103
                    m_fastWorklist.push(successor.block());
104
            }
105
        }
106
97
        m_procedure.resetValueOwners(); // Used by crossesInterference().
107
        m_procedure.resetValueOwners(); // Used by crossesInterference().
98
108
99
        // Lower defs before uses on a global level. This is a good heuristic to lock down a
109
        // Lower defs before uses on a global level. This is a good heuristic to lock down a
Lines 103-108 public: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec3
103
            // Reset some state.
113
            // Reset some state.
104
            m_insts.resize(0);
114
            m_insts.resize(0);
105
115
116
            m_isRare = !m_fastWorklist.saw(block);
117
106
            if (verbose)
118
            if (verbose)
107
                dataLog("Lowering Block ", *block, ":\n");
119
                dataLog("Lowering Block ", *block, ":\n");
108
            
120
            
Lines 1541-1577 private: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec4
1541
            inverted);
1553
            inverted);
1542
    }
1554
    }
1543
1555
1544
    template<typename BankInfo>
1545
    Arg marshallCCallArgument(unsigned& argumentCount, unsigned& stackOffset, Value* child)
1546
    {
1547
        unsigned argumentIndex = argumentCount++;
1548
        if (argumentIndex < BankInfo::numberOfArgumentRegisters) {
1549
            Tmp result = Tmp(BankInfo::toArgumentRegister(argumentIndex));
1550
            append(relaxedMoveForType(child->type()), immOrTmp(child), result);
1551
            return result;
1552
        }
1553
1554
#if CPU(ARM64) && PLATFORM(IOS)
1555
        // iOS does not follow the ARM64 ABI regarding function calls.
1556
        // Arguments must be packed.
1557
        unsigned slotSize = sizeofType(child->type());
1558
        stackOffset = WTF::roundUpToMultipleOf(slotSize, stackOffset);
1559
#else
1560
        unsigned slotSize = sizeof(void*);
1561
#endif
1562
        Arg result = Arg::callArg(stackOffset);
1563
        stackOffset += slotSize;
1564
        
1565
        // Put the code for storing the argument before anything else. This significantly eases the
1566
        // burden on the register allocator. If we could, we'd hoist these stores as far as
1567
        // possible.
1568
        // FIXME: Add a phase to hoist stores as high as possible to relieve register pressure.
1569
        // https://bugs.webkit.org/show_bug.cgi?id=151063
1570
        m_insts.last().insert(0, createStore(child, result));
1571
        
1572
        return result;
1573
    }
1574
1575
    void lower()
1556
    void lower()
1576
    {
1557
    {
1577
        switch (m_value->opcode()) {
1558
        switch (m_value->opcode()) {
Lines 1919-1932 private: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec5
1919
            return;
1900
            return;
1920
        }
1901
        }
1921
1902
1922
        case CCall: {
1903
        case B3::CCall: {
1923
            CCallValue* cCall = m_value->as<CCallValue>();
1904
            CCallValue* cCall = m_value->as<CCallValue>();
1924
            Inst inst(Patch, cCall, Arg::special(m_code.cCallSpecial()));
1905
            Inst inst(m_isRare ? Air::ColdCCall : Air::CCall, cCall);
1925
1926
            // This is a bit weird - we have a super intense contract with Arg::CCallSpecial. It might
1927
            // be better if we factored Air::CCallSpecial out of the Air namespace and made it a B3
1928
            // thing.
1929
            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151045
1930
1906
1931
            // We have a ton of flexibility regarding the callee argument, but currently, we don't
1907
            // We have a ton of flexibility regarding the callee argument, but currently, we don't
1932
            // use it yet. It gets weird for reasons:
1908
            // use it yet. It gets weird for reasons:
Lines 1939-1986 private: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec6
1939
            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151052
1915
            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151052
1940
            inst.args.append(tmp(cCall->child(0)));
1916
            inst.args.append(tmp(cCall->child(0)));
1941
1917
1942
            // We need to tell Air what registers this defines.
1918
            if (cCall->type() != Void)
1943
            inst.args.append(Tmp(GPRInfo::returnValueGPR));
1919
                inst.args.append(tmp(cCall));
1944
            inst.args.append(Tmp(GPRInfo::returnValueGPR2));
1945
            inst.args.append(Tmp(FPRInfo::returnValueFPR));
1946
1947
            // Now marshall the arguments. This is where we implement the C calling convention. After
1948
            // this, Air does not know what the convention is; it just takes our word for it.
1949
            unsigned gpArgumentCount = 0;
1950
            unsigned fpArgumentCount = 0;
1951
            unsigned stackOffset = 0;
1952
            for (unsigned i = 1; i < cCall->numChildren(); ++i) {
1953
                Value* argChild = cCall->child(i);
1954
                Arg arg;
1955
                
1956
                switch (Arg::typeForB3Type(argChild->type())) {
1957
                case Arg::GP:
1958
                    arg = marshallCCallArgument<GPRInfo>(gpArgumentCount, stackOffset, argChild);
1959
                    break;
1960
1920
1961
                case Arg::FP:
1921
            for (unsigned i = 1; i < cCall->numChildren(); ++i)
1962
                    arg = marshallCCallArgument<FPRInfo>(fpArgumentCount, stackOffset, argChild);
1922
                inst.args.append(immOrTmp(cCall->child(i)));
1963
                    break;
1964
                }
1965
1923
1966
                if (arg.isTmp())
1967
                    inst.args.append(arg);
1968
            }
1969
            
1970
            m_insts.last().append(WTFMove(inst));
1924
            m_insts.last().append(WTFMove(inst));
1971
1972
            switch (cCall->type()) {
1973
            case Void:
1974
                break;
1975
            case Int32:
1976
            case Int64:
1977
                append(Move, Tmp(GPRInfo::returnValueGPR), tmp(cCall));
1978
                break;
1979
            case Float:
1980
            case Double:
1981
                append(MoveDouble, Tmp(FPRInfo::returnValueFPR), tmp(cCall));
1982
                break;
1983
            }
1984
            return;
1925
            return;
1985
        }
1926
        }
1986
1927
Lines 2272-2282 private: Source/JavaScriptCore/b3/B3LowerToAir.cpp_sec7
2272
2213
2273
    UseCounts m_useCounts;
2214
    UseCounts m_useCounts;
2274
    PhiChildren m_phiChildren;
2215
    PhiChildren m_phiChildren;
2216
    BlockWorklist m_fastWorklist;
2275
2217
2276
    Vector<Vector<Inst, 4>> m_insts;
2218
    Vector<Vector<Inst, 4>> m_insts;
2277
    Vector<Inst> m_prologue;
2219
    Vector<Inst> m_prologue;
2278
2220
2279
    B3::BasicBlock* m_block;
2221
    B3::BasicBlock* m_block;
2222
    bool m_isRare;
2280
    unsigned m_index;
2223
    unsigned m_index;
2281
    Value* m_value;
2224
    Value* m_value;
2282
2225
- Source/JavaScriptCore/b3/B3OpaqueByproducts.h -2 / +2 lines
Lines 1-5 Source/JavaScriptCore/b3/B3OpaqueByproducts.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 39-45 class OpaqueByproducts { Source/JavaScriptCore/b3/B3OpaqueByproducts.h_sec2
39
    WTF_MAKE_FAST_ALLOCATED;
39
    WTF_MAKE_FAST_ALLOCATED;
40
public:
40
public:
41
    OpaqueByproducts();
41
    OpaqueByproducts();
42
    ~OpaqueByproducts();
42
    JS_EXPORT_PRIVATE ~OpaqueByproducts();
43
43
44
    size_t count() const { return m_byproducts.size(); }
44
    size_t count() const { return m_byproducts.size(); }
45
    
45
    
- Source/JavaScriptCore/b3/B3StackmapSpecial.cpp -11 / +4 lines
Lines 200-220 bool StackmapSpecial::isArgValidForValue Source/JavaScriptCore/b3/B3StackmapSpecial.cpp_sec1
200
    case Arg::Tmp:
200
    case Arg::Tmp:
201
    case Arg::Imm:
201
    case Arg::Imm:
202
    case Arg::Imm64:
202
    case Arg::Imm64:
203
    case Arg::Stack:
204
    case Arg::CallArg:
205
        break; // OK
206
    case Arg::Addr:
207
        if (arg.base() != Tmp(GPRInfo::callFrameRegister)
208
            && arg.base() != Tmp(MacroAssembler::stackPointerRegister))
209
            return false;
210
        break;
203
        break;
211
    default:
204
    default:
212
        return false;
205
        if (!arg.isStackMemory())
206
            return false;
207
        break;
213
    }
208
    }
214
    
215
    Arg::Type type = Arg::typeForB3Type(value->type());
216
209
217
    return arg.isType(type);
210
    return arg.canRepresent(value);
218
}
211
}
219
212
220
bool StackmapSpecial::isArgValidForRep(Air::Code& code, const Air::Arg& arg, const ValueRep& rep)
213
bool StackmapSpecial::isArgValidForRep(Air::Code& code, const Air::Arg& arg, const ValueRep& rep)
- Source/JavaScriptCore/b3/air/AirArg.cpp -4 / +43 lines
Lines 30-38 Source/JavaScriptCore/b3/air/AirArg.cpp_sec1
30
30
31
#include "AirSpecial.h"
31
#include "AirSpecial.h"
32
#include "AirStackSlot.h"
32
#include "AirStackSlot.h"
33
#include "B3Value.h"
34
#include "FPRInfo.h"
35
#include "GPRInfo.h"
33
36
34
namespace JSC { namespace B3 { namespace Air {
37
namespace JSC { namespace B3 { namespace Air {
35
38
39
bool Arg::isStackMemory() const
40
{
41
    switch (kind()) {
42
    case Addr:
43
        return base() == Air::Tmp(GPRInfo::callFrameRegister)
44
            || base() == Air::Tmp(MacroAssembler::stackPointerRegister);
45
    case Stack:
46
    case CallArg:
47
        return true;
48
    default:
49
        return false;
50
    }
51
}
52
36
bool Arg::isRepresentableAs(Width width, Signedness signedness) const
53
bool Arg::isRepresentableAs(Width width, Signedness signedness) const
37
{
54
{
38
    switch (signedness) {
55
    switch (signedness) {
Lines 61-66 bool Arg::isRepresentableAs(Width width, Source/JavaScriptCore/b3/air/AirArg.cpp_sec2
61
    }
78
    }
62
}
79
}
63
80
81
bool Arg::usesTmp(Air::Tmp tmp) const
82
{
83
    bool uses = false;
84
    const_cast<Arg*>(this)->forEachTmpFast(
85
        [&] (Air::Tmp otherTmp) {
86
            if (otherTmp == tmp)
87
                uses = true;
88
        });
89
    return uses;
90
}
91
92
bool Arg::canRepresent(Value* value) const
93
{
94
    return isType(typeForB3Type(value->type()));
95
}
96
64
void Arg::dump(PrintStream& out) const
97
void Arg::dump(PrintStream& out) const
65
{
98
{
66
    switch (m_kind) {
99
    switch (m_kind) {
Lines 111-116 void Arg::dump(PrintStream& out) const Source/JavaScriptCore/b3/air/AirArg.cpp_sec3
111
    case Special:
144
    case Special:
112
        out.print(pointerDump(special()));
145
        out.print(pointerDump(special()));
113
        return;
146
        return;
147
    case WidthArg:
148
        out.print(width());
149
        return;
114
    }
150
    }
115
151
116
    RELEASE_ASSERT_NOT_REACHED();
152
    RELEASE_ASSERT_NOT_REACHED();
Lines 161-166 void printInternal(PrintStream& out, Arg Source/JavaScriptCore/b3/air/AirArg.cpp_sec4
161
    case Arg::Special:
197
    case Arg::Special:
162
        out.print("Special");
198
        out.print("Special");
163
        return;
199
        return;
200
    case Arg::WidthArg:
201
        out.print("WidthArg");
202
        return;
164
    }
203
    }
165
204
166
    RELEASE_ASSERT_NOT_REACHED();
205
    RELEASE_ASSERT_NOT_REACHED();
Lines 225-240 void printInternal(PrintStream& out, Arg Source/JavaScriptCore/b3/air/AirArg.cpp_sec5
225
{
264
{
226
    switch (width) {
265
    switch (width) {
227
    case Arg::Width8:
266
    case Arg::Width8:
228
        out.print("Width8");
267
        out.print("8");
229
        return;
268
        return;
230
    case Arg::Width16:
269
    case Arg::Width16:
231
        out.print("Width16");
270
        out.print("16");
232
        return;
271
        return;
233
    case Arg::Width32:
272
    case Arg::Width32:
234
        out.print("Width32");
273
        out.print("32");
235
        return;
274
        return;
236
    case Arg::Width64:
275
    case Arg::Width64:
237
        out.print("Width64");
276
        out.print("64");
238
        return;
277
        return;
239
    }
278
    }
240
279
- Source/JavaScriptCore/b3/air/AirArg.h -14 / +81 lines
Lines 33-39 Source/JavaScriptCore/b3/air/AirArg.h_sec1
33
#include "B3Type.h"
33
#include "B3Type.h"
34
#include <wtf/Optional.h>
34
#include <wtf/Optional.h>
35
35
36
namespace JSC { namespace B3 { namespace Air {
36
namespace JSC { namespace B3 {
37
38
class Value;
39
40
namespace Air {
37
41
38
class Special;
42
class Special;
39
class StackSlot;
43
class StackSlot;
Lines 69-75 public: Source/JavaScriptCore/b3/air/AirArg.h_sec2
69
        RelCond,
73
        RelCond,
70
        ResCond,
74
        ResCond,
71
        DoubleCond,
75
        DoubleCond,
72
        Special
76
        Special,
77
        WidthArg
73
    };
78
    };
74
79
75
    enum Role : int8_t {
80
    enum Role : int8_t {
Lines 156-161 public: Source/JavaScriptCore/b3/air/AirArg.h_sec3
156
161
157
    static const unsigned numTypes = 2;
162
    static const unsigned numTypes = 2;
158
163
164
    template<typename Functor>
165
    static void forEachType(const Functor& functor)
166
    {
167
        functor(GP);
168
        functor(FP);
169
    }
170
159
    enum Width : int8_t {
171
    enum Width : int8_t {
160
        Width8,
172
        Width8,
161
        Width16,
173
        Width16,
Lines 220-225 public: Source/JavaScriptCore/b3/air/AirArg.h_sec4
220
        return isAnyUse(role) && !isColdUse(role);
232
        return isAnyUse(role) && !isColdUse(role);
221
    }
233
    }
222
234
235
    static Role cooled(Role role)
236
    {
237
        switch (role) {
238
        case ColdUse:
239
        case LateColdUse:
240
        case UseDef:
241
        case UseZDef:
242
        case Def:
243
        case ZDef:
244
        case UseAddr:
245
        case Scratch:
246
        case EarlyDef:
247
            return role;
248
        case Use:
249
            return ColdUse;
250
        case LateUse:
251
            return LateColdUse;
252
        }
253
    }
254
223
    // Returns true if the Role implies that the Inst will Use the Arg before doing anything else.
255
    // Returns true if the Role implies that the Inst will Use the Arg before doing anything else.
224
    static bool isEarlyUse(Role role)
256
    static bool isEarlyUse(Role role)
225
    {
257
    {
Lines 549-554 public: Source/JavaScriptCore/b3/air/AirArg.h_sec5
549
        return result;
581
        return result;
550
    }
582
    }
551
583
584
    static Arg widthArg(Width width)
585
    {
586
        Arg result;
587
        result.m_kind = WidthArg;
588
        result.m_offset = width;
589
        return result;
590
    }
591
552
    bool operator==(const Arg& other) const
592
    bool operator==(const Arg& other) const
553
    {
593
    {
554
        return m_offset == other.m_offset
594
        return m_offset == other.m_offset
Lines 585-590 public: Source/JavaScriptCore/b3/air/AirArg.h_sec6
585
        return kind() == Imm64;
625
        return kind() == Imm64;
586
    }
626
    }
587
627
628
    bool isSomeImm() const
629
    {
630
        return isImm() || isImm64();
631
    }
632
588
    bool isAddr() const
633
    bool isAddr() const
589
    {
634
    {
590
        return kind() == Addr;
635
        return kind() == Addr;
Lines 605-610 public: Source/JavaScriptCore/b3/air/AirArg.h_sec7
605
        return kind() == Index;
650
        return kind() == Index;
606
    }
651
    }
607
652
653
    bool isMemory() const
654
    {
655
        switch (kind()) {
656
        case Addr:
657
        case Stack:
658
        case CallArg:
659
        case Index:
660
            return true;
661
        default:
662
            return false;
663
        }
664
    }
665
666
    bool isStackMemory() const;
667
608
    bool isRelCond() const
668
    bool isRelCond() const
609
    {
669
    {
610
        return kind() == RelCond;
670
        return kind() == RelCond;
Lines 637-642 public: Source/JavaScriptCore/b3/air/AirArg.h_sec8
637
        return kind() == Special;
697
        return kind() == Special;
638
    }
698
    }
639
699
700
    bool isWidthArg() const
701
    {
702
        return kind() == WidthArg;
703
    }
704
640
    bool isAlive() const
705
    bool isAlive() const
641
    {
706
    {
642
        return isTmp() || isStack();
707
        return isTmp() || isStack();
Lines 680-697 public: Source/JavaScriptCore/b3/air/AirArg.h_sec9
680
        return m_base;
745
        return m_base;
681
    }
746
    }
682
747
683
    bool hasOffset() const
748
    bool hasOffset() const { return isMemory(); }
684
    {
685
        switch (kind()) {
686
        case Addr:
687
        case Stack:
688
        case CallArg:
689
        case Index:
690
            return true;
691
        default:
692
            return false;
693
        }
694
    }
695
    
749
    
696
    int32_t offset() const
750
    int32_t offset() const
697
    {
751
    {
Lines 730-735 public: Source/JavaScriptCore/b3/air/AirArg.h_sec10
730
        return bitwise_cast<Air::Special*>(m_offset);
784
        return bitwise_cast<Air::Special*>(m_offset);
731
    }
785
    }
732
786
787
    Width width() const
788
    {
789
        ASSERT(kind() == WidthArg);
790
        return static_cast<Width>(m_offset);
791
    }
792
733
    bool isGPTmp() const
793
    bool isGPTmp() const
734
    {
794
    {
735
        return isTmp() && tmp().isGP();
795
        return isTmp() && tmp().isGP();
Lines 754-759 public: Source/JavaScriptCore/b3/air/AirArg.h_sec11
754
        case ResCond:
814
        case ResCond:
755
        case DoubleCond:
815
        case DoubleCond:
756
        case Special:
816
        case Special:
817
        case WidthArg:
757
            return true;
818
            return true;
758
        case Tmp:
819
        case Tmp:
759
            return isGPTmp();
820
            return isGPTmp();
Lines 771-776 public: Source/JavaScriptCore/b3/air/AirArg.h_sec12
771
        case ResCond:
832
        case ResCond:
772
        case DoubleCond:
833
        case DoubleCond:
773
        case Special:
834
        case Special:
835
        case WidthArg:
774
        case Invalid:
836
        case Invalid:
775
            return false;
837
            return false;
776
        case Addr:
838
        case Addr:
Lines 812-817 public: Source/JavaScriptCore/b3/air/AirArg.h_sec13
812
        }
874
        }
813
    }
875
    }
814
876
877
    bool canRepresent(Value* value) const;
878
815
    bool isGPR() const
879
    bool isGPR() const
816
    {
880
    {
817
        return isTmp() && tmp().isGPR();
881
        return isTmp() && tmp().isGPR();
Lines 953-958 public: Source/JavaScriptCore/b3/air/AirArg.h_sec14
953
        case ResCond:
1017
        case ResCond:
954
        case DoubleCond:
1018
        case DoubleCond:
955
        case Special:
1019
        case Special:
1020
        case WidthArg:
956
            return true;
1021
            return true;
957
        }
1022
        }
958
    }
1023
    }
Lines 974-979 public: Source/JavaScriptCore/b3/air/AirArg.h_sec15
974
        }
1039
        }
975
    }
1040
    }
976
1041
1042
    bool usesTmp(Air::Tmp tmp) const;
1043
977
    // This is smart enough to know that an address arg in a Def or UseDef rule will use its
1044
    // This is smart enough to know that an address arg in a Def or UseDef rule will use its
978
    // tmps and never def them. For example, this:
1045
    // tmps and never def them. For example, this:
979
    //
1046
    //
- Source/JavaScriptCore/b3/air/AirBasicBlock.h -2 / +4 lines
Lines 78-92 public: Source/JavaScriptCore/b3/air/AirBasicBlock.h_sec1
78
    InstList& insts() { return m_insts; }
78
    InstList& insts() { return m_insts; }
79
79
80
    template<typename Inst>
80
    template<typename Inst>
81
    void appendInst(Inst&& inst)
81
    Inst& appendInst(Inst&& inst)
82
    {
82
    {
83
        m_insts.append(std::forward<Inst>(inst));
83
        m_insts.append(std::forward<Inst>(inst));
84
        return m_insts.last();
84
    }
85
    }
85
86
86
    template<typename... Arguments>
87
    template<typename... Arguments>
87
    void append(Arguments&&... arguments)
88
    Inst& append(Arguments&&... arguments)
88
    {
89
    {
89
        m_insts.append(Inst(std::forward<Arguments>(arguments)...));
90
        m_insts.append(Inst(std::forward<Arguments>(arguments)...));
91
        return m_insts.last();
90
    }
92
    }
91
93
92
    // The "0" case is the case to which the branch jumps, so the "then" case. The "1" case is the
94
    // The "0" case is the case to which the branch jumps, so the "then" case. The "1" case is the
- Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp +127 lines
Line 0 Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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 "AirCCallingConvention.h"
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirCCallSpecial.h"
32
#include "AirCode.h"
33
#include "B3CCallValue.h"
34
#include "B3ValueInlines.h"
35
36
namespace JSC { namespace B3 { namespace Air {
37
38
namespace {
39
40
template<typename BankInfo>
41
Arg marshallCCallArgumentImpl(unsigned& argumentCount, unsigned& stackOffset, Value* child)
42
{
43
    unsigned argumentIndex = argumentCount++;
44
    if (argumentIndex < BankInfo::numberOfArgumentRegisters)
45
        return Tmp(BankInfo::toArgumentRegister(argumentIndex));
46
47
    unsigned slotSize;
48
    if (isARM64() && isIOS()) {
49
        // Arguments are packed.
50
        slotSize = sizeofType(child->type());
51
    } else {
52
        // Arguments are aligned.
53
        slotSize = 8;
54
    }
55
56
    stackOffset = WTF::roundUpToMultipleOf(slotSize, stackOffset);
57
    Arg result = Arg::callArg(stackOffset);
58
    stackOffset += slotSize;
59
    return result;
60
}
61
62
Arg marshallCCallArgument(
63
    unsigned& gpArgumentCount, unsigned& fpArgumentCount, unsigned& stackOffset, Value* child)
64
{
65
    switch (Arg::typeForB3Type(child->type())) {
66
    case Arg::GP:
67
        return marshallCCallArgumentImpl<GPRInfo>(gpArgumentCount, stackOffset, child);
68
    case Arg::FP:
69
        return marshallCCallArgumentImpl<FPRInfo>(fpArgumentCount, stackOffset, child);
70
    }
71
    RELEASE_ASSERT_NOT_REACHED();
72
    return Arg();
73
}
74
75
} // anonymous namespace
76
77
Vector<Arg> computeCCallingConvention(Code& code, CCallValue* value)
78
{
79
    Vector<Arg> result;
80
    result.append(Tmp(CCallSpecial::scratchRegister));
81
    unsigned gpArgumentCount = 0;
82
    unsigned fpArgumentCount = 0;
83
    unsigned stackOffset = 0;
84
    for (unsigned i = 1; i < value->numChildren(); ++i) {
85
        result.append(
86
            marshallCCallArgument(gpArgumentCount, fpArgumentCount, stackOffset, value->child(i)));
87
    }
88
    code.requestCallArgAreaSize(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset));
89
    return result;
90
}
91
92
Tmp cCallResult(Type type)
93
{
94
    switch (type) {
95
    case Void:
96
        return Tmp();
97
    case Int32:
98
    case Int64:
99
        return Tmp(GPRInfo::returnValueGPR);
100
    case Float:
101
    case Double:
102
        return Tmp(FPRInfo::returnValueFPR);
103
    }
104
105
    RELEASE_ASSERT_NOT_REACHED();
106
    return Tmp();
107
}
108
109
Inst buildCCall(Code& code, Value* origin, const Vector<Arg>& arguments)
110
{
111
    Inst inst(Patch, origin, Arg::special(code.cCallSpecial()));
112
    inst.args.append(arguments[0]);
113
    inst.args.append(Tmp(GPRInfo::returnValueGPR));
114
    inst.args.append(Tmp(GPRInfo::returnValueGPR2));
115
    inst.args.append(Tmp(FPRInfo::returnValueFPR));
116
    for (unsigned i = 1; i < arguments.size(); ++i) {
117
        Arg arg = arguments[i];
118
        if (arg.isTmp())
119
            inst.args.append(arg);
120
    }
121
    return inst;
122
}
123
124
} } } // namespace JSC::B3::Air
125
126
#endif // ENABLE(B3_JIT)
127
- Source/JavaScriptCore/b3/air/AirCCallingConvention.h +55 lines
Line 0 Source/JavaScriptCore/b3/air/AirCCallingConvention.h_sec1
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef AirCCallingConvention_h
27
#define AirCCallingConvention_h
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirArg.h"
32
#include "AirInst.h"
33
#include "B3Type.h"
34
#include <wtf/Vector.h>
35
36
namespace JSC { namespace B3 {
37
38
class CCallValue;
39
40
namespace Air {
41
42
class Code;
43
44
Vector<Arg> computeCCallingConvention(Code&, CCallValue*);
45
46
Tmp cCallResult(Type);
47
48
Inst buildCCall(Code&, Value* origin, const Vector<Arg>&);
49
50
} } } // namespace JSC::B3::Air
51
52
#endif // ENABLE(B3_JIT)
53
54
#endif // AirCCallingConvention_h
55
- Source/JavaScriptCore/b3/air/AirCode.h -3 / +4 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirCode.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 55-66 public: Source/JavaScriptCore/b3/air/AirCode.h_sec2
55
55
56
    Procedure& proc() { return m_proc; }
56
    Procedure& proc() { return m_proc; }
57
57
58
    BasicBlock* addBlock(double frequency = 1);
58
    JS_EXPORT_PRIVATE BasicBlock* addBlock(double frequency = 1);
59
59
60
    // Note that you can rely on stack slots always getting indices that are larger than the index
60
    // Note that you can rely on stack slots always getting indices that are larger than the index
61
    // of any prior stack slot. In fact, all stack slots you create in the future will have an index
61
    // of any prior stack slot. In fact, all stack slots you create in the future will have an index
62
    // that is >= stackSlots().size().
62
    // that is >= stackSlots().size().
63
    StackSlot* addStackSlot(unsigned byteSize, StackSlotKind, StackSlotValue* = nullptr);
63
    JS_EXPORT_PRIVATE StackSlot* addStackSlot(
64
        unsigned byteSize, StackSlotKind, StackSlotValue* = nullptr);
64
    StackSlot* addStackSlot(StackSlotValue*);
65
    StackSlot* addStackSlot(StackSlotValue*);
65
66
66
    Special* addSpecial(std::unique_ptr<Special>);
67
    Special* addSpecial(std::unique_ptr<Special>);
- Source/JavaScriptCore/b3/air/AirCustom.cpp +138 lines
Line 0 Source/JavaScriptCore/b3/air/AirCustom.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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 "AirCustom.h"
28
29
#if ENABLE(B3_JIT)
30
31
#include "B3CCallValue.h"
32
#include "B3ValueInlines.h"
33
34
namespace JSC { namespace B3 { namespace Air {
35
36
bool CCallCustom::isValidForm(Inst& inst)
37
{
38
    CCallValue* value = inst.origin->as<CCallValue>();
39
    if (!value)
40
        return false;
41
42
    if (inst.args.size() != 1 + (value->type() == Void ? 0 : 1) + value->numChildren())
43
        return false;
44
45
    // The arguments can only refer to the stack, tmps, or immediates.
46
    for (Arg& arg : inst.args) {
47
        if (!arg.isTmp() && !arg.isStackMemory() && !arg.isSomeImm())
48
            return false;
49
    }
50
51
    unsigned offset = 1;
52
53
    // If there is a result then it cannot be an immediate.
54
    if (value->type() != Void) {
55
        if (inst.args[1].isSomeImm())
56
            return false;
57
        if (!inst.args[1].canRepresent(value))
58
            return false;
59
        offset++;
60
    }
61
62
    for (unsigned i = value->numChildren(); i--;) {
63
        Value* child = value->child(i);
64
        Arg arg = inst.args[offset + i];
65
        if (!arg.canRepresent(child))
66
            return false;
67
    }
68
69
    return true;
70
}
71
72
CCallHelpers::Jump CCallCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
73
{
74
    dataLog("FATAL: Unlowered C call: ", inst, "\n");
75
    UNREACHABLE_FOR_PLATFORM();
76
    return CCallHelpers::Jump();
77
}
78
79
bool ShuffleCustom::isValidForm(Inst& inst)
80
{
81
    if (inst.args.size() % 3)
82
        return false;
83
84
    // A destination may only appear once. This requirement allows us to avoid the undefined behavior
85
    // of having a destination that is supposed to get multiple inputs simultaneously. It also
86
    // imposes some interesting constraints on the "shape" of the shuffle. If we treat a shuffle pair
87
    // as an edge and the Args as nodes, then the single-destination requirement means that the
88
    // shuffle graph consists of two kinds of subgraphs:
89
    //
90
    // - Spanning trees. We call these shifts. They can be executed as a sequence of Move
91
    //   instructions and don't usually require scratch registers.
92
    //
93
    // - Closed loops. These loops consist of nodes that have one successor and one predecessor, so
94
    //   there is no way to "get into" the loop from outside of it. These can be executed using swaps
95
    //   or by saving one of the Args to a scratch register and executing it as a shift.
96
    HashSet<Arg> dsts;
97
98
    for (unsigned i = 0; i < inst.args.size(); ++i) {
99
        Arg arg = inst.args[i];
100
        unsigned mode = i % 3;
101
102
        if (mode == 2) {
103
            // It's the width.
104
            if (!arg.isWidthArg())
105
                return false;
106
            continue;
107
        }
108
109
        // The source can be an immediate.
110
        if (!mode) {
111
            if (arg.isSomeImm())
112
                continue;
113
        } else {
114
            ASSERT(mode == 1);
115
            if (!dsts.add(arg).isNewEntry)
116
                return false;
117
        }
118
119
        if (arg.isTmp() || arg.isStackMemory())
120
            continue;
121
122
        return false;
123
    }
124
125
    return true;
126
}
127
128
CCallHelpers::Jump ShuffleCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
129
{
130
    dataLog("FATAL: Unlowered shuffle: ", inst, "\n");
131
    UNREACHABLE_FOR_PLATFORM();
132
    return CCallHelpers::Jump();
133
}
134
135
} } } // namespace JSC::B3::Air
136
137
#endif // ENABLE(B3_JIT)
138
- Source/JavaScriptCore/b3/air/AirCustom.h +110 lines
Lines 30-35 Source/JavaScriptCore/b3/air/AirCustom.h_sec1
30
30
31
#include "AirInst.h"
31
#include "AirInst.h"
32
#include "AirSpecial.h"
32
#include "AirSpecial.h"
33
#include "B3Value.h"
33
34
34
namespace JSC { namespace B3 { namespace Air {
35
namespace JSC { namespace B3 { namespace Air {
35
36
Lines 51-56 namespace JSC { namespace B3 { namespace Source/JavaScriptCore/b3/air/AirCustom.h_sec2
51
// you need to carry extra state around with the instruction. Also, Specials mean that you
52
// you need to carry extra state around with the instruction. Also, Specials mean that you
52
// always have access to Code& even in methods that don't take a GenerationContext.
53
// always have access to Code& even in methods that don't take a GenerationContext.
53
54
55
// Definition of Patch instruction. Patch is used to delegate the behavior of the instruction to the
56
// Special object, which will be the first argument to the instruction.
54
struct PatchCustom {
57
struct PatchCustom {
55
    template<typename Functor>
58
    template<typename Functor>
56
    static void forEachArg(Inst& inst, const Functor& functor)
59
    static void forEachArg(Inst& inst, const Functor& functor)
Lines 96-101 struct PatchCustom { Source/JavaScriptCore/b3/air/AirCustom.h_sec3
96
    }
99
    }
97
};
100
};
98
101
102
// Definition of CCall instruction. CCall is used for hot path C function calls. It's lowered to a
103
// Patch with an Air CCallSpecial along with code to marshal instructions. The lowering happens
104
// before register allocation, so that the register allocator sees the clobbers.
105
struct CCallCustom {
106
    template<typename Functor>
107
    static void forEachArg(Inst& inst, const Functor& functor)
108
    {
109
        Value* value = inst.origin;
110
111
        unsigned index = 0;
112
113
        functor(inst.args[index++], Arg::Use, Arg::GP, Arg::pointerWidth()); // callee
114
        
115
        if (value->type() != Void) {
116
            functor(
117
                inst.args[index++], Arg::Def,
118
                Arg::typeForB3Type(value->type()),
119
                Arg::widthForB3Type(value->type()));
120
        }
121
122
        for (Value* child : value->children()) {
123
            functor(
124
                inst.args[index++], Arg::Use,
125
                Arg::typeForB3Type(child->type()),
126
                Arg::widthForB3Type(child->type()));
127
        }
128
    }
129
130
    template<typename... Arguments>
131
    static bool isValidFormStatic(Arguments...)
132
    {
133
        return false;
134
    }
135
136
    static bool isValidForm(Inst&);
137
138
    static bool admitsStack(Inst&, unsigned)
139
    {
140
        return true;
141
    }
142
143
    static bool hasNonArgNonControlEffects(Inst&)
144
    {
145
        return true;
146
    }
147
148
    // This just crashes, since we expect C calls to be lowered before generation.
149
    static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&);
150
};
151
152
struct ColdCCallCustom : CCallCustom {
153
    template<typename Functor>
154
    static void forEachArg(Inst& inst, const Functor& functor)
155
    {
156
        // This is just like a call, but uses become cold.
157
        CCallCustom::forEachArg(
158
            inst,
159
            [&] (Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width) {
160
                functor(arg, Arg::cooled(role), type, width);
161
            });
162
    }
163
};
164
165
struct ShuffleCustom {
166
    template<typename Functor>
167
    static void forEachArg(Inst& inst, const Functor& functor)
168
    {
169
        unsigned limit = inst.args.size() / 3 * 3;
170
        for (unsigned i = 0; i < limit; i += 3) {
171
            Arg& src = inst.args[i + 0];
172
            Arg& dst = inst.args[i + 1];
173
            Arg& widthArg = inst.args[i + 2];
174
            Arg::Width width = widthArg.width();
175
            Arg::Type type = src.isGP() && dst.isGP() ? Arg::GP : Arg::FP;
176
            functor(src, Arg::Use, type, width);
177
            functor(dst, Arg::Def, type, width);
178
            functor(widthArg, Arg::Use, Arg::GP, Arg::Width8);
179
        }
180
    }
181
182
    template<typename... Arguments>
183
    static bool isValidFormStatic(Arguments...)
184
    {
185
        return false;
186
    }
187
188
    static bool isValidForm(Inst&);
189
    
190
    static bool admitsStack(Inst&, unsigned index)
191
    {
192
        switch (index % 3) {
193
        case 0:
194
        case 1:
195
            return true;
196
        default:
197
            return false;
198
        }
199
    }
200
201
    static bool hasNonArgNonControlEffects(Inst&)
202
    {
203
        return false;
204
    }
205
206
    static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&);
207
};
208
99
} } } // namespace JSC::B3::Air
209
} } } // namespace JSC::B3::Air
100
210
101
#endif // ENABLE(B3_JIT)
211
#endif // ENABLE(B3_JIT)
- Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp +461 lines
Line 0 Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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 "AirEmitShuffle.h"
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirInstInlines.h"
32
#include "AirRegisterPriority.h"
33
#include <wtf/GraphNodeWorklist.h>
34
35
namespace JSC { namespace B3 { namespace Air {
36
37
namespace {
38
39
template<typename Functor>
40
Tmp findPossibleScratch(Arg::Type type, const Functor& functor) {
41
    for (Reg reg : regsInPriorityOrder(type)) {
42
        Tmp tmp(reg);
43
        if (functor(tmp))
44
            return tmp;
45
    }
46
    return Tmp();
47
}
48
49
Tmp findPossibleScratch(Arg::Type type, const Arg& arg1, const Arg& arg2) {
50
    return findPossibleScratch(
51
        type,
52
        [&] (Tmp tmp) -> bool {
53
            return !arg1.usesTmp(tmp) && !arg2.usesTmp(tmp);
54
        });
55
}
56
57
// Example: (a => b, b => a, a => c, b => d)
58
struct Rotate {
59
    Vector<ShufflePair> loop; // in the example, this is the loop: (a => b, b => a)
60
    Vector<ShufflePair> fringe; // in the example, these are the associated shifts: (a => c, b => d)
61
};
62
63
} // anonymous namespace
64
65
void ShufflePair::dump(PrintStream& out) const
66
{
67
    out.print(width(), ":", src(), "=>", dst());
68
}
69
70
Vector<Inst> emitShuffle(
71
    Vector<ShufflePair> pairs, std::array<Arg, 2> scratches, Arg::Type type, Value* origin)
72
{
73
    pairs.removeAllMatching(
74
        [&] (const ShufflePair& pair) -> bool {
75
            return pair.src() == pair.dst();
76
        });
77
    
78
    // First validate that this is the kind of shuffle that we know how to deal with.
79
    for (const ShufflePair& pair : pairs) {
80
        ASSERT(pair.src().isType(type));
81
        ASSERT(pair.dst().isType(type));
82
        ASSERT(pair.dst().isTmp() || pair.dst().isMemory());
83
    }
84
85
    // There are two possible kinds of operations that we will do:
86
    //
87
    // - Shift. Example: (a => b, b => c). We emit this as "Move b, c; Move a, b". This only requires
88
    //   scratch registers if there are memory->memory moves. We want to find as many of these as
89
    //   possible because they are cheaper. Note that shifts can involve the same source mentioned
90
    //   multiple times. Example: (a => b, a => c, b => d, b => e).
91
    //
92
    // - Rotate. Example: (a => b, b => a). We want to emit this as "Swap a, b", but that instruction
93
    //   may not be available, in which case we may need a scratch register or a scratch memory
94
    //   location. A gnarlier example is (a => b, b => c, c => a). We can emit this as "Swap b, c;
95
    //   Swap a, b". Note that swapping has to be careful about differing widths.
96
    //
97
    // Note that a rotate can have "fringe". For example, we might have (a => b, b => a, a =>c,
98
    // b => d). This has a rotate loop (a => b, b => a) and some fringe (a => c, b => d). We treat
99
    // the whole thing as a single rotate.
100
    //
101
    // We will find multiple disjoint such operations. We can execute them in any order.
102
103
    // We interpret these as Moves that should be executed backwards. All shifts are keyed by their
104
    // starting source.
105
    HashMap<Arg, Vector<ShufflePair>> shifts;
106
107
    // We interpret these as Swaps over src()'s that should be executed backwards, i.e. for a list
108
    // of size 3 we would do "Swap list[1].src(), list[2].src(); Swap list[0].src(), list[1].src()".
109
    // Note that we actually can't do that if the widths don't match or other bad things happen.
110
    // But, prior to executing all of that, we need to execute the fringe: the shifts comming off the
111
    // rotate.
112
    Vector<Rotate> rotates;
113
114
    {
115
        HashMap<Arg, Vector<ShufflePair>> mapping;
116
        for (const ShufflePair& pair : pairs)
117
            mapping.add(pair.src(), Vector<ShufflePair>()).iterator->value.append(pair);
118
119
        Vector<ShufflePair> currentPairs;
120
121
        while (!mapping.isEmpty()) {
122
            ASSERT(currentPairs.isEmpty());
123
            Arg originalSrc = mapping.begin()->key;
124
            ASSERT(!shifts.contains(originalSrc));
125
            
126
            GraphNodeWorklist<Arg> worklist;
127
            worklist.push(originalSrc);
128
            while (Arg src = worklist.pop()) {
129
                HashMap<Arg, Vector<ShufflePair>>::iterator iter = mapping.find(src);
130
                if (iter == mapping.end()) {
131
                    // With a shift it's possible that we previously built the tail of this shift.
132
                    // See if that's the case now.
133
                    currentPairs.appendVector(shifts.take(src));
134
                    continue;
135
                }
136
                Vector<ShufflePair> pairs = WTFMove(iter->value);
137
                mapping.remove(iter);
138
139
                for (const ShufflePair& pair : pairs) {
140
                    currentPairs.append(pair);
141
                    ASSERT(pair.src() == src);
142
                    worklist.push(pair.dst());
143
                }
144
            }
145
146
            ASSERT(currentPairs.size());
147
            ASSERT(currentPairs[0].src() == originalSrc);
148
149
            bool isRotate = false;
150
            for (const ShufflePair& pair : currentPairs) {
151
                if (pair.dst() == originalSrc) {
152
                    isRotate = true;
153
                    break;
154
                }
155
            }
156
157
            if (isRotate) {
158
                Rotate rotate;
159
                
160
                // The common case is that the rotate does not have fringe. When this happens, the
161
                // last element is the rotate.
162
                if (currentPairs.last().dst() == originalSrc)
163
                    rotate.loop = WTFMove(currentPairs);
164
                else {
165
                    // This is the slow path. The rotate has fringe. We figure this out by working
166
                    // backward.
167
                    
168
                    HashMap<Arg, ShufflePair> dstMapping;
169
                    for (const ShufflePair& pair : currentPairs)
170
                        dstMapping.add(pair.dst(), pair);
171
172
                    ShufflePair pair = dstMapping.take(originalSrc);
173
                    for (;;) {
174
                        rotate.loop.append(pair);
175
176
                        auto iter = dstMapping.find(pair.src());
177
                        if (iter == dstMapping.end())
178
                            break;
179
                        pair = iter->value;
180
                        dstMapping.remove(iter);
181
                    }
182
183
                    rotate.loop.reverse();
184
185
                    // Make sure that the fringe appears in the same order as how it appeared in the
186
                    // currentPairs, since that's the DFS order.
187
                    for (const ShufflePair& pair : currentPairs) {
188
                        // But of course we only include it if it's not in the loop.
189
                        if (dstMapping.contains(pair.dst()))
190
                            rotate.fringe.append(pair);
191
                    }
192
                }
193
                
194
                // If the graph search terminates because we returned to the first source, then the
195
                // pair list has to have a very particular shape.
196
                for (unsigned i = rotate.loop.size() - 1; i--;)
197
                    ASSERT(rotate.loop[i].dst() == rotate.loop[i + 1].src());
198
                rotates.append(WTFMove(rotate));
199
            } else
200
                shifts.add(originalSrc, WTFMove(currentPairs));
201
        }
202
    }
203
204
    // In the worst case, we need two scratch registers. The way we do this is that the client passes
205
    // us what scratch registers he happens to have laying around. We will need scratch registers in
206
    // the following cases:
207
    //
208
    // - Shuffle pairs where both src and dst refer to memory.
209
    // - Rotate when no Swap instruction is available.
210
    //
211
    // Lucky for us, we are guaranteed to have extra scratch registers anytime we have a Shift that
212
    // ends with a register. We search for such a register right now.
213
214
    auto moveForWidth = [&] (Arg::Width width) -> Opcode {
215
        switch (width) {
216
        case Arg::Width32:
217
            return type == Arg::GP ? Move32 : MoveFloat;
218
        case Arg::Width64:
219
            return type == Arg::GP ? Move : MoveDouble;
220
        default:
221
            RELEASE_ASSERT_NOT_REACHED();
222
        }
223
    };
224
225
    Opcode conservativeMove = moveForWidth(Arg::conservativeWidth(type));
226
227
    // We will emit things in reverse. We maintain a list of packs of instructions, and then we emit
228
    // append them together in reverse (for example the thing at the end of resultPacks is placed
229
    // first). This is useful because the last thing we emit frees up its destination registers, so
230
    // it affects how we emit things before it.
231
    Vector<Vector<Inst>> resultPacks;
232
    Vector<Inst> result;
233
234
    auto commitResult = [&] () {
235
        resultPacks.append(WTFMove(result));
236
    };
237
238
    auto getScratch = [&] (unsigned index, Tmp possibleScratch) -> Tmp {
239
        if (scratches[index].isTmp())
240
            return scratches[index].tmp();
241
242
        if (!possibleScratch)
243
            return Tmp();
244
        result.append(Inst(conservativeMove, origin, possibleScratch, scratches[index]));
245
        return possibleScratch;
246
    };
247
248
    auto returnScratch = [&] (unsigned index, Tmp tmp) {
249
        if (Arg(tmp) != scratches[index])
250
            result.append(Inst(conservativeMove, origin, scratches[index], tmp));
251
    };
252
253
    auto handleShiftPair = [&] (const ShufflePair& pair, unsigned scratchIndex) {
254
        Opcode move = moveForWidth(pair.width());
255
        
256
        if (!isValidForm(move, pair.src().kind(), pair.dst().kind())) {
257
            Tmp scratch =
258
                getScratch(scratchIndex, findPossibleScratch(type, pair.src(), pair.dst()));
259
            RELEASE_ASSERT(scratch);
260
            if (isValidForm(move, pair.src().kind(), Arg::Tmp))
261
                result.append(Inst(moveForWidth(pair.width()), origin, pair.src(), scratch));
262
            else {
263
                ASSERT(pair.src().isSomeImm());
264
                ASSERT(move == Move32);
265
                result.append(Inst(Move, origin, Arg::imm64(pair.src().value()), scratch));
266
            }
267
            result.append(Inst(moveForWidth(pair.width()), origin, scratch, pair.dst()));
268
            returnScratch(scratchIndex, scratch);
269
            return;
270
        }
271
        
272
        result.append(Inst(move, origin, pair.src(), pair.dst()));
273
    };
274
275
    auto handleShift = [&] (Vector<ShufflePair>& shift) {
276
        for (unsigned i = shift.size(); i--;)
277
            handleShiftPair(shift[i], 0);
278
279
        Arg lastDst = shift.last().dst();
280
        if (lastDst.isTmp()) {
281
            for (Arg& scratch : scratches) {
282
                ASSERT(scratch != lastDst);
283
                if (!scratch.isTmp()) {
284
                    scratch = lastDst;
285
                    break;
286
                }
287
            }
288
        }
289
    };
290
291
    // First handle shifts whose last destination is a tmp because these free up scratch registers.
292
    // These end up last in the final sequence, so the final destination of these shifts will be
293
    // available as a scratch location for anything emitted prior (so, after, since we're emitting in
294
    // reverse).
295
    for (auto& entry : shifts) {
296
        Vector<ShufflePair>& shift = entry.value;
297
        if (shift.last().dst().isTmp())
298
            handleShift(shift);
299
        commitResult();
300
    }
301
302
    // Now handle the rest of the shifts.
303
    for (auto& entry : shifts) {
304
        Vector<ShufflePair>& shift = entry.value;
305
        if (!shift.last().dst().isTmp())
306
            handleShift(shift);
307
        commitResult();
308
    }
309
310
    for (Rotate& rotate : rotates) {
311
        if (!rotate.fringe.isEmpty()) {
312
            // Make sure we do the fringe first! This won't clobber any of the registers that are
313
            // part of the rotation.
314
            handleShift(rotate.fringe);
315
        }
316
        
317
        bool canSwap = false;
318
        Opcode swap = Oops;
319
        Arg::Width swapWidth = Arg::Width8; // bogus value
320
        
321
        if (type == Arg::GP) {
322
            swap = Swap32;
323
            swapWidth = Arg::Width32;
324
            for (ShufflePair& pair : rotate.loop) {
325
                switch (pair.width()) {
326
                case Arg::Width32:
327
                    break;
328
                case Arg::Width64:
329
                    swap = Swap64;
330
                    swapWidth = Arg::Width64;
331
                    break;
332
                default:
333
                    RELEASE_ASSERT_NOT_REACHED();
334
                    break;
335
                }
336
            }
337
            
338
            canSwap = isValidForm(swap, Arg::Tmp, Arg::Tmp);
339
            for (ShufflePair& pair : rotate.loop) {
340
                if (pair.src().isMemory() || pair.dst().isMemory()) {
341
                    canSwap &= isValidForm(swap, Arg::Tmp, Arg::Addr);
342
343
                    // We don't take the swapping path if there is a mix of widths and some of the
344
                    // shuffles involve memory. That gets too confusing.
345
                    canSwap &= (pair.width() < swapWidth);
346
                }
347
            }
348
        }
349
350
        if (canSwap) {
351
            for (unsigned i = rotate.loop.size() - 1; i--;) {
352
                Arg left = rotate.loop[i].src();
353
                Arg right = rotate.loop[i + 1].src();
354
355
                if (left.isMemory() && right.isMemory()) {
356
                    // Note that this is a super rare outcome. Rotates are rare. Spills are rare.
357
                    // Moving data between two spills is rare. To get here a lot of rare stuff has to
358
                    // all happen at once.
359
                    
360
                    Tmp scratch = getScratch(0, findPossibleScratch(type, left, right));
361
                    RELEASE_ASSERT(scratch);
362
                    result.append(Inst(moveForWidth(swapWidth), origin, left, scratch));
363
                    result.append(Inst(swap, origin, scratch, right));
364
                    result.append(Inst(moveForWidth(swapWidth), origin, scratch, left));
365
                    returnScratch(0, scratch);
366
                    continue;
367
                }
368
369
                if (left.isMemory())
370
                    std::swap(left, right);
371
                
372
                result.append(Inst(swap, origin, left, right));
373
            }
374
375
            for (ShufflePair pair : rotate.loop) {
376
                if (pair.width() == swapWidth)
377
                    continue;
378
379
                RELEASE_ASSERT(pair.width() == Arg::Width32);
380
                RELEASE_ASSERT(swapWidth == Arg::Width64);
381
                RELEASE_ASSERT(pair.dst().isTmp());
382
383
                // Need to do an extra zero extension.
384
                result.append(Inst(Move32, origin, pair.dst(), pair.dst()));
385
            }
386
        } else {
387
            // We can treat this as a shift so long as we take the last destination (i.e. first
388
            // source) and save it first. Then we handle the first entry in the pair in the rotate
389
            // specially, after we restore the last destination. This requires some special care to
390
            // find a scratch register. It's possible that we have a rotate that uses the entire
391
            // available register file.
392
393
            Tmp scratch = findPossibleScratch(
394
                type,
395
                [&] (Tmp tmp) -> bool {
396
                    for (ShufflePair pair : rotate.loop) {
397
                        if (pair.src().usesTmp(tmp))
398
                            return false;
399
                        if (pair.dst().usesTmp(tmp))
400
                            return false;
401
                    }
402
                    return true;
403
                });
404
405
            scratch = getScratch(0, scratch);
406
407
            Arg rotateSave = scratch ? Arg(scratch) : scratches[0];
408
            
409
            handleShiftPair(
410
                ShufflePair(rotate.loop.last().dst(), rotateSave, rotate.loop[0].width()), 1);
411
412
            for (unsigned i = rotate.loop.size(); i-- > 1;)
413
                handleShiftPair(rotate.loop[i], 1);
414
415
            handleShiftPair(
416
                ShufflePair(rotateSave, rotate.loop[0].dst(), rotate.loop[0].width()), 1);
417
418
            if (scratch)
419
                returnScratch(0, scratch);
420
        }
421
422
        commitResult();
423
    }
424
425
    ASSERT(result.isEmpty());
426
427
    for (unsigned i = resultPacks.size(); i--;)
428
        result.appendVector(resultPacks[i]);
429
430
    return result;
431
}
432
433
Vector<Inst> emitShuffle(
434
    const Vector<ShufflePair>& pairs,
435
    const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch,
436
    Value* origin)
437
{
438
    Vector<ShufflePair> gpPairs;
439
    Vector<ShufflePair> fpPairs;
440
    for (const ShufflePair& pair : pairs) {
441
        if (pair.src().isMemory() && pair.dst().isMemory() && pair.width() > Arg::pointerWidth()) {
442
            // 8-byte memory-to-memory moves on a 32-bit platform are best handled as float moves.
443
            fpPairs.append(pair);
444
        } else if (pair.src().isGP() && pair.dst().isGP()) {
445
            // This means that gpPairs gets memory-to-memory shuffles. The assumption is that we
446
            // can do that more efficiently using GPRs, except in the special case above.
447
            gpPairs.append(pair);
448
        } else
449
            fpPairs.append(pair);
450
    }
451
452
    Vector<Inst> result;
453
    result.appendVector(emitShuffle(gpPairs, gpScratch, Arg::GP, origin));
454
    result.appendVector(emitShuffle(fpPairs, fpScratch, Arg::FP, origin));
455
    return result;
456
}
457
458
} } } // namespace JSC::B3::Air
459
460
#endif // ENABLE(B3_JIT)
461
- Source/JavaScriptCore/b3/air/AirEmitShuffle.h +112 lines
Line 0 Source/JavaScriptCore/b3/air/AirEmitShuffle.h_sec1
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef AirEmitShuffle_h
27
#define AirEmitShuffle_h
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirArg.h"
32
#include "AirInst.h"
33
#include <wtf/Vector.h>
34
35
namespace JSC { namespace B3 {
36
37
class Value;
38
39
namespace Air {
40
41
class ShufflePair {
42
public:
43
    ShufflePair()
44
    {
45
    }
46
    
47
    ShufflePair(const Arg& src, const Arg& dst, Arg::Width width)
48
        : m_src(src)
49
        , m_dst(dst)
50
        , m_width(width)
51
    {
52
    }
53
54
    const Arg& src() const { return m_src; }
55
    const Arg& dst() const { return m_dst; }
56
57
    // The width determines the kind of move we do. You can only choose Width32 or Width64 right now.
58
    // For GP, it picks between Move32 and Move. For FP, it picks between MoveFloat and MoveDouble.
59
    Arg::Width width() const { return m_width; }
60
61
    void dump(PrintStream&) const;
62
    
63
private:
64
    Arg m_src;
65
    Arg m_dst;
66
    Arg::Width m_width { Arg::Width8 };
67
};
68
69
// Perform a shuffle of a given type. The scratch argument is mandatory. You should pass it as
70
// follows: If you know that you have scratch registers or temporaries available - that is, they're
71
// registers that are not mentioned in the shuffle, have the same type as the shuffle, and are not
72
// live at the shuffle - then you can pass them. If you don't have scratch registers available or if
73
// you don't feel like looking for them, you can pass memory locations. It's always safe to pass a
74
// pair of memory locations, and replacing either memory location with a register can be viewed as an
75
// optimization. It's a pretty important optimization. Some more notes:
76
//
77
// - We define scratch registers as things that are not live before the shuffle and are not one of
78
//   the destinations of the shuffle. Not being live before the shuffle also means that they cannot
79
//   be used 
80
//
81
// - A second scratch location is only needed when you have shuffle pairs where memory is used both
82
//   as source and destination.
83
//
84
// - You're guaranteed not to need any scratch locations if there is a Swap instruction available for
85
//   the type and you don't have any memory locations that are both the source and the destination of
86
//   some pairs. GP supports Swap on x86 while FP never supports Swap.
87
//
88
// - Passing memory locations as scratch if are running emitShuffle() before register allocation is
89
//   silly, since that will cause emitShuffle() to pick some specific registers when it does need
90
//   scratch. One easy way to avoid that predicament is to ensure that you call emitShuffle() after
91
//   register allocation. For this reason we could add a Shuffle instruction so that we can defer
92
//   shufflings until after regalloc.
93
//
94
// - Shuffles with memory=>memory pairs are not very well tuned. You should avoid them if you want
95
//   performance. If you need to do them, then making sure that you reserve a temporary is one way to
96
//   get acceptable performance.
97
Vector<Inst> emitShuffle(
98
    Vector<ShufflePair>, std::array<Arg, 2> scratch, Arg::Type, Value* origin);
99
100
// Perform a shuffle that involves any number of types. Pass scratch registers or memory locations
101
// for each type according to the rules above.
102
Vector<Inst> emitShuffle(
103
    const Vector<ShufflePair>&,
104
    const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch,
105
    Value* origin);
106
107
} } } // namespace JSC::B3::Air
108
109
#endif // ENABLE(B3_JIT)
110
111
#endif // AirEmitShuffle_h
112
- Source/JavaScriptCore/b3/air/AirGenerate.cpp -1 / +7 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirGenerate.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 35-40 Source/JavaScriptCore/b3/air/AirGenerate.cpp_sec2
35
#include "AirGenerationContext.h"
35
#include "AirGenerationContext.h"
36
#include "AirHandleCalleeSaves.h"
36
#include "AirHandleCalleeSaves.h"
37
#include "AirIteratedRegisterCoalescing.h"
37
#include "AirIteratedRegisterCoalescing.h"
38
#include "AirLowerAfterRegAlloc.h"
39
#include "AirLowerMacros.h"
38
#include "AirOpcodeUtils.h"
40
#include "AirOpcodeUtils.h"
39
#include "AirOptimizeBlockOrder.h"
41
#include "AirOptimizeBlockOrder.h"
40
#include "AirReportUsedRegisters.h"
42
#include "AirReportUsedRegisters.h"
Lines 65-70 void prepareForGeneration(Code& code) Source/JavaScriptCore/b3/air/AirGenerate.cpp_sec3
65
        dataLog(code);
67
        dataLog(code);
66
    }
68
    }
67
69
70
    lowerMacros(code);
71
68
    // This is where we run our optimizations and transformations.
72
    // This is where we run our optimizations and transformations.
69
    // FIXME: Add Air optimizations.
73
    // FIXME: Add Air optimizations.
70
    // https://bugs.webkit.org/show_bug.cgi?id=150456
74
    // https://bugs.webkit.org/show_bug.cgi?id=150456
Lines 80-85 void prepareForGeneration(Code& code) Source/JavaScriptCore/b3/air/AirGenerate.cpp_sec4
80
    else
84
    else
81
        iteratedRegisterCoalescing(code);
85
        iteratedRegisterCoalescing(code);
82
86
87
    lowerAfterRegAlloc(code);
88
83
    // Prior to this point the prologue and epilogue is implicit. This makes it explicit. It also
89
    // Prior to this point the prologue and epilogue is implicit. This makes it explicit. It also
84
    // does things like identify which callee-saves we're using and saves them.
90
    // does things like identify which callee-saves we're using and saves them.
85
    handleCalleeSaves(code);
91
    handleCalleeSaves(code);
- Source/JavaScriptCore/b3/air/AirGenerate.h -3 / +3 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirGenerate.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 38-48 class Code; Source/JavaScriptCore/b3/air/AirGenerate.h_sec2
38
38
39
// This takes an Air::Code that hasn't had any stack allocation and optionally hasn't had any
39
// This takes an Air::Code that hasn't had any stack allocation and optionally hasn't had any
40
// register allocation and does both of those things.
40
// register allocation and does both of those things.
41
void prepareForGeneration(Code&);
41
JS_EXPORT_PRIVATE void prepareForGeneration(Code&);
42
42
43
// This generates the code using the given CCallHelpers instance. Note that this may call callbacks
43
// This generates the code using the given CCallHelpers instance. Note that this may call callbacks
44
// in the supplied code as it is generating.
44
// in the supplied code as it is generating.
45
void generate(Code&, CCallHelpers&);
45
JS_EXPORT_PRIVATE void generate(Code&, CCallHelpers&);
46
46
47
} } } // namespace JSC::B3::Air
47
} } } // namespace JSC::B3::Air
48
48
- Source/JavaScriptCore/b3/air/AirInsertionSet.cpp -1 / +13 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirInsertionSet.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 33-38 Source/JavaScriptCore/b3/air/AirInsertionSet.cpp_sec2
33
33
34
namespace JSC { namespace B3 { namespace Air {
34
namespace JSC { namespace B3 { namespace Air {
35
35
36
void InsertionSet::insertInsts(size_t index, const Vector<Inst>& insts)
37
{
38
    for (const Inst& inst : insts)
39
        insertInst(index, inst);
40
}
41
42
void InsertionSet::insertInsts(size_t index, Vector<Inst>&& insts)
43
{
44
    for (Inst& inst : insts)
45
        insertInst(index, WTFMove(inst));
46
}
47
36
void InsertionSet::execute(BasicBlock* block)
48
void InsertionSet::execute(BasicBlock* block)
37
{
49
{
38
    bubbleSort(m_insertions.begin(), m_insertions.end());
50
    bubbleSort(m_insertions.begin(), m_insertions.end());
- Source/JavaScriptCore/b3/air/AirInsertionSet.h -1 / +4 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirInsertionSet.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 59-64 public: Source/JavaScriptCore/b3/air/AirInsertionSet.h_sec2
59
    {
59
    {
60
        appendInsertion(Insertion(index, std::forward<Inst>(inst)));
60
        appendInsertion(Insertion(index, std::forward<Inst>(inst)));
61
    }
61
    }
62
63
    void insertInsts(size_t index, const Vector<Inst>&);
64
    void insertInsts(size_t index, Vector<Inst>&&);
62
    
65
    
63
    template<typename... Arguments>
66
    template<typename... Arguments>
64
    void insert(size_t index, Arguments&&... arguments)
67
    void insert(size_t index, Arguments&&... arguments)
- Source/JavaScriptCore/b3/air/AirInst.h +9 lines
Lines 85-90 public: Source/JavaScriptCore/b3/air/AirInst.h_sec1
85
85
86
    explicit operator bool() const { return origin || opcode != Nop || args.size(); }
86
    explicit operator bool() const { return origin || opcode != Nop || args.size(); }
87
87
88
    void append() { }
89
    
90
    template<typename... Arguments>
91
    void append(Arg arg, Arguments... arguments)
92
    {
93
        args.append(arg);
94
        append(arguments...);
95
    }
96
88
    // Note that these functors all avoid using "const" because we want to use them for things that
97
    // Note that these functors all avoid using "const" because we want to use them for things that
89
    // edit IR. IR is meant to be edited; if you're carrying around a "const Inst&" then you're
98
    // edit IR. IR is meant to be edited; if you're carrying around a "const Inst&" then you're
90
    // probably doing it wrong.
99
    // probably doing it wrong.
- Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp +207 lines
Line 0 Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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 "AirLowerAfterRegAlloc.h"
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirCCallingConvention.h"
32
#include "AirCode.h"
33
#include "AirEmitShuffle.h"
34
#include "AirInsertionSet.h"
35
#include "AirInstInlines.h"
36
#include "AirLiveness.h"
37
#include "AirPhaseScope.h"
38
#include "AirRegisterPriority.h"
39
#include "B3CCallValue.h"
40
#include "RegisterSet.h"
41
#include <wtf/HashMap.h>
42
43
namespace JSC { namespace B3 { namespace Air {
44
45
void lowerAfterRegAlloc(Code& code)
46
{
47
    PhaseScope phaseScope(code, "lowerAfterRegAlloc");
48
49
    HashMap<Inst*, RegisterSet> usedRegisters;
50
51
    RegLiveness liveness(code);
52
    for (BasicBlock* block : code) {
53
        RegLiveness::LocalCalc localCalc(liveness, block);
54
55
        for (unsigned instIndex = block->size(); instIndex--;) {
56
            Inst& inst = block->at(instIndex);
57
            
58
            RegisterSet set;
59
60
            if (inst.opcode == Shuffle || inst.opcode == ColdCCall) {
61
                for (Reg reg : localCalc.live())
62
                    set.set(reg);
63
            }
64
            
65
            localCalc.execute(instIndex);
66
67
            if (set.numberOfSetRegisters())
68
                usedRegisters.add(&inst, set);
69
        }
70
    }
71
72
    auto getScratches = [&] (const RegisterSet& set, Arg::Type type) -> std::array<Arg, 2> {
73
        std::array<Arg, 2> result;
74
        for (unsigned i = 0; i < 2; ++i) {
75
            bool found = false;
76
            for (Reg reg : regsInPriorityOrder(type)) {
77
                if (!set.get(reg)) {
78
                    result[i] = Tmp(reg);
79
                    found = true;
80
                    break;
81
                }
82
            }
83
            if (!found) {
84
                result[i] = Arg::stack(
85
                    code.addStackSlot(
86
                        Arg::bytes(Arg::conservativeWidth(type)),
87
                        StackSlotKind::Anonymous));
88
            }
89
        }
90
        return result;
91
    };
92
93
    // Now transform the code.
94
    InsertionSet insertionSet(code);
95
    for (BasicBlock* block : code) {
96
        for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
97
            Inst& inst = block->at(instIndex);
98
99
            switch (inst.opcode) {
100
            case Shuffle: {
101
                RegisterSet set = usedRegisters.get(&inst);
102
                Vector<ShufflePair> pairs;
103
                for (unsigned i = 0; i < inst.args.size(); i += 3) {
104
                    Arg src = inst.args[i + 0];
105
                    Arg dst = inst.args[i + 1];
106
                    Arg::Width width = inst.args[i + 2].width();
107
                    if (src.isReg())
108
                        set.set(src.reg());
109
                    pairs.append(ShufflePair(src, dst, width));
110
                }
111
                std::array<Arg, 2> gpScratch = getScratches(set, Arg::GP);
112
                std::array<Arg, 2> fpScratch = getScratches(set, Arg::FP);
113
                insertionSet.insertInsts(
114
                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
115
                inst = Inst();
116
                break;
117
            }
118
119
            case ColdCCall: {
120
                CCallValue* value = inst.origin->as<CCallValue>();
121
122
                RegisterSet preUsed;
123
                Vector<Arg> destinations = computeCCallingConvention(code, value);
124
                Tmp result = cCallResult(value->type());
125
                
126
                Vector<ShufflePair> pairs;
127
                for (unsigned i = 0; i < destinations.size(); ++i) {
128
                    Value* child = value->child(i);
129
                    Arg src = inst.args[result ? (i >= 1 ? i + 1 : i) : i ];
130
                    Arg dst = destinations[i];
131
                    Arg::Width width = Arg::widthForB3Type(child->type());
132
                    pairs.append(ShufflePair(src, dst, width));
133
                    if (src.isReg())
134
                        preUsed.set(src.reg());
135
                }
136
137
                std::array<Arg, 2> gpScratch = getScratches(preUsed, Arg::GP);
138
                std::array<Arg, 2> fpScratch = getScratches(preUsed, Arg::FP);
139
                
140
                RegisterSet regsToSave = usedRegisters.get(&inst);
141
142
                // Also need to save all live registers. Don't need to worry about the result
143
                // register.
144
                if (result)
145
                    regsToSave.clear(result.reg());
146
                Vector<StackSlot*> stackSlots;
147
                regsToSave.forEach(
148
                    [&] (Reg reg) {
149
                        Tmp tmp(reg);
150
                        Arg arg(tmp);
151
                        Arg::Width width = Arg::conservativeWidth(arg.type());
152
                        StackSlot* stackSlot =
153
                            code.addStackSlot(Arg::bytes(width), StackSlotKind::Anonymous);
154
                        pairs.append(ShufflePair(arg, Arg::stack(stackSlot), width));
155
                        stackSlots.append(stackSlot);
156
                    });
157
                
158
                insertionSet.insertInsts(
159
                    instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
160
161
                inst = buildCCall(code, inst.origin, destinations);
162
163
                // Now we need to emit code to restore registers.
164
                pairs.resize(0);
165
                unsigned stackSlotIndex = 0;
166
                regsToSave.forEach(
167
                    [&] (Reg reg) {
168
                        Tmp tmp(reg);
169
                        Arg arg(tmp);
170
                        Arg::Width width = Arg::conservativeWidth(arg.type());
171
                        StackSlot* stackSlot = stackSlots[stackSlotIndex++];
172
                        pairs.append(ShufflePair(Arg::stack(stackSlot), arg, width));
173
                    });
174
                if (result) {
175
                    ShufflePair pair(result, inst.args[1], Arg::widthForB3Type(value->type()));
176
                    pairs.append(pair);
177
                }
178
179
                if (result)
180
                    regsToSave.set(result.reg());
181
                
182
                gpScratch = getScratches(regsToSave, Arg::GP);
183
                fpScratch = getScratches(regsToSave, Arg::FP);
184
                
185
                insertionSet.insertInsts(
186
                    instIndex + 1, emitShuffle(pairs, gpScratch, fpScratch, inst.origin));
187
                break;
188
            }
189
190
            default:
191
                break;
192
            }
193
        }
194
195
        insertionSet.execute(block);
196
197
        block->insts().removeAllMatching(
198
            [&] (Inst& inst) -> bool {
199
                return !inst;
200
            });
201
    }
202
}
203
204
} } } // namespace JSC::B3::Air
205
206
#endif // ENABLE(B3_JIT)
207
- Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.h +44 lines
Line 0 Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.h_sec1
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef AirLowerAfterRegAlloc_h
27
#define AirLowerAfterRegAlloc_h
28
29
#if ENABLE(B3_JIT)
30
31
namespace JSC { namespace B3 { namespace Air {
32
33
class Code;
34
35
// This lowers Shuffle and ColdCCall instructions. This phase is designed to be run after register
36
// allocation.
37
38
void lowerAfterRegAlloc(Code&);
39
40
} } } // namespace JSC::B3::Air
41
42
#endif // ENABLE(B3_JIT)
43
44
#endif // AirLowerAfterRegAlloc_h
- Source/JavaScriptCore/b3/air/AirLowerMacros.cpp +105 lines
Line 0 Source/JavaScriptCore/b3/air/AirLowerMacros.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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 "AirLowerMacros.h"
28
29
#if ENABLE(B3_JIT)
30
31
#include "AirCCallingConvention.h"
32
#include "AirCode.h"
33
#include "AirInsertionSet.h"
34
#include "AirInstInlines.h"
35
#include "AirPhaseScope.h"
36
#include "B3CCallValue.h"
37
#include "B3ValueInlines.h"
38
39
namespace JSC { namespace B3 { namespace Air {
40
41
void lowerMacros(Code& code)
42
{
43
    PhaseScope phaseScope(code, "lowerMacros");
44
45
    InsertionSet insertionSet(code);
46
    for (BasicBlock* block : code) {
47
        for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
48
            Inst& inst = block->at(instIndex);
49
50
            switch (inst.opcode) {
51
            case CCall: {
52
                CCallValue* value = inst.origin->as<CCallValue>();
53
54
                Vector<Arg> destinations = computeCCallingConvention(code, value);
55
56
                Inst shuffleArguments(Shuffle, value);
57
                unsigned offset = value->type() == Void ? 0 : 1;
58
                for (unsigned i = 1; i < destinations.size(); ++i) {
59
                    Value* child = value->child(i);
60
                    shuffleArguments.args.append(inst.args[offset + i]);
61
                    shuffleArguments.args.append(destinations[i]);
62
                    shuffleArguments.args.append(Arg::widthArg(Arg::widthForB3Type(child->type())));
63
                }
64
                insertionSet.insertInst(instIndex, WTFMove(shuffleArguments));
65
66
                // Indicate that we're using our original callee argument.
67
                destinations[0] = inst.args[0];
68
69
                // Save where the original instruction put its result.
70
                Arg resultDst = value->type() == Void ? Arg() : inst.args[1];
71
                
72
                inst = buildCCall(code, inst.origin, destinations);
73
74
                Tmp result = cCallResult(value->type());
75
                switch (value->type()) {
76
                case Void:
77
                    break;
78
                case Float:
79
                    insertionSet.insert(instIndex + 1, MoveFloat, value, result, resultDst);
80
                    break;
81
                case Double:
82
                    insertionSet.insert(instIndex + 1, MoveDouble, value, result, resultDst);
83
                    break;
84
                case Int32:
85
                    insertionSet.insert(instIndex + 1, Move32, value, result, resultDst);
86
                    break;
87
                case Int64:
88
                    insertionSet.insert(instIndex + 1, Move, value, result, resultDst);
89
                    break;
90
                }
91
                break;
92
            }
93
94
            default:
95
                break;
96
            }
97
        }
98
        insertionSet.execute(block);
99
    }
100
}
101
102
} } } // namespace JSC::B3::Air
103
104
#endif // ENABLE(B3_JIT)
105
- Source/JavaScriptCore/b3/air/AirLowerMacros.h +45 lines
Line 0 Source/JavaScriptCore/b3/air/AirLowerMacros.h_sec1
1
/*
2
 * Copyright (C) 2016 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef AirLowerMacros_h
27
#define AirLowerMacros_h
28
29
#if ENABLE(B3_JIT)
30
31
namespace JSC { namespace B3 { namespace Air {
32
33
class Code;
34
35
// Air has some opcodes that are very high-level and are meant to reduce the amount of low-level
36
// knowledge in the B3->Air lowering. The current example is CCall.
37
38
void lowerMacros(Code&);
39
40
} } } // namespace JSC::B3::Air
41
42
#endif // ENABLE(B3_JIT)
43
44
#endif // AirLowerMacros_h
45
- Source/JavaScriptCore/b3/air/AirOpcode.opcodes +20 lines
Lines 407-412 Move U:G:Ptr, D:G:Ptr Source/JavaScriptCore/b3/air/AirOpcode.opcodes_sec1
407
    Tmp, Index as storePtr
407
    Tmp, Index as storePtr
408
    x86: Imm, Addr as storePtr
408
    x86: Imm, Addr as storePtr
409
409
410
x86: Swap32 UD:G:32, UD:G:32
411
    Tmp, Tmp
412
    Tmp, Addr
413
414
x86_64: Swap64 UD:G:64, UD:G:64
415
    Tmp, Tmp
416
    Tmp, Addr
417
410
Move32 U:G:32, ZD:G:32
418
Move32 U:G:32, ZD:G:32
411
    Tmp, Tmp as zeroExtend32ToPtr
419
    Tmp, Tmp as zeroExtend32ToPtr
412
    Addr, Tmp as load32
420
    Addr, Tmp as load32
Lines 672-678 RetDouble U:F:64 /return Source/JavaScriptCore/b3/air/AirOpcode.opcodes_sec2
672
680
673
Oops /terminal
681
Oops /terminal
674
682
683
# A Shuffle is a multi-source, multi-destination move. It simultaneously does multiple moves at once.
684
# The moves are specified as triplets of src, dst, and width. For example you can request a swap this
685
# way:
686
#     Shuffle %tmp1, %tmp2, 64, %tmp2, %tmp1, 64
687
custom Shuffle
688
675
# Air allows for exotic behavior. A Patch's behavior is determined entirely by the Special operand,
689
# Air allows for exotic behavior. A Patch's behavior is determined entirely by the Special operand,
676
# which must be the first operand.
690
# which must be the first operand.
677
custom Patch
691
custom Patch
678
692
693
# Instructions used for lowering C calls. These don't make it to Air generation. They get lowered to
694
# something else first. The origin Value must be a CCallValue.
695
custom CCall
696
custom ColdCCall
697
698
- Source/JavaScriptCore/b3/air/AirRegisterPriority.h -2 / +2 lines
Lines 1-5 Source/JavaScriptCore/b3/air/AirRegisterPriority.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2015 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 52-58 const Vector<typename Bank::RegisterType Source/JavaScriptCore/b3/air/AirRegisterPriority.h_sec2
52
    return RegistersInPriorityOrder<Bank>::inPriorityOrder();
52
    return RegistersInPriorityOrder<Bank>::inPriorityOrder();
53
}
53
}
54
54
55
const Vector<Reg>& regsInPriorityOrder(Arg::Type);
55
JS_EXPORT_PRIVATE const Vector<Reg>& regsInPriorityOrder(Arg::Type);
56
56
57
} } } // namespace JSC::B3::Air
57
} } } // namespace JSC::B3::Air
58
58
- Source/JavaScriptCore/b3/air/testair.cpp +809 lines
Line 0 Source/JavaScriptCore/b3/air/testair.cpp_sec1
1
/*
2
 * Copyright (C) 2016 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
28
#include "AirCode.h"
29
#include "AirGenerate.h"
30
#include "AirInstInlines.h"
31
#include "AirRegisterPriority.h"
32
#include "AllowMacroScratchRegisterUsage.h"
33
#include "B3Compilation.h"
34
#include "B3Procedure.h"
35
#include "CCallHelpers.h"
36
#include "InitializeThreading.h"
37
#include "JSCInlines.h"
38
#include "LinkBuffer.h"
39
#include "PureNaN.h"
40
#include "VM.h"
41
#include <cmath>
42
#include <string>
43
#include <wtf/Lock.h>
44
#include <wtf/NumberOfCores.h>
45
#include <wtf/Threading.h>
46
47
// We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
48
static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
49
50
static void usage()
51
{
52
    dataLog("Usage: testb3 [<filter>]\n");
53
    if (hiddenTruthBecauseNoReturnIsStupid())
54
        exit(1);
55
}
56
57
#if ENABLE(B3_JIT)
58
59
using namespace JSC;
60
using namespace JSC::B3::Air;
61
62
namespace {
63
64
StaticLock crashLock;
65
66
// Nothing fancy for now; we just use the existing WTF assertion machinery.
67
#define CHECK(x) do {                                                   \
68
        if (!!(x))                                                      \
69
            break;                                                      \
70
        crashLock.lock();                                               \
71
        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
72
        CRASH();                                                        \
73
    } while (false)
74
75
VM* vm;
76
77
std::unique_ptr<B3::Compilation> compile(B3::Procedure& proc)
78
{
79
    prepareForGeneration(proc.code());
80
    CCallHelpers jit(vm);
81
    generate(proc.code(), jit);
82
    LinkBuffer linkBuffer(*vm, jit, nullptr);
83
84
    return std::make_unique<B3::Compilation>(
85
        FINALIZE_CODE(linkBuffer, ("testair compilation")), proc.releaseByproducts());
86
}
87
88
template<typename T, typename... Arguments>
89
T invoke(const B3::Compilation& code, Arguments... arguments)
90
{
91
    T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(code.code().executableAddress());
92
    return function(arguments...);
93
}
94
95
template<typename T, typename... Arguments>
96
T compileAndRun(B3::Procedure& procedure, Arguments... arguments)
97
{
98
    return invoke<T>(*compile(procedure), arguments...);
99
}
100
101
void testSimple()
102
{
103
    B3::Procedure proc;
104
    Code& code = proc.code();
105
106
    BasicBlock* root = code.addBlock();
107
    root->append(Move, nullptr, Arg::imm(42), Tmp(GPRInfo::returnValueGPR));
108
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
109
110
    CHECK(compileAndRun<int>(proc) == 42);
111
}
112
113
void testShuffleSimpleSwap()
114
{
115
    B3::Procedure proc;
116
    Code& code = proc.code();
117
118
    BasicBlock* root = code.addBlock();
119
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
120
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
121
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
122
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
123
    root->append(
124
        Shuffle, nullptr,
125
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
126
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32));
127
128
    int32_t things[4];
129
    Tmp base = code.newTmp(Arg::GP);
130
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
131
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
132
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
133
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
134
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
135
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
136
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
137
138
    memset(things, 0, sizeof(things));
139
    
140
    CHECK(!compileAndRun<int>(proc));
141
142
    CHECK(things[0] == 1);
143
    CHECK(things[1] == 2);
144
    CHECK(things[2] == 4);
145
    CHECK(things[3] == 3);
146
}
147
148
void testShuffleSimpleShift()
149
{
150
    B3::Procedure proc;
151
    Code& code = proc.code();
152
153
    BasicBlock* root = code.addBlock();
154
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
155
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
156
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
157
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
158
    root->append(
159
        Shuffle, nullptr,
160
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
161
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32));
162
163
    int32_t things[5];
164
    Tmp base = code.newTmp(Arg::GP);
165
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
166
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
167
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
168
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
169
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
170
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
171
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
172
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
173
174
    memset(things, 0, sizeof(things));
175
    
176
    CHECK(!compileAndRun<int>(proc));
177
178
    CHECK(things[0] == 1);
179
    CHECK(things[1] == 2);
180
    CHECK(things[2] == 3);
181
    CHECK(things[3] == 3);
182
    CHECK(things[4] == 4);
183
}
184
185
void testShuffleLongShift()
186
{
187
    B3::Procedure proc;
188
    Code& code = proc.code();
189
190
    BasicBlock* root = code.addBlock();
191
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
192
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
193
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
194
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
195
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
196
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
197
    root->append(Move, nullptr, Arg::imm(7), Tmp(GPRInfo::regT6));
198
    root->append(Move, nullptr, Arg::imm(8), Tmp(GPRInfo::regT7));
199
    root->append(
200
        Shuffle, nullptr,
201
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
202
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
203
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
204
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
205
        Tmp(GPRInfo::regT4), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32),
206
        Tmp(GPRInfo::regT5), Tmp(GPRInfo::regT6), Arg::widthArg(Arg::Width32),
207
        Tmp(GPRInfo::regT6), Tmp(GPRInfo::regT7), Arg::widthArg(Arg::Width32));
208
209
    int32_t things[8];
210
    Tmp base = code.newTmp(Arg::GP);
211
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
212
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
213
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
214
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
215
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
216
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
217
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
218
    root->append(Move32, nullptr, Tmp(GPRInfo::regT6), Arg::addr(base, 6 * sizeof(int32_t)));
219
    root->append(Move32, nullptr, Tmp(GPRInfo::regT7), Arg::addr(base, 7 * sizeof(int32_t)));
220
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
221
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
222
223
    memset(things, 0, sizeof(things));
224
    
225
    CHECK(!compileAndRun<int>(proc));
226
227
    CHECK(things[0] == 1);
228
    CHECK(things[1] == 1);
229
    CHECK(things[2] == 2);
230
    CHECK(things[3] == 3);
231
    CHECK(things[4] == 4);
232
    CHECK(things[5] == 5);
233
    CHECK(things[6] == 6);
234
    CHECK(things[7] == 7);
235
}
236
237
void testShuffleLongShiftBackwards()
238
{
239
    B3::Procedure proc;
240
    Code& code = proc.code();
241
242
    BasicBlock* root = code.addBlock();
243
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
244
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
245
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
246
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
247
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
248
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
249
    root->append(Move, nullptr, Arg::imm(7), Tmp(GPRInfo::regT6));
250
    root->append(Move, nullptr, Arg::imm(8), Tmp(GPRInfo::regT7));
251
    root->append(
252
        Shuffle, nullptr,
253
        Tmp(GPRInfo::regT6), Tmp(GPRInfo::regT7), Arg::widthArg(Arg::Width32),
254
        Tmp(GPRInfo::regT5), Tmp(GPRInfo::regT6), Arg::widthArg(Arg::Width32),
255
        Tmp(GPRInfo::regT4), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32),
256
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
257
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
258
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
259
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32));
260
261
    int32_t things[8];
262
    Tmp base = code.newTmp(Arg::GP);
263
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
264
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
265
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
266
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
267
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
268
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
269
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
270
    root->append(Move32, nullptr, Tmp(GPRInfo::regT6), Arg::addr(base, 6 * sizeof(int32_t)));
271
    root->append(Move32, nullptr, Tmp(GPRInfo::regT7), Arg::addr(base, 7 * sizeof(int32_t)));
272
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
273
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
274
275
    memset(things, 0, sizeof(things));
276
    
277
    CHECK(!compileAndRun<int>(proc));
278
279
    CHECK(things[0] == 1);
280
    CHECK(things[1] == 1);
281
    CHECK(things[2] == 2);
282
    CHECK(things[3] == 3);
283
    CHECK(things[4] == 4);
284
    CHECK(things[5] == 5);
285
    CHECK(things[6] == 6);
286
    CHECK(things[7] == 7);
287
}
288
289
void testShuffleSimpleRotate()
290
{
291
    B3::Procedure proc;
292
    Code& code = proc.code();
293
294
    BasicBlock* root = code.addBlock();
295
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
296
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
297
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
298
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
299
    root->append(
300
        Shuffle, nullptr,
301
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
302
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
303
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT0), Arg::widthArg(Arg::Width32));
304
305
    int32_t things[4];
306
    Tmp base = code.newTmp(Arg::GP);
307
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
308
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
309
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
310
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
311
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
312
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
313
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
314
315
    memset(things, 0, sizeof(things));
316
    
317
    CHECK(!compileAndRun<int>(proc));
318
319
    CHECK(things[0] == 3);
320
    CHECK(things[1] == 1);
321
    CHECK(things[2] == 2);
322
    CHECK(things[3] == 4);
323
}
324
325
void testShuffleSimpleBroadcast()
326
{
327
    B3::Procedure proc;
328
    Code& code = proc.code();
329
330
    BasicBlock* root = code.addBlock();
331
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
332
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
333
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
334
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
335
    root->append(
336
        Shuffle, nullptr,
337
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
338
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
339
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32));
340
341
    int32_t things[4];
342
    Tmp base = code.newTmp(Arg::GP);
343
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
344
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
345
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
346
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
347
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
348
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
349
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
350
351
    memset(things, 0, sizeof(things));
352
    
353
    CHECK(!compileAndRun<int>(proc));
354
355
    CHECK(things[0] == 1);
356
    CHECK(things[1] == 1);
357
    CHECK(things[2] == 1);
358
    CHECK(things[3] == 1);
359
}
360
361
void testShuffleBroadcastAllRegs()
362
{
363
    B3::Procedure proc;
364
    Code& code = proc.code();
365
366
    const Vector<Reg>& regs = regsInPriorityOrder(Arg::GP);
367
368
    BasicBlock* root = code.addBlock();
369
    root->append(Move, nullptr, Arg::imm(35), Tmp(GPRInfo::regT0));
370
    unsigned count = 1;
371
    for (Reg reg : regs) {
372
        if (reg != Reg(GPRInfo::regT0))
373
            root->append(Move, nullptr, Arg::imm(count++), Tmp(reg));
374
    }
375
    Inst& shuffle = root->append(Shuffle, nullptr);
376
    for (Reg reg : regs) {
377
        if (reg != Reg(GPRInfo::regT0))
378
            shuffle.append(Tmp(GPRInfo::regT0), Tmp(reg), Arg::widthArg(Arg::Width32));
379
    }
380
381
    StackSlot* slot = code.addStackSlot(sizeof(int32_t) * regs.size(), B3::StackSlotKind::Locked);
382
    for (unsigned i = 0; i < regs.size(); ++i)
383
        root->append(Move32, nullptr, Tmp(regs[i]), Arg::stack(slot, i * sizeof(int32_t)));
384
385
    Vector<int32_t> things(regs.size(), 666);
386
    Tmp base = code.newTmp(Arg::GP);
387
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things[0])), base);
388
    for (unsigned i = 0; i < regs.size(); ++i) {
389
        root->append(Move32, nullptr, Arg::stack(slot, i * sizeof(int32_t)), Tmp(GPRInfo::regT0));
390
        root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, i * sizeof(int32_t)));
391
    }
392
    
393
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
394
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
395
396
    CHECK(!compileAndRun<int>(proc));
397
398
    for (int32_t thing : things)
399
        CHECK(thing == 35);
400
}
401
402
void testShuffleTreeShift()
403
{
404
    B3::Procedure proc;
405
    Code& code = proc.code();
406
407
    BasicBlock* root = code.addBlock();
408
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
409
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
410
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
411
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
412
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
413
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
414
    root->append(Move, nullptr, Arg::imm(7), Tmp(GPRInfo::regT6));
415
    root->append(Move, nullptr, Arg::imm(8), Tmp(GPRInfo::regT7));
416
    root->append(
417
        Shuffle, nullptr,
418
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
419
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
420
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
421
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
422
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32),
423
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT6), Arg::widthArg(Arg::Width32),
424
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT7), Arg::widthArg(Arg::Width32));
425
426
    int32_t things[8];
427
    Tmp base = code.newTmp(Arg::GP);
428
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
429
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
430
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
431
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
432
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
433
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
434
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
435
    root->append(Move32, nullptr, Tmp(GPRInfo::regT6), Arg::addr(base, 6 * sizeof(int32_t)));
436
    root->append(Move32, nullptr, Tmp(GPRInfo::regT7), Arg::addr(base, 7 * sizeof(int32_t)));
437
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
438
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
439
440
    memset(things, 0, sizeof(things));
441
    
442
    CHECK(!compileAndRun<int>(proc));
443
444
    CHECK(things[0] == 1);
445
    CHECK(things[1] == 1);
446
    CHECK(things[2] == 1);
447
    CHECK(things[3] == 2);
448
    CHECK(things[4] == 2);
449
    CHECK(things[5] == 3);
450
    CHECK(things[6] == 3);
451
    CHECK(things[7] == 4);
452
}
453
454
void testShuffleTreeShiftBackward()
455
{
456
    B3::Procedure proc;
457
    Code& code = proc.code();
458
459
    BasicBlock* root = code.addBlock();
460
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
461
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
462
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
463
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
464
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
465
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
466
    root->append(Move, nullptr, Arg::imm(7), Tmp(GPRInfo::regT6));
467
    root->append(Move, nullptr, Arg::imm(8), Tmp(GPRInfo::regT7));
468
    root->append(
469
        Shuffle, nullptr,
470
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT7), Arg::widthArg(Arg::Width32),
471
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT6), Arg::widthArg(Arg::Width32),
472
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32),
473
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
474
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
475
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
476
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32));
477
478
    int32_t things[8];
479
    Tmp base = code.newTmp(Arg::GP);
480
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
481
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
482
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
483
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
484
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
485
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
486
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
487
    root->append(Move32, nullptr, Tmp(GPRInfo::regT6), Arg::addr(base, 6 * sizeof(int32_t)));
488
    root->append(Move32, nullptr, Tmp(GPRInfo::regT7), Arg::addr(base, 7 * sizeof(int32_t)));
489
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
490
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
491
492
    memset(things, 0, sizeof(things));
493
    
494
    CHECK(!compileAndRun<int>(proc));
495
496
    CHECK(things[0] == 1);
497
    CHECK(things[1] == 1);
498
    CHECK(things[2] == 1);
499
    CHECK(things[3] == 2);
500
    CHECK(things[4] == 2);
501
    CHECK(things[5] == 3);
502
    CHECK(things[6] == 3);
503
    CHECK(things[7] == 4);
504
}
505
506
void testShuffleTreeShiftOtherBackward()
507
{
508
    // NOTE: This test was my original attempt at TreeShiftBackward but mistakes were made. So, this
509
    // ends up being just a weird test. But weird tests are useful, so I kept it.
510
    
511
    B3::Procedure proc;
512
    Code& code = proc.code();
513
514
    BasicBlock* root = code.addBlock();
515
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
516
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
517
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
518
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
519
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
520
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
521
    root->append(Move, nullptr, Arg::imm(7), Tmp(GPRInfo::regT6));
522
    root->append(Move, nullptr, Arg::imm(8), Tmp(GPRInfo::regT7));
523
    root->append(
524
        Shuffle, nullptr,
525
        Tmp(GPRInfo::regT4), Tmp(GPRInfo::regT7), Arg::widthArg(Arg::Width32),
526
        Tmp(GPRInfo::regT5), Tmp(GPRInfo::regT6), Arg::widthArg(Arg::Width32),
527
        Tmp(GPRInfo::regT5), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32),
528
        Tmp(GPRInfo::regT6), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
529
        Tmp(GPRInfo::regT6), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
530
        Tmp(GPRInfo::regT7), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
531
        Tmp(GPRInfo::regT7), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32));
532
533
    int32_t things[8];
534
    Tmp base = code.newTmp(Arg::GP);
535
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
536
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
537
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
538
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
539
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
540
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
541
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
542
    root->append(Move32, nullptr, Tmp(GPRInfo::regT6), Arg::addr(base, 6 * sizeof(int32_t)));
543
    root->append(Move32, nullptr, Tmp(GPRInfo::regT7), Arg::addr(base, 7 * sizeof(int32_t)));
544
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
545
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
546
547
    memset(things, 0, sizeof(things));
548
    
549
    CHECK(!compileAndRun<int>(proc));
550
551
    CHECK(things[0] == 1);
552
    CHECK(things[1] == 8);
553
    CHECK(things[2] == 8);
554
    CHECK(things[3] == 7);
555
    CHECK(things[4] == 7);
556
    CHECK(things[5] == 6);
557
    CHECK(things[6] == 6);
558
    CHECK(things[7] == 5);
559
}
560
561
void testShuffleMultipleShifts()
562
{
563
    B3::Procedure proc;
564
    Code& code = proc.code();
565
566
    BasicBlock* root = code.addBlock();
567
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
568
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
569
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
570
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
571
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
572
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
573
    root->append(
574
        Shuffle, nullptr,
575
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
576
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
577
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
578
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32));
579
580
    int32_t things[6];
581
    Tmp base = code.newTmp(Arg::GP);
582
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
583
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
584
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
585
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
586
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
587
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
588
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
589
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
590
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
591
592
    memset(things, 0, sizeof(things));
593
    
594
    CHECK(!compileAndRun<int>(proc));
595
596
    CHECK(things[0] == 1);
597
    CHECK(things[1] == 1);
598
    CHECK(things[2] == 3);
599
    CHECK(things[3] == 3);
600
    CHECK(things[4] == 3);
601
    CHECK(things[5] == 1);
602
}
603
604
void testShuffleRotateWithFringe()
605
{
606
    B3::Procedure proc;
607
    Code& code = proc.code();
608
609
    BasicBlock* root = code.addBlock();
610
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
611
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
612
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
613
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
614
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
615
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
616
    root->append(
617
        Shuffle, nullptr,
618
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
619
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
620
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT0), Arg::widthArg(Arg::Width32),
621
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
622
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
623
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32));
624
625
    int32_t things[6];
626
    Tmp base = code.newTmp(Arg::GP);
627
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
628
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
629
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
630
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
631
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
632
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
633
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
634
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
635
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
636
637
    memset(things, 0, sizeof(things));
638
    
639
    CHECK(!compileAndRun<int>(proc));
640
641
    CHECK(things[0] == 3);
642
    CHECK(things[1] == 1);
643
    CHECK(things[2] == 2);
644
    CHECK(things[3] == 1);
645
    CHECK(things[4] == 2);
646
    CHECK(things[5] == 3);
647
}
648
649
void testShuffleRotateWithLongFringe()
650
{
651
    B3::Procedure proc;
652
    Code& code = proc.code();
653
654
    BasicBlock* root = code.addBlock();
655
    root->append(Move, nullptr, Arg::imm(1), Tmp(GPRInfo::regT0));
656
    root->append(Move, nullptr, Arg::imm(2), Tmp(GPRInfo::regT1));
657
    root->append(Move, nullptr, Arg::imm(3), Tmp(GPRInfo::regT2));
658
    root->append(Move, nullptr, Arg::imm(4), Tmp(GPRInfo::regT3));
659
    root->append(Move, nullptr, Arg::imm(5), Tmp(GPRInfo::regT4));
660
    root->append(Move, nullptr, Arg::imm(6), Tmp(GPRInfo::regT5));
661
    root->append(
662
        Shuffle, nullptr,
663
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT1), Arg::widthArg(Arg::Width32),
664
        Tmp(GPRInfo::regT1), Tmp(GPRInfo::regT2), Arg::widthArg(Arg::Width32),
665
        Tmp(GPRInfo::regT2), Tmp(GPRInfo::regT0), Arg::widthArg(Arg::Width32),
666
        Tmp(GPRInfo::regT0), Tmp(GPRInfo::regT3), Arg::widthArg(Arg::Width32),
667
        Tmp(GPRInfo::regT3), Tmp(GPRInfo::regT4), Arg::widthArg(Arg::Width32),
668
        Tmp(GPRInfo::regT4), Tmp(GPRInfo::regT5), Arg::widthArg(Arg::Width32));
669
670
    int32_t things[6];
671
    Tmp base = code.newTmp(Arg::GP);
672
    root->append(Move, nullptr, Arg::imm64(bitwise_cast<intptr_t>(&things)), base);
673
    root->append(Move32, nullptr, Tmp(GPRInfo::regT0), Arg::addr(base, 0 * sizeof(int32_t)));
674
    root->append(Move32, nullptr, Tmp(GPRInfo::regT1), Arg::addr(base, 1 * sizeof(int32_t)));
675
    root->append(Move32, nullptr, Tmp(GPRInfo::regT2), Arg::addr(base, 2 * sizeof(int32_t)));
676
    root->append(Move32, nullptr, Tmp(GPRInfo::regT3), Arg::addr(base, 3 * sizeof(int32_t)));
677
    root->append(Move32, nullptr, Tmp(GPRInfo::regT4), Arg::addr(base, 4 * sizeof(int32_t)));
678
    root->append(Move32, nullptr, Tmp(GPRInfo::regT5), Arg::addr(base, 5 * sizeof(int32_t)));
679
    root->append(Move, nullptr, Arg::imm(0), Tmp(GPRInfo::returnValueGPR));
680
    root->append(Ret32, nullptr, Tmp(GPRInfo::returnValueGPR));
681
682
    memset(things, 0, sizeof(things));
683
    
684
    CHECK(!compileAndRun<int>(proc));
685
686
    CHECK(things[0] == 3);
687
    CHECK(things[1] == 1);
688
    CHECK(things[2] == 2);
689
    CHECK(things[3] == 1);
690
    CHECK(things[4] == 4);
691
    CHECK(things[5] == 5);
692
}
693
694
#define RUN(test) do {                          \
695
        if (!shouldRun(#test))                  \
696
            break;                              \
697
        tasks.append(                           \
698
            createSharedTask<void()>(           \
699
                [&] () {                        \
700
                    dataLog(#test "...\n");     \
701
                    test;                       \
702
                    dataLog(#test ": OK!\n");   \
703
                }));                            \
704
    } while (false);
705
706
void run(const char* filter)
707
{
708
    JSC::initializeThreading();
709
    vm = &VM::create(LargeHeap).leakRef();
710
711
    Deque<RefPtr<SharedTask<void()>>> tasks;
712
713
    auto shouldRun = [&] (const char* testName) -> bool {
714
        return !filter || !!strcasestr(testName, filter);
715
    };
716
717
    RUN(testSimple());
718
    RUN(testShuffleSimpleSwap());
719
    RUN(testShuffleSimpleShift());
720
    RUN(testShuffleLongShift());
721
    RUN(testShuffleLongShiftBackwards());
722
    RUN(testShuffleSimpleRotate());
723
    RUN(testShuffleSimpleBroadcast());
724
    RUN(testShuffleBroadcastAllRegs());
725
    RUN(testShuffleTreeShift());
726
    RUN(testShuffleTreeShiftBackward());
727
    RUN(testShuffleTreeShiftOtherBackward());
728
    RUN(testShuffleMultipleShifts());
729
    RUN(testShuffleRotateWithFringe());
730
    RUN(testShuffleRotateWithLongFringe());
731
732
    // Still need the following tests:
733
    // - multiple shifts
734
    // - multiple rotates
735
    // - shift and rotate
736
    // - shift over all registers
737
    // - rotate over all registers
738
    // - rotate with multiple widths
739
    // - memory shift
740
    // - memory->memory shift
741
    // - memory->memory shift with no spare registers
742
    // - memory rotate
743
    // - memory rotate with multiple widths
744
    // - memory->memory rotate
745
    // - memory->memory rotate with multiple widths
746
    // - memory rotate with no spare registers
747
    // - memory rotate with no spare registers with multiple widths
748
    // - memory->memory rotate with no spare registers
749
    // - memory->memory rotate with no spare registers with multiple widths
750
    // - floating point
751
752
    if (tasks.isEmpty())
753
        usage();
754
755
    Lock lock;
756
757
    Vector<ThreadIdentifier> threads;
758
    for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
759
        threads.append(
760
            createThread(
761
                "testb3 thread",
762
                [&] () {
763
                    for (;;) {
764
                        RefPtr<SharedTask<void()>> task;
765
                        {
766
                            LockHolder locker(lock);
767
                            if (tasks.isEmpty())
768
                                return;
769
                            task = tasks.takeFirst();
770
                        }
771
772
                        task->run();
773
                    }
774
                }));
775
    }
776
777
    for (ThreadIdentifier thread : threads)
778
        waitForThreadCompletion(thread);
779
    crashLock.lock();
780
}
781
782
} // anonymois namespace
783
784
#else // ENABLE(B3_JIT)
785
786
static void run(const char*)
787
{
788
    dataLog("B3 JIT is not enabled.\n");
789
}
790
791
#endif // ENABLE(B3_JIT)
792
793
int main(int argc, char** argv)
794
{
795
    const char* filter = nullptr;
796
    switch (argc) {
797
    case 1:
798
        break;
799
    case 2:
800
        filter = argv[1];
801
        break;
802
    default:
803
        usage();
804
        break;
805
    }
806
    
807
    run(filter);
808
    return 0;
809
}

Return to Bug 152952