WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
it compiles!
blah.patch (text/plain), 86.78 KB, created by
Filip Pizlo
on 2016-01-12 18:47:33 PST
(
hide
)
Description:
it compiles!
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2016-01-12 18:47:33 PST
Size:
86.78 KB
patch
obsolete
>Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 194856) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -400,6 +400,15 @@ > 0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; }; > 0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183201C45BF070072450B /* AirCCallingConvention.cpp */; }; >+ 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; }; >+ 0F61832B1C45BF070072450B /* AirCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183221C45BF070072450B /* AirCustom.cpp */; }; >+ 0F61832C1C45BF070072450B /* AirEmitShuffle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183231C45BF070072450B /* AirEmitShuffle.cpp */; }; >+ 0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183241C45BF070072450B /* AirEmitShuffle.h */; }; >+ 0F61832E1C45BF070072450B /* AirLowerAfterRegAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */; }; >+ 0F61832F1C45BF070072450B /* AirLowerAfterRegAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */; }; >+ 0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6183271C45BF070072450B /* AirLowerMacros.cpp */; }; >+ 0F6183311C45BF070072450B /* AirLowerMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183281C45BF070072450B /* AirLowerMacros.h */; }; > 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; }; > 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; }; > 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; }; >@@ -2541,6 +2550,15 @@ > 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; }; > 0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; }; > 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; }; >+ 0F6183201C45BF070072450B /* AirCCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCCallingConvention.cpp; path = b3/air/AirCCallingConvention.cpp; sourceTree = "<group>"; }; >+ 0F6183211C45BF070072450B /* AirCCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirCCallingConvention.h; path = b3/air/AirCCallingConvention.h; sourceTree = "<group>"; }; >+ 0F6183221C45BF070072450B /* AirCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCustom.cpp; path = b3/air/AirCustom.cpp; sourceTree = "<group>"; }; >+ 0F6183231C45BF070072450B /* AirEmitShuffle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirEmitShuffle.cpp; path = b3/air/AirEmitShuffle.cpp; sourceTree = "<group>"; }; >+ 0F6183241C45BF070072450B /* AirEmitShuffle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirEmitShuffle.h; path = b3/air/AirEmitShuffle.h; sourceTree = "<group>"; }; >+ 0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerAfterRegAlloc.cpp; path = b3/air/AirLowerAfterRegAlloc.cpp; sourceTree = "<group>"; }; >+ 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerAfterRegAlloc.h; path = b3/air/AirLowerAfterRegAlloc.h; sourceTree = "<group>"; }; >+ 0F6183271C45BF070072450B /* AirLowerMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirLowerMacros.cpp; path = b3/air/AirLowerMacros.cpp; sourceTree = "<group>"; }; >+ 0F6183281C45BF070072450B /* AirLowerMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLowerMacros.h; path = b3/air/AirLowerMacros.h; sourceTree = "<group>"; }; > 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; }; > 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; }; > 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; }; >@@ -3370,8 +3388,8 @@ > 7013CA8A1B491A9400CAE613 /* JSJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSJob.h; sourceTree = "<group>"; }; > 7035587C1C418419004BD7BF /* MapPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = MapPrototype.js; sourceTree = "<group>"; }; > 7035587D1C418419004BD7BF /* SetPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SetPrototype.js; sourceTree = "<group>"; }; >- 7035587E1C418458004BD7BF /* MapPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapPrototype.lut.h; path = MapPrototype.lut.h; sourceTree = "<group>"; }; >- 7035587F1C418458004BD7BF /* SetPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SetPrototype.lut.h; path = SetPrototype.lut.h; sourceTree = "<group>"; }; >+ 7035587E1C418458004BD7BF /* MapPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapPrototype.lut.h; sourceTree = "<group>"; }; >+ 7035587F1C418458004BD7BF /* SetPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetPrototype.lut.h; sourceTree = "<group>"; }; > 704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; }; > 705B41A31A6E501E00716757 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbol.cpp; sourceTree = "<group>"; }; > 705B41A41A6E501E00716757 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Symbol.h; sourceTree = "<group>"; }; >@@ -4791,13 +4809,18 @@ > 0FEC854C1BDACDC70080FF74 /* AirBasicBlock.cpp */, > 0FEC854D1BDACDC70080FF74 /* AirBasicBlock.h */, > 0FB3878B1BFBC44D00E3AB1E /* AirBlockWorklist.h */, >+ 0F6183201C45BF070072450B /* AirCCallingConvention.cpp */, >+ 0F6183211C45BF070072450B /* AirCCallingConvention.h */, > 0FEC854E1BDACDC70080FF74 /* AirCCallSpecial.cpp */, > 0FEC854F1BDACDC70080FF74 /* AirCCallSpecial.h */, > 0FEC85501BDACDC70080FF74 /* AirCode.cpp */, > 0FEC85511BDACDC70080FF74 /* AirCode.h */, >+ 0F6183221C45BF070072450B /* AirCustom.cpp */, > 0F10F1A21C420BF0001C07D2 /* AirCustom.h */, > 0F4570361BE44C910062A629 /* AirEliminateDeadCode.cpp */, > 0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */, >+ 0F6183231C45BF070072450B /* AirEmitShuffle.cpp */, >+ 0F6183241C45BF070072450B /* AirEmitShuffle.h */, > 262D85B41C0D650F006ACB61 /* AirFixPartialRegisterStalls.cpp */, > 262D85B51C0D650F006ACB61 /* AirFixPartialRegisterStalls.h */, > 0F4C91671C2B3D68004341A6 /* AirFixSpillSlotZDef.h */, >@@ -4816,6 +4839,10 @@ > 26718BA21BE99F780052017B /* AirIteratedRegisterCoalescing.cpp */, > 26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */, > 2684D4371C00161C0081D663 /* AirLiveness.h */, >+ 0F6183251C45BF070072450B /* AirLowerAfterRegAlloc.cpp */, >+ 0F6183261C45BF070072450B /* AirLowerAfterRegAlloc.h */, >+ 0F6183271C45BF070072450B /* AirLowerMacros.cpp */, >+ 0F6183281C45BF070072450B /* AirLowerMacros.h */, > 264091FA1BE2FD4100684DB2 /* AirOpcode.opcodes */, > 0FB3878C1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.cpp */, > 0FB3878D1BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h */, >@@ -6896,6 +6923,7 @@ > 0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */, > 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */, > 79D5CD5B1C1106A900CECA07 /* SamplingProfiler.h in Headers */, >+ 0F6183311C45BF070072450B /* AirLowerMacros.h in Headers */, > 0FEC85771BDACDC70080FF74 /* AirFrequentedBlock.h in Headers */, > 0FEC85791BDACDC70080FF74 /* AirGenerate.h in Headers */, > 79DF66B11BF26A570001CF11 /* FTLExceptionHandlerManager.h in Headers */, >@@ -6958,6 +6986,7 @@ > 0FEC85141BDACDAC0080FF74 /* B3ControlValue.h in Headers */, > 0FEC85C11BE167A00080FF74 /* B3Effects.h in Headers */, > 0FEC85161BDACDAC0080FF74 /* B3FrequencyClass.h in Headers */, >+ 0F61832F1C45BF070072450B /* AirLowerAfterRegAlloc.h in Headers */, > 0FEC85171BDACDAC0080FF74 /* B3FrequentedBlock.h in Headers */, > 0FEC85191BDACDAC0080FF74 /* B3Generate.h in Headers */, > 0FEC851A1BDACDAC0080FF74 /* B3GenericFrequentedBlock.h in Headers */, >@@ -7150,6 +7179,7 @@ > A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */, > 0F37308D1C0BD29100052BFA /* B3PhiChildren.h in Headers */, > A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */, >+ 0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */, > 0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */, > 0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */, > 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */, >@@ -7624,6 +7654,7 @@ > 0F2B66F717B6B5AB00A7AE3F /* JSInt8Array.h in Headers */, > A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */, > E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */, >+ 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */, > E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */, > E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */, > E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */, >@@ -8693,6 +8724,7 @@ > 52B717B51A0597E1007AF4F3 /* ControlFlowProfiler.cpp in Sources */, > 0FBADF541BD1F4B800E073C1 /* CopiedBlock.cpp in Sources */, > C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */, >+ 0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */, > C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */, > 2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */, > 62E3D5F01B8D0B7300B868BB /* DataFormat.cpp in Sources */, >@@ -8741,6 +8773,7 @@ > 0F0981F71BC5E565004814F8 /* DFGCopyBarrierOptimizationPhase.cpp in Sources */, > 0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */, > A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */, >+ 0F6183291C45BF070072450B /* AirCCallingConvention.cpp in Sources */, > 0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */, > 0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */, > 0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */, >@@ -8757,6 +8790,7 @@ > A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */, > A78A9776179738B8009DF744 /* DFGFinalizer.cpp in Sources */, > 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */, >+ 0F61832C1C45BF070072450B /* AirEmitShuffle.cpp in Sources */, > 0F9D339617FFC4E60073C2BC /* DFGFlushedAt.cpp in Sources */, > A7D89CF717A0B8CC00773AD8 /* DFGFlushFormat.cpp in Sources */, > 0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */, >@@ -9068,6 +9102,7 @@ > E33F50841B8437A000413856 /* JSInternalPromiseDeferred.cpp in Sources */, > E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */, > A503FA1B188E0FB000110F14 /* JSJavaScriptCallFrame.cpp in Sources */, >+ 0F61832E1C45BF070072450B /* AirLowerAfterRegAlloc.cpp in Sources */, > A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */, > 7013CA8B1B491A9400CAE613 /* JSJob.cpp in Sources */, > 140B7D1D0DC69AF7009C42B8 /* JSLexicalEnvironment.cpp in Sources */, >@@ -9210,6 +9245,7 @@ > 0F9D4C0C1C3E1C11006CD984 /* FTLExceptionTarget.cpp in Sources */, > 0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */, > 0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */, >+ 0F61832B1C45BF070072450B /* AirCustom.cpp in Sources */, > 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */, > 0FD3E40D1B618B6600C80E1E /* PropertyCondition.cpp in Sources */, > A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */, >Index: Source/JavaScriptCore/assembler/AbstractMacroAssembler.h >=================================================================== >--- Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (revision 194856) >+++ Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (working copy) >@@ -76,6 +76,15 @@ inline bool isX86_64() > #endif > } > >+inline bool isIOS() >+{ >+#if PLATFORM(IOS) >+ return true; >+#else >+ return false; >+#endif >+} >+ > inline bool optimizeForARMv7IDIVSupported() > { > return isARMv7IDIVSupported() && Options::useArchitectureSpecificOptimizations(); >Index: Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h >=================================================================== >--- Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (revision 194856) >+++ Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (working copy) >@@ -1411,6 +1411,16 @@ public: > } > #endif > >+ void swap32(RegisterID src, RegisterID dest) >+ { >+ m_assembler.xchgl_rr(src, dest); >+ } >+ >+ void swap32(RegisterID src, Address dest) >+ { >+ m_assembler.xchgl_rm(src, dest.offset, dest.base); >+ } >+ > void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID src, RegisterID dest) > { > m_assembler.cmpl_rr(right, left); >Index: Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h >=================================================================== >--- Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (revision 194856) >+++ Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (working copy) >@@ -655,6 +655,16 @@ public: > return DataLabel32(this); > } > >+ void swap64(RegisterID src, RegisterID dest) >+ { >+ m_assembler.xchgq_rr(src, dest); >+ } >+ >+ void swap64(RegisterID src, Address dest) >+ { >+ m_assembler.xchgq_rm(src, dest.offset, dest.base); >+ } >+ > void move64ToDouble(RegisterID src, FPRegisterID dest) > { > m_assembler.movq_rr(src, dest); >Index: Source/JavaScriptCore/assembler/X86Assembler.h >=================================================================== >--- Source/JavaScriptCore/assembler/X86Assembler.h (revision 194856) >+++ Source/JavaScriptCore/assembler/X86Assembler.h (working copy) >@@ -1431,6 +1431,11 @@ public: > m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst); > } > >+ void xchgl_rm(RegisterID src, int offset, RegisterID base) >+ { >+ m_formatter.oneByteOp(OP_XCHG_EvGv, src, base, offset); >+ } >+ > #if CPU(X86_64) > void xchgq_rr(RegisterID src, RegisterID dst) > { >@@ -1441,6 +1446,11 @@ public: > else > m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst); > } >+ >+ void xchgq_rm(RegisterID src, int offset, RegisterID base) >+ { >+ m_formatter.oneByteOp64(OP_XCHG_EvGv, src, base, offset); >+ } > #endif > > void movl_rr(RegisterID src, RegisterID dst) >Index: Source/JavaScriptCore/b3/B3CCallValue.cpp >=================================================================== >--- Source/JavaScriptCore/b3/B3CCallValue.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/B3CCallValue.cpp (working copy) >@@ -34,6 +34,11 @@ CCallValue::~CCallValue() > { > } > >+void CCallValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const >+{ >+ out.print(comma, "isWarm = ", isWarm); >+} >+ > } } // namespace JSC::B3 > > #endif // ENABLE(B3_JIT) >Index: Source/JavaScriptCore/b3/B3CCallValue.h >=================================================================== >--- Source/JavaScriptCore/b3/B3CCallValue.h (revision 194856) >+++ Source/JavaScriptCore/b3/B3CCallValue.h (working copy) >@@ -39,7 +39,12 @@ public: > > ~CCallValue(); > >- Effects effects; >+ Effects effects { Effects::forCall() }; >+ >+ bool isWarm { true }; >+ >+protected: >+ void dumpMeta(CommaPrinter&, PrintStream&) const override; > > private: > friend class Procedure; >@@ -47,7 +52,6 @@ private: > template<typename... Arguments> > CCallValue(unsigned index, Type type, Origin origin, Arguments... arguments) > : Value(index, CheckedOpcode, CCall, type, origin, arguments...) >- , effects(Effects::forCall()) > { > RELEASE_ASSERT(numChildren() >= 1); > } >Index: Source/JavaScriptCore/b3/B3LowerToAir.cpp >=================================================================== >--- Source/JavaScriptCore/b3/B3LowerToAir.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/B3LowerToAir.cpp (working copy) >@@ -1541,37 +1541,6 @@ private: > inverted); > } > >- template<typename BankInfo> >- Arg marshallCCallArgument(unsigned& argumentCount, unsigned& stackOffset, Value* child) >- { >- unsigned argumentIndex = argumentCount++; >- if (argumentIndex < BankInfo::numberOfArgumentRegisters) { >- Tmp result = Tmp(BankInfo::toArgumentRegister(argumentIndex)); >- append(relaxedMoveForType(child->type()), immOrTmp(child), result); >- return result; >- } >- >-#if CPU(ARM64) && PLATFORM(IOS) >- // iOS does not follow the ARM64 ABI regarding function calls. >- // Arguments must be packed. >- unsigned slotSize = sizeofType(child->type()); >- stackOffset = WTF::roundUpToMultipleOf(slotSize, stackOffset); >-#else >- unsigned slotSize = sizeof(void*); >-#endif >- Arg result = Arg::callArg(stackOffset); >- stackOffset += slotSize; >- >- // Put the code for storing the argument before anything else. This significantly eases the >- // burden on the register allocator. If we could, we'd hoist these stores as far as >- // possible. >- // FIXME: Add a phase to hoist stores as high as possible to relieve register pressure. >- // https://bugs.webkit.org/show_bug.cgi?id=151063 >- m_insts.last().insert(0, createStore(child, result)); >- >- return result; >- } >- > void lower() > { > switch (m_value->opcode()) { >@@ -1919,14 +1888,9 @@ private: > return; > } > >- case CCall: { >+ case B3::CCall: { > CCallValue* cCall = m_value->as<CCallValue>(); >- Inst inst(Patch, cCall, Arg::special(m_code.cCallSpecial())); >- >- // This is a bit weird - we have a super intense contract with Arg::CCallSpecial. It might >- // be better if we factored Air::CCallSpecial out of the Air namespace and made it a B3 >- // thing. >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151045 >+ Inst inst(cCall->isWarm ? Air::CCall : Air::ColdCCall, cCall); > > // We have a ton of flexibility regarding the callee argument, but currently, we don't > // use it yet. It gets weird for reasons: >@@ -1939,48 +1903,13 @@ private: > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=151052 > inst.args.append(tmp(cCall->child(0))); > >- // We need to tell Air what registers this defines. >- inst.args.append(Tmp(GPRInfo::returnValueGPR)); >- inst.args.append(Tmp(GPRInfo::returnValueGPR2)); >- inst.args.append(Tmp(FPRInfo::returnValueFPR)); >- >- // Now marshall the arguments. This is where we implement the C calling convention. After >- // this, Air does not know what the convention is; it just takes our word for it. >- unsigned gpArgumentCount = 0; >- unsigned fpArgumentCount = 0; >- unsigned stackOffset = 0; >- for (unsigned i = 1; i < cCall->numChildren(); ++i) { >- Value* argChild = cCall->child(i); >- Arg arg; >- >- switch (Arg::typeForB3Type(argChild->type())) { >- case Arg::GP: >- arg = marshallCCallArgument<GPRInfo>(gpArgumentCount, stackOffset, argChild); >- break; >+ if (cCall->type() != Void) >+ inst.args.append(tmp(cCall)); > >- case Arg::FP: >- arg = marshallCCallArgument<FPRInfo>(fpArgumentCount, stackOffset, argChild); >- break; >- } >+ for (unsigned i = 1; i < cCall->numChildren(); ++i) >+ inst.args.append(immOrTmp(cCall->child(i))); > >- if (arg.isTmp()) >- inst.args.append(arg); >- } >- > m_insts.last().append(WTFMove(inst)); >- >- switch (cCall->type()) { >- case Void: >- break; >- case Int32: >- case Int64: >- append(Move, Tmp(GPRInfo::returnValueGPR), tmp(cCall)); >- break; >- case Float: >- case Double: >- append(MoveDouble, Tmp(FPRInfo::returnValueFPR), tmp(cCall)); >- break; >- } > return; > } > >Index: Source/JavaScriptCore/b3/B3StackmapSpecial.cpp >=================================================================== >--- Source/JavaScriptCore/b3/B3StackmapSpecial.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/B3StackmapSpecial.cpp (working copy) >@@ -200,21 +200,14 @@ bool StackmapSpecial::isArgValidForValue > case Arg::Tmp: > case Arg::Imm: > case Arg::Imm64: >- case Arg::Stack: >- case Arg::CallArg: >- break; // OK >- case Arg::Addr: >- if (arg.base() != Tmp(GPRInfo::callFrameRegister) >- && arg.base() != Tmp(MacroAssembler::stackPointerRegister)) >- return false; > break; > default: >- return false; >+ if (!arg.isStackMemory()) >+ return false; >+ break; > } >- >- Arg::Type type = Arg::typeForB3Type(value->type()); > >- return arg.isType(type); >+ return arg.canRepresent(value); > } > > bool StackmapSpecial::isArgValidForRep(Air::Code& code, const Air::Arg& arg, const ValueRep& rep) >Index: Source/JavaScriptCore/b3/air/AirArg.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirArg.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirArg.cpp (working copy) >@@ -30,9 +30,26 @@ > > #include "AirSpecial.h" > #include "AirStackSlot.h" >+#include "B3Value.h" >+#include "FPRInfo.h" >+#include "GPRInfo.h" > > namespace JSC { namespace B3 { namespace Air { > >+bool Arg::isStackMemory() const >+{ >+ switch (kind()) { >+ case Addr: >+ return base() == Air::Tmp(GPRInfo::callFrameRegister) >+ || base() == Air::Tmp(MacroAssembler::stackPointerRegister); >+ case Stack: >+ case CallArg: >+ return true; >+ default: >+ return false; >+ } >+} >+ > bool Arg::isRepresentableAs(Width width, Signedness signedness) const > { > switch (signedness) { >@@ -61,6 +78,22 @@ bool Arg::isRepresentableAs(Width width, > } > } > >+bool Arg::usesTmp(Air::Tmp tmp) const >+{ >+ bool uses = false; >+ const_cast<Arg*>(this)->forEachTmpFast( >+ [&] (Air::Tmp otherTmp) { >+ if (otherTmp == tmp) >+ uses = true; >+ }); >+ return uses; >+} >+ >+bool Arg::canRepresent(Value* value) const >+{ >+ return isType(typeForB3Type(value->type())); >+} >+ > void Arg::dump(PrintStream& out) const > { > switch (m_kind) { >@@ -111,6 +144,9 @@ void Arg::dump(PrintStream& out) const > case Special: > out.print(pointerDump(special())); > return; >+ case WidthArg: >+ out.print(width()); >+ return; > } > > RELEASE_ASSERT_NOT_REACHED(); >@@ -161,6 +197,9 @@ void printInternal(PrintStream& out, Arg > case Arg::Special: > out.print("Special"); > return; >+ case Arg::WidthArg: >+ out.print("WidthArg"); >+ return; > } > > RELEASE_ASSERT_NOT_REACHED(); >@@ -225,16 +264,16 @@ void printInternal(PrintStream& out, Arg > { > switch (width) { > case Arg::Width8: >- out.print("Width8"); >+ out.print("8"); > return; > case Arg::Width16: >- out.print("Width16"); >+ out.print("16"); > return; > case Arg::Width32: >- out.print("Width32"); >+ out.print("32"); > return; > case Arg::Width64: >- out.print("Width64"); >+ out.print("64"); > return; > } > >Index: Source/JavaScriptCore/b3/air/AirArg.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirArg.h (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirArg.h (working copy) >@@ -33,7 +33,11 @@ > #include "B3Type.h" > #include <wtf/Optional.h> > >-namespace JSC { namespace B3 { namespace Air { >+namespace JSC { namespace B3 { >+ >+class Value; >+ >+namespace Air { > > class Special; > class StackSlot; >@@ -69,7 +73,8 @@ public: > RelCond, > ResCond, > DoubleCond, >- Special >+ Special, >+ WidthArg > }; > > enum Role : int8_t { >@@ -156,6 +161,13 @@ public: > > static const unsigned numTypes = 2; > >+ template<typename Functor> >+ static void forEachType(const Functor& functor) >+ { >+ functor(GP); >+ functor(FP); >+ } >+ > enum Width : int8_t { > Width8, > Width16, >@@ -220,6 +232,26 @@ public: > return isAnyUse(role) && !isColdUse(role); > } > >+ static Role cooled(Role role) >+ { >+ switch (role) { >+ case ColdUse: >+ case LateColdUse: >+ case UseDef: >+ case UseZDef: >+ case Def: >+ case ZDef: >+ case UseAddr: >+ case Scratch: >+ case EarlyDef: >+ return role; >+ case Use: >+ return ColdUse; >+ case LateUse: >+ return LateColdUse; >+ } >+ } >+ > // Returns true if the Role implies that the Inst will Use the Arg before doing anything else. > static bool isEarlyUse(Role role) > { >@@ -549,6 +581,14 @@ public: > return result; > } > >+ static Arg widthArg(Width width) >+ { >+ Arg result; >+ result.m_kind = WidthArg; >+ result.m_offset = width; >+ return result; >+ } >+ > bool operator==(const Arg& other) const > { > return m_offset == other.m_offset >@@ -585,6 +625,11 @@ public: > return kind() == Imm64; > } > >+ bool isSomeImm() const >+ { >+ return isImm() || isImm64(); >+ } >+ > bool isAddr() const > { > return kind() == Addr; >@@ -605,6 +650,21 @@ public: > return kind() == Index; > } > >+ bool isMemory() const >+ { >+ switch (kind()) { >+ case Addr: >+ case Stack: >+ case CallArg: >+ case Index: >+ return true; >+ default: >+ return false; >+ } >+ } >+ >+ bool isStackMemory() const; >+ > bool isRelCond() const > { > return kind() == RelCond; >@@ -637,6 +697,11 @@ public: > return kind() == Special; > } > >+ bool isWidthArg() const >+ { >+ return kind() == WidthArg; >+ } >+ > bool isAlive() const > { > return isTmp() || isStack(); >@@ -680,18 +745,7 @@ public: > return m_base; > } > >- bool hasOffset() const >- { >- switch (kind()) { >- case Addr: >- case Stack: >- case CallArg: >- case Index: >- return true; >- default: >- return false; >- } >- } >+ bool hasOffset() const { return isMemory(); } > > int32_t offset() const > { >@@ -730,6 +784,12 @@ public: > return bitwise_cast<Air::Special*>(m_offset); > } > >+ Width width() const >+ { >+ ASSERT(kind() == WidthArg); >+ return static_cast<Width>(m_offset); >+ } >+ > bool isGPTmp() const > { > return isTmp() && tmp().isGP(); >@@ -754,6 +814,7 @@ public: > case ResCond: > case DoubleCond: > case Special: >+ case WidthArg: > return true; > case Tmp: > return isGPTmp(); >@@ -771,6 +832,7 @@ public: > case ResCond: > case DoubleCond: > case Special: >+ case WidthArg: > case Invalid: > return false; > case Addr: >@@ -812,6 +874,8 @@ public: > } > } > >+ bool canRepresent(Value* value) const; >+ > bool isGPR() const > { > return isTmp() && tmp().isGPR(); >@@ -953,6 +1017,7 @@ public: > case ResCond: > case DoubleCond: > case Special: >+ case WidthArg: > return true; > } > } >@@ -974,6 +1039,8 @@ public: > } > } > >+ bool usesTmp(Air::Tmp tmp) const; >+ > // This is smart enough to know that an address arg in a Def or UseDef rule will use its > // tmps and never def them. For example, this: > // >Index: Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirCCallingConvention.cpp (working copy) >@@ -0,0 +1,127 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "AirCCallingConvention.h" >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirCCallSpecial.h" >+#include "AirCode.h" >+#include "B3CCallValue.h" >+#include "B3ValueInlines.h" >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+namespace { >+ >+template<typename BankInfo> >+Arg marshallCCallArgumentImpl(unsigned& argumentCount, unsigned& stackOffset, Value* child) >+{ >+ unsigned argumentIndex = argumentCount++; >+ if (argumentIndex < BankInfo::numberOfArgumentRegisters) >+ return Tmp(BankInfo::toArgumentRegister(argumentIndex)); >+ >+ unsigned slotSize; >+ if (isARM64() && isIOS()) { >+ // Arguments are packed. >+ slotSize = sizeofType(child->type()); >+ } else { >+ // Arguments are aligned. >+ slotSize = 8; >+ } >+ >+ stackOffset = WTF::roundUpToMultipleOf(slotSize, stackOffset); >+ Arg result = Arg::callArg(stackOffset); >+ stackOffset += slotSize; >+ return result; >+} >+ >+Arg marshallCCallArgument( >+ unsigned& gpArgumentCount, unsigned& fpArgumentCount, unsigned& stackOffset, Value* child) >+{ >+ switch (Arg::typeForB3Type(child->type())) { >+ case Arg::GP: >+ return marshallCCallArgumentImpl<GPRInfo>(gpArgumentCount, stackOffset, child); >+ case Arg::FP: >+ return marshallCCallArgumentImpl<FPRInfo>(fpArgumentCount, stackOffset, child); >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+ return Arg(); >+} >+ >+} // anonymous namespace >+ >+Vector<Arg> computeCCallingConvention(Code& code, CCallValue* value) >+{ >+ Vector<Arg> result; >+ result.append(Tmp(CCallSpecial::scratchRegister)); >+ unsigned gpArgumentCount = 0; >+ unsigned fpArgumentCount = 0; >+ unsigned stackOffset = 0; >+ for (unsigned i = 1; i < value->numChildren(); ++i) { >+ result.append( >+ marshallCCallArgument(gpArgumentCount, fpArgumentCount, stackOffset, value->child(i))); >+ } >+ code.requestCallArgAreaSize(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset)); >+ return result; >+} >+ >+Tmp cCallResult(Type type) >+{ >+ switch (type) { >+ case Void: >+ return Tmp(); >+ case Int32: >+ case Int64: >+ return Tmp(GPRInfo::returnValueGPR); >+ case Float: >+ case Double: >+ return Tmp(FPRInfo::returnValueFPR); >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+ return Tmp(); >+} >+ >+Inst buildCCall(Code& code, Value* origin, const Vector<Arg>& arguments) >+{ >+ Inst inst(Patch, origin, Arg::special(code.cCallSpecial())); >+ inst.args.append(arguments[0]); >+ inst.args.append(Tmp(GPRInfo::returnValueGPR)); >+ inst.args.append(Tmp(GPRInfo::returnValueGPR2)); >+ inst.args.append(Tmp(FPRInfo::returnValueFPR)); >+ for (unsigned i = 1; i < arguments.size(); ++i) { >+ Arg arg = arguments[i]; >+ if (arg.isTmp()) >+ inst.args.append(arg); >+ } >+ return inst; >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirCCallingConvention.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirCCallingConvention.h (revision 0) >+++ Source/JavaScriptCore/b3/air/AirCCallingConvention.h (working copy) >@@ -0,0 +1,55 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef AirCCallingConvention_h >+#define AirCCallingConvention_h >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirArg.h" >+#include "AirInst.h" >+#include "B3Type.h" >+#include <wtf/Vector.h> >+ >+namespace JSC { namespace B3 { >+ >+class CCallValue; >+ >+namespace Air { >+ >+class Code; >+ >+Vector<Arg> computeCCallingConvention(Code&, CCallValue*); >+ >+Tmp cCallResult(Type); >+ >+Inst buildCCall(Code&, Value* origin, const Vector<Arg>&); >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >+#endif // AirCCallingConvention_h >+ >Index: Source/JavaScriptCore/b3/air/AirCustom.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirCustom.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirCustom.cpp (working copy) >@@ -0,0 +1,138 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "AirCustom.h" >+ >+#if ENABLE(B3_JIT) >+ >+#include "B3CCallValue.h" >+#include "B3ValueInlines.h" >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+bool CCallCustom::isValidForm(Inst& inst) >+{ >+ CCallValue* value = inst.origin->as<CCallValue>(); >+ if (!value) >+ return false; >+ >+ if (inst.args.size() != 1 + (value->type() == Void ? 0 : 1) + value->numChildren()) >+ return false; >+ >+ // The arguments can only refer to the stack, tmps, or immediates. >+ for (Arg& arg : inst.args) { >+ if (!arg.isTmp() && !arg.isStackMemory() && !arg.isSomeImm()) >+ return false; >+ } >+ >+ unsigned offset = 1; >+ >+ // If there is a result then it cannot be an immediate. >+ if (value->type() != Void) { >+ if (inst.args[1].isSomeImm()) >+ return false; >+ if (!inst.args[1].canRepresent(value)) >+ return false; >+ offset++; >+ } >+ >+ for (unsigned i = value->numChildren(); i--;) { >+ Value* child = value->child(i); >+ Arg arg = inst.args[offset + i]; >+ if (!arg.canRepresent(child)) >+ return false; >+ } >+ >+ return true; >+} >+ >+CCallHelpers::Jump CCallCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&) >+{ >+ dataLog("FATAL: Unlowered C call: ", inst, "\n"); >+ UNREACHABLE_FOR_PLATFORM(); >+ return CCallHelpers::Jump(); >+} >+ >+bool ShuffleCustom::isValidForm(Inst& inst) >+{ >+ if (inst.args.size() % 3) >+ return false; >+ >+ // A destination may only appear once. This requirement allows us to avoid the undefined behavior >+ // of having a destination that is supposed to get multiple inputs simultaneously. It also >+ // imposes some interesting constraints on the "shape" of the shuffle. If we treat a shuffle pair >+ // as an edge and the Args as nodes, then the single-destination requirement means that the >+ // shuffle graph consists of two kinds of subgraphs: >+ // >+ // - Spanning trees. We call these shifts. They can be executed as a sequence of Move >+ // instructions and don't usually require scratch registers. >+ // >+ // - Closed loops. These loops consist of nodes that have one successor and one predecessor, so >+ // there is no way to "get into" the loop from outside of it. These can be executed using swaps >+ // or by saving one of the Args to a scratch register and executing it as a shift. >+ HashSet<Arg> dsts; >+ >+ for (unsigned i = 0; i < inst.args.size(); ++i) { >+ Arg arg = inst.args[0]; >+ unsigned mode = i % 3; >+ >+ if (mode == 2) { >+ // It's the width. >+ if (!arg.isWidthArg()) >+ return false; >+ continue; >+ } >+ >+ // The source can be an immediate. >+ if (!mode) { >+ if (arg.isSomeImm()) >+ continue; >+ } else { >+ ASSERT(mode == 1); >+ if (!dsts.add(arg).isNewEntry) >+ return false; >+ } >+ >+ if (arg.isTmp() || arg.isMemory()) >+ continue; >+ >+ return false; >+ } >+ >+ return true; >+} >+ >+CCallHelpers::Jump ShuffleCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&) >+{ >+ dataLog("FATAL: Unlowered shuffle: ", inst, "\n"); >+ UNREACHABLE_FOR_PLATFORM(); >+ return CCallHelpers::Jump(); >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirCustom.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirCustom.h (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirCustom.h (working copy) >@@ -30,6 +30,7 @@ > > #include "AirInst.h" > #include "AirSpecial.h" >+#include "B3Value.h" > > namespace JSC { namespace B3 { namespace Air { > >@@ -51,6 +52,8 @@ namespace JSC { namespace B3 { namespace > // you need to carry extra state around with the instruction. Also, Specials mean that you > // always have access to Code& even in methods that don't take a GenerationContext. > >+// Definition of Patch instruction. Patch is used to delegate the behavior of the instruction to the >+// Special object, which will be the first argument to the instruction. > struct PatchCustom { > template<typename Functor> > static void forEachArg(Inst& inst, const Functor& functor) >@@ -96,6 +99,113 @@ struct PatchCustom { > } > }; > >+// Definition of CCall instruction. CCall is used for hot path C function calls. It's lowered to a >+// Patch with an Air CCallSpecial along with code to marshal instructions. The lowering happens >+// before register allocation, so that the register allocator sees the clobbers. >+struct CCallCustom { >+ template<typename Functor> >+ static void forEachArg(Inst& inst, const Functor& functor) >+ { >+ Value* value = inst.origin; >+ >+ unsigned index = 0; >+ >+ functor(inst.args[index++], Arg::Use, Arg::GP, Arg::pointerWidth()); // callee >+ >+ if (value->type() != Void) { >+ functor( >+ inst.args[index++], Arg::Def, >+ Arg::typeForB3Type(value->type()), >+ Arg::widthForB3Type(value->type())); >+ } >+ >+ for (Value* child : value->children()) { >+ functor( >+ inst.args[index++], Arg::Use, >+ Arg::typeForB3Type(child->type()), >+ Arg::widthForB3Type(child->type())); >+ } >+ } >+ >+ template<typename... Arguments> >+ static bool isValidFormStatic(Arguments...) >+ { >+ return false; >+ } >+ >+ static bool isValidForm(Inst&); >+ >+ static bool admitsStack(Inst&, unsigned) >+ { >+ return true; >+ } >+ >+ static bool hasNonArgNonControlEffects(Inst&) >+ { >+ return true; >+ } >+ >+ // This just crashes, since we expect C calls to be lowered before generation. >+ static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&); >+}; >+ >+struct ColdCCallCustom : CCallCustom { >+ template<typename Functor> >+ static void forEachArg(Inst& inst, const Functor& functor) >+ { >+ // This is just like a call, but uses become cold. >+ CCallCustom::forEachArg( >+ inst, >+ [&] (Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width) { >+ functor(arg, Arg::cooled(role), type, width); >+ }); >+ } >+}; >+ >+struct ShuffleCustom { >+ template<typename Functor> >+ static void forEachArg(Inst& inst, const Functor& functor) >+ { >+ unsigned limit = inst.args.size() / 3 * 3; >+ for (unsigned i = 0; i < limit; i += 3) { >+ Arg& src = inst.args[i + 0]; >+ Arg& dst = inst.args[i + 1]; >+ Arg& widthArg = inst.args[i + 2]; >+ Arg::Width width = widthArg.width(); >+ Arg::Type type = src.isGP() && dst.isGP() ? Arg::GP : Arg::FP; >+ functor(src, Arg::Use, type, width); >+ functor(dst, Arg::Def, type, width); >+ functor(widthArg, Arg::Use, Arg::GP, Arg::Width8); >+ } >+ } >+ >+ template<typename... Arguments> >+ static bool isValidFormStatic(Arguments...) >+ { >+ return false; >+ } >+ >+ static bool isValidForm(Inst&); >+ >+ static bool admitsStack(Inst&, unsigned index) >+ { >+ switch (index % 3) { >+ case 0: >+ case 1: >+ return true; >+ default: >+ return false; >+ } >+ } >+ >+ static bool hasNonArgNonControlEffects(Inst&) >+ { >+ return false; >+ } >+ >+ static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&); >+}; >+ > } } } // namespace JSC::B3::Air > > #endif // ENABLE(B3_JIT) >Index: Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirEmitShuffle.cpp (working copy) >@@ -0,0 +1,395 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "AirEmitShuffle.h" >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirInstInlines.h" >+#include "AirRegisterPriority.h" >+#include <wtf/GraphNodeWorklist.h> >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+namespace { >+ >+template<typename Functor> >+Tmp findPossibleScratch(Arg::Type type, const Functor& functor) { >+ for (Reg reg : regsInPriorityOrder(type)) { >+ Tmp tmp(reg); >+ if (functor(tmp)) >+ return tmp; >+ } >+ return Tmp(); >+} >+ >+Tmp findPossibleScratch(Arg::Type type, const Arg& arg1, const Arg& arg2) { >+ return findPossibleScratch( >+ type, >+ [&] (Tmp tmp) -> bool { >+ return !arg1.usesTmp(tmp) && !arg2.usesTmp(tmp); >+ }); >+} >+ >+} // anonymous namespace >+ >+void ShufflePair::dump(PrintStream& out) const >+{ >+ out.print(width(), ":", src(), "=>", dst()); >+} >+ >+Vector<Inst> emitShuffle( >+ Vector<ShufflePair> pairs, std::array<Arg, 2> scratches, Arg::Type type, Value* origin) >+{ >+ pairs.removeAllMatching( >+ [&] (const ShufflePair& pair) -> bool { >+ return pair.src() == pair.dst(); >+ }); >+ >+ // First validate that this is the kind of shuffle that we know how to deal with. >+ for (const ShufflePair& pair : pairs) { >+ ASSERT(pair.src().isType(type)); >+ ASSERT(pair.dst().isType(type)); >+ ASSERT(pair.dst().isTmp() || pair.dst().isMemory()); >+ } >+ >+ // There are two possible kinds of operations that we will do: >+ // >+ // - Shift. Example: (a => b, b => c). We emit this as "Move b, c; Move a, b". This only requires >+ // scratch registers if there are memory->memory moves. We want to find as many of these as >+ // possible because they are cheaper. Note that shifts can involve the same source mentioned >+ // multiple times. Example: (a => b, a => c, b => d, b => e). >+ // >+ // - Rotate. Example: (a => b, b => a). We want to emit this as "Swap a, b", but that instruction >+ // may not be available, in which case we may need a scratch register or a scratch memory >+ // location. A gnarlier example is (a => b, b => c, c => a). We can emit this as "Swap b, c; >+ // Swap a, b". Note that swapping has to be careful about differing widths. >+ // >+ // We will find multiple disjoint such operations. We can execute them in any order. >+ >+ // We interpret these as Moves that should be executed backwards. All shifts are keyed by their >+ // starting source. >+ HashMap<Arg, Vector<ShufflePair>> shifts; >+ >+ // We interpret these as Swaps over src()'s that should be executed backwards, i.e. for a list >+ // of size 3 we would do "Swap list[1].src(), list[2].src(); Swap list[0].src(), list[1].src()". >+ // Note that we actually can't do that if the widths don't match or other bad things happen. >+ Vector<Vector<ShufflePair>> rotates; >+ >+ { >+ HashMap<Arg, Vector<ShufflePair>> mapping; >+ for (const ShufflePair& pair : pairs) >+ mapping.add(pair.src(), Vector<ShufflePair>()).iterator->value.append(pair); >+ >+ Vector<ShufflePair> currentPairs; >+ >+ GraphNodeWorklist<Arg> worklist; >+ while (!mapping.isEmpty()) { >+ Arg originalSrc = mapping.begin()->key; >+ ASSERT(!shifts.contains(originalSrc)); >+ worklist.push(originalSrc); >+ while (Arg src = worklist.pop()) { >+ HashMap<Arg, Vector<ShufflePair>>::iterator iter = mapping.find(src); >+ if (iter == mapping.end()) { >+ // With a shift it's possible that we previously built the tail of this shift. >+ // See if that's the case now. >+ currentPairs.appendVector(shifts.take(src)); >+ continue; >+ } >+ Vector<ShufflePair> pairs = WTFMove(iter->value); >+ mapping.remove(iter); >+ >+ for (const ShufflePair& pair : pairs) { >+ currentPairs.append(pair); >+ ASSERT(pair.src() == src); >+ worklist.push(pair.dst()); >+ } >+ } >+ >+ ASSERT(currentPairs.size()); >+ ASSERT(currentPairs[0].src() == originalSrc); >+ >+ if (currentPairs.last().dst() == currentPairs[0].src()) { >+ // If the graph search terminates because we returned to the first source, then the >+ // pair list has to have a very particular shape. >+ for (unsigned i = currentPairs.size() - 1; i--;) >+ ASSERT(currentPairs[i].dst() == currentPairs[i + 1].src()); >+ rotates.append(currentPairs); >+ } else >+ shifts.add(originalSrc, currentPairs); >+ } >+ } >+ >+ // In the worst case, we need two scratch registers. The way we do this is that the client passes >+ // us what scratch registers he happens to have laying around. We will need scratch registers in >+ // the following cases: >+ // >+ // - Shuffle pairs where both src and dst refer to memory. >+ // - Rotate when no Swap instruction is available. >+ // >+ // Lucky for us, we are guaranteed to have extra scratch registers anytime we have a Shift that >+ // ends with a register. We search for such a register right now. >+ >+ auto moveForWidth = [&] (Arg::Width width) -> Opcode { >+ switch (width) { >+ case Arg::Width32: >+ return type == Arg::GP ? Move32 : MoveFloat; >+ case Arg::Width64: >+ return type == Arg::GP ? Move : MoveDouble; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ }; >+ >+ Opcode conservativeMove = moveForWidth(Arg::conservativeWidth(type)); >+ >+ // We will emit things in reverse. We maintain a list of packs of instructions, and then we emit >+ // append them together in reverse (for example the thing at the end of resultPacks is placed >+ // first). This is useful because the last thing we emit frees up its destination registers, so >+ // it affects how we emit things before it. >+ Vector<Vector<Inst>> resultPacks; >+ Vector<Inst> result; >+ >+ auto commitResult = [&] () { >+ resultPacks.append(WTFMove(result)); >+ }; >+ >+ auto getScratch = [&] (unsigned index, Tmp possibleScratch) -> Tmp { >+ if (scratches[index].isTmp()) >+ return scratches[index].tmp(); >+ >+ if (!possibleScratch) >+ return Tmp(); >+ result.append(Inst(conservativeMove, origin, possibleScratch, scratches[index])); >+ return possibleScratch; >+ }; >+ >+ auto returnScratch = [&] (unsigned index, Tmp tmp) { >+ if (Arg(tmp) != scratches[index]) >+ result.append(Inst(conservativeMove, origin, scratches[index], tmp)); >+ }; >+ >+ auto handleShiftPair = [&] (const ShufflePair& pair, unsigned scratchIndex) { >+ Opcode move = moveForWidth(pair.width()); >+ >+ if (!isValidForm(move, pair.src().kind(), pair.dst().kind())) { >+ Tmp scratch = >+ getScratch(scratchIndex, findPossibleScratch(type, pair.src(), pair.dst())); >+ RELEASE_ASSERT(scratch); >+ if (isValidForm(move, pair.src().kind(), Arg::Tmp)) >+ result.append(Inst(moveForWidth(pair.width()), origin, pair.src(), scratch)); >+ else { >+ ASSERT(pair.src().isSomeImm()); >+ ASSERT(move == Move32); >+ result.append(Inst(Move, origin, Arg::imm64(pair.src().value()), scratch)); >+ } >+ result.append(Inst(moveForWidth(pair.width()), origin, scratch, pair.dst())); >+ returnScratch(scratchIndex, scratch); >+ return; >+ } >+ >+ result.append(Inst(move, origin, pair.src(), pair.dst())); >+ }; >+ >+ auto handleShift = [&] (Vector<ShufflePair>& shift) { >+ for (unsigned i = shift.size(); i--;) >+ handleShiftPair(shift[i], 0); >+ >+ Arg lastDst = shift.last().dst(); >+ if (lastDst.isTmp()) { >+ for (Arg& scratch : scratches) { >+ ASSERT(scratch != lastDst); >+ if (!scratch.isTmp()) { >+ scratch = lastDst; >+ break; >+ } >+ } >+ } >+ }; >+ >+ // First handle shifts whose last destination is a tmp because these free up scratch registers. >+ // These end up last in the final sequence, so the final destination of these shifts will be >+ // available as a scratch location for anything emitted prior (so, after, since we're emitting in >+ // reverse). >+ for (auto& entry : shifts) { >+ Vector<ShufflePair>& shift = entry.value; >+ if (shift.last().dst().isTmp()) >+ handleShift(shift); >+ commitResult(); >+ } >+ >+ // Now handle the rest of the shifts. >+ for (auto& entry : shifts) { >+ Vector<ShufflePair>& shift = entry.value; >+ if (!shift.last().dst().isTmp()) >+ handleShift(shift); >+ commitResult(); >+ } >+ >+ for (Vector<ShufflePair>& rotate : rotates) { >+ bool canSwap = false; >+ Opcode swap = Oops; >+ Arg::Width swapWidth = Arg::Width8; // bogus value >+ >+ if (type == Arg::GP) { >+ swap = Swap32; >+ swapWidth = Arg::Width32; >+ for (ShufflePair& pair : rotate) { >+ switch (pair.width()) { >+ case Arg::Width32: >+ break; >+ case Arg::Width64: >+ swap = Swap64; >+ swapWidth = Arg::Width64; >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ } >+ >+ canSwap = isValidForm(swap, Arg::Tmp, Arg::Tmp); >+ for (ShufflePair& pair : rotate) { >+ if (pair.src().isMemory() || pair.dst().isMemory()) { >+ canSwap &= isValidForm(swap, Arg::Tmp, Arg::Addr); >+ >+ // We don't take the swapping path if there is a mix of widths and some of the >+ // shuffles involve memory. That gets too confusing. >+ canSwap &= (pair.width() < swapWidth); >+ } >+ } >+ } >+ >+ if (canSwap) { >+ for (unsigned i = rotate.size() - 1; i--;) { >+ Arg left = rotate[i].src(); >+ Arg right = rotate[i + 1].src(); >+ >+ if (left.isMemory() && right.isMemory()) { >+ // Note that this is a super rare outcome. Rotates are rare. Spills are rare. >+ // Moving data between two spills is rare. To get here a lot of rare stuff has to >+ // all happen at once. >+ >+ Tmp scratch = getScratch(0, findPossibleScratch(type, left, right)); >+ RELEASE_ASSERT(scratch); >+ result.append(Inst(moveForWidth(swapWidth), origin, left, scratch)); >+ result.append(Inst(swap, origin, scratch, right)); >+ result.append(Inst(moveForWidth(swapWidth), origin, scratch, left)); >+ returnScratch(0, scratch); >+ continue; >+ } >+ >+ if (left.isMemory()) >+ std::swap(left, right); >+ >+ result.append(Inst(swap, origin, left, right)); >+ } >+ >+ for (ShufflePair pair : rotate) { >+ if (pair.width() == swapWidth) >+ continue; >+ >+ RELEASE_ASSERT(pair.width() == Arg::Width32); >+ RELEASE_ASSERT(swapWidth == Arg::Width64); >+ RELEASE_ASSERT(pair.dst().isTmp()); >+ >+ // Need to do an extra zero extension. >+ result.append(Inst(Move32, origin, pair.dst(), pair.dst())); >+ } >+ } else { >+ // We can treat this as a shift so long as we take the last destination (i.e. first >+ // source) and save it first. Then we handle the first entry in the pair in the rotate >+ // specially, after we restore the last destination. This requires some special care to >+ // find a scratch register. It's possible that we have a rotate that uses the entire >+ // available register file. >+ >+ Tmp scratch = findPossibleScratch( >+ type, >+ [&] (Tmp tmp) -> bool { >+ for (ShufflePair pair : rotate) { >+ if (pair.src().usesTmp(tmp)) >+ return false; >+ if (pair.dst().usesTmp(tmp)) >+ return false; >+ } >+ return true; >+ }); >+ >+ scratch = getScratch(0, scratch); >+ >+ Arg rotateSave = scratch ? Arg(scratch) : scratches[0]; >+ >+ handleShiftPair(ShufflePair(rotate.last().dst(), rotateSave, rotate[0].width()), 1); >+ >+ for (unsigned i = rotate.size(); i-- > 1;) >+ handleShiftPair(rotate[i], 1); >+ >+ handleShiftPair(ShufflePair(rotateSave, rotate[0].dst(), rotate[0].width()), 1); >+ >+ if (scratch) >+ returnScratch(0, scratch); >+ } >+ >+ commitResult(); >+ } >+ >+ ASSERT(result.isEmpty()); >+ >+ for (unsigned i = resultPacks.size(); i--;) >+ result.appendVector(resultPacks[i]); >+ >+ return result; >+} >+ >+Vector<Inst> emitShuffle( >+ const Vector<ShufflePair>& pairs, >+ const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch, >+ Value* origin) >+{ >+ Vector<ShufflePair> gpPairs; >+ Vector<ShufflePair> fpPairs; >+ for (const ShufflePair& pair : pairs) { >+ if (pair.src().isMemory() && pair.dst().isMemory() && pair.width() > Arg::pointerWidth()) { >+ // 8-byte memory-to-memory moves on a 32-bit platform are best handled as float moves. >+ fpPairs.append(pair); >+ } else if (pair.src().isGP() && pair.dst().isGP()) { >+ // This means that gpPairs gets memory-to-memory shuffles. The assumption is that we >+ // can do that more efficiently using GPRs, except in the special case above. >+ gpPairs.append(pair); >+ } else >+ fpPairs.append(pair); >+ } >+ >+ Vector<Inst> result; >+ result.appendVector(emitShuffle(gpPairs, gpScratch, Arg::GP, origin)); >+ result.appendVector(emitShuffle(fpPairs, fpScratch, Arg::FP, origin)); >+ return result; >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirEmitShuffle.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirEmitShuffle.h (revision 0) >+++ Source/JavaScriptCore/b3/air/AirEmitShuffle.h (working copy) >@@ -0,0 +1,112 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef AirEmitShuffle_h >+#define AirEmitShuffle_h >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirArg.h" >+#include "AirInst.h" >+#include <wtf/Vector.h> >+ >+namespace JSC { namespace B3 { >+ >+class Value; >+ >+namespace Air { >+ >+class ShufflePair { >+public: >+ ShufflePair() >+ { >+ } >+ >+ ShufflePair(const Arg& src, const Arg& dst, Arg::Width width) >+ : m_src(src) >+ , m_dst(dst) >+ , m_width(width) >+ { >+ } >+ >+ const Arg& src() const { return m_src; } >+ const Arg& dst() const { return m_dst; } >+ >+ // The width determines the kind of move we do. You can only choose Width32 or Width64 right now. >+ // For GP, it picks between Move32 and Move. For FP, it picks between MoveFloat and MoveDouble. >+ Arg::Width width() const { return m_width; } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ Arg m_src; >+ Arg m_dst; >+ Arg::Width m_width { Arg::Width8 }; >+}; >+ >+// Perform a shuffle of a given type. The scratch argument is mandatory. You should pass it as >+// follows: If you know that you have scratch registers or temporaries available - that is, they're >+// registers that are not mentioned in the shuffle, have the same type as the shuffle, and are not >+// live at the shuffle - then you can pass them. If you don't have scratch registers available or if >+// you don't feel like looking for them, you can pass memory locations. It's always safe to pass a >+// pair of memory locations, and replacing either memory location with a register can be viewed as an >+// optimization. It's a pretty important optimization. Some more notes: >+// >+// - We define scratch registers as things that are not live before the shuffle and are not one of >+// the destinations of the shuffle. Not being live before the shuffle also means that they cannot >+// be used >+// >+// - A second scratch location is only needed when you have shuffle pairs where memory is used both >+// as source and destination. >+// >+// - You're guaranteed not to need any scratch locations if there is a Swap instruction available for >+// the type and you don't have any memory locations that are both the source and the destination of >+// some pairs. GP supports Swap on x86 while FP never supports Swap. >+// >+// - Passing memory locations as scratch if are running emitShuffle() before register allocation is >+// silly, since that will cause emitShuffle() to pick some specific registers when it does need >+// scratch. One easy way to avoid that predicament is to ensure that you call emitShuffle() after >+// register allocation. For this reason we could add a Shuffle instruction so that we can defer >+// shufflings until after regalloc. >+// >+// - Shuffles with memory=>memory pairs are not very well tuned. You should avoid them if you want >+// performance. If you need to do them, then making sure that you reserve a temporary is one way to >+// get acceptable performance. >+Vector<Inst> emitShuffle( >+ Vector<ShufflePair>, std::array<Arg, 2> scratch, Arg::Type, Value* origin); >+ >+// Perform a shuffle that involves any number of types. Pass scratch registers or memory locations >+// for each type according to the rules above. >+Vector<Inst> emitShuffle( >+ const Vector<ShufflePair>&, >+ const std::array<Arg, 2>& gpScratch, const std::array<Arg, 2>& fpScratch, >+ Value* origin); >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >+#endif // AirEmitShuffle_h >+ >Index: Source/JavaScriptCore/b3/air/AirGenerate.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirGenerate.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirGenerate.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -35,6 +35,8 @@ > #include "AirGenerationContext.h" > #include "AirHandleCalleeSaves.h" > #include "AirIteratedRegisterCoalescing.h" >+#include "AirLowerAfterRegAlloc.h" >+#include "AirLowerMacros.h" > #include "AirOpcodeUtils.h" > #include "AirOptimizeBlockOrder.h" > #include "AirReportUsedRegisters.h" >@@ -65,6 +67,8 @@ void prepareForGeneration(Code& code) > dataLog(code); > } > >+ lowerMacros(code); >+ > // This is where we run our optimizations and transformations. > // FIXME: Add Air optimizations. > // https://bugs.webkit.org/show_bug.cgi?id=150456 >@@ -80,6 +84,8 @@ void prepareForGeneration(Code& code) > else > iteratedRegisterCoalescing(code); > >+ lowerAfterRegAlloc(code); >+ > // Prior to this point the prologue and epilogue is implicit. This makes it explicit. It also > // does things like identify which callee-saves we're using and saves them. > handleCalleeSaves(code); >Index: Source/JavaScriptCore/b3/air/AirInsertionSet.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirInsertionSet.cpp (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirInsertionSet.cpp (working copy) >@@ -33,6 +33,18 @@ > > namespace JSC { namespace B3 { namespace Air { > >+void InsertionSet::insertInsts(size_t index, const Vector<Inst>& insts) >+{ >+ for (const Inst& inst : insts) >+ insertInst(index, inst); >+} >+ >+void InsertionSet::insertInsts(size_t index, Vector<Inst>&& insts) >+{ >+ for (Inst& inst : insts) >+ insertInst(index, WTFMove(inst)); >+} >+ > void InsertionSet::execute(BasicBlock* block) > { > bubbleSort(m_insertions.begin(), m_insertions.end()); >Index: Source/JavaScriptCore/b3/air/AirInsertionSet.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirInsertionSet.h (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirInsertionSet.h (working copy) >@@ -59,6 +59,9 @@ public: > { > appendInsertion(Insertion(index, std::forward<Inst>(inst))); > } >+ >+ void insertInsts(size_t index, const Vector<Inst>&); >+ void insertInsts(size_t index, Vector<Inst>&&); > > template<typename... Arguments> > void insert(size_t index, Arguments&&... arguments) >Index: Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp (working copy) >@@ -0,0 +1,202 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "AirLowerAfterRegAlloc.h" >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirCCallingConvention.h" >+#include "AirCode.h" >+#include "AirEmitShuffle.h" >+#include "AirInsertionSet.h" >+#include "AirInstInlines.h" >+#include "AirLiveness.h" >+#include "AirPhaseScope.h" >+#include "AirRegisterPriority.h" >+#include "B3CCallValue.h" >+#include "RegisterSet.h" >+#include <wtf/HashMap.h> >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+void lowerAfterRegAlloc(Code& code) >+{ >+ PhaseScope phaseScope(code, "lowerAfterRegAlloc"); >+ >+ HashMap<Inst*, RegisterSet> usedRegisters; >+ >+ RegLiveness liveness(code); >+ for (BasicBlock* block : code) { >+ RegLiveness::LocalCalc localCalc(liveness, block); >+ >+ for (unsigned instIndex = block->size(); instIndex--;) { >+ Inst& inst = block->at(instIndex); >+ >+ RegisterSet set; >+ >+ if (inst.opcode == Shuffle || inst.opcode == ColdCCall) { >+ for (Reg reg : localCalc.live()) >+ set.set(reg); >+ } >+ >+ localCalc.execute(instIndex); >+ >+ if (set.numberOfSetRegisters()) >+ usedRegisters.add(&inst, set); >+ } >+ } >+ >+ auto getScratches = [&] (const RegisterSet& set, Arg::Type type) -> std::array<Arg, 2> { >+ std::array<Arg, 2> result; >+ for (unsigned i = 0; i < 2; ++i) { >+ bool found = false; >+ for (Reg reg : regsInPriorityOrder(type)) { >+ if (!set.get(reg)) { >+ result[i] = Tmp(reg); >+ found = true; >+ break; >+ } >+ } >+ if (!found) { >+ result[i] = Arg::stack( >+ code.addStackSlot( >+ Arg::bytes(Arg::conservativeWidth(type)), >+ StackSlotKind::Anonymous)); >+ } >+ } >+ return result; >+ }; >+ >+ // Now transform the code. >+ InsertionSet insertionSet(code); >+ for (BasicBlock* block : code) { >+ for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) { >+ Inst& inst = block->at(instIndex); >+ >+ switch (inst.opcode) { >+ case Shuffle: { >+ RegisterSet set = usedRegisters.get(&inst); >+ Vector<ShufflePair> pairs; >+ for (unsigned i = 0; i < inst.args.size(); i += 3) { >+ Arg src = inst.args[i + 0]; >+ Arg dst = inst.args[i + 1]; >+ Arg::Width width = inst.args[i + 2].width(); >+ if (src.isReg()) >+ set.set(src.reg()); >+ pairs.append(ShufflePair(src, dst, width)); >+ } >+ std::array<Arg, 2> gpScratch = getScratches(set, Arg::GP); >+ std::array<Arg, 2> fpScratch = getScratches(set, Arg::FP); >+ insertionSet.insertInsts( >+ instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin)); >+ inst = Inst(); >+ break; >+ } >+ >+ case ColdCCall: { >+ CCallValue* value = inst.origin->as<CCallValue>(); >+ >+ RegisterSet preUsed; >+ Vector<Arg> destinations = computeCCallingConvention(code, value); >+ Tmp result = cCallResult(value->type()); >+ >+ Vector<ShufflePair> pairs; >+ for (unsigned i = 0; i < destinations.size(); ++i) { >+ Value* child = value->child(i); >+ Arg src = inst.args[result ? (i >= 1 ? i + 1 : i) : i ]; >+ Arg dst = destinations[i]; >+ Arg::Width width = Arg::widthForB3Type(child->type()); >+ pairs.append(ShufflePair(src, dst, width)); >+ if (src.isReg()) >+ preUsed.set(src.reg()); >+ } >+ >+ std::array<Arg, 2> gpScratch = getScratches(preUsed, Arg::GP); >+ std::array<Arg, 2> fpScratch = getScratches(preUsed, Arg::FP); >+ >+ RegisterSet regsToSave = usedRegisters.get(&inst); >+ >+ // Also need to save all live registers. Don't need to worry about the result >+ // register. >+ if (result) >+ regsToSave.clear(result.reg()); >+ Vector<StackSlot*> stackSlots; >+ regsToSave.forEach( >+ [&] (Reg reg) { >+ Tmp tmp(reg); >+ Arg arg(tmp); >+ Arg::Width width = Arg::conservativeWidth(arg.type()); >+ StackSlot* stackSlot = >+ code.addStackSlot(Arg::bytes(width), StackSlotKind::Anonymous); >+ pairs.append(ShufflePair(arg, Arg::stack(stackSlot), width)); >+ stackSlots.append(stackSlot); >+ }); >+ >+ insertionSet.insertInsts( >+ instIndex, emitShuffle(pairs, gpScratch, fpScratch, inst.origin)); >+ >+ inst = buildCCall(code, inst.origin, destinations); >+ >+ // Now we need to emit code to restore registers. >+ pairs.resize(0); >+ unsigned stackSlotIndex = 0; >+ regsToSave.forEach( >+ [&] (Reg reg) { >+ Tmp tmp(reg); >+ Arg arg(tmp); >+ Arg::Width width = Arg::conservativeWidth(arg.type()); >+ StackSlot* stackSlot = stackSlots[stackSlotIndex++]; >+ pairs.append(ShufflePair(Arg::stack(stackSlot), arg, width)); >+ }); >+ if (result) { >+ ShufflePair pair(result, inst.args[1], Arg::widthForB3Type(value->type())); >+ pairs.append(pair); >+ } >+ >+ if (result) >+ regsToSave.set(result.reg()); >+ >+ gpScratch = getScratches(regsToSave, Arg::GP); >+ fpScratch = getScratches(regsToSave, Arg::FP); >+ >+ insertionSet.insertInsts( >+ instIndex + 1, emitShuffle(pairs, gpScratch, fpScratch, inst.origin)); >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ >+ insertionSet.execute(block); >+ } >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.h (revision 0) >+++ Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.h (working copy) >@@ -0,0 +1,44 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef AirLowerAfterRegAlloc_h >+#define AirLowerAfterRegAlloc_h >+ >+#if ENABLE(B3_JIT) >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+class Code; >+ >+// This lowers Shuffle and ColdCCall instructions. This phase is designed to be run after register >+// allocation. >+ >+void lowerAfterRegAlloc(Code&); >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >+#endif // AirLowerAfterRegAlloc_h >Index: Source/JavaScriptCore/b3/air/AirLowerMacros.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirLowerMacros.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirLowerMacros.cpp (working copy) >@@ -0,0 +1,105 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "AirLowerMacros.h" >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirCCallingConvention.h" >+#include "AirCode.h" >+#include "AirInsertionSet.h" >+#include "AirInstInlines.h" >+#include "AirPhaseScope.h" >+#include "B3CCallValue.h" >+#include "B3ValueInlines.h" >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+void lowerMacros(Code& code) >+{ >+ PhaseScope phaseScope(code, "lowerMacros"); >+ >+ InsertionSet insertionSet(code); >+ for (BasicBlock* block : code) { >+ for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) { >+ Inst& inst = block->at(instIndex); >+ >+ switch (inst.opcode) { >+ case CCall: { >+ CCallValue* value = inst.origin->as<CCallValue>(); >+ >+ Vector<Arg> destinations = computeCCallingConvention(code, value); >+ >+ Inst shuffleArguments(Shuffle, value); >+ unsigned offset = value->type() == Void ? 0 : 1; >+ for (unsigned i = 1; i < destinations.size(); ++i) { >+ Value* child = value->child(i); >+ shuffleArguments.args.append(inst.args[offset + i]); >+ shuffleArguments.args.append(destinations[i]); >+ shuffleArguments.args.append(Arg::widthArg(Arg::widthForB3Type(child->type()))); >+ } >+ insertionSet.insertInst(instIndex, WTFMove(shuffleArguments)); >+ >+ // Indicate that we're using our original callee argument. >+ destinations[0] = inst.args[0]; >+ >+ // Save where the original instruction put its result. >+ Arg resultDst = value->type() == Void ? Arg() : inst.args[1]; >+ >+ inst = buildCCall(code, inst.origin, destinations); >+ >+ Tmp result = cCallResult(value->type()); >+ switch (value->type()) { >+ case Void: >+ break; >+ case Float: >+ insertionSet.insert(instIndex + 1, MoveFloat, value, result, resultDst); >+ break; >+ case Double: >+ insertionSet.insert(instIndex + 1, MoveDouble, value, result, resultDst); >+ break; >+ case Int32: >+ insertionSet.insert(instIndex + 1, Move32, value, result, resultDst); >+ break; >+ case Int64: >+ insertionSet.insert(instIndex + 1, Move, value, result, resultDst); >+ break; >+ } >+ break; >+ } >+ >+ default: >+ break; >+ } >+ } >+ insertionSet.execute(block); >+ } >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirLowerMacros.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirLowerMacros.h (revision 0) >+++ Source/JavaScriptCore/b3/air/AirLowerMacros.h (working copy) >@@ -0,0 +1,45 @@ >+/* >+ * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef AirLowerMacros_h >+#define AirLowerMacros_h >+ >+#if ENABLE(B3_JIT) >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+class Code; >+ >+// Air has some opcodes that are very high-level and are meant to reduce the amount of low-level >+// knowledge in the B3->Air lowering. The current example is CCall. >+ >+void lowerMacros(Code&); >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >+#endif // AirLowerMacros_h >+ >Index: Source/JavaScriptCore/b3/air/AirOpcode.opcodes >=================================================================== >--- Source/JavaScriptCore/b3/air/AirOpcode.opcodes (revision 194856) >+++ Source/JavaScriptCore/b3/air/AirOpcode.opcodes (working copy) >@@ -407,6 +407,14 @@ Move U:G:Ptr, D:G:Ptr > Tmp, Index as storePtr > x86: Imm, Addr as storePtr > >+x86: Swap32 UD:G:32, UD:G:32 >+ Tmp, Tmp >+ Tmp, Addr >+ >+x86_64: Swap64 UD:G:64, UD:G:64 >+ Tmp, Tmp >+ Tmp, Addr >+ > Move32 U:G:32, ZD:G:32 > Tmp, Tmp as zeroExtend32ToPtr > Addr, Tmp as load32 >@@ -672,7 +680,19 @@ RetDouble U:F:64 /return > > Oops /terminal > >+# A Shuffle is a multi-source, multi-destination move. It simultaneously does multiple moves at once. >+# The moves are specified as triplets of src, dst, and width. For example you can request a swap this >+# way: >+# Shuffle %tmp1, %tmp2, 64, %tmp2, %tmp1, 64 >+custom Shuffle >+ > # Air allows for exotic behavior. A Patch's behavior is determined entirely by the Special operand, > # which must be the first operand. > custom Patch > >+# Instructions used for lowering C calls. These don't make it to Air generation. They get lowered to >+# something else first. The origin Value must be a CCallValue. >+custom CCall >+custom ColdCCall >+ >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 152952
:
268720
|
268731
|
268740
|
268743
|
268746
|
268792
|
268817
|
268836
|
268837
|
268841
|
268893
|
268904
|
268906
|
268928
|
268929
|
268931
|
268942
|
268982
|
268990
|
268999
|
269013