Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (193361 => 193362)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2015-12-03 20:01:57 UTC (rev 193362)
@@ -1031,6 +1031,7 @@
ftl/FTLOSREntry.cpp
ftl/FTLOSRExit.cpp
ftl/FTLOSRExitCompiler.cpp
+ ftl/FTLOSRExitHandle.cpp
ftl/FTLOperations.cpp
ftl/FTLOutput.cpp
ftl/FTLRecoveryOpcode.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (193361 => 193362)
--- trunk/Source/_javascript_Core/ChangeLog 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-12-03 20:01:57 UTC (rev 193362)
@@ -1,3 +1,125 @@
+2015-12-02 Filip Pizlo <fpi...@apple.com>
+
+ FTL B3 should support OSR exit
+ https://bugs.webkit.org/show_bug.cgi?id=151710
+
+ Reviewed by Saam Barati.
+
+ This adds OSR exit support using the same style that I established with lazy slow paths. All of
+ the work is driven by FTL::LowerDFGToLLVM, and from there any work that needs to be deferred
+ until after B3 finishes is attached to the stackmap generator. In order to make it easy to port
+ all of the different forms of OSR exit - invalidation points, exceptions, etc. - the logic for
+ registering an OSR exit is abstracted behind OSRExitDescriptor and OSRExitHandle.
+
+ An issue that I encountered repeatedly in this patch is OSRExitDescriptor being passed as a
+ reference (&) rather than pointer (*). The new code uses a lot of lambdas that run after the
+ current frame pops, so the capture list cannot be [&]. I believe that always listing all of the
+ captured variables is not scalable considering how sophisticated our use of lambdas is. So, it
+ makes sense to use [=]. But anytime we captured a variable whose type was OSRExitDescriptor&, it
+ would be captured by value, because that's how references work. One has to be mindful of these
+ things whenever using [=]. Note that it's not enough to say that we should have listed the
+ captured variables explicitly - in that case, we still could have made the mistake by forgetting
+ to put & in front of the variant. The pattern that worked for me to reason about whether I'm
+ capturing an object or a pointer to an object is to always use pointer types for pointers: either
+ RefPtr<> when we also want the lambda to prolong the object's life, or * if we are confident that
+ the object will stay alive. For this reason, this patch changes all code that references
+ OSRExitDescriptor to use * instead of &. Consistency makes the code easier to grok, and it made
+ it easier to introduce the required uses of * in places where there were lambdas.
+
+ I tested this by running imaging-gaussian-blur, and running some tests that reqiure OSR exit. I'm
+ not promising that all kinds of exits work, but we have to begin somewhere.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * b3/B3Compilation.cpp:
+ (JSC::B3::Compilation::Compilation):
+ (JSC::B3::Compilation::~Compilation):
+ * b3/B3Procedure.cpp:
+ (JSC::B3::Procedure::addDataSection):
+ (JSC::B3::Procedure::frameSize):
+ (JSC::B3::Procedure::calleeSaveRegisters):
+ * b3/B3Procedure.h:
+ (JSC::B3::Procedure::releaseByproducts):
+ (JSC::B3::Procedure::code):
+ (JSC::B3::Procedure::takeByproducts): Deleted.
+ * b3/air/AirCode.h:
+ (JSC::B3::Air::Code::setFrameSize):
+ (JSC::B3::Air::Code::calleeSaveRegisters):
+ * b3/air/AirGenerationContext.h:
+ * ftl/FTLB3Compile.cpp:
+ (JSC::FTL::compile):
+ * ftl/FTLCompile.cpp:
+ (JSC::FTL::mmAllocateDataSection):
+ * ftl/FTLExceptionHandlerManager.cpp:
+ (JSC::FTL::ExceptionHandlerManager::lazySlowPathExceptionTarget):
+ (JSC::FTL::ExceptionHandlerManager::getCallOSRExitCommon):
+ * ftl/FTLExitThunkGenerator.cpp:
+ * ftl/FTLExitThunkGenerator.h:
+ * ftl/FTLJITCode.cpp:
+ (JSC::FTL::JITCode::JITCode):
+ (JSC::FTL::JITCode::initializeB3Code):
+ (JSC::FTL::JITCode::initializeB3Byproducts):
+ (JSC::FTL::JITCode::initializeExitThunks):
+ (JSC::FTL::JITCode::validateReferences):
+ (JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite):
+ * ftl/FTLJITCode.h:
+ * ftl/FTLJITFinalizer.cpp:
+ (JSC::FTL::JITFinalizer::finalizeFunction):
+ * ftl/FTLJITFinalizer.h:
+ * ftl/FTLJSCall.cpp:
+ (JSC::FTL::JSCall::emit):
+ * ftl/FTLJSCallBase.cpp:
+ (JSC::FTL::JSCallBase::emit):
+ * ftl/FTLJSTailCall.cpp:
+ (JSC::FTL::JSTailCall::JSTailCall):
+ (JSC::FTL::JSTailCall::emit):
+ (JSC::FTL::DFG::getRegisterWithAddend): Deleted.
+ (JSC::FTL::m_instructionOffset): Deleted.
+ * ftl/FTLJSTailCall.h:
+ (JSC::FTL::JSTailCall::patchpoint):
+ (JSC::FTL::JSTailCall::stackmapID):
+ (JSC::FTL::JSTailCall::estimatedSize):
+ (JSC::FTL::JSTailCall::operator<):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileInvalidationPoint):
+ (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitArgumentsForPatchpointIfWillCatchException):
+ (JSC::FTL::DFG::LowerDFGToLLVM::lowBlock):
+ (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExitDescriptor):
+ (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
+ (JSC::FTL::DFG::LowerDFGToLLVM::blessSpeculation):
+ (JSC::FTL::DFG::LowerDFGToLLVM::emitOSRExitCall):
+ (JSC::FTL::DFG::LowerDFGToLLVM::buildExitArguments):
+ (JSC::FTL::DFG::LowerDFGToLLVM::callStackmap):
+ (JSC::FTL::lowerDFGToLLVM):
+ * ftl/FTLOSRExit.cpp:
+ (JSC::FTL::OSRExitDescriptor::OSRExitDescriptor):
+ (JSC::FTL::OSRExitDescriptor::validateReferences):
+ (JSC::FTL::OSRExitDescriptor::appendOSRExit):
+ (JSC::FTL::OSRExitDescriptor::appendOSRExitLater):
+ (JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle):
+ (JSC::FTL::OSRExit::OSRExit):
+ (JSC::FTL::OSRExit::codeLocationForRepatch):
+ (JSC::FTL::OSRExit::gatherRegistersToSpillForCallIfException):
+ (JSC::FTL::OSRExit::spillRegistersToSpillSlot):
+ (JSC::FTL::OSRExit::recoverRegistersFromSpillSlot):
+ (JSC::FTL::OSRExit::willArriveAtExitFromIndirectExceptionCheck):
+ * ftl/FTLOSRExit.h:
+ (JSC::FTL::OSRExit::considerAddingAsFrequentExitSite):
+ * ftl/FTLOSRExitCompilationInfo.h:
+ (JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo):
+ * ftl/FTLOSRExitCompiler.cpp:
+ (JSC::FTL::reboxAccordingToFormat):
+ (JSC::FTL::compileRecovery):
+ (JSC::FTL::compileStub):
+ (JSC::FTL::compileFTLOSRExit):
+ * ftl/FTLOSRExitHandle.cpp: Added.
+ (JSC::FTL::OSRExitHandle::emitExitThunk):
+ * ftl/FTLOSRExitHandle.h: Added.
+ (JSC::FTL::OSRExitHandle::OSRExitHandle):
+ * ftl/FTLState.cpp:
+ (JSC::FTL::State::State):
+ (JSC::FTL::State::~State):
+
2015-12-03 Joseph Pecoraro <pecor...@apple.com>
REGRESSION:(r192753): Remote Web Inspector: RemoteInspector::sendMessageToRemote with null connection
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (193361 => 193362)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-12-03 20:01:57 UTC (rev 193362)
@@ -494,6 +494,9 @@
0F978B3B1AAEA71D007C7369 /* ConstantMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */; };
0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */; };
0F98206116BFE38300240D02 /* PreciseJumpTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9B1DB41C0E42A500E5BFD2 /* FTLB3Output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */; };
+ 0F9B1DB71C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */; };
+ 0F9B1DB81C0E42BD00E5BFD2 /* FTLOSRExitHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */; };
0F9C5E5E18E35F5E00D431C3 /* FTLDWARFRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9C5E5C18E35F5E00D431C3 /* FTLDWARFRegister.cpp */; };
0F9C5E5F18E35F5E00D431C3 /* FTLDWARFRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9C5E5D18E35F5E00D431C3 /* FTLDWARFRegister.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9D3370165DBB90005AD387 /* Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D336E165DBB8D005AD387 /* Disassembler.cpp */; };
@@ -1092,7 +1095,6 @@
26718BA51BE99F780052017B /* AirIteratedRegisterCoalescing.h in Headers */ = {isa = PBXBuildFile; fileRef = 26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */; };
2684D4381C00161C0081D663 /* AirLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684D4371C00161C0081D663 /* AirLiveness.h */; };
269D636E1BFBE5D100101B1D /* FTLB3Output.h in Headers */ = {isa = PBXBuildFile; fileRef = 269D636D1BFBE5D000101B1D /* FTLB3Output.h */; };
- 26BB57601BFC4328005F12EB /* FTLB3Output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BB575F1BFC4328005F12EB /* FTLB3Output.cpp */; };
2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */; };
2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */; };
@@ -2580,6 +2582,9 @@
0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantMode.cpp; sourceTree = "<group>"; };
0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreciseJumpTargets.cpp; sourceTree = "<group>"; };
0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargets.h; sourceTree = "<group>"; };
+ 0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLB3Output.cpp; path = ftl/FTLB3Output.cpp; sourceTree = "<group>"; };
+ 0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLOSRExitHandle.cpp; path = ftl/FTLOSRExitHandle.cpp; sourceTree = "<group>"; };
+ 0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLOSRExitHandle.h; path = ftl/FTLOSRExitHandle.h; sourceTree = "<group>"; };
0F9C5E5C18E35F5E00D431C3 /* FTLDWARFRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDWARFRegister.cpp; path = ftl/FTLDWARFRegister.cpp; sourceTree = "<group>"; };
0F9C5E5D18E35F5E00D431C3 /* FTLDWARFRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFRegister.h; path = ftl/FTLDWARFRegister.h; sourceTree = "<group>"; };
0F9D336E165DBB8D005AD387 /* Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disassembler.cpp; path = disassembler/Disassembler.cpp; sourceTree = "<group>"; };
@@ -3147,7 +3152,6 @@
26718BA31BE99F780052017B /* AirIteratedRegisterCoalescing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirIteratedRegisterCoalescing.h; path = b3/air/AirIteratedRegisterCoalescing.h; sourceTree = "<group>"; };
2684D4371C00161C0081D663 /* AirLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirLiveness.h; path = b3/air/AirLiveness.h; sourceTree = "<group>"; };
269D636D1BFBE5D000101B1D /* FTLB3Output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLB3Output.h; path = ftl/FTLB3Output.h; sourceTree = "<group>"; };
- 26BB575F1BFC4328005F12EB /* FTLB3Output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLB3Output.cpp; path = ftl/FTLB3Output.cpp; sourceTree = "<group>"; };
2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = "<group>"; };
2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = "<group>"; };
2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = "<group>"; };
@@ -4424,6 +4428,7 @@
0F485323187DFDEC0083B687 /* FTLAvailableRecovery.cpp */,
0F485324187DFDEC0083B687 /* FTLAvailableRecovery.h */,
0FB387911BFD31A100E3AB1E /* FTLB3Compile.cpp */,
+ 0F9B1DB31C0E42A500E5BFD2 /* FTLB3Output.cpp */,
269D636D1BFBE5D000101B1D /* FTLB3Output.h */,
0FEA09FE170513DB00BB722C /* FTLCapabilities.cpp */,
0FEA09FF170513DB00BB722C /* FTLCapabilities.h */,
@@ -4496,6 +4501,8 @@
0F235BC817178E1C00690C7F /* FTLOSRExitCompilationInfo.h */,
0F235BC917178E1C00690C7F /* FTLOSRExitCompiler.cpp */,
0F235BCA17178E1C00690C7F /* FTLOSRExitCompiler.h */,
+ 0F9B1DB51C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp */,
+ 0F9B1DB61C0E42BD00E5BFD2 /* FTLOSRExitHandle.h */,
0FEA0A291709629600BB722C /* FTLOutput.cpp */,
0FEA0A06170513DB00BB722C /* FTLOutput.h */,
0F485325187DFDEC0083B687 /* FTLRecoveryOpcode.cpp */,
@@ -7575,6 +7582,7 @@
A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */,
C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */,
142D6F0913539A2800B02E86 /* MarkedBlock.h in Headers */,
+ 0F9B1DB81C0E42BD00E5BFD2 /* FTLOSRExitHandle.h in Headers */,
141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
142D6F1213539A4100B02E86 /* MarkStack.h in Headers */,
@@ -8618,6 +8626,7 @@
0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
+ 0F9B1DB41C0E42A500E5BFD2 /* FTLB3Output.cpp in Sources */,
0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */,
0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */,
@@ -8832,6 +8841,7 @@
A51007C0187CC3C600B38879 /* JSGlobalObjectInspectorController.cpp in Sources */,
A50E4B6318809DD50068A46D /* JSGlobalObjectRuntimeAgent.cpp in Sources */,
A503FA29188F105900110F14 /* JSGlobalObjectScriptDebugServer.cpp in Sources */,
+ 0F9B1DB71C0E42BD00E5BFD2 /* FTLOSRExitHandle.cpp in Sources */,
A513E5BF185BFACC007E95AD /* JSInjectedScriptHost.cpp in Sources */,
A513E5C1185BFACC007E95AD /* JSInjectedScriptHostPrototype.cpp in Sources */,
E33F50801B8429A400413856 /* JSInternalPromise.cpp in Sources */,
@@ -8987,7 +8997,6 @@
0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */,
0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */,
- 26BB57601BFC4328005F12EB /* FTLB3Output.cpp in Sources */,
0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
E33637A51B63220200EE0840 /* ReflectObject.cpp in Sources */,
0FA7A8EB18B413C80052371D /* Reg.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/b3/B3Compilation.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/b3/B3Compilation.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/b3/B3Compilation.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -42,13 +42,14 @@
{
TimingScope timingScope("Compilation");
+ prepareForGeneration(proc, optLevel);
+
CCallHelpers jit(&vm);
- prepareForGeneration(proc, optLevel);
generate(proc, jit);
LinkBuffer linkBuffer(vm, jit, nullptr);
m_codeRef = FINALIZE_CODE(linkBuffer, ("B3::Compilation"));
- m_byproducts = proc.takeByproducts();
+ m_byproducts = proc.releaseByproducts();
}
Compilation::~Compilation()
Modified: trunk/Source/_javascript_Core/b3/B3Procedure.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/b3/B3Procedure.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/b3/B3Procedure.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -148,8 +148,13 @@
return result;
}
-const RegisterAtOffsetList& Procedure::calleeSaveRegisters()
+unsigned Procedure::frameSize() const
{
+ return code().frameSize();
+}
+
+const RegisterAtOffsetList& Procedure::calleeSaveRegisters() const
+{
return code().calleeSaveRegisters();
}
Modified: trunk/Source/_javascript_Core/b3/B3Procedure.h (193361 => 193362)
--- trunk/Source/_javascript_Core/b3/B3Procedure.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/b3/B3Procedure.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -219,11 +219,13 @@
// just keeps alive things like the double constant pool and switch lookup tables. If this sounds
// confusing, you should probably be using the B3::Compilation API to compile code. If you use
// that API, then you don't have to worry about this.
- std::unique_ptr<OpaqueByproducts> takeByproducts() { return WTF::move(m_byproducts); }
+ std::unique_ptr<OpaqueByproducts> releaseByproducts() { return WTF::move(m_byproducts); }
+ const Air::Code& code() const { return *m_code; }
Air::Code& code() { return *m_code; }
- const RegisterAtOffsetList& calleeSaveRegisters();
+ unsigned frameSize() const;
+ const RegisterAtOffsetList& calleeSaveRegisters() const;
private:
friend class BlockInsertionSet;
Modified: trunk/Source/_javascript_Core/b3/air/AirCode.h (193361 => 193362)
--- trunk/Source/_javascript_Core/b3/air/AirCode.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/b3/air/AirCode.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -103,6 +103,7 @@
m_frameSize = frameSize;
}
+ const RegisterAtOffsetList& calleeSaveRegisters() const { return m_calleeSaveRegisters; }
RegisterAtOffsetList& calleeSaveRegisters() { return m_calleeSaveRegisters; }
// Recomputes predecessors and deletes unreachable blocks.
Modified: trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h (193361 => 193362)
--- trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -29,9 +29,12 @@
#if ENABLE(B3_JIT)
#include <wtf/SharedTask.h>
+#include <wtf/Vector.h>
namespace JSC { namespace B3 { namespace Air {
+class Code;
+
struct GenerationContext {
typedef void LatePathFunction(CCallHelpers&, GenerationContext&);
typedef SharedTask<LatePathFunction> LatePath;
Modified: trunk/Source/_javascript_Core/ftl/FTLB3Compile.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLB3Compile.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Compile.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -77,6 +77,8 @@
dataLog(" ", *registerOffsets, "\n");
}
state.graph.m_codeBlock->setCalleeSaveRegisters(WTF::move(registerOffsets));
+ ASSERT(!(state.proc->frameSize() % sizeof(EncodedJSValue)));
+ state.jitCode->common.frameRegisterCount = state.proc->frameSize() / sizeof(EncodedJSValue);
CCallHelpers jit(&vm, codeBlock);
B3::generate(*state.proc, jit);
@@ -90,6 +92,7 @@
state.generatedFunction = bitwise_cast<GeneratedFunction>(
state.finalizer->b3CodeLinkBuffer->entrypoint().executableAddress());
+ state.jitCode->initializeB3Byproducts(state.proc->releaseByproducts());
}
} } // namespace JSC::FTL
Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -498,7 +498,7 @@
for (unsigned j = 0; j < iter->value.size(); j++) {
{
uint32_t stackmapRecordIndex = iter->value[j].index;
- OSRExit exit(exitDescriptor, stackmapRecordIndex);
+ OSRExit exit(&exitDescriptor, stackmapRecordIndex);
state.jitCode->osrExit.append(exit);
state.finalizer->osrExit.append(OSRExitCompilationInfo());
}
@@ -506,8 +506,8 @@
OSRExit& exit = state.jitCode->osrExit.last();
if (exit.willArriveAtExitFromIndirectExceptionCheck()) {
StackMaps::Record& record = iter->value[j].record;
- RELEASE_ASSERT(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader.isSet());
- CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
+ RELEASE_ASSERT(exit.m_descriptor->m_semanticCodeOriginForCallFrameHeader.isSet());
+ CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor->m_semanticCodeOriginForCallFrameHeader);
exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
OSRExit* callOperationExit = nullptr;
@@ -523,12 +523,12 @@
// and the other that will be arrived at from the callOperation exception handler path.
// This code here generates the second callOperation variant.
uint32_t stackmapRecordIndex = iter->value[j].index;
- OSRExit exit(exitDescriptor, stackmapRecordIndex);
+ OSRExit exit(&exitDescriptor, stackmapRecordIndex);
if (exitDescriptor.m_exceptionType == ExceptionType::GetById)
exit.m_exceptionType = ExceptionType::GetByIdCallOperation;
else
exit.m_exceptionType = ExceptionType::PutByIdCallOperation;
- CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor.m_semanticCodeOriginForCallFrameHeader);
+ CallSiteIndex callSiteIndex = state.jitCode->common.addUniqueCallSiteIndex(exit.m_descriptor->m_semanticCodeOriginForCallFrameHeader);
exit.m_exceptionHandlerCallSiteIndex = callSiteIndex;
state.jitCode->osrExit.append(exit);
@@ -586,13 +586,13 @@
OSRExit& exit = state.jitCode->osrExit[i];
if (verboseCompilationEnabled())
- dataLog("Handling OSR stackmap #", exit.m_descriptor.m_stackmapID, " for ", exit.m_codeOrigin, "\n");
+ dataLog("Handling OSR stackmap #", exit.m_descriptor->m_stackmapID, " for ", exit.m_codeOrigin, "\n");
info.m_thunkAddress = linkBuffer->locationOf(info.m_thunkLabel);
exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
if (exit.willArriveAtOSRExitFromGenericUnwind()) {
- HandlerInfo newHandler = exit.m_descriptor.m_baselineExceptionHandler;
+ HandlerInfo newHandler = exit.m_descriptor->m_baselineExceptionHandler;
newHandler.start = exit.m_exceptionHandlerCallSiteIndex.bits();
newHandler.end = exit.m_exceptionHandlerCallSiteIndex.bits() + 1;
newHandler.nativeCode = info.m_thunkAddress;
@@ -601,10 +601,10 @@
if (verboseCompilationEnabled()) {
DumpContext context;
- dataLog(" Exit values: ", inContext(exit.m_descriptor.m_values, &context), "\n");
- if (!exit.m_descriptor.m_materializations.isEmpty()) {
+ dataLog(" Exit values: ", inContext(exit.m_descriptor->m_values, &context), "\n");
+ if (!exit.m_descriptor->m_materializations.isEmpty()) {
dataLog(" Materializations: \n");
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations)
dataLog(" Materialize(", pointerDump(materialization), ")\n");
}
}
@@ -997,7 +997,7 @@
codeAddresses.append(bitwise_cast<char*>(generatedFunction) + record.instructionOffset + MacroAssembler::maxJumpReplacementSize());
- if (exit.m_descriptor.m_isInvalidationPoint)
+ if (exit.m_descriptor->m_isInvalidationPoint)
jitCode->common.jumpReplacements.append(JumpReplacement(source, info.m_thunkAddress));
else
MacroAssembler::replaceWithJump(source, info.m_thunkAddress);
Modified: trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLExceptionHandlerManager.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -82,7 +82,7 @@
return CodeLocationLabel();
size_t osrExitIndex = findResult->value;
- RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_descriptor.m_exceptionType == ExceptionType::LazySlowPath);
+ RELEASE_ASSERT(m_state.jitCode->osrExit[osrExitIndex].m_descriptor->m_exceptionType == ExceptionType::LazySlowPath);
OSRExitCompilationInfo& info = m_state.finalizer->osrExit[osrExitIndex];
RELEASE_ASSERT(info.m_thunkLabel.isSet());
return m_state.finalizer->exitThunksLinkBuffer->locationOf(info.m_thunkLabel);
@@ -109,7 +109,7 @@
return nullptr;
size_t osrExitIndex = findResult->value;
OSRExit* exit = &m_state.jitCode->osrExit[osrExitIndex];
- RELEASE_ASSERT(exit->m_descriptor.m_exceptionType == ExceptionType::JSCall);
+ RELEASE_ASSERT(exit->m_descriptor->m_exceptionType == ExceptionType::JSCall);
return exit;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -26,7 +26,7 @@
#include "config.h"
#include "FTLExitThunkGenerator.h"
-#if ENABLE(FTL_JIT)
+#if ENABLE(FTL_JIT) && !FTL_USES_B3
#include "FTLOSRExitCompilationInfo.h"
#include "FTLState.h"
@@ -79,5 +79,5 @@
} } // namespace JSC::FTL
-#endif // ENABLE(FTL_JIT)
+#endif // ENABLE(FTL_JIT) && !FTL_USES_B3
Modified: trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLExitThunkGenerator.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -26,8 +26,10 @@
#ifndef FTLExitThunkGenerator_h
#define FTLExitThunkGenerator_h
-#if ENABLE(FTL_JIT)
+#include "DFGCommon.h"
+#if ENABLE(FTL_JIT) && !FTL_USES_B3
+
#include "CCallHelpers.h"
namespace JSC { namespace FTL {
@@ -52,7 +54,7 @@
} } // namespace JSC::FTL
-#endif // ENABLE(FTL_JIT)
+#endif // ENABLE(FTL_JIT) && !FTL_USES_B3
#endif // FTLExitThunkGenerator_h
Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -32,6 +32,8 @@
namespace JSC { namespace FTL {
+using namespace B3;
+
JITCode::JITCode()
: JSC::JITCode(FTLJIT)
{
@@ -60,6 +62,11 @@
{
m_b3Code = b3Code;
}
+
+void JITCode::initializeB3Byproducts(std::unique_ptr<OpaqueByproducts> byproducts)
+{
+ m_b3Byproducts = WTF::move(byproducts);
+}
#else // FTL_USES_B3
void JITCode::initializeExitThunks(CodeRef exitThunks)
{
@@ -155,17 +162,21 @@
common.validateReferences(trackedReferences);
for (OSRExit& exit : osrExit)
- exit.m_descriptor.validateReferences(trackedReferences);
+ exit.m_descriptor->validateReferences(trackedReferences);
}
RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex callSiteIndex)
{
+#if FTL_USES_B3
+ UNUSED_PARAM(callSiteIndex);
+#else // FTL_USES_B3
for (OSRExit& exit : osrExit) {
if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
RELEASE_ASSERT(exit.m_isExceptionHandler);
return stackmaps.records[exit.m_stackmapRecordIndex].usedRegisterSet();
}
}
+#endif // FTL_USES_B3
return RegisterSet();
}
Modified: trunk/Source/_javascript_Core/ftl/FTLJITCode.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJITCode.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJITCode.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -28,6 +28,7 @@
#if ENABLE(FTL_JIT)
+#include "B3OpaqueByproducts.h"
#include "DFGCommonData.h"
#include "FTLDataSection.h"
#include "FTLLazySlowPath.h"
@@ -68,6 +69,7 @@
#if FTL_USES_B3
void initializeB3Code(CodeRef);
+ void initializeB3Byproducts(std::unique_ptr<B3::OpaqueByproducts>);
#else
void initializeExitThunks(CodeRef);
void addHandle(PassRefPtr<ExecutableMemoryHandle>);
@@ -95,13 +97,16 @@
DFG::CommonData common;
SegmentedVector<OSRExit, 8> osrExit;
SegmentedVector<OSRExitDescriptor, 8> osrExitDescriptors;
+#if !FTL_USES_B3
StackMaps stackmaps;
+#endif // !FTL_USES_B3
Vector<std::unique_ptr<LazySlowPath>> lazySlowPaths;
private:
CodePtr m_addressForCall;
#if FTL_USES_B3
CodeRef m_b3Code;
+ std::unique_ptr<B3::OpaqueByproducts> m_b3Byproducts;
#else
Vector<RefPtr<DataSection>> m_dataSections;
Vector<RefPtr<ExecutableMemoryHandle>> m_handles;
Modified: trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -82,13 +82,6 @@
bool dumpDisassembly = shouldDumpDisassembly() || Options::asyncDisassembly();
#if FTL_USES_B3
- for (OSRExitCompilationInfo& info : osrExit) {
- b3CodeLinkBuffer->link(
- info.m_thunkJump,
- CodeLocationLabel(
- m_plan.vm.getCTIStub(osrExitGenerationThunkGenerator).code()));
- }
-
jitCode->initializeB3Code(
FINALIZE_CODE_IF(
dumpDisassembly, *b3CodeLinkBuffer,
Modified: trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJITFinalizer.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -73,9 +73,9 @@
std::unique_ptr<LinkBuffer> sideCodeLinkBuffer;
std::unique_ptr<LinkBuffer> handleExceptionsLinkBuffer;
Vector<OutOfLineCodeInfo> outOfLineCodeInfos;
+ Vector<OSRExitCompilationInfo> osrExit;
#endif
-
- Vector<OSRExitCompilationInfo> osrExit;
+
Vector<CCallHelpers::Jump> lazySlowPathGeneratorJumps;
GeneratedFunction function;
RefPtr<JITCode> jitCode;
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCall.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -54,7 +54,11 @@
{
JSCallBase::emit(jit, state, osrExitFromGenericUnwindSpillSlots);
+#if FTL_USES_B3
+ jit.addPtr(CCallHelpers::TrustedImm32(- static_cast<int64_t>(state.jitCode->common.frameRegisterCount * sizeof(EncodedJSValue))), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+#else // FTL_USES_B3
jit.addPtr(CCallHelpers::TrustedImm32(- static_cast<int64_t>(state.jitCode->stackmaps.stackSizeForLocals())), CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+#endif // FTL_USES_B3
}
} } // namespace JSC::FTL
Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -54,9 +54,13 @@
void JSCallBase::emit(CCallHelpers& jit, State& /*state*/, int32_t osrExitFromGenericUnwindStackSpillSlot)
{
RELEASE_ASSERT(!!m_callSiteIndex);
-
+
+#if FTL_USES_B3
+ UNUSED_PARAM(osrExitFromGenericUnwindStackSpillSlot);
+#else // FTL_USES_B3
if (m_correspondingGenericUnwindOSRExit)
m_correspondingGenericUnwindOSRExit->spillRegistersToSpillSlot(jit, osrExitFromGenericUnwindStackSpillSlot);
+#endif // FTL_USES_B3
jit.store32(CCallHelpers::TrustedImm32(m_callSiteIndex.bits()), CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
Modified: trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJSTailCall.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -38,8 +38,27 @@
namespace JSC { namespace FTL {
+using namespace B3;
using namespace DFG;
+#if FTL_USES_B3
+
+JSTailCall::JSTailCall(PatchpointValue* patchpoint, Node* node, const Vector<ExitValue>& arguments)
+ : JSCallBase(CallLinkInfo::TailCall, node->origin.semantic, node->origin.semantic)
+ , m_patchpoint(patchpoint)
+ , m_arguments(arguments)
+ , m_instructionOffset(0)
+{
+ UNREACHABLE_FOR_PLATFORM();
+}
+
+void JSTailCall::emit(JITCode&, CCallHelpers&)
+{
+ UNREACHABLE_FOR_PLATFORM();
+}
+
+#else // FTL_USES_B3
+
namespace {
FTL::Location getRegisterWithAddend(const ExitValue& value, StackMaps::Record& record, StackMaps& stackmaps)
@@ -180,10 +199,10 @@
} // anonymous namespace
-JSTailCall::JSTailCall(unsigned stackmapID, Node* node, Vector<ExitValue> arguments)
+JSTailCall::JSTailCall(unsigned stackmapID, Node* node, const Vector<ExitValue>& arguments)
: JSCallBase(CallLinkInfo::TailCall, node->origin.semantic, node->origin.semantic)
, m_stackmapID(stackmapID)
- , m_arguments { WTF::move(arguments) }
+ , m_arguments(arguments)
, m_instructionOffset(0)
{
ASSERT(node->op() == TailCall);
@@ -323,6 +342,8 @@
m_callLinkInfo->setUpCall(m_type, m_semanticeOrigin, calleeGPR);
}
+#endif // FTL_USES_B3
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
Modified: trunk/Source/_javascript_Core/ftl/FTLJSTailCall.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLJSTailCall.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLJSTailCall.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -28,6 +28,8 @@
#if ENABLE(FTL_JIT)
+#include "B3PatchpointValue.h"
+#include "DFGCommon.h"
#include "FTLExitValue.h"
#include "FTLJSCallBase.h"
#include "FTLStackmapArgumentList.h"
@@ -42,11 +44,21 @@
class JSTailCall : public JSCallBase {
public:
- JSTailCall(unsigned stackmapID, DFG::Node*, Vector<ExitValue> arguments);
+ JSTailCall(
+#if FTL_USES_B3
+ B3::PatchpointValue*,
+#else // FTL_USES_B3
+ unsigned stackmapID,
+#endif // FTL_USES_B3
+ DFG::Node*, const Vector<ExitValue>& arguments);
void emit(JITCode&, CCallHelpers&);
-
+
+#if FTL_USES_B3
+ B3::PatchpointValue* patchpoint() const { return m_patchpoint; }
+#else // FTL_USES_B3
unsigned stackmapID() const { return m_stackmapID; }
+#endif // FTL_USES_B3
unsigned estimatedSize() const { return m_estimatedSize; }
@@ -58,7 +70,11 @@
}
private:
+#if FTL_USES_B3
+ B3::PatchpointValue* m_patchpoint;
+#else // FTL_USES_B3
unsigned m_stackmapID;
+#endif // FTL_USES_B3
Vector<ExitValue> m_arguments;
unsigned m_estimatedSize;
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -5374,14 +5374,12 @@
DFG_ASSERT(m_graph, m_node, m_origin.exitOK);
- appendOSRExitDescriptor(UncountableInvalidation, ExceptionType::None, noValue(), nullptr, m_origin);
+ OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(UncountableInvalidation, ExceptionType::None, noValue(), nullptr, m_origin);
- OSRExitDescriptor& exitDescriptor = m_ftlState.jitCode->osrExitDescriptors.last();
-
StackmapArgumentList arguments = buildExitArguments(exitDescriptor, FormattedValue());
callStackmap(exitDescriptor, arguments);
- exitDescriptor.m_isInvalidationPoint = true;
+ exitDescriptor->m_isInvalidationPoint = true;
#endif // FTL_USES_B3
}
@@ -9267,11 +9265,10 @@
if (!willCatchException)
return;
- appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
- OSRExitDescriptor& exitDescriptor = m_ftlState.jitCode->osrExitDescriptors.last();
- exitDescriptor.m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
- exitDescriptor.m_baselineExceptionHandler = *exceptionHandler;
- exitDescriptor.m_stackmapID = m_stackmapIDs - 1;
+ OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(Uncountable, exceptionType, noValue(), nullptr, m_origin.withForExitAndExitOK(opCatchOrigin, true));
+ exitDescriptor->m_semanticCodeOriginForCallFrameHeader = codeOriginDescriptionOfCallSite();
+ exitDescriptor->m_baselineExceptionHandler = *exceptionHandler;
+ exitDescriptor->m_stackmapID = m_stackmapIDs - 1;
StackmapArgumentList freshList =
buildExitArguments(exitDescriptor, noValue(), offsetOfExitArguments);
@@ -9295,9 +9292,9 @@
return m_blocks.get(block);
}
- OSRExitDescriptor& appendOSRExitDescriptor(ExitKind kind, ExceptionType exceptionType, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
+ OSRExitDescriptor* appendOSRExitDescriptor(ExitKind kind, ExceptionType exceptionType, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
{
- return m_ftlState.jitCode->osrExitDescriptors.alloc(
+ return &m_ftlState.jitCode->osrExitDescriptors.alloc(
kind, exceptionType, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
origin.forExit, origin.semantic,
availabilityMap().m_locals.numberOfArguments(),
@@ -9342,7 +9339,7 @@
blessSpeculation(
m_out.speculate(failCondition), kind, lowValue, highValue, origin, isExceptionHandler);
#else // FTL_USES_B3
- OSRExitDescriptor& exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
+ OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
if (failCondition == m_out.booleanTrue) {
emitOSRExitCall(exitDescriptor, lowValue);
@@ -9368,26 +9365,32 @@
}
#if FTL_USES_B3
- void blessSpeculation(B3::StackmapValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
+ void blessSpeculation(B3::CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin, bool isExceptionHandler = false)
{
- OSRExitDescriptor& exitDescriptor = appendOSRExitDescriptor(kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue, highValue, origin);
+ OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(
+ kind, isExceptionHandler ? ExceptionType::CCallException : ExceptionType::None, lowValue,
+ highValue, origin);
+
+ unsigned offset = value->numChildren();
value->appendAnys(buildExitArguments(exitDescriptor, lowValue));
+
+ State* state = &m_ftlState;
value->setGenerator(
- [&] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
- jit.oops();
+ [=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
+ exitDescriptor->emitOSRExit(*state, jit, params, offset);
});
}
#endif
#if !FTL_USES_B3
- void emitOSRExitCall(OSRExitDescriptor& exitDescriptor, FormattedValue lowValue)
+ void emitOSRExitCall(OSRExitDescriptor* exitDescriptor, FormattedValue lowValue)
{
callStackmap(exitDescriptor, buildExitArguments(exitDescriptor, lowValue));
}
#endif
StackmapArgumentList buildExitArguments(
- OSRExitDescriptor& exitDescriptor, FormattedValue lowValue,
+ OSRExitDescriptor* exitDescriptor, FormattedValue lowValue,
unsigned offsetOfExitArgumentsInStackmapLocations = 0)
{
StackmapArgumentList result;
@@ -9397,14 +9400,14 @@
}
void buildExitArguments(
- OSRExitDescriptor& exitDescriptor, StackmapArgumentList& arguments, FormattedValue lowValue,
+ OSRExitDescriptor* exitDescriptor, StackmapArgumentList& arguments, FormattedValue lowValue,
unsigned offsetOfExitArgumentsInStackmapLocations = 0)
{
if (!!lowValue)
arguments.append(lowValue.value());
AvailabilityMap availabilityMap = this->availabilityMap();
- availabilityMap.pruneByLiveness(m_graph, exitDescriptor.m_codeOrigin);
+ availabilityMap.pruneByLiveness(m_graph, exitDescriptor->m_codeOrigin);
HashMap<Node*, ExitTimeObjectMaterialization*> map;
availabilityMap.forEachAvailability(
@@ -9419,24 +9422,24 @@
auto result = map.add(node, nullptr);
if (result.isNewEntry) {
result.iterator->value =
- exitDescriptor.m_materializations.add(node->op(), node->origin.semantic);
+ exitDescriptor->m_materializations.add(node->op(), node->origin.semantic);
}
});
- for (unsigned i = 0; i < exitDescriptor.m_values.size(); ++i) {
- int operand = exitDescriptor.m_values.operandForIndex(i);
+ for (unsigned i = 0; i < exitDescriptor->m_values.size(); ++i) {
+ int operand = exitDescriptor->m_values.operandForIndex(i);
Availability availability = availabilityMap.m_locals[i];
if (Options::validateFTLOSRExitLiveness()) {
DFG_ASSERT(
m_graph, m_node,
- (!(availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptor.m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
+ (!(availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitDescriptor->m_codeOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode);
}
ExitValue exitValue = exitValueForAvailability(arguments, map, availability);
if (exitValue.hasIndexInStackmapLocations())
exitValue.adjustStackmapLocationsIndexByOffset(offsetOfExitArgumentsInStackmapLocations);
- exitDescriptor.m_values[i] = exitValue;
+ exitDescriptor->m_values[i] = exitValue;
}
for (auto heapPair : availabilityMap.m_heap) {
@@ -9451,21 +9454,21 @@
}
if (verboseCompilationEnabled()) {
- dataLog(" Exit values: ", exitDescriptor.m_values, "\n");
- if (!exitDescriptor.m_materializations.isEmpty()) {
+ dataLog(" Exit values: ", exitDescriptor->m_values, "\n");
+ if (!exitDescriptor->m_materializations.isEmpty()) {
dataLog(" Materializations: \n");
- for (ExitTimeObjectMaterialization* materialization : exitDescriptor.m_materializations)
+ for (ExitTimeObjectMaterialization* materialization : exitDescriptor->m_materializations)
dataLog(" ", pointerDump(materialization), "\n");
}
}
}
#if !FTL_USES_B3
- void callStackmap(OSRExitDescriptor& exitDescriptor, StackmapArgumentList arguments)
+ void callStackmap(OSRExitDescriptor* exitDescriptor, StackmapArgumentList arguments)
{
- exitDescriptor.m_stackmapID = m_stackmapIDs++;
+ exitDescriptor->m_stackmapID = m_stackmapIDs++;
arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
- arguments.insert(0, m_out.constInt64(exitDescriptor.m_stackmapID));
+ arguments.insert(0, m_out.constInt64(exitDescriptor->m_stackmapID));
m_out.call(m_out.voidType, m_out.stackmapIntrinsic(), arguments);
}
@@ -9929,10 +9932,6 @@
void lowerDFGToLLVM(State& state)
{
-#if FTL_USES_B3
- state.proc = std::make_unique<Procedure>();
-#endif
-
LowerDFGToLLVM lowering(state);
lowering.lower();
}
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,16 +28,20 @@
#if ENABLE(FTL_JIT)
+#include "AirGenerationContext.h"
+#include "B3StackmapValue.h"
#include "CodeBlock.h"
#include "DFGBasicBlock.h"
#include "DFGNode.h"
#include "FTLExitArgument.h"
#include "FTLJITCode.h"
#include "FTLLocation.h"
+#include "FTLState.h"
#include "JSCInlines.h"
namespace JSC { namespace FTL {
+using namespace B3;
using namespace DFG;
OSRExitDescriptor::OSRExitDescriptor(
@@ -70,23 +74,61 @@
materialization->validateReferences(trackedReferences);
}
+#if FTL_USES_B3
+RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExit(
+ State& state, CCallHelpers& jit, const StackmapGenerationParams& params, unsigned offset)
+{
+ RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, params, offset);
+ handle->emitExitThunk(jit);
+ return handle;
+}
-OSRExit::OSRExit(OSRExitDescriptor& descriptor, uint32_t stackmapRecordIndex)
- : OSRExitBase(descriptor.m_kind, descriptor.m_codeOrigin, descriptor.m_codeOriginForExitProfile)
+RefPtr<OSRExitHandle> OSRExitDescriptor::emitOSRExitLater(
+ State& state, const StackmapGenerationParams& params, unsigned offset)
+{
+ RefPtr<OSRExitHandle> handle = prepareOSRExitHandle(state, params, offset);
+ params.context->latePaths.append(
+ createSharedTask<Air::GenerationContext::LatePathFunction>(
+ [handle] (CCallHelpers& jit, Air::GenerationContext&) {
+ handle->emitExitThunk(jit);
+ }));
+ return handle;
+}
+
+RefPtr<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
+ State& state, const StackmapGenerationParams& params, unsigned offset)
+{
+ unsigned index = state.jitCode->osrExit.size();
+ RefPtr<OSRExitHandle> handle = adoptRef(
+ new OSRExitHandle(index, state.jitCode->osrExit.alloc(this)));
+ for (unsigned i = offset; i < params.reps.size(); ++i)
+ handle->exit.m_valueReps.append(params.reps[i]);
+ handle->exit.m_valueReps.shrinkToFit();
+ return handle;
+}
+#endif // FTL_USES_B3
+
+OSRExit::OSRExit(
+ OSRExitDescriptor* descriptor
+#if !FTL_USES_B3
+ , uint32_t stackmapRecordIndex
+#endif // !FTL_USES_B3
+ )
+ : OSRExitBase(descriptor->m_kind, descriptor->m_codeOrigin, descriptor->m_codeOriginForExitProfile)
, m_descriptor(descriptor)
+#if !FTL_USES_B3
, m_stackmapRecordIndex(stackmapRecordIndex)
- , m_exceptionType(descriptor.m_exceptionType)
+#endif // !FTL_USES_B3
+ , m_exceptionType(descriptor->m_exceptionType)
{
- m_isExceptionHandler = descriptor.isExceptionHandler();
+ m_isExceptionHandler = descriptor->isExceptionHandler();
}
CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const
{
#if FTL_USES_B3
- return CodeLocationJump(
- reinterpret_cast<char*>(
- ftlCodeBlock->jitCode()->ftl()->b3Code().code().dataLocation()) +
- m_patchableCodeOffset);
+ UNUSED_PARAM(ftlCodeBlock);
+ return m_patchableJump;
#else // FTL_USES_B3
return CodeLocationJump(
reinterpret_cast<char*>(
@@ -95,9 +137,10 @@
#endif // FTL_USES_B3
}
+#if !FTL_USES_B3
void OSRExit::gatherRegistersToSpillForCallIfException(StackMaps& stackmaps, StackMaps::Record& record)
{
- RELEASE_ASSERT(m_descriptor.m_exceptionType == ExceptionType::JSCall);
+ RELEASE_ASSERT(m_descriptor->m_exceptionType == ExceptionType::JSCall);
RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall();
@@ -121,12 +164,12 @@
break;
}
};
- for (ExitTimeObjectMaterialization* materialization : m_descriptor.m_materializations) {
+ for (ExitTimeObjectMaterialization* materialization : m_descriptor->m_materializations) {
for (unsigned propertyIndex = materialization->properties().size(); propertyIndex--;)
addNeededRegisters(materialization->properties()[propertyIndex].value());
}
- for (unsigned index = m_descriptor.m_values.size(); index--;)
- addNeededRegisters(m_descriptor.m_values[index]);
+ for (unsigned index = m_descriptor->m_values.size(); index--;)
+ addNeededRegisters(m_descriptor->m_values[index]);
}
void OSRExit::spillRegistersToSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot)
@@ -164,6 +207,7 @@
}
}
}
+#endif // !FTL_USES_B3
bool OSRExit::willArriveAtExitFromIndirectExceptionCheck() const
{
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExit.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExit.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExit.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -28,6 +28,7 @@
#if ENABLE(FTL_JIT)
+#include "B3ValueRep.h"
#include "CodeOrigin.h"
#include "DFGExitProfile.h"
#include "DFGOSRExitBase.h"
@@ -35,6 +36,7 @@
#include "FTLExitTimeObjectMaterialization.h"
#include "FTLExitValue.h"
#include "FTLFormattedValue.h"
+#include "FTLOSRExitHandle.h"
#include "FTLStackMaps.h"
#include "FTLStackmapArgumentList.h"
#include "HandlerInfo.h"
@@ -48,93 +50,16 @@
class TrackedReferences;
+namespace B3 {
+struct StackmapGenerationParams;
+namespace Air {
+struct GenerationContext;
+} // namespace Air
+} // namespace B3
+
namespace FTL {
-// Tracks one OSR exit site within the FTL JIT. OSR exit in FTL works by deconstructing
-// the crazy that is OSR down to simple SSA CFG primitives that any compiler backend
-// (including of course LLVM) can grok and do meaningful things to. An exit is just a
-// conditional branch in the emitted code where one destination is the continuation and
-// the other is a basic block that performs a no-return tail-call to an exit thunk.
-// This thunk takes as its arguments the live non-constant not-already-accounted-for
-// bytecode state. To appreciate how this works consider the following _javascript_
-// program, and its lowering down to LLVM IR including the relevant exits:
-//
-// function foo(o) {
-// var a = o.a; // predicted int
-// var b = o.b;
-// var c = o.c; // NB this is dead
-// a = a | 5; // our example OSR exit: need to check if a is an int
-// return a + b;
-// }
-//
-// Just consider the "a | 5". In the DFG IR, this looks like:
-//
-// BitOr(Check:Int32:@a, Int32:5)
-//
-// Where @a is the node for the value of the 'a' variable. Conceptually, this node can
-// be further broken down to the following (note that this particular lowering never
-// actually happens - we skip this step and go straight to LLVM IR - but it's still
-// useful to see this):
-//
-// exitIf(@a is not int32);
-// continuation;
-//
-// Where 'exitIf()' is a function that will exit if the argument is true, and
-// 'continuation' is the stuff that we will do after the exitIf() check. (Note that
-// FTL refers to 'exitIf()' as 'speculate()', which is in line with DFG terminology.)
-// This then gets broken down to the following LLVM IR, assuming that %0 is the LLVM
-// value corresponding to variable 'a', and %1 is the LLVM value for variable 'b':
-//
-// %2 = ... // the predictate corresponding to '@a is not int32'
-// br i1 %2, label %3, label %4
-// ; <label>:3
-// call void exitThunk1(%0, %1) // pass 'a' and 'b', since they're both live-in-bytecode
-// unreachable
-// ; <label>:4
-// ... // code for the continuation
-//
-// Where 'exitThunk1' is the IR to get the exit thunk for *this* OSR exit. Each OSR
-// exit will appear to LLVM to have a distinct exit thunk.
-//
-// Note that this didn't have to pass '5', 'o', or 'c' to the exit thunk. 5 is a
-// constant and the DFG already knows that, and can already tell the OSR exit machinery
-// what that contant is and which bytecode variables (if any) it needs to be dropped
-// into. This is conveyed to the exit statically, via the OSRExit data structure below.
-// See the code for ExitValue for details. 'o' is an argument, and arguments are always
-// "flushed" - if you never assign them then their values are still in the argument
-// stack slots, and if you do assign them then we eagerly store them into those slots.
-// 'c' is dead in bytecode, and the DFG knows this; we statically tell the exit thunk
-// that it's dead and don't have to pass anything. The exit thunk will "initialize" its
-// value to Undefined.
-//
-// This approach to OSR exit has a number of virtues:
-//
-// - It is an entirely unsurprising representation for a compiler that already groks
-// CFG-like IRs for C-like languages. All existing analyses and transformations just
-// work.
-//
-// - It lends itself naturally to modern approaches to code motion. For example, you
-// could sink operations from above the exit to below it, if you just duplicate the
-// operation into the OSR exit block. This is both legal and desirable. It works
-// because the backend sees the OSR exit block as being no different than any other,
-// and LLVM already supports sinking if it sees that a value is only partially used.
-// Hence there exists a value that dominates the exit but is only used by the exit
-// thunk and not by the continuation, sinking ought to kick in for that value.
-// Hoisting operations from below it to above it is also possible, for similar
-// reasons.
-//
-// - The no-return tail-call to the OSR exit thunk can be subjected to specialized
-// code-size reduction optimizations, though this is optional. For example, instead
-// of actually emitting a call along with all that goes with it (like placing the
-// arguments into argument position), the backend could choose to simply inform us
-// where it had placed the arguments and expect the callee (i.e. the exit thunk) to
-// figure it out from there. It could also tell us what we need to do to pop stack,
-// although again, it doesn't have to; it could just emit that code normally. We do
-// all of these things through the patchpoint/stackmap LLVM intrinsics.
-//
-// - It could be extended to allow the backend to do its own exit hoisting, by using
-// intrinsics (or meta-data, or something) to inform the backend that it's safe to
-// make the predicate passed to 'exitIf()' more truthy.
+class State;
enum class ExceptionType : uint8_t {
None,
@@ -175,20 +100,59 @@
uint32_t m_stackmapID;
HandlerInfo m_baselineExceptionHandler;
- bool m_isInvalidationPoint : 1;
+ bool m_isInvalidationPoint;
void validateReferences(const TrackedReferences&);
+
+#if FTL_USES_B3
+ // Call this once we have a place to emit the OSR exit jump and we have data about how the state
+ // should be recovered. This effectively emits code that does the exit, though the code is really a
+ // patchable jump and we emit the real code lazily. The description of how to emit the real code is
+ // up to the OSRExit object, which this creates. Note that it's OK to drop the OSRExitHandle object
+ // on the ground. It contains information that is mostly not useful if you use this API, since after
+ // this call, the OSRExit is simply ready to go.
+ RefPtr<OSRExitHandle> emitOSRExit(
+ State&, CCallHelpers&, const B3::StackmapGenerationParams&, unsigned offset);
+
+ // In some cases you want an OSRExit to come into existence, but you don't want to emit it right now.
+ // This will emit the OSR exit in a late path. You can't be sure exactly when that will happen, but
+ // you know that it will be done by the time late path emission is done. So, a linker task will
+ // surely happen after that. You can use the OSRExitHandle to retrieve the exit's label.
+ //
+ // This API is meant to be used for things like exception handling, where some patchpoint wants to
+ // have a place to jump to for OSR exit. It doesn't care where that OSR exit is emitted so long as it
+ // eventually gets access to its label.
+ RefPtr<OSRExitHandle> emitOSRExitLater(
+ State&, const B3::StackmapGenerationParams&, unsigned offset);
+
+ // This is the low-level interface. It will create a handle representing the desire to emit code for
+ // an OSR exit. You can call OSRExitHandle::emitExitThunk() once you have a place to emit it. Note
+ // that the above two APIs are written in terms of this and OSRExitHandle::emitExitThunk().
+ RefPtr<OSRExitHandle> prepareOSRExitHandle(
+ State&, const B3::StackmapGenerationParams&, unsigned offset);
+#endif // FTL_USES_B3
};
struct OSRExit : public DFG::OSRExitBase {
- OSRExit(OSRExitDescriptor&, uint32_t stackmapRecordIndex);
+ OSRExit(
+ OSRExitDescriptor*
+#if !FTL_USES_B3
+ , uint32_t stackmapRecordIndex
+#endif // !FTL_USES_B3
+ );
- OSRExitDescriptor& m_descriptor;
+ OSRExitDescriptor* m_descriptor;
MacroAssemblerCodeRef m_code;
+#if FTL_USES_B3
+ // This tells us where to place a jump.
+ CodeLocationJump m_patchableJump;
+ Vector<B3::ValueRep> m_valueReps;
+#else // FTL_USES_B3
// Offset within the exit stubs of the stub for this exit.
unsigned m_patchableCodeOffset;
// Offset within Stackmap::records
uint32_t m_stackmapRecordIndex;
+#endif // FTL_USES_B3
ExceptionType m_exceptionType;
RegisterSet registersToPreserveForCallThatMightThrow;
@@ -199,9 +163,11 @@
OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromFTL);
}
+#if !FTL_USES_B3
void gatherRegistersToSpillForCallIfException(StackMaps&, StackMaps::Record&);
void spillRegistersToSpillSlot(CCallHelpers&, int32_t stackSpillSlot);
void recoverRegistersFromSpillSlot(CCallHelpers& jit, int32_t stackSpillSlot);
+#endif // !FTL_USES_B3
bool willArriveAtOSRExitFromGenericUnwind() const;
bool willArriveAtExitFromIndirectExceptionCheck() const;
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitCompilationInfo.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -26,8 +26,10 @@
#ifndef FTLOSRExitCompilationInfo_h
#define FTLOSRExitCompilationInfo_h
-#if ENABLE(FTL_JIT)
+#include "DFGCommon.h"
+#if ENABLE(FTL_JIT) && !FTL_USES_B3
+
#include "FTLAbbreviatedTypes.h"
#include "MacroAssembler.h"
@@ -37,7 +39,7 @@
OSRExitCompilationInfo()
{
}
-
+
MacroAssembler::Label m_thunkLabel;
MacroAssembler::PatchableJump m_thunkJump;
CodeLocationLabel m_thunkAddress;
@@ -45,7 +47,7 @@
} } // namespace JSC::FTL
-#endif // ENABLE(FTL_JIT)
+#endif // ENABLE(FTL_JIT) && !FTL_USES_B3
#endif // FTLOSRExitCompilationInfo_h
Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -98,7 +98,12 @@
}
static void compileRecovery(
- CCallHelpers& jit, const ExitValue& value, StackMaps::Record* record, StackMaps& stackmaps,
+ CCallHelpers& jit, const ExitValue& value,
+#if FTL_USES_B3
+ Vector<B3::ValueRep>& valueReps,
+#else // FTL_USES_B3
+ StackMaps::Record* record, StackMaps& stackmaps,
+#endif // FTL_USES_B3
char* registerScratch,
const HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*>& materializationToPointer)
{
@@ -112,8 +117,13 @@
break;
case ExitValueArgument:
+#if FTL_USES_B3
+ Location::forValueRep(valueReps[value.exitArgument().argument()]).restoreInto(
+ jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
record->locations[value.exitArgument().argument()].restoreInto(
jit, stackmaps, registerScratch, GPRInfo::regT0);
+#endif // FTL_USES_B3
break;
case ExitValueInJSStack:
@@ -124,10 +134,17 @@
break;
case ExitValueRecovery:
+#if FTL_USES_B3
+ Location::forValueRep(valueReps[value.rightRecoveryArgument()]).restoreInto(
+ jit, registerScratch, GPRInfo::regT1);
+ Location::forValueRep(valueReps[value.leftRecoveryArgument()]).restoreInto(
+ jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
record->locations[value.rightRecoveryArgument()].restoreInto(
jit, stackmaps, registerScratch, GPRInfo::regT1);
record->locations[value.leftRecoveryArgument()].restoreInto(
jit, stackmaps, registerScratch, GPRInfo::regT0);
+#endif // FTL_USES_B3
switch (value.recoveryOpcode()) {
case AddRecovery:
switch (value.recoveryFormat()) {
@@ -177,8 +194,12 @@
static void compileStub(
unsigned exitID, JITCode* jitCode, OSRExit& exit, VM* vm, CodeBlock* codeBlock)
{
+#if FTL_USES_B3
+ UNUSED_PARAM(jitCode);
+#else // FTL_USES_B3
StackMaps::Record* record = &jitCode->stackmaps.records[exit.m_stackmapRecordIndex];
- RELEASE_ASSERT(record->patchpointID == exit.m_descriptor.m_stackmapID);
+ RELEASE_ASSERT(record->patchpointID == exit.m_descriptor->m_stackmapID);
+#endif // FTL_USES_B3
// This code requires framePointerRegister is the same as callFrameRegister
static_assert(MacroAssembler::framePointerRegister == GPRInfo::callFrameRegister, "MacroAssembler::framePointerRegister and GPRInfo::callFrameRegister must be the same");
@@ -192,7 +213,7 @@
// Figure out how much space we need for those object allocations.
unsigned numMaterializations = 0;
size_t maxMaterializationNumArguments = 0;
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations) {
numMaterializations++;
maxMaterializationNumArguments = std::max(
@@ -202,21 +223,32 @@
ScratchBuffer* scratchBuffer = vm->scratchBufferForSize(
sizeof(EncodedJSValue) * (
- exit.m_descriptor.m_values.size() + numMaterializations + maxMaterializationNumArguments) +
+ exit.m_descriptor->m_values.size() + numMaterializations + maxMaterializationNumArguments) +
requiredScratchMemorySizeInBytes() +
codeBlock->calleeSaveRegisters()->size() * sizeof(uint64_t));
EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
- EncodedJSValue* materializationPointers = scratch + exit.m_descriptor.m_values.size();
+ EncodedJSValue* materializationPointers = scratch + exit.m_descriptor->m_values.size();
EncodedJSValue* materializationArguments = materializationPointers + numMaterializations;
char* registerScratch = bitwise_cast<char*>(materializationArguments + maxMaterializationNumArguments);
uint64_t* unwindScratch = bitwise_cast<uint64_t*>(registerScratch + requiredScratchMemorySizeInBytes());
HashMap<ExitTimeObjectMaterialization*, EncodedJSValue*> materializationToPointer;
unsigned materializationCount = 0;
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations) {
materializationToPointer.add(
materialization, materializationPointers + materializationCount++);
}
+
+ auto recoverValue = [&] (const ExitValue& value) {
+ compileRecovery(
+ jit, value,
+#if FTL_USES_B3
+ exit.m_valueReps,
+#else // FTL_USES_B3
+ record, jitCode->stackmaps,
+#endif // FTL_USES_B3
+ registerScratch, materializationToPointer);
+ };
// Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave().
// We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use
@@ -247,10 +279,14 @@
jit.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
// Do some value profiling.
- if (exit.m_descriptor.m_profileDataFormat != DataFormatNone) {
+ if (exit.m_descriptor->m_profileDataFormat != DataFormatNone) {
+#if FTL_USES_B3
+ Location::forValueRep(exit.m_valueReps[0]).restoreInto(jit, registerScratch, GPRInfo::regT0);
+#else // FTL_USES_B3
record->locations[0].restoreInto(jit, jitCode->stackmaps, registerScratch, GPRInfo::regT0);
+#endif // FTL_USES_B3
reboxAccordingToFormat(
- exit.m_descriptor.m_profileDataFormat, jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
+ exit.m_descriptor->m_profileDataFormat, jit, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2);
if (exit.m_kind == BadCache || exit.m_kind == BadIndexingType) {
CodeOrigin codeOrigin = exit.m_codeOriginForExitProfile;
@@ -264,8 +300,8 @@
}
}
- if (!!exit.m_descriptor.m_valueProfile)
- jit.store64(GPRInfo::regT0, exit.m_descriptor.m_valueProfile.getSpecFailBucket(0));
+ if (!!exit.m_descriptor->m_valueProfile)
+ jit.store64(GPRInfo::regT0, exit.m_descriptor->m_valueProfile.getSpecFailBucket(0));
}
// Materialize all objects. Don't materialize an object until all
@@ -275,7 +311,7 @@
// allocation of the former.
HashSet<ExitTimeObjectMaterialization*> toMaterialize;
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations)
toMaterialize.add(materialization);
while (!toMaterialize.isEmpty()) {
@@ -307,13 +343,10 @@
// We only recover the fields that are needed for the allocation.
for (unsigned propertyIndex = materialization->properties().size(); propertyIndex--;) {
const ExitPropertyValue& property = materialization->properties()[propertyIndex];
- const ExitValue& value = property.value();
if (!property.location().neededForMaterialization())
continue;
- compileRecovery(
- jit, value, record, jitCode->stackmaps, registerScratch,
- materializationToPointer);
+ recoverValue(property.value());
jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex);
}
@@ -338,12 +371,9 @@
// Now that all the objects have been allocated, we populate them
// with the correct values. This time we can recover all the
// fields, including those that are only needed for the allocation.
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations) {
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations) {
for (unsigned propertyIndex = materialization->properties().size(); propertyIndex--;) {
- const ExitValue& value = materialization->properties()[propertyIndex].value();
- compileRecovery(
- jit, value, record, jitCode->stackmaps, registerScratch,
- materializationToPointer);
+ recoverValue(materialization->properties()[propertyIndex].value());
jit.storePtr(GPRInfo::regT0, materializationArguments + propertyIndex);
}
@@ -359,16 +389,14 @@
// Save all state from wherever the exit data tells us it was, into the appropriate place in
// the scratch buffer. This also does the reboxing.
- for (unsigned index = exit.m_descriptor.m_values.size(); index--;) {
- compileRecovery(
- jit, exit.m_descriptor.m_values[index], record, jitCode->stackmaps, registerScratch,
- materializationToPointer);
+ for (unsigned index = exit.m_descriptor->m_values.size(); index--;) {
+ recoverValue(exit.m_descriptor->m_values[index]);
jit.store64(GPRInfo::regT0, scratch + index);
}
// Henceforth we make it look like the exiting function was called through a register
// preservation wrapper. This implies that FP must be nudged down by a certain amount. Then
- // we restore the various things according to either exit.m_descriptor.m_values or by copying from the
+ // we restore the various things according to either exit.m_descriptor->m_values or by copying from the
// old frame, and finally we save the various callee-save registers into where the
// restoration thunk would restore them from.
@@ -416,7 +444,7 @@
// First set up SP so that our data doesn't get clobbered by signals.
unsigned conservativeStackDelta =
- (exit.m_descriptor.m_values.numberOfLocals() + baselineCodeBlock->calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
+ (exit.m_descriptor->m_values.numberOfLocals() + baselineCodeBlock->calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
maxFrameExtentForSlowPathCall;
conservativeStackDelta = WTF::roundUpToMultipleOf(
stackAlignmentBytes(), conservativeStackDelta);
@@ -493,8 +521,8 @@
// Now get state out of the scratch buffer and place it back into the stack. The values are
// already reboxed so we just move them.
- for (unsigned index = exit.m_descriptor.m_values.size(); index--;) {
- VirtualRegister reg = exit.m_descriptor.m_values.virtualRegisterForIndex(index);
+ for (unsigned index = exit.m_descriptor->m_values.size(); index--;) {
+ VirtualRegister reg = exit.m_descriptor->m_values.virtualRegisterForIndex(index);
if (reg.isLocal() && reg.toLocal() < static_cast<int>(baselineVirtualRegistersForCalleeSaves))
continue;
@@ -511,11 +539,19 @@
exit.m_code = FINALIZE_CODE_IF(
shouldDumpDisassembly() || Options::verboseOSR() || Options::verboseFTLOSRExit(),
patchBuffer,
+#if FTL_USES_B3
+ ("FTL OSR exit #%u (%s, %s) from %s, with operands = %s",
+ exitID, toCString(exit.m_codeOrigin).data(),
+ exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
+ toCString(ignoringContext<DumpContext>(exit.m_descriptor->m_values)).data())
+#else // FTL_USES_B3
("FTL OSR exit #%u (%s, %s) from %s, with operands = %s, and record = %s",
exitID, toCString(exit.m_codeOrigin).data(),
exitKindToString(exit.m_kind), toCString(*codeBlock).data(),
- toCString(ignoringContext<DumpContext>(exit.m_descriptor.m_values)).data(),
- toCString(*record).data()));
+ toCString(ignoringContext<DumpContext>(exit.m_descriptor->m_values)).data(),
+ toCString(*record).data())
+#endif // FTL_USES_B3
+ );
}
extern "C" void* compileFTLOSRExit(ExecState* exec, unsigned exitID)
@@ -544,15 +580,15 @@
dataLog(" Origin: ", exit.m_codeOrigin, "\n");
if (exit.m_codeOriginForExitProfile != exit.m_codeOrigin)
dataLog(" Origin for exit profile: ", exit.m_codeOriginForExitProfile, "\n");
- dataLog(" Exit stackmap ID: ", exit.m_descriptor.m_stackmapID, "\n");
+ dataLog(" Exit stackmap ID: ", exit.m_descriptor->m_stackmapID, "\n");
dataLog(" Current call site index: ", exec->callSiteIndex().bits(), "\n");
dataLog(" Exit is exception handler: ", exit.m_isExceptionHandler,
" will arrive at exit from genericUnwind(): ", exit.willArriveAtOSRExitFromGenericUnwind(),
- " will arrive at exit from lazy slow path: ", exit.m_descriptor.m_exceptionType == ExceptionType::LazySlowPath, "\n");
- dataLog(" Exit values: ", exit.m_descriptor.m_values, "\n");
- if (!exit.m_descriptor.m_materializations.isEmpty()) {
+ " will arrive at exit from lazy slow path: ", exit.m_descriptor->m_exceptionType == ExceptionType::LazySlowPath, "\n");
+ dataLog(" Exit values: ", exit.m_descriptor->m_values, "\n");
+ if (!exit.m_descriptor->m_materializations.isEmpty()) {
dataLog(" Materializations:\n");
- for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor.m_materializations)
+ for (ExitTimeObjectMaterialization* materialization : exit.m_descriptor->m_materializations)
dataLog(" ", pointerDump(materialization), "\n");
}
}
Added: trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.cpp (0 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.cpp (rev 0)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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 "FTLOSRExitHandle.h"
+
+#if ENABLE(FTL_JIT) && FTL_USES_B3
+
+#include "FTLOSRExit.h"
+#include "FTLThunks.h"
+#include "LinkBuffer.h"
+
+namespace JSC { namespace FTL {
+
+void OSRExitHandle::emitExitThunk(CCallHelpers& jit)
+{
+ label = jit.label();
+ jit.pushToSaveImmediateWithoutTouchingRegisters(CCallHelpers::TrustedImm32(index));
+ CCallHelpers::PatchableJump jump = jit.patchableJump();
+ jit.addLinkTask(
+ [this, jump] (LinkBuffer& linkBuffer) {
+ exit.m_patchableJump = CodeLocationJump(linkBuffer.locationOf(jump));
+
+ linkBuffer.link(
+ jump.m_jump,
+ CodeLocationLabel(linkBuffer.vm().getCTIStub(osrExitGenerationThunkGenerator).code()));
+ });
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) && FTL_USES_B3
+
Added: trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.h (0 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.h (rev 0)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitHandle.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 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 FTLOSRExitHandle_h
+#define FTLOSRExitHandle_h
+
+#include "DFGCommon.h"
+
+#if ENABLE(FTL_JIT) && FTL_USES_B3
+
+#include "CCallHelpers.h"
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace JSC { namespace FTL {
+
+struct OSRExit;
+
+// This is an object that stores some interesting data about an OSR exit. It's expected that you will
+// scrape this data from this object by the time compilation finishes.
+struct OSRExitHandle : public ThreadSafeRefCounted<OSRExitHandle> {
+ OSRExitHandle(unsigned index, OSRExit& exit)
+ : index(index)
+ , exit(exit)
+ {
+ }
+
+ unsigned index;
+ OSRExit& exit;
+
+ // This is the label at which the OSR exit jump lives. This will get populated once the OSR exit
+ // emits its jump. This happens immediately when you call OSRExit::appendOSRExit(). It happens at
+ // some time during late path emission if you do OSRExit::appendOSRExitLater().
+ CCallHelpers::Label label;
+
+ // This emits the exit thunk and populates 'label'.
+ void emitExitThunk(CCallHelpers&);
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT) && FTL_USES_B3
+
+#endif // FTLOSRExitHandle_h
+
Modified: trunk/Source/_javascript_Core/ftl/FTLState.cpp (193361 => 193362)
--- trunk/Source/_javascript_Core/ftl/FTLState.cpp 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/_javascript_Core/ftl/FTLState.cpp 2015-12-03 20:01:57 UTC (rev 193362)
@@ -38,6 +38,7 @@
namespace JSC { namespace FTL {
+using namespace B3;
using namespace DFG;
State::State(Graph& graph)
@@ -68,6 +69,10 @@
graph.m_plan.finalizer = std::make_unique<JITFinalizer>(graph.m_plan);
finalizer = static_cast<JITFinalizer*>(graph.m_plan.finalizer.get());
+
+#if FTL_USES_B3
+ proc = std::make_unique<Procedure>();
+#endif // FTL_USES_B3
}
State::~State()
Modified: trunk/Source/WTF/ChangeLog (193361 => 193362)
--- trunk/Source/WTF/ChangeLog 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/WTF/ChangeLog 2015-12-03 20:01:57 UTC (rev 193362)
@@ -1,3 +1,16 @@
+2015-12-02 Filip Pizlo <fpi...@apple.com>
+
+ FTL B3 should support OSR exit
+ https://bugs.webkit.org/show_bug.cgi?id=151710
+
+ Reviewed by Saam Barati.
+
+ Make sure that this has perfect forwarding.
+
+ * wtf/SegmentedVector.h:
+ (WTF::SegmentedVector::append):
+ (WTF::SegmentedVector::alloc):
+
2015-12-01 Yusuke Suzuki <utatane....@gmail.com>
[ES6] Implement LLInt/Baseline Support for ES6 Generators and enable this feature
Modified: trunk/Source/WTF/wtf/SegmentedVector.h (193361 => 193362)
--- trunk/Source/WTF/wtf/SegmentedVector.h 2015-12-03 19:56:44 UTC (rev 193361)
+++ trunk/Source/WTF/wtf/SegmentedVector.h 2015-12-03 20:01:57 UTC (rev 193362)
@@ -141,9 +141,9 @@
}
template<typename... Args>
- T& alloc(Args... args)
+ T& alloc(Args&&... args)
{
- append<T>(T(args...));
+ append<T>(T(std::forward<Args>(args)...));
return last();
}