bytecode/CodeOrigin.cpp
bytecode/CodeType.cpp
bytecode/DFGExitProfile.cpp
+ bytecode/DeferredCompilationCallback.cpp
bytecode/ExecutionCounter.cpp
bytecode/ExitKind.cpp
bytecode/GetByIdStatus.cpp
jit/JITStubRoutine.cpp
jit/JITStubs.cpp
jit/JITThunks.cpp
+ jit/JITToDFGDeferredCompilationCallback.cpp
jit/JumpReplacementWatchpoint.cpp
jit/ThunkGenerators.cpp
+2013-08-28 Filip Pizlo <fpizlo@apple.com>
+
+ CodeBlock compilation and installation should be simplified and rationalized
+ https://bugs.webkit.org/show_bug.cgi?id=120326
+
+ Reviewed by Oliver Hunt.
+
+ Previously Executable owned the code for generating JIT code; you always had
+ to go through Executable. But often you also had to go through CodeBlock,
+ because ScriptExecutable couldn't have virtual methods, but CodeBlock could.
+ So you'd ask CodeBlock to do something, which would dispatch through a
+ virtual method that would select the appropriate Executable subtype's method.
+ This all meant that the same code would often be duplicated, because most of
+ the work needed to compile something was identical regardless of code type.
+ But then we tried to fix this, by having templatized helpers in
+ ExecutionHarness.h and JITDriver.h. The result was that if you wanted to find
+ out what happened when you asked for something to be compiled, you'd go on a
+ wild ride that started with CodeBlock, touched upon Executable, and then
+ ricocheted into either ExecutionHarness or JITDriver (likely both).
+
+ Another awkwardness was that for concurrent compiles, the DFG::Worklist had
+ super-special inside knowledge of what JITStubs.cpp's cti_optimize would have
+ done once the compilation finished.
+
+ Also, most of the DFG JIT drivers assumed that they couldn't install the
+ JITCode into the CodeBlock directly - instead they would return it via a
+ reference, which happened to be a reference to the JITCode pointer in
+ Executable. This was super weird.
+
+ Finally, there was no notion of compiling code into a special CodeBlock that
+ wasn't used for handling calls into an Executable. I'd like this for FTL OSR
+ entry.
+
+ This patch solves these problems by reducing all of that complexity into just
+ three primitives:
+
+ - Executable::newCodeBlock(). This gives you a new code block, either for call
+ or for construct, and either to serve as the baseline code or the optimized
+ code. The new code block is then owned by the caller; Executable doesn't
+ register it anywhere. The new code block has no JITCode and isn't callable,
+ but it has all of the bytecode.
+
+ - CodeBlock::prepareForExecution(). This takes the CodeBlock's bytecode and
+ produces a JITCode, and then installs the JITCode into the CodeBlock. This
+ method takes a JITType, and always compiles with that JIT. If you ask for
+ JITCode::InterpreterThunk then you'll get JITCode that just points to the
+ LLInt entrypoints. Once this returns, it is possible to call into the
+ CodeBlock if you do so manually - but the Executable still won't know about
+ it so JS calls to that Executable will still be routed to whatever CodeBlock
+ is associated with the Executable.
+
+ - Executable::installCode(). This takes a CodeBlock and makes it the code-for-
+ entry for that Executable. This involves unlinking the Executable's last
+ CodeBlock, if there was one. This also tells the GC about any effect on
+ memory usage and does a bunch of weird data structure rewiring, since
+ Executable caches some of CodeBlock's fields for the benefit of virtual call
+ fast paths.
+
+ This functionality is then wrapped around three convenience methods:
+
+ - Executable::prepareForExecution(). If there is no code block for that
+ Executable, then one is created (newCodeBlock()), compiled
+ (CodeBlock::prepareForExecution()) and installed (installCode()).
+
+ - CodeBlock::newReplacement(). Asks the Executable for a new CodeBlock that
+ can serve as an optimized replacement of the current one.
+
+ - CodeBlock::install(). Asks the Executable to install this code block.
+
+ This patch allows me to kill *a lot* of code and to remove a lot of
+ specializations for functions vs. not-functions, and a lot of places where we
+ pass around JITCode references and such. ExecutionHarness and JITDriver are
+ both gone. Overall this patch has more red than green.
+
+ It also allows me to work on FTL OSR entry and tier-up:
+
+ - FTL tier-up: this will involve DFGOperations.cpp asking the DFG::Worklist
+ to do some compilation, but it will require the DFG::Worklist to do
+ something different than what JITStubs.cpp would want, once the compilation
+ finishes. This patch introduces a callback mechanism for that purpose.
+
+ - FTL OSR entry: this will involve creating a special auto-jettisoned
+ CodeBlock that is used only for FTL OSR entry. The new set of primitives
+ allows for this: Executable can vend you a fresh new CodeBlock, and you can
+ ask that CodeBlock to compile itself with any JIT of your choosing. Or you
+ can take that CodeBlock and compile it yourself. Previously the act of
+ producing a CodeBlock-for-optimization and the act of compiling code for it
+ were tightly coupled; now you can separate them and you can create such
+ auto-jettisoned CodeBlocks that are used for a one-shot OSR entry.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::prepareForExecution):
+ (JSC::CodeBlock::install):
+ (JSC::CodeBlock::newReplacement):
+ (JSC::FunctionCodeBlock::jettisonImpl):
+ (JSC::CodeBlock::setOptimizationThresholdBasedOnCompilationResult):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::hasBaselineJITProfiling):
+ * bytecode/DeferredCompilationCallback.cpp: Added.
+ (JSC::DeferredCompilationCallback::DeferredCompilationCallback):
+ (JSC::DeferredCompilationCallback::~DeferredCompilationCallback):
+ * bytecode/DeferredCompilationCallback.h: Added.
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::tryCompile):
+ * dfg/DFGDriver.h:
+ (JSC::DFG::tryCompile):
+ * dfg/DFGFailedFinalizer.cpp:
+ (JSC::DFG::FailedFinalizer::finalize):
+ (JSC::DFG::FailedFinalizer::finalizeFunction):
+ * dfg/DFGFailedFinalizer.h:
+ * dfg/DFGFinalizer.h:
+ * dfg/DFGJITFinalizer.cpp:
+ (JSC::DFG::JITFinalizer::finalize):
+ (JSC::DFG::JITFinalizer::finalizeFunction):
+ * dfg/DFGJITFinalizer.h:
+ * dfg/DFGOSRExitPreparation.cpp:
+ (JSC::DFG::prepareCodeOriginForOSRExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGPlan.cpp:
+ (JSC::DFG::Plan::Plan):
+ (JSC::DFG::Plan::compileInThreadImpl):
+ (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
+ (JSC::DFG::Plan::finalizeAndNotifyCallback):
+ * dfg/DFGPlan.h:
+ * dfg/DFGWorklist.cpp:
+ (JSC::DFG::Worklist::completeAllReadyPlansForVM):
+ * ftl/FTLJITFinalizer.cpp:
+ (JSC::FTL::JITFinalizer::finalize):
+ (JSC::FTL::JITFinalizer::finalizeFunction):
+ * ftl/FTLJITFinalizer.h:
+ * heap/Heap.h:
+ (JSC::Heap::isDeferred):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::prepareForRepeatCall):
+ * jit/JITDriver.h: Removed.
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC::jitCompileFor):
+ (JSC::lazyLinkFor):
+ * jit/JITToDFGDeferredCompilationCallback.cpp: Added.
+ (JSC::JITToDFGDeferredCompilationCallback::JITToDFGDeferredCompilationCallback):
+ (JSC::JITToDFGDeferredCompilationCallback::~JITToDFGDeferredCompilationCallback):
+ (JSC::JITToDFGDeferredCompilationCallback::create):
+ (JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
+ * jit/JITToDFGDeferredCompilationCallback.h: Added.
+ * llint/LLIntEntrypoints.cpp:
+ (JSC::LLInt::setFunctionEntrypoint):
+ (JSC::LLInt::setEvalEntrypoint):
+ (JSC::LLInt::setProgramEntrypoint):
+ * llint/LLIntEntrypoints.h:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::jitCompileAndSetHeuristics):
+ (JSC::LLInt::setUpCall):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::isNumericCompareFunction):
+ * runtime/CommonSlowPaths.cpp:
+ * runtime/CompilationResult.cpp:
+ (WTF::printInternal):
+ * runtime/CompilationResult.h:
+ * runtime/Executable.cpp:
+ (JSC::ScriptExecutable::installCode):
+ (JSC::ScriptExecutable::newCodeBlockFor):
+ (JSC::ScriptExecutable::newReplacementCodeBlockFor):
+ (JSC::ScriptExecutable::prepareForExecutionImpl):
+ * runtime/Executable.h:
+ (JSC::ScriptExecutable::prepareForExecution):
+ (JSC::FunctionExecutable::jettisonOptimizedCodeFor):
+ * runtime/ExecutionHarness.h: Removed.
+
2013-08-28 Chris Curtis <chris_curtis@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=119548
Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h \
Source/JavaScriptCore/bytecode/CodeOrigin.cpp \
Source/JavaScriptCore/bytecode/CodeOrigin.h \
- Source/JavaScriptCore/bytecode/DataFormat.h \
Source/JavaScriptCore/bytecode/DFGExitProfile.cpp \
Source/JavaScriptCore/bytecode/DFGExitProfile.h \
+ Source/JavaScriptCore/bytecode/DataFormat.h \
+ Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp \
+ Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h \
Source/JavaScriptCore/bytecode/EvalCodeCache.h \
Source/JavaScriptCore/bytecode/ExecutionCounter.cpp \
Source/JavaScriptCore/bytecode/ExecutionCounter.h \
Source/JavaScriptCore/jit/JITCompilationEffort.h \
Source/JavaScriptCore/jit/JITDisassembler.cpp \
Source/JavaScriptCore/jit/JITDisassembler.h \
- Source/JavaScriptCore/jit/JITDriver.h \
Source/JavaScriptCore/jit/JIT.cpp \
Source/JavaScriptCore/jit/JIT.h \
Source/JavaScriptCore/jit/JITExceptions.cpp \
Source/JavaScriptCore/jit/JITStubsX86Common.h \
Source/JavaScriptCore/jit/JITThunks.cpp \
Source/JavaScriptCore/jit/JITThunks.h \
+ Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp \
+ Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.h \
Source/JavaScriptCore/jit/JITWriteBarrier.h \
Source/JavaScriptCore/jit/JSInterfaceJIT.h \
Source/JavaScriptCore/jit/JumpReplacementWatchpoint.cpp \
Source/JavaScriptCore/runtime/ExceptionHelpers.h \
Source/JavaScriptCore/runtime/Executable.cpp \
Source/JavaScriptCore/runtime/Executable.h \
- Source/JavaScriptCore/runtime/ExecutionHarness.h \
Source/JavaScriptCore/runtime/Float32Array.h \
Source/JavaScriptCore/runtime/Float64Array.h \
Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
<ClCompile Include="..\bytecode\CodeBlockHash.cpp" />\r
<ClCompile Include="..\bytecode\CodeOrigin.cpp" />\r
<ClCompile Include="..\bytecode\CodeType.cpp" />\r
+ <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp" />\r
<ClCompile Include="..\bytecode\ExecutionCounter.cpp" />\r
<ClCompile Include="..\bytecode\ExitKind.cpp" />\r
<ClCompile Include="..\bytecode\GetByIdStatus.cpp" />\r
<ClCompile Include="..\jit\JITStubRoutine.cpp" />\r
<ClCompile Include="..\jit\JITStubs.cpp" />\r
<ClCompile Include="..\jit\JITThunks.cpp" />\r
+ <ClCompile Include="..\jit\JITToDFGDeferredCompilationCallback.cpp" />\r
<ClCompile Include="..\jit\JumpReplacementWatchpoint.cpp" />\r
<ClCompile Include="..\jit\ThunkGenerators.cpp" />\r
<ClCompile Include="..\llint\LLIntCLoop.cpp" />\r
<ClInclude Include="..\bytecode\CodeType.h" />\r
<ClInclude Include="..\bytecode\Comment.h" />\r
<ClInclude Include="..\bytecode\DataFormat.h" />\r
+ <ClInclude Include="..\bytecode\DeferredCompilationCallback.h" />\r
<ClInclude Include="..\bytecode\EvalCodeCache.h" />\r
<ClInclude Include="..\bytecode\ExecutionCounter.h" />\r
<ClInclude Include="..\bytecode\ExitKind.h" />\r
<ClInclude Include="..\jit\JITCode.h" />\r
<ClInclude Include="..\jit\JITCompilationEffort.h" />\r
<ClInclude Include="..\jit\JITDisassembler.h" />\r
- <ClInclude Include="..\jit\JITDriver.h" />\r
<ClInclude Include="..\jit\JITExceptions.h" />\r
<ClInclude Include="..\jit\JITInlines.h" />\r
<ClInclude Include="..\jit\JITStubCall.h" />\r
<ClInclude Include="..\jit\JITStubsX86Common.h" />\r
<ClInclude Include="..\jit\JITStubsX86_64.h" />\r
<ClInclude Include="..\jit\JITThunks.h" />\r
+ <ClInclude Include="..\jit\JITToDFGDeferredCompilationCallback.h" />\r
<ClInclude Include="..\jit\JITWriteBarrier.h" />\r
<ClInclude Include="..\jit\JSInterfaceJIT.h" />\r
<ClInclude Include="..\jit\JumpReplacementWatchpoint.h" />\r
<ClInclude Include="..\runtime\ErrorPrototype.h" />\r
<ClInclude Include="..\runtime\ExceptionHelpers.h" />\r
<ClInclude Include="..\runtime\Executable.h" />\r
- <ClInclude Include="..\runtime\ExecutionHarness.h" />\r
<ClInclude Include="..\runtime\Float32Array.h" />\r
<ClInclude Include="..\runtime\Float64Array.h" />\r
<ClInclude Include="..\runtime\FunctionConstructor.h" />\r
0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F235BD117178E1C00690C7F /* FTLCArgumentGetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F235BBB17178E1C00690C7F /* FTLCArgumentGetter.cpp */; };
0FC09792146A6F7300CF2442 /* DFGOSRExitCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0978F146A6F6300CF2442 /* DFGOSRExitCompiler.cpp */; };
0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0979F146B28C700CF2442 /* DFGThunks.cpp */; };
0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097A0146B28C700CF2442 /* DFGThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */; };
+ 0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0FC712E217CD8791008CC93C /* JITToDFGDeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */; };
+ 0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC815141405118D00CFA603 /* VTableSpectrum.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDoubleFormatState.h; path = dfg/DFGDoubleFormatState.h; sourceTree = "<group>"; };
0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSlowPathGenerator.h; path = dfg/DFGSlowPathGenerator.h; sourceTree = "<group>"; };
0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSilentRegisterSavePlan.h; path = dfg/DFGSilentRegisterSavePlan.h; sourceTree = "<group>"; };
- 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; };
0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; };
- 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; };
0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; };
0F235BBB17178E1C00690C7F /* FTLCArgumentGetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLCArgumentGetter.cpp; path = ftl/FTLCArgumentGetter.cpp; sourceTree = "<group>"; };
0F235BBC17178E1C00690C7F /* FTLCArgumentGetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLCArgumentGetter.h; path = ftl/FTLCArgumentGetter.h; sourceTree = "<group>"; };
0FC0978F146A6F6300CF2442 /* DFGOSRExitCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompiler.cpp; path = dfg/DFGOSRExitCompiler.cpp; sourceTree = "<group>"; };
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThunks.cpp; path = dfg/DFGThunks.cpp; sourceTree = "<group>"; };
0FC097A0146B28C700CF2442 /* DFGThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThunks.h; path = dfg/DFGThunks.h; sourceTree = "<group>"; };
+ 0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DeferredCompilationCallback.cpp; sourceTree = "<group>"; };
+ 0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeferredCompilationCallback.h; sourceTree = "<group>"; };
+ 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JITToDFGDeferredCompilationCallback.cpp; sourceTree = "<group>"; };
+ 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = "<group>"; };
0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
0FC815121405118600CFA603 /* VTableSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTableSpectrum.cpp; sourceTree = "<group>"; };
0F0776BD14FF002800102332 /* JITCompilationEffort.h */,
0FAF7EFA165BA919000C8455 /* JITDisassembler.cpp */,
0FAF7EFB165BA919000C8455 /* JITDisassembler.h */,
- 0F21C26614BE5F5E00ADC64B /* JITDriver.h */,
0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
0F46808014BA572700BFE272 /* JITExceptions.h */,
86CC85A00EE79A4700288682 /* JITInlines.h */,
A7A4AE0C17973B4D005612B1 /* JITStubsX86Common.h */,
0F5EF91B16878F78003E5C25 /* JITThunks.cpp */,
0F5EF91C16878F78003E5C25 /* JITThunks.h */,
+ 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */,
+ 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */,
A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
A76C51741182748D00715B05 /* JSInterfaceJIT.h */,
0F766D3215AE2535008F363E /* JumpReplacementWatchpoint.cpp */,
A72701B30DADE94900E548D7 /* ExceptionHelpers.h */,
86CA032D1038E8440028A609 /* Executable.cpp */,
86CAFEE21035DDE60028A609 /* Executable.h */,
- 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */,
A7A8AF2917ADB5F3005AB174 /* Float32Array.h */,
A7A8AF2A17ADB5F3005AB174 /* Float64Array.h */,
BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */,
0F8F943F1667632D00D61971 /* CodeType.cpp */,
0F0B83A514BCF50400885B4F /* CodeType.h */,
0F426A4A1460CD6B00131F8F /* DataFormat.h */,
+ 0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */,
+ 0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */,
0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */,
0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */,
969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */,
5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */,
0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */,
0F2B66DF17B6B5AB00A7AE3F /* DataView.h in Headers */,
+ 0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */,
BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */,
41359CF30FDD89AD00206180 /* DateConversion.h in Headers */,
BC1166020E1997B4008066DD /* DateInstance.h in Headers */,
86CAFEE31035DDE60028A609 /* Executable.h in Headers */,
A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */,
0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */,
- 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */,
0FB105861675481200F8AB6E /* ExitKind.h in Headers */,
0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */,
A7A8AF3817ADB5F3005AB174 /* Float32Array.h in Headers */,
86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */,
0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */,
0FAF7EFE165BA91F000C8455 /* JITDisassembler.h in Headers */,
- 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */,
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
86CC85A10EE79A4700288682 /* JITInlines.h in Headers */,
960626960FB8EC02009798AB /* JITStubCall.h in Headers */,
BC18C4240E16F5CD00B34460 /* JSObject.h in Headers */,
BC18C4250E16F5CD00B34460 /* JSObjectRef.h in Headers */,
A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */,
+ 0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */,
A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */,
BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */,
9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */,
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */,
148F21BC107EC54D0042EC2C /* Parser.cpp in Sources */,
93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */,
+ 0FC712E217CD8791008CC93C /* JITToDFGDeferredCompilationCallback.cpp in Sources */,
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */,
0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */,
95742F650DD11F5A000917FB /* Profile.cpp in Sources */,
14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */,
14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */,
14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */,
+ 0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */,
0F6E5C191724AF3D005C574F /* WebKitLLVMLibraryAnchor.cpp in Sources */,
0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */,
A7E5AB3A1799E4B200D2833D /* X86Disassembler.cpp in Sources */,
bytecode/CodeOrigin.cpp \
bytecode/CodeType.cpp \
bytecode/DFGExitProfile.cpp \
+ bytecode/DeferredCompilationCallback.cpp \
bytecode/ExecutionCounter.cpp \
bytecode/ExitKind.cpp \
bytecode/GetByIdStatus.cpp \
jit/JITStubRoutine.cpp \
jit/JITStubs.cpp \
jit/JITThunks.cpp \
+ jit/JITToDFGDeferredCompilationCallback.cpp \
jit/JumpReplacementWatchpoint.cpp \
jit/ThunkGenerators.cpp \
llint/LLIntCLoop.cpp \
#include "CallLinkStatus.h"
#include "DFGCapabilities.h"
#include "DFGCommon.h"
+#include "DFGDriver.h"
#include "DFGNode.h"
#include "DFGRepatch.h"
#include "DFGWorklist.h"
#include "JSCJSValue.h"
#include "JSFunction.h"
#include "JSNameScope.h"
+#include "LLIntEntrypoints.h"
#include "LowLevelInterpreter.h"
#include "Operations.h"
#include "PolymorphicPutByIdList.h"
noticeIncomingCall(callerFrame);
m_incomingCalls.push(incoming);
}
+#endif // ENABLE(JIT)
void CodeBlock::unlinkIncomingCalls()
{
#if ENABLE(LLINT)
while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
m_incomingLLIntCalls.begin()->unlink();
-#endif
+#endif // ENABLE(LLINT)
+#if ENABLE(JIT)
if (m_incomingCalls.isEmpty())
return;
RepatchBuffer repatchBuffer(this);
while (m_incomingCalls.begin() != m_incomingCalls.end())
m_incomingCalls.begin()->unlink(*m_vm, repatchBuffer);
-}
#endif // ENABLE(JIT)
+}
#if ENABLE(LLINT)
void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* incoming)
copyPostParseDataFrom(m_alternative.get());
}
-#if ENABLE(JIT)
-void CodeBlock::reoptimize()
-{
- ASSERT(replacement() != this);
- ASSERT(replacement()->alternative() == this);
- if (DFG::shouldShowDisassembly())
- dataLog(*replacement(), " will be jettisoned due to reoptimization of ", *this, ".\n");
- replacement()->jettison();
- countReoptimization();
-}
-
-CodeBlock* ProgramCodeBlock::replacement()
+CompilationResult CodeBlock::prepareForExecutionImpl(
+ ExecState* exec, JITCode::JITType jitType, JITCompilationEffort effort,
+ unsigned bytecodeIndex, PassRefPtr<DeferredCompilationCallback> callback)
{
- return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
+ VM& vm = exec->vm();
+
+ if (jitType == JITCode::InterpreterThunk) {
+ switch (codeType()) {
+ case GlobalCode:
+ LLInt::setProgramEntrypoint(vm, static_cast<ProgramCodeBlock*>(this));
+ break;
+ case EvalCode:
+ LLInt::setEvalEntrypoint(vm, static_cast<EvalCodeBlock*>(this));
+ break;
+ case FunctionCode:
+ LLInt::setFunctionEntrypoint(vm, static_cast<FunctionCodeBlock*>(this));
+ break;
+ }
+ return CompilationSuccessful;
+ }
+
+#if ENABLE(JIT)
+ if (JITCode::isOptimizingJIT(jitType)) {
+ ASSERT(effort == JITCompilationCanFail);
+ bool hadCallback = !!callback;
+ CompilationResult result = DFG::tryCompile(exec, this, bytecodeIndex, callback);
+ ASSERT_UNUSED(hadCallback, result != CompilationDeferred || hadCallback);
+ return result;
+ }
+
+ MacroAssemblerCodePtr jitCodeWithArityCheck;
+ RefPtr<JITCode> jitCode = JIT::compile(&vm, this, effort, &jitCodeWithArityCheck);
+ if (!jitCode)
+ return CompilationFailed;
+ setJITCode(jitCode, jitCodeWithArityCheck);
+ return CompilationSuccessful;
+#else
+ UNUSED_PARAM(effort);
+ UNUSED_PARAM(bytecodeIndex);
+ UNUSED_PARAM(callback);
+ return CompilationFailed;
+#endif // ENABLE(JIT)
}
-CodeBlock* EvalCodeBlock::replacement()
+CompilationResult CodeBlock::prepareForExecution(
+ ExecState* exec, JITCode::JITType jitType,
+ JITCompilationEffort effort, unsigned bytecodeIndex)
{
- return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode();
+ CompilationResult result =
+ prepareForExecutionImpl(exec, jitType, effort, bytecodeIndex, 0);
+ ASSERT(result != CompilationDeferred);
+ return result;
}
-CodeBlock* FunctionCodeBlock::replacement()
+CompilationResult CodeBlock::prepareForExecutionAsynchronously(
+ ExecState* exec, JITCode::JITType jitType,
+ PassRefPtr<DeferredCompilationCallback> passedCallback,
+ JITCompilationEffort effort, unsigned bytecodeIndex)
{
- return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
+ RefPtr<DeferredCompilationCallback> callback = passedCallback;
+ CompilationResult result =
+ prepareForExecutionImpl(exec, jitType, effort, bytecodeIndex, callback);
+ if (result != CompilationDeferred)
+ callback->compilationDidComplete(this, result);
+ return result;
}
-#if ENABLE(DFG_JIT)
-JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
+void CodeBlock::install()
{
- if (JITCode::isHigherTier(replacement()->jitType(), jitType())) {
- result = CompilationNotNeeded;
- return 0;
- }
- JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scope, result, bytecodeIndex);
- return error;
+ ownerExecutable()->installCode(this);
}
-CompilationResult ProgramCodeBlock::replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan> plan)
+PassRefPtr<CodeBlock> CodeBlock::newReplacement()
{
- return static_cast<ProgramExecutable*>(ownerExecutable())->replaceWithDeferredOptimizedCode(plan);
+ return ownerExecutable()->newReplacementCodeBlockFor(specializationKind());
}
-JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
+#if ENABLE(JIT)
+void CodeBlock::reoptimize()
{
- if (JITCode::isHigherTier(replacement()->jitType(), jitType())) {
- result = CompilationNotNeeded;
- return 0;
- }
- JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scope, result, bytecodeIndex);
- return error;
+ ASSERT(replacement() != this);
+ ASSERT(replacement()->alternative() == this);
+ if (DFG::shouldShowDisassembly())
+ dataLog(*replacement(), " will be jettisoned due to reoptimization of ", *this, ".\n");
+ replacement()->jettison();
+ countReoptimization();
}
-CompilationResult EvalCodeBlock::replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan> plan)
+CodeBlock* ProgramCodeBlock::replacement()
{
- return static_cast<EvalExecutable*>(ownerExecutable())->replaceWithDeferredOptimizedCode(plan);
+ return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
}
-JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
+CodeBlock* EvalCodeBlock::replacement()
{
- if (JITCode::isHigherTier(replacement()->jitType(), jitType())) {
- result = CompilationNotNeeded;
- return 0;
- }
- JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scope, result, bytecodeIndex, m_isConstructor ? CodeForConstruct : CodeForCall);
- return error;
+ return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode();
}
-CompilationResult FunctionCodeBlock::replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan> plan)
+CodeBlock* FunctionCodeBlock::replacement()
{
- return static_cast<FunctionExecutable*>(ownerExecutable())->replaceWithDeferredOptimizedCodeFor(plan, m_isConstructor ? CodeForConstruct : CodeForCall);
+ return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
}
-#endif // ENABLE(DFG_JIT)
DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
{
{
static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*vm(), m_isConstructor ? CodeForConstruct : CodeForCall);
}
-
-CompilationResult ProgramCodeBlock::jitCompileImpl(ExecState* exec)
-{
- ASSERT(jitType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(exec);
-}
-
-CompilationResult EvalCodeBlock::jitCompileImpl(ExecState* exec)
-{
- ASSERT(jitType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(exec);
-}
-
-CompilationResult FunctionCodeBlock::jitCompileImpl(ExecState* exec)
-{
- ASSERT(jitType() == JITCode::InterpreterThunk);
- ASSERT(this == replacement());
- return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(exec, m_isConstructor ? CodeForConstruct : CodeForCall);
-}
#endif
JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
#include "DFGOSREntry.h"
#include "DFGOSRExit.h"
#include "DFGVariableEventStream.h"
+#include "DeferredCompilationCallback.h"
#include "EvalCodeCache.h"
#include "ExecutionCounter.h"
#include "ExpressionRangeInfo.h"
unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
+ void unlinkIncomingCalls();
+
#if ENABLE(JIT)
unsigned bytecodeOffsetForCallAtIndex(unsigned index)
{
void linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo*);
#endif // ENABLE(LLINT)
- void unlinkIncomingCalls();
-
#if ENABLE(DFG_JIT) || ENABLE(LLINT)
void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
{
int argumentIndexAfterCapture(size_t argument);
-#if ENABLE(JIT)
+ // Prepares this code block for execution. This is synchronous. This compile
+ // may fail, if you passed JITCompilationCanFail.
+ CompilationResult prepareForExecution(
+ ExecState*, JITCode::JITType,
+ JITCompilationEffort = JITCompilationMustSucceed,
+ unsigned bytecodeIndex = UINT_MAX);
+
+ // Use this method for asynchronous compiles. This will do a compile at some
+ // point in time between when you called into this method and some point in the
+ // future. If you're lucky then it might complete before this method returns.
+ // Once it completes, the callback is called with the result. If the compile
+ // did happen to complete before the method returns, the result of the compile
+ // may be returned. If the compile didn't happen to complete yet, or if we
+ // didn't happen to notice that the compile already completed, we return
+ // CompilationDeferred.
+ //
+ // Note that asynchronous compiles don't actually complete unless you call into
+ // DFG::Worklist::completeAllReadyPlansForVM(). You usually force a call to
+ // this on the main thread by listening to the callback's
+ // compilationDidBecomeReadyAsynchronously() notification. Note that this call
+ // happens on another thread.
+ CompilationResult prepareForExecutionAsynchronously(
+ ExecState*, JITCode::JITType, PassRefPtr<DeferredCompilationCallback>,
+ JITCompilationEffort = JITCompilationMustSucceed,
+ unsigned bytecodeIndex = UINT_MAX);
+
+ // Exactly equivalent to codeBlock->ownerExecutable()->installCode(codeBlock);
+ void install();
+
+ // Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())
+ PassRefPtr<CodeBlock> newReplacement();
+
void setJITCode(PassRefPtr<JITCode> code, MacroAssemblerCodePtr codeWithArityCheck)
{
ConcurrentJITLocker locker(m_lock);
WTF::loadLoadFence(); // This probably isn't needed. Oh well, paranoia is good.
return result;
}
+
+#if ENABLE(JIT)
bool hasBaselineJITProfiling() const
{
return jitType() == JITCode::BaselineJIT;
}
-#if ENABLE(DFG_JIT)
- virtual JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex) = 0;
- virtual CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>) = 0;
-#endif // ENABLE(DFG_JIT)
void jettison();
- CompilationResult jitCompile(ExecState* exec)
- {
- if (jitType() != JITCode::InterpreterThunk) {
- ASSERT(jitType() == JITCode::BaselineJIT);
- return CompilationNotNeeded;
- }
- return jitCompileImpl(exec);
- }
+
virtual CodeBlock* replacement() = 0;
virtual DFG::CapabilityLevel capabilityLevelInternal() = 0;
DFG::CapabilityLevel capabilityLevelState() { return m_capabilityLevelState; }
bool hasOptimizedReplacement();
-#else
- JITCode::JITType jitType() const { return JITCode::InterpreterThunk; }
#endif
ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
protected:
#if ENABLE(JIT)
- virtual CompilationResult jitCompileImpl(ExecState*) = 0;
virtual void jettisonImpl() = 0;
#endif
virtual void visitWeakReferences(SlotVisitor&);
private:
friend class DFGCodeBlocks;
+ CompilationResult prepareForExecutionImpl(
+ ExecState*, JITCode::JITType, JITCompilationEffort, unsigned bytecodeIndex,
+ PassRefPtr<DeferredCompilationCallback>);
+
void noticeIncomingCall(ExecState* callerFrame);
double optimizationThresholdScalingFactor();
SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
#endif
+ RefPtr<JITCode> m_jitCode;
+ MacroAssemblerCodePtr m_jitCodeWithArityCheck;
#if ENABLE(JIT)
Vector<StructureStubInfo> m_structureStubInfos;
Vector<ByValInfo> m_byValInfos;
Vector<CallLinkInfo> m_callLinkInfos;
- RefPtr<JITCode> m_jitCode;
- MacroAssemblerCodePtr m_jitCodeWithArityCheck;
SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo> > m_incomingCalls;
#endif
#if ENABLE(DFG_JIT) || ENABLE(LLINT)
#if ENABLE(JIT)
protected:
-#if ENABLE(DFG_JIT)
- virtual JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- virtual CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
virtual void jettisonImpl();
- virtual CompilationResult jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
virtual DFG::CapabilityLevel capabilityLevelInternal();
#endif
#if ENABLE(JIT)
protected:
-#if ENABLE(DFG_JIT)
- virtual JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- virtual CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
virtual void jettisonImpl();
- virtual CompilationResult jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
virtual DFG::CapabilityLevel capabilityLevelInternal();
#endif
#if ENABLE(JIT)
protected:
-#if ENABLE(DFG_JIT)
- virtual JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- virtual CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
virtual void jettisonImpl();
- virtual CompilationResult jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
virtual DFG::CapabilityLevel capabilityLevelInternal();
#endif
--- /dev/null
+/*
+ * Copyright (C) 2013 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 "DeferredCompilationCallback.h"
+
+namespace JSC {
+
+DeferredCompilationCallback::DeferredCompilationCallback() { }
+DeferredCompilationCallback::~DeferredCompilationCallback() { }
+
+} // JSC
+
--- /dev/null
+/*
+ * Copyright (C) 2013 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 DeferredCompilationCallback_h
+#define DeferredCompilationCallback_h
+
+#include "CompilationResult.h"
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+class DeferredCompilationCallback : public RefCounted<DeferredCompilationCallback> {
+protected:
+ DeferredCompilationCallback();
+
+public:
+ virtual ~DeferredCompilationCallback();
+
+ virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) = 0;
+ virtual void compilationDidComplete(CodeBlock*, CompilationResult) = 0;
+};
+
+} // namespace JSC
+
+#endif // DeferredCompilationCallback_h
+
return numCompilations;
}
-static CompilationResult compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
+CompilationResult tryCompile(ExecState* exec, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback> callback)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
else
numVarsWithValues = 0;
RefPtr<Plan> plan = adoptRef(
- new Plan(compileMode, codeBlock, osrEntryBytecodeIndex, numVarsWithValues));
+ new Plan(codeBlock, osrEntryBytecodeIndex, numVarsWithValues));
for (size_t i = 0; i < plan->mustHandleValues.size(); ++i) {
int operand = plan->mustHandleValues.operandForIndex(i);
if (operandIsArgument(operand)
&& !operandToArgument(operand)
- && compileMode == CompileFunction
+ && codeBlock->codeType() == FunctionCode
&& codeBlock->specializationKind() == CodeForConstruct) {
// Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
// also never be used. It doesn't matter what we put into the value for this,
plan->mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
}
- if (enableConcurrentJIT()) {
+ if (enableConcurrentJIT() && callback) {
+ plan->callback = callback;
if (!vm.worklist)
vm.worklist = globalWorklist();
if (logCompilationChanges())
}
plan->compileInThread(*vm.dfgState);
- return plan->finalize(jitCode, jitCodeWithArityCheck);
-}
-
-CompilationResult tryCompile(ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, unsigned bytecodeIndex)
-{
- return compile(CompileOther, exec, codeBlock, jitCode, 0, bytecodeIndex);
-}
-
-CompilationResult tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex)
-{
- return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex);
-}
-
-CompilationResult tryFinalizePlan(PassRefPtr<Plan> plan, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
-{
- return plan->finalize(jitCode, jitCodeWithArityCheck);
+ return plan->finalizeWithoutNotifyingCallback();
}
} } // namespace JSC::DFG
JS_EXPORT_PRIVATE unsigned getNumCompilations();
#if ENABLE(DFG_JIT)
-CompilationResult tryCompile(ExecState*, CodeBlock*, RefPtr<JSC::JITCode>&, unsigned bytecodeIndex);
-CompilationResult tryCompileFunction(ExecState*, CodeBlock*, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex);
-CompilationResult tryFinalizePlan(PassRefPtr<Plan>, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr* jitCodeWithArityCheck);
+CompilationResult tryCompile(ExecState*, CodeBlock*, unsigned osrEntryBytecodeIndex, PassRefPtr<DeferredCompilationCallback>);
#else
-inline CompilationResult tryCompile(ExecState*, CodeBlock*, RefPtr<JSC::JITCode>&, unsigned) { return CompilationFailed; }
-inline CompilationResult tryCompileFunction(ExecState*, CodeBlock*, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr&, unsigned) { return CompilationFailed; }
-inline CompilationResult tryFinalizePlan(PassRefPtr<Plan>, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr*)
-{
- UNREACHABLE_FOR_PLATFORM();
- return CompilationFailed;
-}
+inline CompilationResult tryCompile(ExecState*, CodeBlock*, unsigned, PassRefPtr<DeferredCompilationCallback>) { return CompilationFailed; }
#endif
} } // namespace JSC::DFG
{
}
-bool FailedFinalizer::finalize(RefPtr<JSC::JITCode>&)
+bool FailedFinalizer::finalize()
{
return false;
}
-bool FailedFinalizer::finalizeFunction(RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr&)
+bool FailedFinalizer::finalizeFunction()
{
return false;
}
FailedFinalizer(Plan&);
virtual ~FailedFinalizer();
- bool finalize(RefPtr<JSC::JITCode>& entry);
- bool finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck);
+ bool finalize();
+ bool finalizeFunction();
};
} } // namespace JSC::DFG
Finalizer(Plan&);
virtual ~Finalizer();
- virtual bool finalize(RefPtr<JSC::JITCode>& entry) = 0;
- virtual bool finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck) = 0;
+ virtual bool finalize() = 0;
+ virtual bool finalizeFunction() = 0;
protected:
Plan& m_plan;
#if ENABLE(DFG_JIT)
+#include "CodeBlock.h"
#include "DFGCommon.h"
#include "DFGPlan.h"
{
}
-bool JITFinalizer::finalize(RefPtr<JSC::JITCode>& entry)
+bool JITFinalizer::finalize()
{
finalizeCommon();
m_jitCode->initializeCodeRef(m_linkBuffer->finalizeCodeWithoutDisassembly());
- entry = m_jitCode;
+ m_plan.codeBlock->setJITCode(m_jitCode, MacroAssemblerCodePtr());
return true;
}
-bool JITFinalizer::finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck)
+bool JITFinalizer::finalizeFunction()
{
finalizeCommon();
- withArityCheck = m_linkBuffer->locationOf(m_arityCheck);
+ MacroAssemblerCodePtr withArityCheck = m_linkBuffer->locationOf(m_arityCheck);
m_jitCode->initializeCodeRef(m_linkBuffer->finalizeCodeWithoutDisassembly());
- entry = m_jitCode;
+ m_plan.codeBlock->setJITCode(m_jitCode, withArityCheck);
return true;
}
JITFinalizer(Plan&, PassRefPtr<JITCode>, PassOwnPtr<LinkBuffer>, MacroAssembler::Label arityCheck = MacroAssembler::Label());
virtual ~JITFinalizer();
- bool finalize(RefPtr<JSC::JITCode>& entry);
- bool finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck);
+ bool finalize();
+ bool finalizeFunction();
private:
void finalizeCommon();
#include "CodeBlock.h"
#include "Executable.h"
+#include "JITCode.h"
#include "Operations.h"
namespace JSC { namespace DFG {
void prepareCodeOriginForOSRExit(ExecState* exec, CodeOrigin codeOrigin)
{
+ DeferGC deferGC(exec->vm().heap);
+
for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
FunctionExecutable* executable =
static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get());
CodeBlock* codeBlock = executable->baselineCodeBlockFor(
codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct);
- codeBlock->jitCompile(exec);
+ if (codeBlock->jitType() == JSC::JITCode::BaselineJIT)
+ continue;
+ ASSERT(codeBlock->jitType() == JSC::JITCode::InterpreterThunk);
+ CompilationResult result = codeBlock->prepareForExecution(
+ exec, JSC::JITCode::BaselineJIT, JITCompilationMustSucceed);
+ ASSERT_UNUSED(result, result == CompilationSuccessful);
+ codeBlock->install();
}
}
codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
if (error) {
vm->throwException(exec, createStackOverflowError(exec));
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
ExecutableBase* executable = function->executable();
if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, function->scope(), kind);
if (error) {
exec->vm().throwException(execCallee, error);
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
}
Plan::Plan(
- CompileMode compileMode, PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
+ PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
unsigned numVarsWithValues)
- : compileMode(compileMode)
- , vm(*passedCodeBlock->vm())
+ : vm(*passedCodeBlock->vm())
, codeBlock(passedCodeBlock)
, osrEntryBytecodeIndex(osrEntryBytecodeIndex)
, numVarsWithValues(numVarsWithValues)
#if ENABLE(FTL_JIT)
if (Options::useExperimentalFTL()
- && compileMode == CompileFunction
+ && codeBlock->codeType() == FunctionCode
&& FTL::canCompile(dfg)) {
performCriticalEdgeBreaking(dfg);
dumpAndVerifyGraph(dfg, "Graph after optimization:");
JITCompiler dataFlowJIT(dfg);
- if (compileMode == CompileFunction) {
+ if (codeBlock->codeType() == FunctionCode) {
dataFlowJIT.compileFunction();
dataFlowJIT.linkFunction();
} else {
- ASSERT(compileMode == CompileOther);
-
dataFlowJIT.compile();
dataFlowJIT.link();
}
writeBarriers.trigger(vm);
}
-CompilationResult Plan::finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
+void Plan::notifyReady()
+{
+ callback->compilationDidBecomeReadyAsynchronously(codeBlock.get());
+ isCompiled = true;
+}
+
+CompilationResult Plan::finalizeWithoutNotifyingCallback()
{
if (!isStillValid())
return CompilationInvalidated;
bool result;
- if (compileMode == CompileFunction)
- result = finalizer->finalizeFunction(jitCode, *jitCodeWithArityCheck);
+ if (codeBlock->codeType() == FunctionCode)
+ result = finalizer->finalizeFunction();
else
- result = finalizer->finalize(jitCode);
+ result = finalizer->finalize();
if (!result)
return CompilationFailed;
- reallyAdd(jitCode->dfgCommon());
+ reallyAdd(codeBlock->jitCode()->dfgCommon());
return CompilationSuccessful;
}
+void Plan::finalizeAndNotifyCallback()
+{
+ callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
+}
+
CodeBlock* Plan::key()
{
return codeBlock->alternative();
#include "DFGDesiredWeakReferences.h"
#include "DFGDesiredWriteBarriers.h"
#include "DFGFinalizer.h"
+#include "DeferredCompilationCallback.h"
#include "Operands.h"
#include "ProfilerCompilation.h"
#include <wtf/ThreadSafeRefCounted.h>
class LongLivedState;
-enum CompileMode { CompileFunction, CompileOther };
-
#if ENABLE(DFG_JIT)
struct Plan : public ThreadSafeRefCounted<Plan> {
Plan(
- CompileMode compileMode, PassRefPtr<CodeBlock> codeBlock,
- unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues);
+ PassRefPtr<CodeBlock>, unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues);
~Plan();
void compileInThread(LongLivedState&);
- CompilationResult finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck);
+ CompilationResult finalizeWithoutNotifyingCallback();
+ void finalizeAndNotifyCallback();
+
+ void notifyReady();
CodeBlock* key();
- const CompileMode compileMode;
VM& vm;
RefPtr<CodeBlock> codeBlock;
const unsigned osrEntryBytecodeIndex;
bool isCompiled;
+ RefPtr<DeferredCompilationCallback> callback;
+
private:
enum CompilationPath { FailPath, DFGPath, FTLPath };
CompilationPath compileInThreadImpl(LongLivedState&);
break;
}
- if (isCellSpeculation(node->child1()->prediction())) {
+ switch (node->child1().useKind()) {
+ case CellUse: {
SpeculateCellOperand base(this, node->child1());
GPRTemporary resultTag(this, base);
GPRTemporary resultPayload(this);
break;
}
- JSValueOperand base(this, node->child1());
- GPRTemporary resultTag(this, base);
- GPRTemporary resultPayload(this);
+ case UntypedUse: {
+ JSValueOperand base(this, node->child1());
+ GPRTemporary resultTag(this, base);
+ GPRTemporary resultPayload(this);
- GPRReg baseTagGPR = base.tagGPR();
- GPRReg basePayloadGPR = base.payloadGPR();
- GPRReg resultTagGPR = resultTag.gpr();
- GPRReg resultPayloadGPR = resultPayload.gpr();
+ GPRReg baseTagGPR = base.tagGPR();
+ GPRReg basePayloadGPR = base.payloadGPR();
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
- base.use();
+ base.use();
- JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
+ JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
- cachedGetById(node->codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell);
+ cachedGetById(node->codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell);
- jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
+ jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
break;
}
RELEASE_ASSERT(plan->isCompiled);
- CompilationResult compilationResult =
- profiledBlock->replaceWithDeferredOptimizedCode(plan);
- RELEASE_ASSERT(compilationResult != CompilationDeferred);
- profiledBlock->setOptimizationThresholdBasedOnCompilationResult(compilationResult);
+ plan->finalizeAndNotifyCallback();
if (profiledBlock == requestedProfiledBlock)
resultingState = Compiled;
{
MutexLocker locker(m_lock);
- plan->key()->forceOptimizationSlowPathConcurrently();
- plan->isCompiled = true;
+ plan->notifyReady();
if (Options::verboseCompilationQueue()) {
dump(locker, WTF::dataFile());
{
}
-bool JITFinalizer::finalize(RefPtr<JSC::JITCode>&)
+bool JITFinalizer::finalize()
{
RELEASE_ASSERT_NOT_REACHED();
return false;
}
-bool JITFinalizer::finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck)
+bool JITFinalizer::finalizeFunction()
{
for (unsigned i = m_jitCode->handles().size(); i--;) {
MacroAssembler::cacheFlush(
("FTL exit thunks for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data())));
} // else this function had no OSR exits, so no exit thunks.
- withArityCheck = m_entrypointLinkBuffer->locationOf(m_arityCheck);
+ MacroAssemblerCodePtr withArityCheck = m_entrypointLinkBuffer->locationOf(m_arityCheck);
m_jitCode->initializeCode(
FINALIZE_DFG_CODE(
*m_entrypointLinkBuffer,
("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data(), m_function)));
- entry = m_jitCode;
+
+ m_plan.codeBlock->setJITCode(m_jitCode, withArityCheck);
return true;
}
m_jitCode = jitCode;
}
- bool finalize(RefPtr<JSC::JITCode>& entry);
- bool finalizeFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCodePtr& withArityCheck);
+ bool finalize();
+ bool finalizeFunction();
private:
OwnPtr<LinkBuffer> m_exitThunksLinkBuffer;
const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; }
void addReference(JSCell*, ArrayBuffer*);
+
+ bool isDeferred() const { return !!m_deferralDepth; }
private:
friend class CodeBlock;
if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
return checkedReturn(callFrame->vm().throwException(callFrame, error));
- if (JSObject* error = program->compile(callFrame, scope))
+ if (JSObject* error = program->prepareForExecution(callFrame, scope, CodeForCall))
return checkedReturn(callFrame->vm().throwException(callFrame, error));
ProgramCodeBlock* codeBlock = &program->generatedBytecode();
if (isJSCall) {
// Compile the callee:
- JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, scope);
+ JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, scope, CodeForCall);
if (UNLIKELY(!!compileError)) {
return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
}
if (isJSConstruct) {
// Compile the callee:
- JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, scope);
+ JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, scope, CodeForConstruct);
if (UNLIKELY(!!compileError)) {
return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
}
}
// Compile the callee:
- JSObject* error = functionExecutable->compileForCall(callFrame, scope);
+ JSObject* error = functionExecutable->prepareForExecution(callFrame, scope, CodeForCall);
if (error) {
callFrame->vm().throwException(callFrame, error);
return CallFrameClosure();
}
}
- JSObject* compileError = eval->compile(callFrame, scope);
+ JSObject* compileError = eval->prepareForExecution(callFrame, scope, CodeForCall);
if (UNLIKELY(!!compileError))
return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
EvalCodeBlock* codeBlock = &eval->generatedBytecode();
+++ /dev/null
-/*
- * Copyright (C) 2012, 2013 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 JITDriver_h
-#define JITDriver_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(JIT)
-
-#include "BytecodeGenerator.h"
-#include "CompilationResult.h"
-#include "DFGDriver.h"
-#include "JIT.h"
-#include "LLIntEntrypoints.h"
-
-namespace JSC {
-
-template<typename CodeBlockType>
-inline CompilationResult jitCompileIfAppropriateImpl(
- ExecState* exec, CodeBlockType* codeBlock, RefPtr<JITCode>& jitCode,
- JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
-{
- VM& vm = exec->vm();
-
- if (jitType == codeBlock->jitType())
- return CompilationNotNeeded;
-
- if (!vm.canUseJIT())
- return CompilationNotNeeded; // FIXME: Investigate if this is right. https://bugs.webkit.org/show_bug.cgi?id=116246
-
- codeBlock->unlinkIncomingCalls();
-
- RefPtr<JITCode> oldJITCode = jitCode;
-
- if (JITCode::isOptimizingJIT(jitType)) {
- CompilationResult result =
- DFG::tryCompile(exec, codeBlock, jitCode, bytecodeIndex);
- if (result == CompilationSuccessful)
- codeBlock->alternative()->unlinkIncomingCalls();
- else {
- ASSERT(oldJITCode == jitCode);
- return result;
- }
- } else {
- RefPtr<JITCode> result = JIT::compile(&vm, codeBlock, effort);
- if (result)
- jitCode = result;
- else
- return CompilationFailed;
- }
-
- return CompilationSuccessful;
-}
-
-inline CompilationResult jitCompileFunctionIfAppropriateImpl(
- ExecState* exec, FunctionCodeBlock* codeBlock, RefPtr<JITCode>& jitCode,
- MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType,
- unsigned bytecodeIndex, JITCompilationEffort effort)
-{
- VM& vm = exec->vm();
-
- if (jitType == codeBlock->jitType())
- return CompilationNotNeeded;
-
- if (!vm.canUseJIT())
- return CompilationNotNeeded; // FIXME: Investigate if this is right. https://bugs.webkit.org/show_bug.cgi?id=116246
-
- codeBlock->unlinkIncomingCalls();
-
- RefPtr<JITCode> oldJITCode = jitCode;
- MacroAssemblerCodePtr oldJITCodeWithArityCheck = jitCodeWithArityCheck;
-
- if (JITCode::isOptimizingJIT(jitType)) {
- CompilationResult result = DFG::tryCompileFunction(
- exec, codeBlock, jitCode, jitCodeWithArityCheck, bytecodeIndex);
- if (result == CompilationSuccessful)
- codeBlock->alternative()->unlinkIncomingCalls();
- else {
- ASSERT(oldJITCode == jitCode);
- ASSERT_UNUSED(oldJITCodeWithArityCheck, oldJITCodeWithArityCheck == jitCodeWithArityCheck);
- return result;
- }
- } else {
- RefPtr<JITCode> result =
- JIT::compile(&vm, codeBlock, effort, &jitCodeWithArityCheck);
- if (result)
- jitCode = result;
- else {
- ASSERT_UNUSED(oldJITCodeWithArityCheck, oldJITCodeWithArityCheck == jitCodeWithArityCheck);
- return CompilationFailed;
- }
- }
-
- return CompilationSuccessful;
-}
-
-template<typename CodeBlockType>
-inline CompilationResult jitCompileIfAppropriate(
- ExecState* exec, CodeBlockType* codeBlock, RefPtr<JITCode>& jitCode,
- JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
-{
- CompilationResult result = jitCompileIfAppropriateImpl(
- exec, codeBlock, jitCode, jitType, bytecodeIndex, effort);
- if (result == CompilationSuccessful) {
- codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
- codeBlock->vm()->heap.reportExtraMemoryCost(jitCode->size());
- }
- return result;
-}
-
-inline CompilationResult jitCompileFunctionIfAppropriate(
- ExecState* exec, FunctionCodeBlock* codeBlock, RefPtr<JITCode>& jitCode,
- MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType,
- unsigned bytecodeIndex, JITCompilationEffort effort)
-{
- CompilationResult result = jitCompileFunctionIfAppropriateImpl(
- exec, codeBlock, jitCode, jitCodeWithArityCheck, jitType, bytecodeIndex, effort);
- if (result == CompilationSuccessful) {
- codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
- codeBlock->vm()->heap.reportExtraMemoryCost(jitCode->size());
- }
- return result;
-}
-
-} // namespace JSC
-
-#endif // ENABLE(JIT)
-
-#endif // JITDriver_h
-
#include <wtf/InlineASM.h>
#include "JIT.h"
#include "JITExceptions.h"
+#include "JITToDFGDeferredCompilationCallback.h"
#include "JSActivation.h"
#include "JSArray.h"
#include "JSFunction.h"
if (Options::verboseOSR())
dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
// If we have an optimized replacement, then it must be the case that we entered
- // cti_optimize from a loop. That's because is there's an optimized replacement,
+ // cti_optimize from a loop. That's because if there's an optimized replacement,
// then all calls to this function will be relinked to the replacement and so
// the prologue OSR will never fire.
if (Options::verboseOSR())
dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
- JSScope* scope = callFrame->scope();
- CompilationResult result;
- JSObject* error = codeBlock->compileOptimized(callFrame, scope, result, bytecodeIndex);
- if (Options::verboseOSR()) {
- dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
- if (error)
- dataLog("WARNING: optimized compilation failed with a JS error.\n");
- }
+ RefPtr<DeferredCompilationCallback> callback =
+ JITToDFGDeferredCompilationCallback::create();
+ RefPtr<CodeBlock> newCodeBlock = codeBlock->newReplacement();
+ CompilationResult result = newCodeBlock->prepareForExecutionAsynchronously(
+ callFrame, JITCode::DFGJIT, callback, JITCompilationCanFail, bytecodeIndex);
- codeBlock->setOptimizationThresholdBasedOnCompilationResult(result);
if (result != CompilationSuccessful)
return;
}
ASSERT(!function->isHostFunction());
FunctionExecutable* executable = function->jsExecutable();
JSScope* callDataScopeChain = function->scope();
- JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind);
+ JSObject* error = executable->prepareForExecution(callFrame, callDataScopeChain, kind);
if (!error)
return function;
callFrame->vm().throwException(callFrame, error);
codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) {
+ if (JSObject* error = functionExecutable->prepareForExecution(callFrame, callee->scope(), kind)) {
callFrame->vm().throwException(callFrame, error);
return 0;
}
FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
JSScope* scopeChain = callee->scope();
- JSObject* error = functionExecutable->compileFor(callFrame, scopeChain, CodeForCall);
+ JSObject* error = functionExecutable->prepareForExecution(callFrame, scopeChain, CodeForCall);
if (error) {
callFrame->vm().throwException(callFrame, error);
return 0;
--- /dev/null
+/*
+ * Copyright (C) 2013 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 "JITToDFGDeferredCompilationCallback.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "Executable.h"
+
+namespace JSC {
+
+JITToDFGDeferredCompilationCallback::JITToDFGDeferredCompilationCallback() { }
+JITToDFGDeferredCompilationCallback::~JITToDFGDeferredCompilationCallback() { }
+
+PassRefPtr<JITToDFGDeferredCompilationCallback> JITToDFGDeferredCompilationCallback::create()
+{
+ return adoptRef(new JITToDFGDeferredCompilationCallback());
+}
+
+void JITToDFGDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
+ CodeBlock* codeBlock)
+{
+ ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
+
+ if (Options::verboseOSR())
+ dataLog("Optimizing compilation of ", *codeBlock, " did become ready.\n");
+
+ codeBlock->alternative()->forceOptimizationSlowPathConcurrently();
+}
+
+void JITToDFGDeferredCompilationCallback::compilationDidComplete(
+ CodeBlock* codeBlock, CompilationResult result)
+{
+ ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
+
+ if (Options::verboseOSR())
+ dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
+
+ if (result == CompilationSuccessful)
+ codeBlock->install();
+
+ codeBlock->alternative()->setOptimizationThresholdBasedOnCompilationResult(result);
+}
+
+} // JSC
+
+#endif // ENABLE(DFG_JIT)
--- /dev/null
+/*
+ * Copyright (C) 2013 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 JITToDFGDeferredCompilationCallback_h
+#define JITToDFGDeferredCompilationCallback_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DeferredCompilationCallback.h"
+#include <wtf/PassRefPtr.h>
+
+namespace JSC {
+
+class ScriptExecutable;
+
+class JITToDFGDeferredCompilationCallback : public DeferredCompilationCallback {
+protected:
+ JITToDFGDeferredCompilationCallback();
+
+public:
+ virtual ~JITToDFGDeferredCompilationCallback();
+
+ static PassRefPtr<JITToDFGDeferredCompilationCallback> create();
+
+ virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*);
+ virtual void compilationDidComplete(CodeBlock*, CompilationResult);
+};
+
+} // namespace JSC
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // JITToDFGDeferredCompilationCallback_h
+
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#if ENABLE(LLINT)
+#include "CodeBlock.h"
#include "JITCode.h"
-#include "VM.h"
#include "JSObject.h"
#include "LLIntThunks.h"
#include "LowLevelInterpreter.h"
+#include "VM.h"
namespace JSC { namespace LLInt {
-void getFunctionEntrypoint(VM& vm, CodeSpecializationKind kind, RefPtr<JITCode>& jitCode, MacroAssemblerCodePtr& arityCheck)
+void setFunctionEntrypoint(VM& vm, FunctionCodeBlock* codeBlock)
{
+ CodeSpecializationKind kind = codeBlock->specializationKind();
+
if (!vm.canUseJIT()) {
if (kind == CodeForCall) {
- jitCode = adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk));
- arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check);
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check));
return;
}
ASSERT(kind == CodeForConstruct);
- jitCode = adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk));
- arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check);
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check));
return;
}
#if ENABLE(JIT)
if (kind == CodeForCall) {
- jitCode = adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk));
- arityCheck = vm.getCTIStub(functionForCallArityCheckThunkGenerator).code();
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk)),
+ vm.getCTIStub(functionForCallArityCheckThunkGenerator).code());
return;
}
ASSERT(kind == CodeForConstruct);
- jitCode = adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk));
- arityCheck = vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code();
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk)),
+ vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code());
#endif // ENABLE(JIT)
}
-void getEvalEntrypoint(VM& vm, RefPtr<JITCode>& jitCode)
+void setEvalEntrypoint(VM& vm, EvalCodeBlock* codeBlock)
{
if (!vm.canUseJIT()) {
- jitCode = adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk));
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr());
return;
}
-#if ENABLE(JIT)
- jitCode = adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk));
+#if ENABLE(JIT)
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr());
#endif
}
-void getProgramEntrypoint(VM& vm, RefPtr<JITCode>& jitCode)
+void setProgramEntrypoint(VM& vm, ProgramCodeBlock* codeBlock)
{
if (!vm.canUseJIT()) {
- jitCode = adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk));
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr());
return;
}
#if ENABLE(JIT)
- jitCode = adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk));
+ codeBlock->setJITCode(
+ adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk)),
+ MacroAssemblerCodePtr());
#endif
}
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
namespace JSC {
class EvalCodeBlock;
+class FunctionCodeBlock;
class VM;
class MacroAssemblerCodePtr;
class MacroAssemblerCodeRef;
namespace LLInt {
-void getFunctionEntrypoint(VM&, CodeSpecializationKind, RefPtr<JITCode>&, MacroAssemblerCodePtr& arityCheck);
-void getEvalEntrypoint(VM&, RefPtr<JITCode>&);
-void getProgramEntrypoint(VM&, RefPtr<JITCode>&);
-
-inline void getEntrypoint(VM& vm, EvalCodeBlock*, RefPtr<JITCode>& jitCode)
-{
- getEvalEntrypoint(vm, jitCode);
-}
-
-inline void getEntrypoint(VM& vm, ProgramCodeBlock*, RefPtr<JITCode>& jitCode)
-{
- getProgramEntrypoint(vm, jitCode);
-}
+void setFunctionEntrypoint(VM&, FunctionCodeBlock*);
+void setEvalEntrypoint(VM&, EvalCodeBlock*);
+void setProgramEntrypoint(VM&, ProgramCodeBlock*);
} } // namespace JSC::LLInt
#include "HostCallReturnValue.h"
#include "Interpreter.h"
#include "JIT.h"
-#include "JITDriver.h"
#include "JSActivation.h"
#include "JSCJSValue.h"
#include "JSGlobalObjectFunctions.h"
// Returns true if we should try to OSR.
inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
{
+ DeferGC deferGC(exec->vm().heap);
+
codeBlock->updateAllValueProfilePredictions();
if (!codeBlock->checkIfJITThresholdReached()) {
return false;
}
- CompilationResult result = codeBlock->jitCompile(exec);
- switch (result) {
- case CompilationNotNeeded:
+ switch (codeBlock->jitType()) {
+ case JITCode::BaselineJIT: {
if (Options::verboseOSR())
dataLogF(" Code was already compiled.\n");
codeBlock->jitSoon();
return true;
- case CompilationFailed:
- if (Options::verboseOSR())
- dataLogF(" JIT compilation failed.\n");
- codeBlock->dontJITAnytimeSoon();
- return false;
- case CompilationSuccessful:
- if (Options::verboseOSR())
- dataLogF(" JIT compilation successful.\n");
- codeBlock->jitSoon();
- return true;
+ }
+ case JITCode::InterpreterThunk: {
+ CompilationResult result = codeBlock->prepareForExecution(
+ exec, JITCode::BaselineJIT, JITCompilationCanFail);
+ switch (result) {
+ case CompilationFailed:
+ if (Options::verboseOSR())
+ dataLogF(" JIT compilation failed.\n");
+ codeBlock->dontJITAnytimeSoon();
+ return false;
+ case CompilationSuccessful:
+ if (Options::verboseOSR())
+ dataLogF(" JIT compilation successful.\n");
+ codeBlock->install();
+ codeBlock->jitSoon();
+ return true;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
+ }
+ }
default:
RELEASE_ASSERT_NOT_REACHED();
return false;
codePtr = executable->hostCodeEntryFor(kind);
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
if (error)
LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
codeBlock = &functionExecutable->generatedBytecodeFor(kind);
FunctionExecutable* executable = callData.js.functionExecutable;
- JSObject* error = executable->compileForCall(exec, callData.js.scope);
+ JSObject* error = executable->prepareForExecution(exec, callData.js.scope, CodeForCall);
if (error)
return false;
#include "HostCallReturnValue.h"
#include "Interpreter.h"
#include "JIT.h"
-#include "JITDriver.h"
#include "JITStubs.h"
#include "JSActivation.h"
#include "JSCJSValue.h"
case CompilationSuccessful:
out.print("CompilationSuccessful");
return;
- case CompilationNotNeeded:
- out.print("CompilationNotNeeded");
- return;
case CompilationDeferred:
out.print("CompilationDeferred");
return;
namespace JSC {
-enum CompilationResult { CompilationFailed, CompilationInvalidated, CompilationSuccessful, CompilationNotNeeded, CompilationDeferred };
+enum CompilationResult {
+ // We tried to compile the code, but we couldn't compile it. This could be
+ // because we ran out of memory, or because the compiler encountered an
+ // internal error and decided to bail out gracefully. Either way, this implies
+ // that we shouldn't try to compile this code block again.
+ CompilationFailed,
+
+ // The profiling assumptions that were fed into the compiler were invalidated
+ // even before we finished compiling. This means we should try again: in such
+ // cases the profiling will now be updated and the next compilation won't
+ // encounter the same problem. But it does mean that we should exercise
+ // exponential back-off, to get even more profiling so that new profiling
+ // pathologies aren't encountered.
+ CompilationInvalidated,
+
+ // The compilation succeeded and the code block now has JITCode for the newly
+ // compiled code. However, compilation success doesn't mean that the CodeBlock
+ // will execute yet; you typically have to install it first, unless you plan
+ // on invoking it manually (something that *could* be done for some kinds of
+ // OSR entry).
+ CompilationSuccessful,
+
+ // We decided to do the compilation asynchronously. This means that we haven't
+ // yet compiled the code. This only happens when you pass a
+ // DeferredCompilationCallback. That callback will get called with some
+ // interesting result, once compilation completes.
+ CompilationDeferred
+};
} // namespace JSC
/*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "BytecodeGenerator.h"
#include "CodeBlock.h"
#include "DFGDriver.h"
-#include "ExecutionHarness.h"
#include "JIT.h"
-#include "JITDriver.h"
#include "Operations.h"
#include "Parser.h"
#include <wtf/Vector.h>
}
#endif
+void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
+{
+ RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
+
+ VM& vm = *genericCodeBlock->vm();
+
+ if (vm.m_perBytecodeProfiler)
+ vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
+
+ ASSERT(vm.heap.isDeferred());
+
+ if (JITCode::isJIT(genericCodeBlock->jitType())) {
+ vm.heap.reportExtraMemoryCost(
+ sizeof(CodeBlock) + genericCodeBlock->jitCode()->size());
+ } else
+ vm.heap.reportExtraMemoryCost(sizeof(CodeBlock));
+
+ CodeSpecializationKind kind = genericCodeBlock->specializationKind();
+
+ RefPtr<CodeBlock> oldCodeBlock;
+
+ switch (kind) {
+ case CodeForCall:
+ m_jitCodeForCall = genericCodeBlock->jitCode();
+ m_jitCodeForCallWithArityCheck = genericCodeBlock->jitCodeWithArityCheck();
+ m_numParametersForCall = genericCodeBlock->numParameters();
+ break;
+ case CodeForConstruct:
+ m_jitCodeForConstruct = genericCodeBlock->jitCode();
+ m_jitCodeForConstructWithArityCheck = genericCodeBlock->jitCodeWithArityCheck();
+ m_numParametersForConstruct = genericCodeBlock->numParameters();
+ break;
+ }
+
+ switch (genericCodeBlock->codeType()) {
+ case GlobalCode: {
+ ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
+ ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
+
+ ASSERT(!codeBlock->jitCodeWithArityCheck());
+ ASSERT(kind == CodeForCall);
+
+ oldCodeBlock = executable->m_programCodeBlock;
+ executable->m_programCodeBlock = codeBlock;
+ break;
+ }
+
+ case EvalCode: {
+ EvalExecutable* executable = jsCast<EvalExecutable*>(this);
+ EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
+
+ ASSERT(!codeBlock->jitCodeWithArityCheck());
+ ASSERT(kind == CodeForCall);
+
+ oldCodeBlock = executable->m_evalCodeBlock;
+ executable->m_evalCodeBlock = codeBlock;
+ break;
+ }
+
+ case FunctionCode: {
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
+ FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
+
+ switch (kind) {
+ case CodeForCall:
+ oldCodeBlock = executable->m_codeBlockForCall;
+ executable->m_codeBlockForCall = codeBlock;
+ break;
+ case CodeForConstruct:
+ oldCodeBlock = executable->m_codeBlockForConstruct;
+ executable->m_codeBlockForConstruct = codeBlock;
+ break;
+ }
+ break;
+ } }
+
+ if (oldCodeBlock)
+ oldCodeBlock->unlinkIncomingCalls();
+}
+
+PassRefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
+ CodeSpecializationKind kind, JSScope* scope, JSObject*& exception)
+{
+ VM* vm = scope->vm();
+
+ ASSERT(vm->heap.isDeferred());
+
+ if (classInfo() == EvalExecutable::info()) {
+ EvalExecutable* executable = jsCast<EvalExecutable*>(this);
+ RELEASE_ASSERT(kind == CodeForCall);
+ RELEASE_ASSERT(!executable->m_evalCodeBlock);
+ return adoptRef(new EvalCodeBlock(
+ executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
+ executable->source().provider()));
+ }
+
+ if (classInfo() == ProgramExecutable::info()) {
+ ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
+ RELEASE_ASSERT(kind == CodeForCall);
+ RELEASE_ASSERT(!executable->m_programCodeBlock);
+ return adoptRef(new ProgramCodeBlock(
+ executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
+ executable->source().provider(), executable->source().startColumn()));
+ }
+
+ RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
+ RELEASE_ASSERT(!executable->codeBlockFor(kind));
+ JSGlobalObject* globalObject = scope->globalObject();
+ ParserError error;
+ DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
+ ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
+ UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
+ executable->m_unlinkedExecutable->codeBlockFor(
+ *vm, executable->m_source, kind, debuggerMode, profilerMode, error);
+ if (!unlinkedCodeBlock) {
+ exception = vm->throwException(
+ globalObject->globalExec(),
+ error.toErrorObject(globalObject, executable->m_source));
+ return 0;
+ }
+
+ SourceProvider* provider = executable->source().provider();
+ unsigned sourceOffset = executable->source().startOffset();
+ unsigned startColumn = executable->source().startColumn();
+
+ return adoptRef(new FunctionCodeBlock(
+ executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
+}
+
+PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
+ CodeSpecializationKind kind)
+{
+ if (classInfo() == EvalExecutable::info()) {
+ RELEASE_ASSERT(kind == CodeForCall);
+ EvalExecutable* executable = jsCast<EvalExecutable*>(this);
+ RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
+ CodeBlock::CopyParsedBlock, *executable->m_evalCodeBlock));
+ result->setAlternative(executable->m_evalCodeBlock);
+ return result;
+ }
+
+ if (classInfo() == ProgramExecutable::info()) {
+ RELEASE_ASSERT(kind == CodeForCall);
+ ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
+ RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
+ CodeBlock::CopyParsedBlock, *executable->m_programCodeBlock));
+ result->setAlternative(executable->m_programCodeBlock);
+ return result;
+ }
+
+ RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
+ RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
+ CodeBlock::CopyParsedBlock, *executable->codeBlockFor(kind)));
+ result->setAlternative(executable->codeBlockFor(kind));
+ return result;
+}
+
+JSObject* ScriptExecutable::prepareForExecutionImpl(
+ ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
+{
+ VM& vm = exec->vm();
+ DeferGC deferGC(vm.heap);
+
+ JSObject* exception = 0;
+ RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, scope, exception);
+ if (!codeBlock) {
+ RELEASE_ASSERT(exception);
+ return exception;
+ }
+
+ JITCode::JITType jitType;
+#if ENABLE(LLINT)
+ jitType = JITCode::InterpreterThunk;
+#else
+ jitType = JITCode::BaselineJIT;
+#endif
+ codeBlock->prepareForExecution(exec, jitType);
+
+ installCode(codeBlock.get());
+ return 0;
+}
+
const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext)
static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
}
-#if ENABLE(DFG_JIT)
-JSObject* EvalExecutable::compileOptimized(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
-{
- ASSERT(exec->vm().dynamicGlobalObject);
- ASSERT(!!m_evalCodeBlock);
- JSObject* error = 0;
- if (!JITCode::isOptimizingJIT(m_evalCodeBlock->jitType()))
- error = compileInternal(exec, scope, JITCode::nextTierJIT(m_evalCodeBlock->jitType()), &result, bytecodeIndex);
- else
- result = CompilationNotNeeded;
- ASSERT(!!m_evalCodeBlock);
- return error;
-}
-#endif // ENABLE(DFG_JIT)
-
-#if ENABLE(JIT)
-CompilationResult EvalExecutable::jitCompile(ExecState* exec)
-{
- return jitCompileIfAppropriate(exec, m_evalCodeBlock.get(), m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
-}
-#endif
-
inline const char* samplingDescription(JITCode::JITType jitType)
{
switch (jitType) {
}
}
-JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
-{
- SamplingRegion samplingRegion(samplingDescription(jitType));
-
- if (result)
- *result = CompilationFailed;
-
- RefPtr<EvalCodeBlock> newCodeBlock;
-
- if (!!m_evalCodeBlock) {
- newCodeBlock = adoptRef(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
- newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock));
- } else {
- newCodeBlock = adoptRef(new EvalCodeBlock(this, m_unlinkedEvalCodeBlock.get(), scope, source().provider()));
- ASSERT((jitType == JITCode::bottomTierJIT()) == !m_evalCodeBlock);
- }
-
- CompilationResult theResult = prepareForExecution(
- exec, m_evalCodeBlock, newCodeBlock.get(), m_jitCodeForCall, jitType, bytecodeIndex);
- if (result)
- *result = theResult;
-
- return 0;
-}
-
-#if ENABLE(DFG_JIT)
-CompilationResult EvalExecutable::replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan> plan)
-{
- return JSC::replaceWithDeferredOptimizedCode(
- plan, m_evalCodeBlock, m_jitCodeForCall, 0, 0);
-}
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void EvalExecutable::jettisonOptimizedCode(VM& vm)
{
return error.toErrorObject(lexicalGlobalObject, m_source);
}
-#if ENABLE(DFG_JIT)
-JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
-{
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- ASSERT(!!m_programCodeBlock);
- JSObject* error = 0;
- if (!JITCode::isOptimizingJIT(m_programCodeBlock->jitType()))
- error = compileInternal(exec, scope, JITCode::nextTierJIT(m_programCodeBlock->jitType()), &result, bytecodeIndex);
- else
- result = CompilationNotNeeded;
- ASSERT(!!m_programCodeBlock);
- return error;
-}
-#endif // ENABLE(DFG_JIT)
-
-#if ENABLE(JIT)
-CompilationResult ProgramExecutable::jitCompile(ExecState* exec)
-{
- return jitCompileIfAppropriate(exec, m_programCodeBlock.get(), m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
-}
-#endif
-
-JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
-{
- SamplingRegion samplingRegion(samplingDescription(jitType));
-
- if (result)
- *result = CompilationFailed;
-
- RefPtr<ProgramCodeBlock> newCodeBlock;
-
- if (!!m_programCodeBlock) {
- newCodeBlock = adoptRef(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
- newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock));
- } else {
- newCodeBlock = adoptRef(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), scope, source().provider(), source().startColumn()));
- }
-
- CompilationResult theResult = prepareForExecution(
- exec, m_programCodeBlock, newCodeBlock.get(), m_jitCodeForCall, jitType, bytecodeIndex);
- if (result)
- *result = theResult;
-
- return 0;
-}
-
-#if ENABLE(DFG_JIT)
-CompilationResult ProgramExecutable::replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan> plan)
-{
- return JSC::replaceWithDeferredOptimizedCode(
- plan, m_programCodeBlock, m_jitCodeForCall, 0, 0);
-}
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void ProgramExecutable::jettisonOptimizedCode(VM& vm)
{
return result;
}
-#if ENABLE(DFG_JIT)
-JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
-{
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- ASSERT(!!m_codeBlockForCall);
- JSObject* error = 0;
- if (!JITCode::isOptimizingJIT(m_codeBlockForCall->jitType()))
- error = compileForCallInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForCall->jitType()), &result, bytecodeIndex);
- else
- result = CompilationNotNeeded;
- ASSERT(!!m_codeBlockForCall);
- return error;
-}
-
-JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex)
-{
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- ASSERT(!!m_codeBlockForConstruct);
- JSObject* error = 0;
- if (!JITCode::isOptimizingJIT(m_codeBlockForConstruct->jitType()))
- error = compileForConstructInternal(exec, scope, JITCode::nextTierJIT(m_codeBlockForConstruct->jitType()), &result, bytecodeIndex);
- else
- result = CompilationNotNeeded;
- ASSERT(!!m_codeBlockForConstruct);
- return error;
-}
-#endif // ENABLE(DFG_JIT)
-
-#if ENABLE(JIT)
-CompilationResult FunctionExecutable::jitCompileForCall(ExecState* exec)
-{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
-}
-
-CompilationResult FunctionExecutable::jitCompileForConstruct(ExecState* exec)
-{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct.get(), m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
-}
-#endif
-
-PassRefPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
-{
- RefPtr<FunctionCodeBlock> alternative = codeBlockFor(specializationKind);
-
- if (!!alternative) {
- RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
- result->setAlternative(alternative);
- return result.release();
- }
-
- VM* vm = scope->vm();
- JSGlobalObject* globalObject = scope->globalObject();
- ParserError error;
- DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
- ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
- UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*vm, m_source, specializationKind, debuggerMode, profilerMode, error);
- recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn());
-
- if (!unlinkedCodeBlock) {
- exception = vm->throwException(globalObject->globalExec(), error.toErrorObject(globalObject, m_source));
- return 0;
- }
-
- SourceProvider* provider = source().provider();
- unsigned sourceOffset = source().startOffset();
- unsigned startColumn = source().startColumn();
-
- return adoptRef(new FunctionCodeBlock(this, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
-}
-
-
-JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
-{
- SamplingRegion samplingRegion(samplingDescription(jitType));
-
- if (result)
- *result = CompilationFailed;
-
- ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
- JSObject* exception = 0;
-
- RefPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
- if (!newCodeBlock)
- return exception;
-
- CompilationResult theResult = prepareFunctionForExecution(
- exec, m_codeBlockForCall, newCodeBlock.get(), m_jitCodeForCall,
- m_jitCodeForCallWithArityCheck, m_numParametersForCall, jitType,
- bytecodeIndex, CodeForCall);
- if (result)
- *result = theResult;
- return 0;
-}
-
-#if ENABLE(DFG_JIT)
-CompilationResult FunctionExecutable::replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan> plan)
-{
- return JSC::replaceWithDeferredOptimizedCode(
- plan, m_codeBlockForCall, m_jitCodeForCall, &m_jitCodeForCallWithArityCheck,
- &m_numParametersForCall);
-}
-#endif // ENABLE(DFG_JIT)
-
-JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, CompilationResult* result, unsigned bytecodeIndex)
-{
- SamplingRegion samplingRegion(samplingDescription(jitType));
-
- if (result)
- *result = CompilationFailed;
-
- ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
- JSObject* exception = 0;
- RefPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
- if (!newCodeBlock)
- return exception;
-
- CompilationResult theResult = prepareFunctionForExecution(
- exec, m_codeBlockForConstruct, newCodeBlock.get(), m_jitCodeForConstruct,
- m_jitCodeForConstructWithArityCheck, m_numParametersForConstruct, jitType,
- bytecodeIndex, CodeForConstruct);
- if (result)
- *result = theResult;
-
- return 0;
-}
-
-#if ENABLE(DFG_JIT)
-CompilationResult FunctionExecutable::replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan> plan)
-{
- return JSC::replaceWithDeferredOptimizedCode(
- plan, m_codeBlockForConstruct, m_jitCodeForConstruct,
- &m_jitCodeForConstructWithArityCheck, &m_numParametersForConstruct);
-}
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
{
return generatedJITCodeForConstructWithArityCheck();
}
+ static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
+ }
+
+ static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
+ }
+#endif // ENABLE(JIT)
+
bool hasJITCodeForCall() const
{
return m_numParametersForCall >= 0;
return hasJITCodeForConstruct();
}
- static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
- {
- if (kind == CodeForCall)
- return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
- ASSERT(kind == CodeForConstruct);
- return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
- }
-
- static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
- {
- if (kind == CodeForCall)
- return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
- ASSERT(kind == CodeForConstruct);
- return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
- }
-#endif // ENABLE(JIT)
-
// Intrinsics are only for calls, currently.
Intrinsic intrinsic() const;
return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
#endif
}
+
#endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
protected:
m_startColumn = startColumn;
}
+ void installCode(CodeBlock*);
+ PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*& exception);
+ PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
+
+ JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
+ {
+ if (hasJITCodeFor(kind))
+ return 0;
+ return prepareForExecutionImpl(exec, scope, kind);
+ }
+
+private:
+ JSObject* prepareForExecutionImpl(ExecState*, JSScope*, CodeSpecializationKind);
+
protected:
void finishCreation(VM& vm)
{
static void destroy(JSCell*);
- JSObject* compile(ExecState* exec, JSScope* scope)
- {
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- JSObject* error = 0;
- if (!m_evalCodeBlock)
- error = compileInternal(exec, scope, JITCode::bottomTierJIT());
- ASSERT(!error == !!m_evalCodeBlock);
- return error;
- }
-
-#if ENABLE(DFG_JIT)
- JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void jettisonOptimizedCode(VM&);
- CompilationResult jitCompile(ExecState*);
#endif
EvalCodeBlock& generatedBytecode()
unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
private:
+ friend class ScriptExecutable;
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
EvalExecutable(ExecState*, const SourceCode&, bool);
- JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
RefPtr<EvalCodeBlock> m_evalCodeBlock;
static void destroy(JSCell*);
- JSObject* compile(ExecState* exec, JSScope* scope)
- {
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- JSObject* error = 0;
- if (!m_programCodeBlock)
- error = compileInternal(exec, scope, JITCode::bottomTierJIT());
- ASSERT(!error == !!m_programCodeBlock);
- return error;
- }
-
-#if ENABLE(DFG_JIT)
- JSObject* compileOptimized(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- CompilationResult replaceWithDeferredOptimizedCode(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void jettisonOptimizedCode(VM&);
- CompilationResult jitCompile(ExecState*);
#endif
ProgramCodeBlock& generatedBytecode()
ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
private:
+ friend class ScriptExecutable;
+
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
ProgramExecutable(ExecState*, const SourceCode&);
- JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
return *m_codeBlockForConstruct;
}
- PassRefPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
-
- JSObject* compileForCall(ExecState* exec, JSScope* scope)
- {
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- JSObject* error = 0;
- if (!m_codeBlockForCall)
- error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
- ASSERT(!error == !!m_codeBlockForCall);
- return error;
- }
-
-#if ENABLE(DFG_JIT)
- JSObject* compileOptimizedForCall(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- CompilationResult replaceWithDeferredOptimizedCodeForCall(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void jettisonOptimizedCodeForCall(VM&);
- CompilationResult jitCompileForCall(ExecState*);
#endif
bool isGeneratedForCall() const
return *m_codeBlockForCall;
}
- JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
- {
- RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
- JSObject* error = 0;
- if (!m_codeBlockForConstruct)
- error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
- ASSERT(!error == !!m_codeBlockForConstruct);
- return error;
- }
-
-#if ENABLE(DFG_JIT)
- JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, CompilationResult&, unsigned bytecodeIndex);
- CompilationResult replaceWithDeferredOptimizedCodeForConstruct(PassRefPtr<DFG::Plan>);
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void jettisonOptimizedCodeForConstruct(VM&);
- CompilationResult jitCompileForConstruct(ExecState*);
#endif
bool isGeneratedForConstruct() const
return *m_codeBlockForConstruct;
}
- JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
- {
- ASSERT(exec->callee());
- ASSERT(exec->callee()->inherits(JSFunction::info()));
- ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
-
- if (kind == CodeForCall)
- return compileForCall(exec, scope);
- ASSERT(kind == CodeForConstruct);
- return compileForConstruct(exec, scope);
- }
-
-#if ENABLE(DFG_JIT)
- JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, CompilationResult& result, unsigned bytecodeIndex, CodeSpecializationKind kind)
- {
- ASSERT(exec->callee());
- ASSERT(exec->callee()->inherits(JSFunction::info()));
- ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
-
- if (kind == CodeForCall)
- return compileOptimizedForCall(exec, scope, result, bytecodeIndex);
- ASSERT(kind == CodeForConstruct);
- return compileOptimizedForConstruct(exec, scope, result, bytecodeIndex);
- }
-
- CompilationResult replaceWithDeferredOptimizedCodeFor(PassRefPtr<DFG::Plan> plan, CodeSpecializationKind kind)
- {
- if (kind == CodeForCall)
- return replaceWithDeferredOptimizedCodeForCall(plan);
- return replaceWithDeferredOptimizedCodeForConstruct(plan);
- }
-#endif // ENABLE(DFG_JIT)
-
#if ENABLE(JIT)
void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
{
jettisonOptimizedCodeForConstruct(vm);
}
}
-
- CompilationResult jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
- {
- if (kind == CodeForCall)
- return jitCompileForCall(exec);
- ASSERT(kind == CodeForConstruct);
- return jitCompileForConstruct(exec);
- }
#endif
bool isGeneratedFor(CodeSpecializationKind kind)
private:
FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
- JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
- JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, CompilationResult* = 0, unsigned bytecodeIndex = UINT_MAX);
-
RefPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
{
if (kind == CodeForCall)
return false;
}
+ friend class ScriptExecutable;
+
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
RefPtr<FunctionCodeBlock> m_codeBlockForCall;
+++ /dev/null
-/*
- * Copyright (C) 2012, 2013 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 ExecutionHarness_h
-#define ExecutionHarness_h
-
-#include <wtf/Platform.h>
-
-#include "CompilationResult.h"
-#include "DFGDriver.h"
-#include "DFGPlan.h"
-#include "JITDriver.h"
-#include "LLIntEntrypoints.h"
-
-namespace JSC {
-
-template<typename CodeBlockType>
-inline CompilationResult prepareForExecutionImpl(
- ExecState* exec, CodeBlockType* codeBlock, RefPtr<JITCode>& jitCode,
- JITCode::JITType jitType, unsigned bytecodeIndex)
-{
- UNUSED_PARAM(bytecodeIndex);
-#if ENABLE(LLINT)
- if (JITCode::isBaselineCode(jitType)) {
- // Start off in the low level interpreter.
- LLInt::getEntrypoint(exec->vm(), codeBlock, jitCode);
- if (exec->vm().m_perBytecodeProfiler)
- exec->vm().m_perBytecodeProfiler->ensureBytecodesFor(codeBlock);
- return CompilationSuccessful;
- }
-#endif // ENABLE(LLINT)
-#if ENABLE(JIT)
- return jitCompileIfAppropriateImpl(
- exec, codeBlock, jitCode, jitType, bytecodeIndex,
- JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
-#endif
- RELEASE_ASSERT_NOT_REACHED();
- return CompilationFailed;
-}
-
-inline CompilationResult prepareFunctionForExecutionImpl(
- ExecState* exec, FunctionCodeBlock* codeBlock, RefPtr<JITCode>& jitCode,
- MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType,
- unsigned bytecodeIndex, CodeSpecializationKind kind)
-{
- UNUSED_PARAM(bytecodeIndex);
- UNUSED_PARAM(jitCodeWithArityCheck);
-#if ENABLE(LLINT)
- if (JITCode::isBaselineCode(jitType)) {
- // Start off in the low level interpreter.
- LLInt::getFunctionEntrypoint(exec->vm(), kind, jitCode, jitCodeWithArityCheck);
- if (exec->vm().m_perBytecodeProfiler)
- exec->vm().m_perBytecodeProfiler->ensureBytecodesFor(codeBlock);
- return CompilationSuccessful;
- }
-#else
- UNUSED_PARAM(kind);
-#endif // ENABLE(LLINT)
-#if ENABLE(JIT)
- return jitCompileFunctionIfAppropriateImpl(
- exec, codeBlock, jitCode, jitCodeWithArityCheck, jitType, bytecodeIndex,
- JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
-#endif
- RELEASE_ASSERT_NOT_REACHED();
- return CompilationFailed;
-}
-
-template<typename CodeBlockType>
-inline CompilationResult installOptimizedCode(
- CompilationResult result, RefPtr<CodeBlockType>& sink, CodeBlockType* codeBlock,
- PassRefPtr<JITCode> jitCode, MacroAssemblerCodePtr jitCodeWithArityCheck,
- int* numParameters)
-{
- UNUSED_PARAM(jitCodeWithArityCheck);
- if (result != CompilationSuccessful)
- return result;
-
-#if ENABLE(JIT)
- codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
-#endif
-
- sink = codeBlock;
-
- if (numParameters)
- *numParameters = codeBlock->numParameters();
-
- if (jitCode)
- codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock) + jitCode->size());
- else
- codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock));
-
- if (sink != codeBlock) {
- // This can happen if we GC and decide that the code is invalid.
- return CompilationInvalidated;
- }
-
- return result;
-}
-
-template<typename CodeBlockType>
-inline CompilationResult prepareForExecution(
- ExecState* exec, RefPtr<CodeBlockType>& sink, CodeBlockType* codeBlock,
- RefPtr<JITCode>& jitCode, JITCode::JITType jitType, unsigned bytecodeIndex)
-{
- CompilationResult result = prepareForExecutionImpl(exec, codeBlock, jitCode, jitType, bytecodeIndex);
- return installOptimizedCode(result, sink, codeBlock, jitCode, MacroAssemblerCodePtr(), 0);
-}
-
-inline CompilationResult prepareFunctionForExecution(
- ExecState* exec, RefPtr<FunctionCodeBlock>& sink, FunctionCodeBlock* codeBlock,
- RefPtr<JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck,
- int& numParameters, JITCode::JITType jitType, unsigned bytecodeIndex,
- CodeSpecializationKind kind)
-{
- CompilationResult result = prepareFunctionForExecutionImpl(exec, codeBlock,
- jitCode, jitCodeWithArityCheck, jitType, bytecodeIndex, kind);
- return installOptimizedCode(result, sink, codeBlock, jitCode, jitCodeWithArityCheck, &numParameters);
-}
-
-#if ENABLE(DFG_JIT)
-template<typename CodeBlockType>
-inline CompilationResult replaceWithDeferredOptimizedCode(
- PassRefPtr<DFG::Plan> passedPlan, RefPtr<CodeBlockType>& sink, RefPtr<JITCode>& jitCode,
- MacroAssemblerCodePtr* jitCodeWithArityCheck, int* numParameters)
-{
- RefPtr<DFG::Plan> plan = passedPlan;
- CompilationResult result = DFG::tryFinalizePlan(plan, jitCode, jitCodeWithArityCheck);
- if (Options::verboseOSR()) {
- dataLog(
- "Deferred optimizing compilation ", *plan->key(), " -> ", *plan->codeBlock,
- " result: ", result, "\n");
- }
- if (result == CompilationSuccessful)
- plan->codeBlock->alternative()->unlinkIncomingCalls();
- return installOptimizedCode(
- result, sink, static_cast<CodeBlockType*>(plan->codeBlock.get()), jitCode,
- jitCodeWithArityCheck ? *jitCodeWithArityCheck : MacroAssemblerCodePtr(),
- numParameters);
-}
-#endif // ENABLE(DFG_JIT)
-
-} // namespace JSC
-
-#endif // ExecutionHarness_h
-