WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
more
blah.patch (text/plain), 139.49 KB, created by
Filip Pizlo
on 2013-04-10 00:16:18 PDT
(
hide
)
Description:
more
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-04-10 00:16:18 PDT
Size:
139.49 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 148047) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,188 @@ >+2013-04-05 Filip Pizlo <fpizlo@apple.com> >+ >+ FTL should have OSR exit >+ https://bugs.webkit.org/show_bug.cgi?id=113623 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Work in progress. >+ >+ * assembler/LinkBuffer.h: >+ (JSC::LinkBuffer::offsetOf): >+ (LinkBuffer): >+ * dfg/DFGAbstractState.cpp: >+ (JSC::DFG::AbstractState::initialize): >+ * dfg/DFGMinifiedNode.h: >+ (JSC::DFG::belongsInMinifiedGraph): >+ * dfg/DFGNodeType.h: >+ (JSC::DFG::needsOSRBackwardRewiring): >+ (DFG): >+ (JSC::DFG::needsOSRForwardRewiring): >+ * dfg/DFGOSRExit.cpp: >+ (JSC::DFG::OSRExit::OSRExit): >+ (DFG): >+ (JSC::DFG::OSRExit::convertToForward): >+ * dfg/DFGOSRExit.h: >+ (OSRExit): >+ * dfg/DFGOSRExitBase.cpp: Added. >+ (DFG): >+ (JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSiteSlow): >+ (JSC::DFG::OSRExitBase::doSearchForForwardConversion): >+ * dfg/DFGOSRExitBase.h: Added. >+ (DFG): >+ (JSC::DFG::OSRExitBase::OSRExitBase): >+ (OSRExitBase): >+ (JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSite): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes): >+ * dfg/DFGValueSource.h: >+ (JSC::DFG::ValueSource::forSpeculation): >+ * dfg/DFGVariableEventStream.cpp: >+ (JSC::DFG::VariableEventStream::reconstruct): >+ * ftl/FTLAbbreviations.h: >+ (FTL): >+ (JSC::FTL::functionType): >+ (JSC::FTL::typeOf): >+ (JSC::FTL::buildCall): >+ (JSC::FTL::setTailCall): >+ * ftl/FTLExitArgument.cpp: Added. >+ (FTL): >+ (JSC::FTL::ExitArgument::dump): >+ * ftl/FTLExitArgument.h: Added. >+ (FTL): >+ (ExitArgumentRepresentation): >+ (ExitArgument): >+ (JSC::FTL::ExitArgument::ExitArgument): >+ (JSC::FTL::ExitArgument::operator!): >+ (JSC::FTL::ExitArgument::format): >+ (JSC::FTL::ExitArgument::argument): >+ (JSC::FTL::ExitArgument::withFormat): >+ (JSC::FTL::ExitArgument::representation): >+ * ftl/FTLExitArgumentList.h: Added. >+ (FTL): >+ * ftl/FTLExitThunkGenerator.cpp: Added. >+ (FTL): >+ (JSC::FTL::ExitThunkGenerator::ExitThunkGenerator): >+ (JSC::FTL::ExitThunkGenerator::~ExitThunkGenerator): >+ (JSC::FTL::ExitThunkGenerator::emitThunk): >+ * ftl/FTLExitThunkGenerator.h: Added. >+ (FTL): >+ (ExitThunkGenerator): >+ * ftl/FTLExitValue.cpp: Added. >+ (FTL): >+ (JSC::FTL::ExitValue::dump): >+ * ftl/FTLExitValue.h: Added. >+ (FTL): >+ (ExitValue): >+ (JSC::FTL::ExitValue::ExitValue): >+ (JSC::FTL::ExitValue::operator!): >+ (JSC::FTL::ExitValue::dead): >+ (JSC::FTL::ExitValue::inJSStack): >+ (JSC::FTL::ExitValue::inJSStackAsInt32): >+ (JSC::FTL::ExitValue::inJSStackAsBoolean): >+ (JSC::FTL::ExitValue::inJSStackAsDouble): >+ (JSC::FTL::ExitValue::constant): >+ (JSC::FTL::ExitValue::exitArgument): >+ (JSC::FTL::ExitValue::kind): >+ (JSC::FTL::ExitValue::isDead): >+ (JSC::FTL::ExitValue::isInJSStackSomehow): >+ (JSC::FTL::ExitValue::isConstant): >+ (JSC::FTL::ExitValue::isArgument): >+ * ftl/FTLFormattedValue.h: >+ (FTL): >+ (JSC::FTL::noValue): >+ (JSC::FTL::int32Value): >+ (JSC::FTL::uInt32Value): >+ (JSC::FTL::booleanValue): >+ (JSC::FTL::jsValueValue): >+ (JSC::FTL::doubleValue): >+ * ftl/FTLJITCode.cpp: >+ (JSC::FTL::JITCode::initializeExitThunks): >+ (FTL): >+ (JSC::FTL::JITCode::exitThunks): >+ * ftl/FTLJITCode.h: >+ (JITCode): >+ * ftl/FTLLowerDFGToLLVM.cpp: >+ (FTL): >+ (JSC::FTL::LowerDFGToLLVM::LowerDFGToLLVM): >+ (JSC::FTL::LowerDFGToLLVM::lower): >+ (JSC::FTL::LowerDFGToLLVM::transferAndCheckArguments): >+ (JSC::FTL::LowerDFGToLLVM::compileBlock): >+ (JSC::FTL::LowerDFGToLLVM::compileNode): >+ (JSC::FTL::LowerDFGToLLVM::compileGetLocal): >+ (JSC::FTL::LowerDFGToLLVM::compileSetLocal): >+ (LowerDFGToLLVM): >+ (JSC::FTL::LowerDFGToLLVM::compileMovHint): >+ (JSC::FTL::LowerDFGToLLVM::compileZombieHint): >+ (JSC::FTL::LowerDFGToLLVM::compileMovHintAndCheck): >+ (JSC::FTL::LowerDFGToLLVM::compileAdd): >+ (JSC::FTL::LowerDFGToLLVM::compileArithSub): >+ (JSC::FTL::LowerDFGToLLVM::compileArithMul): >+ (JSC::FTL::LowerDFGToLLVM::compileArithNegate): >+ (JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber): >+ (JSC::FTL::LowerDFGToLLVM::compileCheckStructure): >+ (JSC::FTL::LowerDFGToLLVM::compileGetByVal): >+ (JSC::FTL::LowerDFGToLLVM::speculateBackward): >+ (JSC::FTL::LowerDFGToLLVM::speculateForward): >+ (JSC::FTL::LowerDFGToLLVM::speculate): >+ (JSC::FTL::LowerDFGToLLVM::backwardTypeCheck): >+ (JSC::FTL::LowerDFGToLLVM::forwardTypeCheck): >+ (JSC::FTL::LowerDFGToLLVM::typeCheck): >+ (JSC::FTL::LowerDFGToLLVM::appendTypeCheck): >+ (JSC::FTL::LowerDFGToLLVM::lowInt32): >+ (JSC::FTL::LowerDFGToLLVM::lowCell): >+ (JSC::FTL::LowerDFGToLLVM::lowBoolean): >+ (JSC::FTL::LowerDFGToLLVM::speculateObject): >+ (JSC::FTL::LowerDFGToLLVM::isLive): >+ (JSC::FTL::LowerDFGToLLVM::use): >+ (JSC::FTL::LowerDFGToLLVM::initializeOSRExitStateForBlock): >+ (JSC::FTL::LowerDFGToLLVM::appendOSRExit): >+ (JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode): >+ (JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument): >+ (JSC::FTL::LowerDFGToLLVM::addExitArgument): >+ (JSC::FTL::LowerDFGToLLVM::linkOSRExitsAndCompleteInitializationBlock): >+ (JSC::FTL::LowerDFGToLLVM::observeMovHint): >+ * ftl/FTLOSRExit.cpp: Added. >+ (FTL): >+ (JSC::FTL::OSRExit::OSRExit): >+ (JSC::FTL::OSRExit::codeLocationForRepatch): >+ (JSC::FTL::OSRExit::convertToForward): >+ * ftl/FTLOSRExit.h: Added. >+ (FTL): >+ (OSRExit): >+ * ftl/FTLOSRExitCompilationInfo.h: Added. >+ (FTL): >+ (JSC::FTL::OSRExitCompilationInfo::OSRExitCompilationInfo): >+ (OSRExitCompilationInfo): >+ * ftl/FTLOutput.h: >+ (JSC::FTL::Output::intToPtr): >+ (JSC::FTL::Output::load): >+ (JSC::FTL::Output::store): >+ (Output): >+ (JSC::FTL::Output::call): >+ (JSC::FTL::Output::convertToTailCall): >+ * ftl/FTLState.h: >+ (State): >+ * ftl/FTLThunks.h: Added. >+ (JSC): >+ (FTL): >+ * ftl/FTLValueFormat.cpp: Added. >+ (WTF): >+ (WTF::printInternal): >+ * ftl/FTLValueFormat.h: Added. >+ (FTL): >+ (WTF): >+ * ftl/FTLValueSource.cpp: Added. >+ (FTL): >+ (JSC::FTL::ValueSource::dump): >+ * ftl/FTLValueSource.h: Added. >+ (FTL): >+ (ValueSource): >+ (JSC::FTL::ValueSource::ValueSource): >+ (JSC::FTL::ValueSource::kind): >+ (JSC::FTL::ValueSource::operator!): >+ (JSC::FTL::ValueSource::node): >+ > 2013-04-09 Filip Pizlo <fpizlo@apple.com> > > fourthTier: DFG should provide utilities for common OSR exit tasks >Index: Source/JavaScriptCore/assembler/LinkBuffer.h >=================================================================== >--- Source/JavaScriptCore/assembler/LinkBuffer.h (revision 148047) >+++ Source/JavaScriptCore/assembler/LinkBuffer.h (working copy) >@@ -199,6 +199,11 @@ public: > return applyOffset(label.m_label).m_offset; > } > >+ unsigned offsetOf(PatchableJump jump) >+ { >+ return applyOffset(jump.m_jump.m_label).m_offset; >+ } >+ > // Upon completion of all patching 'FINALIZE_CODE()' should be called once to > // complete generation of the code. Alternatively, call > // finalizeCodeWithoutDisassembly() directly if you have your own way of >Index: Source/JavaScriptCore/dfg/DFGAbstractState.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractState.cpp (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGAbstractState.cpp (working copy) >@@ -95,7 +95,8 @@ void AbstractState::initialize(Graph& gr > continue; > } > >- SpeculatedType prediction = node->variableAccessData()->prediction(); >+ SpeculatedType prediction = >+ node->variableAccessData()->argumentAwarePrediction(); > if (isInt32Speculation(prediction)) > root->valuesAtHead.argument(i).set(SpecInt32); > else if (isBooleanSpeculation(prediction)) >Index: Source/JavaScriptCore/dfg/DFGGPRInfo.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGPRInfo.h (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGGPRInfo.h (working copy) >@@ -367,7 +367,7 @@ public: > static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3, argumentGPR4, argumentGPR5 }; > return registerForIndex[index]; > } >- >+ > static unsigned toIndex(GPRReg reg) > { > ASSERT(reg != InvalidGPRReg); >Index: Source/JavaScriptCore/dfg/DFGMinifiedNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGMinifiedNode.h (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGMinifiedNode.h (working copy) >@@ -51,6 +51,7 @@ inline bool belongsInMinifiedGraph(NodeT > case PhantomArguments: > return true; > default: >+ ASSERT(!needsOSRBackwardRewiring(type) && !needsOSRForwardRewiring(type)); > return false; > } > } >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -287,6 +287,25 @@ inline NodeFlags defaultFlags(NodeType o > } > } > >+inline bool needsOSRBackwardRewiring(NodeType op) >+{ >+ return op == UInt32ToNumber; >+} >+ >+inline bool needsOSRForwardRewiring(NodeType op) >+{ >+ switch (op) { >+ case Int32ToDouble: >+ case ForwardInt32ToDouble: >+ case ValueToInt32: >+ case UInt32ToNumber: >+ case DoubleAsInt32: >+ return true; >+ default: >+ return false; >+ } >+} >+ > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGOSRExit.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExit.cpp (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGOSRExit.cpp (working copy) >@@ -36,15 +36,13 @@ > namespace JSC { namespace DFG { > > OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, SpeculativeJIT* jit, unsigned streamIndex, unsigned recoveryIndex) >- : m_jsValueSource(jsValueSource) >+ : OSRExitBase(kind, jit->m_codeOriginForOSR) >+ , m_jsValueSource(jsValueSource) > , m_valueProfile(valueProfile) > , m_patchableCodeOffset(0) > , m_codeOrigin(jit->m_codeOriginForOSR) >- , m_codeOriginForExitProfile(m_codeOrigin) > , m_recoveryIndex(recoveryIndex) > , m_watchpointIndex(std::numeric_limits<unsigned>::max()) >- , m_kind(kind) >- , m_count(0) > , m_streamIndex(streamIndex) > , m_lastSetOperand(jit->m_lastSetOperand) > { >@@ -73,57 +71,14 @@ void OSRExit::correctJump(LinkBuffer& li > m_patchableCodeOffset = linkBuffer.offsetOf(label); > } > >-bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) >-{ >- if (static_cast<double>(m_count) / dfgCodeBlock->osrExitCounter() <= Options::osrExitProminenceForFrequentExitSite()) >- return false; >- >- FrequentExitSite exitSite; >- >- if (m_kind == ArgumentsEscaped) { >- // Count this one globally. It doesn't matter where in the code block the arguments excaped; >- // the fact that they did is not associated with any particular instruction. >- exitSite = FrequentExitSite(m_kind); >- } else >- exitSite = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind); >- >- return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(exitSite); >-} >- > void OSRExit::convertToForward(BasicBlock* block, Node* currentNode, unsigned nodeIndex, const ValueRecovery& valueRecovery) > { >- // Check that either the current node is a SetLocal, or the preceding node was a >- // SetLocal with the same code origin, or that we've provided a valueRecovery. >- if (!ASSERT_DISABLED >- && !valueRecovery >- && !currentNode->containsMovHint()) { >- Node* setLocal = block->at(nodeIndex - 1); >- ASSERT_UNUSED(setLocal, setLocal->containsMovHint()); >- ASSERT_UNUSED(setLocal, setLocal->codeOrigin == currentNode->codeOrigin); >- } >- >- // Find the first node for the next bytecode instruction. Also track the last mov hint >- // on this node. >- unsigned indexInBlock = nodeIndex + 1; >- Node* node = 0; >- Node* lastMovHint = 0; >- for (;;) { >- if (indexInBlock == block->size()) { >- // This is an inline return. Give up and do a backwards speculation. This is safe >- // because an inline return has its own bytecode index and it's always safe to >- // reexecute that bytecode. >- ASSERT(node->op() == Jump); >- return; >- } >- node = block->at(indexInBlock); >- if (node->containsMovHint() && node->child1() == currentNode) >- lastMovHint = node; >- if (node->codeOrigin != currentNode->codeOrigin) >- break; >- indexInBlock++; >- } >- >+ Node* node; >+ Node* lastMovHint; >+ doSearchForForwardConversion(block, currentNode, nodeIndex, !!valueRecovery); >+ > ASSERT(node->codeOrigin != currentNode->codeOrigin); >+ > m_codeOrigin = node->codeOrigin; > > if (!valueRecovery) >Index: Source/JavaScriptCore/dfg/DFGOSRExit.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExit.h (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGOSRExit.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011 Apple Inc. All rights reserved. >+ * Copyright (C) 2011, 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 >@@ -34,6 +34,7 @@ > #include "DFGCommon.h" > #include "DFGExitProfile.h" > #include "DFGGPRInfo.h" >+#include "DFGOSRExitBase.h" > #include "DFGValueRecoveryOverride.h" > #include "MacroAssembler.h" > #include "MethodOfGettingAValueProfile.h" >@@ -84,7 +85,7 @@ private: > // > // This structure describes how to exit the speculative path by > // going into baseline code. >-struct OSRExit { >+struct OSRExit : public OSRExitBase { > OSRExit(ExitKind, JSValueSource, MethodOfGettingAValueProfile, SpeculativeJIT*, unsigned streamIndex, unsigned recoveryIndex = UINT_MAX); > > MacroAssemblerCodeRef m_code; >@@ -94,21 +95,10 @@ struct OSRExit { > > unsigned m_patchableCodeOffset; > CodeOrigin m_codeOrigin; >- CodeOrigin m_codeOriginForExitProfile; > > unsigned m_recoveryIndex; > unsigned m_watchpointIndex; > >- ExitKind m_kind; >- uint32_t m_count; >- >- bool considerAddingAsFrequentExitSite(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) >- { >- if (!m_count || !exitKindIsCountable(m_kind)) >- return false; >- return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock); >- } >- > void setPatchableCodeOffset(MacroAssembler::PatchableJump); > MacroAssembler::Jump getPatchableCodeOffsetAsJump() const; > CodeLocationJump codeLocationForRepatch(CodeBlock*) const; >@@ -120,9 +110,6 @@ struct OSRExit { > int m_lastSetOperand; > > RefPtr<ValueRecoveryOverride> m_valueRecoveryOverride; >- >-private: >- bool considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock); > }; > > struct SpeculationFailureDebugInfo { >Index: Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (working copy) >@@ -0,0 +1,92 @@ >+/* >+ * 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 "DFGOSRExitBase.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+bool OSRExitBase::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) >+{ >+ if (static_cast<double>(m_count) / dfgCodeBlock->osrExitCounter() <= Options::osrExitProminenceForFrequentExitSite()) >+ return false; >+ >+ FrequentExitSite exitSite; >+ >+ if (m_kind == ArgumentsEscaped) { >+ // Count this one globally. It doesn't matter where in the code block the arguments excaped; >+ // the fact that they did is not associated with any particular instruction. >+ exitSite = FrequentExitSite(m_kind); >+ } else >+ exitSite = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind); >+ >+ return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(exitSite); >+} >+ >+bool OSRExitBase::doSearchForForwardConversion( >+ BasicBlock* block, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery, >+ Node*& node, Node*& lastMovHint) >+{ >+ // Check that either the current node is a SetLocal, or the preceding node was a >+ // SetLocal with the same code origin, or that we've provided a valueRecovery. >+ if (!ASSERT_DISABLED >+ && !hasValueRecovery >+ && !currentNode->containsMovHint()) { >+ Node* setLocal = block->at(nodeIndex - 1); >+ ASSERT_UNUSED(setLocal, setLocal->containsMovHint()); >+ ASSERT_UNUSED(setLocal, setLocal->codeOrigin == currentNode->codeOrigin); >+ } >+ >+ // Find the first node for the next bytecode instruction. Also track the last mov hint >+ // on this node. >+ unsigned indexInBlock = nodeIndex + 1; >+ node = 0; >+ lastMovHint = 0; >+ for (;;) { >+ if (indexInBlock == block->size()) { >+ // This is an inline return. Give up and do a backwards speculation. This is safe >+ // because an inline return has its own bytecode index and it's always safe to >+ // reexecute that bytecode. >+ ASSERT(node->op() == Jump); >+ return false; >+ } >+ node = block->at(indexInBlock); >+ if (node->containsMovHint() && node->child1() == currentNode) >+ lastMovHint = node; >+ if (node->codeOrigin != currentNode->codeOrigin) >+ break; >+ indexInBlock++; >+ } >+ >+ ASSERT(node->codeOrigin != currentNode->codeOrigin); >+ return true; >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGOSRExitBase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitBase.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRExitBase.h (working copy) >@@ -0,0 +1,75 @@ >+/* >+ * 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 DFGOSRExitBase_h >+#define DFGOSRExitBase_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(DFG_JIT) >+ >+#include "CodeOrigin.h" >+#include "DFGExitProfile.h" >+ >+namespace JSC { namespace DFG { >+ >+// Provides for the OSR exit profiling functionality that is common between the DFG >+// and the FTL. >+ >+struct OSRExitBase { >+ OSRExitBase(ExitKind kind, CodeOrigin origin) >+ : m_kind(kind) >+ , m_count(0) >+ , m_codeOriginForExitProfile(origin) >+ { >+ } >+ >+ ExitKind m_kind; >+ uint32_t m_count; >+ >+ CodeOrigin m_codeOriginForExitProfile; >+ >+ bool considerAddingAsFrequentExitSite(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) >+ { >+ if (!m_count || !exitKindIsCountable(m_kind)) >+ return false; >+ return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock); >+ } >+ >+ // Returns true if the forward conversion is really needed. >+ bool doSearchForForwardConversion( >+ BasicBlock*, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery, >+ Node*& nextBCNode, Node*& lastMovHint); >+ >+private: >+ bool considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock); >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGOSRExitBase_h >+ >Index: Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp (working copy) >@@ -31,6 +31,7 @@ > #include "CallFrame.h" > #include "DFGCommon.h" > #include "DFGJITCode.h" >+#include "DFGOSRExitPreparation.h" > #include "LinkBuffer.h" > #include "Operations.h" > #include "RepatchBuffer.h" >@@ -54,20 +55,7 @@ void compileOSRExit(ExecState* exec) > uint32_t exitIndex = globalData->osrExitIndex; > OSRExit& exit = codeBlock->getJITCode()->dfg()->osrExit[exitIndex]; > >- // Make sure all code on our inline stack is JIT compiled. This is necessary since >- // we may opt to inline a code block even before it had ever been compiled by the >- // JIT, but our OSR exit infrastructure currently only works if the target of the >- // OSR exit is JIT code. This could be changed since there is nothing particularly >- // hard about doing an OSR exit into the interpreter, but for now this seems to make >- // sense in that if we're OSR exiting from inlined code of a DFG code block, then >- // probably it's a good sign that the thing we're exiting into is hot. Even more >- // interestingly, since the code was inlined, it may never otherwise get JIT >- // compiled since the act of inlining it may ensure that it otherwise never runs. >- for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) { >- static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get()) >- ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct) >- ->jitCompile(exec); >- } >+ prepareCodeOriginForOSRExit(exit.m_codeOrigin); > > // Compute the value recoveries. > Operands<ValueRecovery> operands; >Index: Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp (working copy) >@@ -0,0 +1,45 @@ >+/* >+ * 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 "DFGOSRExitPreparation.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+void prepareCodeOriginForOSRExit(CodeOrigin codeOrigin) >+{ >+ for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) { >+ static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get()) >+ ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct) >+ ->jitCompile(exec); >+ } >+} >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGOSRExitPreparation.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitPreparation.h (revision 0) >+++ Source/JavaScriptCore/dfg/DFGOSRExitPreparation.h (working copy) >@@ -0,0 +1,52 @@ >+/* >+ * 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 DFGOSRExitPreparation_h >+#define DFGOSRExitPreparation_h >+ >+#if ENABLE(DFG_JIT) >+ >+#include "CodeOrigin.h" >+ >+namespace JSC { namespace DFG { >+ >+// Make sure all code on our inline stack is JIT compiled. This is necessary since >+// we may opt to inline a code block even before it had ever been compiled by the >+// JIT, but our OSR exit infrastructure currently only works if the target of the >+// OSR exit is JIT code. This could be changed since there is nothing particularly >+// hard about doing an OSR exit into the interpreter, but for now this seems to make >+// sense in that if we're OSR exiting from inlined code of a DFG code block, then >+// probably it's a good sign that the thing we're exiting into is hot. Even more >+// interestingly, since the code was inlined, it may never otherwise get JIT >+// compiled since the act of inlining it may ensure that it otherwise never runs. >+void prepareCodeOriginForOSRExit(CodeOrigin codeOrigin); >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >+#endif // DFGOSRExitPreparation_h >+ >+ >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (working copy) >@@ -1777,7 +1777,7 @@ void SpeculativeJIT::checkArgumentTypes( > continue; > > VirtualRegister virtualRegister = variableAccessData->local(); >- SpeculatedType predictedType = variableAccessData->prediction(); >+ SpeculatedType predictedType = variableAccessData->argumentAwarePrediction(); > > JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister)); > >Index: Source/JavaScriptCore/dfg/DFGValueSource.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGValueSource.h (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGValueSource.h (working copy) >@@ -131,7 +131,7 @@ public: > { > if (isInt32Speculation(prediction)) > return ValueSource(Int32InJSStack); >- if (isArraySpeculation(prediction) || isCellSpeculation(prediction)) >+ if (isCellSpeculation(prediction)) > return ValueSource(CellInJSStack); > if (isBooleanSpeculation(prediction)) > return ValueSource(BooleanInJSStack); >Index: Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (revision 148047) >+++ Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (working copy) >@@ -214,7 +214,7 @@ void VariableEventStream::reconstruct( > > bool found = false; > >- if (node && node->op() == UInt32ToNumber) { >+ if (node && needsOSRBackwardRewiring(node->op())) { > MinifiedID id = node->child1(); > if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, graph.at(id))) > continue; >@@ -257,6 +257,7 @@ void VariableEventStream::reconstruct( > doubleAsInt32ID = id; > break; > default: >+ ASSERT(!needsOSRForwardRewiring(node->op())); > break; > } > } >Index: Source/JavaScriptCore/ftl/FTLAbbreviations.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLAbbreviations.h (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLAbbreviations.h (working copy) >@@ -84,6 +84,11 @@ static inline LType functionType(LType r > { > return LLVMFunctionType(returnType, paramTypes, paramCount, variadicity == Variadic); > } >+template<typename VectorType> >+inline LType functionType(LType returnType, const VectorType& vector, Variadicity variadicity) >+{ >+ return functionType(returnType, vector.begin(), vector.size(), variadicity); >+} > static inline LType functionType(LType returnType, Variadicity variadicity = NotVariadic) > { > return functionType(returnType, 0, 0, variadicity); >@@ -98,6 +103,8 @@ static inline LType functionType(LType r > return functionType(returnType, paramTypes, 2, variadicity); > } > >+static inline LType typeOf(LValue value) { return LLVMTypeOf(value); } >+ > static inline unsigned mdKindID(const char* string) { return LLVMGetMDKindID(string, strlen(string)); } > static inline LValue mdString(const char* string, unsigned length) { return LLVMMDString(string, length); } > static inline LValue mdString(const char* string) { return mdString(string, strlen(string)); } >@@ -155,6 +162,11 @@ static inline LValue buildCall(LBuilder > { > return LLVMBuildCall(builder, function, args, numArgs, ""); > } >+template<typename VectorType> >+inline LValue buildCall(LBuilder builder, LValue function, const VectorType& vector) >+{ >+ return buildCall(builder, function, vector.begin(), vector.size()); >+} > static inline LValue buildCall(LBuilder builder, LValue function) > { > return buildCall(builder, function, 0, 0); >@@ -168,6 +180,8 @@ static inline LValue buildCall(LBuilder > LValue args[] = { arg1, arg2 }; > return buildCall(builder, function, args, 2); > } >+enum TailCallMode { IsNotTailCall, IsTailCall }; >+static inline void setTailCall(LValue call, TailCallMode mode) { LLVMSetTailCall(call, mode == IsTailCall); } > static inline LValue buildExtractValue(LBuilder builder, LValue aggVal, unsigned index) { return LLVMBuildExtractValue(builder, aggVal, index, ""); } > static inline LValue buildSelect(LBuilder builder, LValue condition, LValue taken, LValue notTaken) { return LLVMBuildSelect(builder, condition, taken, notTaken, ""); } > static inline LValue buildBr(LBuilder builder, LBasicBlock destination) { return LLVMBuildBr(builder, destination); } >Index: Source/JavaScriptCore/ftl/FTLCArgumentGetter.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLCArgumentGetter.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLCArgumentGetter.h (working copy) >@@ -0,0 +1,130 @@ >+/* >+ * 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 FTLCArgumentGetter_h >+#define FTLCArgumentGetter_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "MacroAssembler.h" >+ >+namespace JSC { namespace FTL { >+ >+// This currently only understands how to get arguments on X86-64 cdecl. >+ >+template<typename RegisterKind> >+bool isArgumentRegister(RegisterKind::RegisterType reg) >+{ >+ for (unsigned i = 0; i < RegisterKind::numberOfArgumentRegisters; ++i) { >+ if (RegisterKind::toArgumentRegister(i) == reg) >+ return true; >+ } >+ return false; >+} >+ >+class CArgumentGetter { >+public: >+ // Peek offset is the number of things on the stack below the first argument. >+ // It will be 1 if you haven't pushed or popped after the call; i.e. the only >+ // thing is the return address. >+ CArgumentGetter(MacroAssembler& jit, int peekOffset = 1) >+ : m_jit(jit) >+ , m_peekOffset(peekOffset) >+ , m_gprArgumentIndex(0) >+ , m_fprArgumentIndex(0) >+ , m_stackArgumentIndex(0) >+ { >+ } >+ >+ void loadNext8(GPRReg destination) >+ { >+ ASSERT(!isArgumentRegister<GPRInfo>(destination)); >+ if (m_gprArgumentIndex < GPRInfo::numberOfArgumentRegisters) { >+ m_jit.move(GPRInfo::toArgumentRegister(m_gprArgumentIndex++), destination); >+ return; >+ } >+ >+ m_jit.load8(nextAddress(), destination); >+ } >+ >+ void loadNext32(GPRReg destination) >+ { >+ ASSERT(!isArgumentRegister<GPRInfo>(destination)); >+ if (m_gprArgumentIndex < GPRInfo::numberOfArgumentRegisters) { >+ m_jit.move(GPRInfo::toArgumentRegister(m_gprArgumentIndex++), destination); >+ return; >+ } >+ >+ m_jit.load32(nextAddress(), destination); >+ } >+ >+ void loadNext64(GPRReg destination) >+ { >+ ASSERT(!isArgumentRegister<GPRInfo>(destination)); >+ if (m_gprArgumentIndex < GPRInfo::numberOfArgumentRegisters) { >+ m_jit.move(GPRInfo::toArgumentRegister(m_gprArgumentIndex++), destination); >+ return; >+ } >+ >+ m_jit.load64(nextAddress(), destination); >+ } >+ >+ void loadNextDouble(FPRReg destination) >+ { >+ ASSERT( >+ !isArgumentRegister<FPRInfo>(destination) >+ destination == FPRInfo::argumentFPR0); >+ >+ if (m_fprArgumentIndex < FPRInfo::numberOfArgumentRegisters) { >+ m_jit.moveDouble(FPRInfo::toArgumentRegister(m_fprArgumentIndex++), destination); >+ return; >+ } >+ >+ m_jit.loadDouble(nextAddress(), destination); >+ } >+ >+private: >+ MacroAssembler::Address nextAddress() >+ { >+ return MacroAssembler::Address( >+ MacroAssembler::stackPointerRegister, >+ (m_peekOffset + m_stackArgumentIndex++) * sizeof(void*)); >+ } >+ >+ MacroAssembler& m_jit; >+ unsigned m_peekOffset; >+ unsigned m_gprArgumentIndex; >+ unsigned m_fprArgumentIndex; >+ unsigned m_stackArgumentIndex; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLCArgumentGetter_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitArgument.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitArgument.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitArgument.cpp (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * 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 "FTLExitArgument.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+void ExitArgument::dump(PrintStream& out) const >+{ >+ out.print("arg", argument(), " as ", format()); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitArgument.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitArgument.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitArgument.h (working copy) >@@ -0,0 +1,93 @@ >+/* >+ * 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 FTLExitArgument_h >+#define FTLExitArgument_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLValueFormat.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace FTL { >+ >+struct ExitArgumentRepresentation { >+ ValueFormat format; >+ unsigned argument; >+}; >+ >+class ExitArgument { >+public: >+ ExitArgument() >+ { >+ m_representation.format = InvalidValueFormat; >+ } >+ >+ ExitArgument(ValueFormat format, unsigned argument) >+ { >+ m_representation.format = format; >+ m_representation.argument = argument; >+ } >+ >+ explicit ExitArgument(ExitArgumentRepresentation representation) >+ { >+ m_representation = representation; >+ } >+ >+ bool operator!() const { return m_representation.format == InvalidValueFormat; } >+ >+ ValueFormat format() const >+ { >+ ASSERT(*this); >+ return m_representation.format; >+ } >+ >+ unsigned argument() const >+ { >+ ASSERT(*this); >+ return m_representation.argument; >+ } >+ >+ ExitArgument withFormat(ValueFormat format) >+ { >+ return ExitArgument(format, argument()); >+ } >+ >+ ExitArgumentRepresentation representation() const { return m_representation; } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ ExitArgumentRepresentation m_representation; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitArgument_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.cpp (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * 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 "FTLExitArgumentForOperand.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+void ExitArgumentForOperand::dump(PrintStream& out) const >+{ >+ out.print(m_exitArgument, " for r", operand); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.h (working copy) >@@ -0,0 +1,72 @@ >+/* >+ * 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 FTLExitArgumentForOperand_h >+#define FTLExitArgumentForOperand_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLExitArgument.h" >+ >+namespace JSC { namespace FTL { >+ >+class ExitArgumentForOperand { >+public: >+ ExitArgumentForOperand() >+ : m_operand(-1) >+ { >+ } >+ >+ ExitArgumentForOperand(ExitArgument exitArgument, int operand) >+ : m_exitArgument(exitArgument) >+ , m_operand(operand) >+ { >+ } >+ >+ bool operator!() const { return !m_exitArgument; } >+ >+ const ExitArgument& exitArgument() const { return m_exitArgument; } >+ int operand() const { return m_operand; } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ ExitArgument m_exitArgument; >+ int m_operand; >+}; >+ >+inline bool lesserArgumentIndex(ExitArgument a, ExitArgument b) >+{ >+ return a.exitArgument().argument() < b.exitArgument().argument(); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitArgumentForOperand_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitArgumentList.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitArgumentList.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitArgumentList.h (working copy) >@@ -0,0 +1,45 @@ >+/* >+ * 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 FTLExitArgumentList_h >+#define FTLExitArgumentList_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLAbbreviations.h" >+#incldue <wtf/Vector.h> >+ >+namespace JSC { namespace FTL { >+ >+typedef Vector<LValue, 16> ExitArgumentList; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitArgumentList_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp (working copy) >@@ -0,0 +1,56 @@ >+/* >+ * 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 "FTLExitThunkGenerator.h" >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLOSRExitCompilationInfo.h" >+ >+namespace JSC { namespace FTL { >+ >+using namespace JSC::DFG; >+ >+ExitThunkGenerator::ExitThunkGenerator(State& state) >+ : CCallHelpers(&state.graph.m_globalData, state.graph.m_codeBlock) >+{ >+} >+ >+ExitThunkGenerator::~ExitThunkGenerator() >+{ >+} >+ >+void ExitThunkGenerator::emitThunk(unsigned index, OSRExitCompilationInfo& info) >+{ >+ info.m_thunkLabel = label(); >+ move(TrustedImm32(index), GPRInfo::nonArgGRP0); >+ info.m_thunkJump = patchableJump(); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitThunkGenerator.h (working copy) >@@ -0,0 +1,53 @@ >+/* >+ * 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 FTLExitThunkGenerator_h >+#define FTLExitThunkGenerator_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGCCallHelpers.h" >+ >+namespace JSC { namespace FTL { >+ >+class OSRExitCompilationInfo; >+class State; >+ >+class ExitThunkGenerator : public CCallHelpers { >+public: >+ ExitThunkGenerator(State& state); >+ ~ExitThunkGenerator(); >+ >+ void emitThunk(unsigned index, OSRExitCompilationInfo&); >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitThunkGenerator_h >+ >Index: Source/JavaScriptCore/ftl/FTLExitValue.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitValue.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitValue.cpp (working copy) >@@ -0,0 +1,59 @@ >+/* >+ * 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 "FTLExitValue.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+void ExitValue::dump(PrintStream& out) const >+{ >+ switch (kind()) { >+ case InvalidExitValue: >+ out.print("Invalid"); >+ return; >+ case ExitValueDead: >+ out.print("Dead"); >+ return; >+ case ExitValueArgument: >+ out.print("Argument(", exitArgument(), ")"); >+ return; >+ case ExitValueConstant: >+ out.print("Constant(", constant(), ")"); >+ return; >+ case ExitValueInJSStack: >+ out.print("InJSStack"); >+ return; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLExitValue.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLExitValue.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLExitValue.h (working copy) >@@ -0,0 +1,160 @@ >+/* >+ * 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 FTLExitValue_h >+#define FTLExitValue_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLExitArgument.h" >+#include "JSCJSValue.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace FTL { >+ >+// This is like ValueRecovery, but respects the way that the FTL does OSR >+// exit: the live non-constant non-flushed values are passed as arguments >+// to a noreturn tail call. ExitValue is hence mostly responsible for >+// telling us the mapping between operands in bytecode and the arguments to >+// the call. >+ >+enum ExitValueKind { >+ InvalidExitValue, >+ ExitValueDead, >+ ExitValueArgument, >+ ExitValueConstant >+ ExitValueInJSStack, >+ ExitValueInJSStackAsInt32, >+ ExitValueInJSStackAsBoolean, >+ ExitValueInJSStackAsDouble >+}; >+ >+class ExitValue { >+public: >+ ExitValue() >+ : m_kind(InvalidExitValue) >+ { >+ } >+ >+ bool operator!() const { return m_kind == InvalidExitValue; } >+ >+ static ExitValue dead() >+ { >+ ExitValue result; >+ result.m_kind = ExitValueDead; >+ return result; >+ } >+ >+ static ExitValue inJSStack() >+ { >+ ExitValue result; >+ result.m_kind = ExitValueInJSStack; >+ return result; >+ } >+ >+ static ExitValue inJSStackAsInt32() >+ { >+ ExitValue result; >+ result.m_kind = ExitValueInJSStackAsInt32; >+ return result; >+ } >+ >+ static ExitValue inJSStackAsBoolean() >+ { >+ ExitValue result; >+ result.m_kind = ExitValueInJSStackAsBoolean; >+ return result; >+ } >+ >+ static ExitValue inJSStackAsDouble() >+ { >+ ExitValue result; >+ result.m_kind = ExitValueInJSStackAsDouble; >+ return result; >+ } >+ >+ static ExitValue constant(JSValue value) >+ { >+ ExitValue result; >+ result.m_kind = ExitValueConstant; >+ result.u.constant = JSValue::encode(value); >+ return result; >+ } >+ >+ static ExitValue exitArgument(const ExitArgument& argument) >+ { >+ ExitValue result; >+ result.m_kind = ExitValueArgument; >+ result.u.argument = argument.representation(); >+ return result; >+ } >+ >+ ExitValueKind kind() const { return m_kind; } >+ >+ bool isDead() const { return kind() == ExitValueDead; } >+ bool isInJSStackSomehow() const >+ { >+ switch (kind()) { >+ case ExitValueInJSStack: >+ case ExitValueInJSStackAsInt32: >+ case ExitValueInJSStackAsBoolean: >+ case ExitValueInJSStackAsDouble: >+ return true; >+ default: >+ return false; >+ } >+ } >+ bool isConstant() const { return kind() == ExitValueConstant; } >+ bool isArgument() const { return kind() == ExitValueArgument; } >+ >+ ExitArgument exitArgument() const >+ { >+ ASSERT(isArgument()); >+ return ExitArgument(u.argument); >+ } >+ >+ JSValue constant() const >+ { >+ ASSERT(isConstant()); >+ return JSValue::decode(u.constant); >+ } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ ExitValueKind m_kind; >+ union { >+ ExitArgumentRepresentation argument; >+ EncodedJSValue constant; >+ } u; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLExitValue_h >Index: Source/JavaScriptCore/ftl/FTLFormattedValue.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLFormattedValue.h (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLFormattedValue.h (working copy) >@@ -31,6 +31,7 @@ > #if ENABLE(FTL_JIT) > > #include "FTLAbbreviations.h" >+#include "FTLValueFormat.h" > > namespace JSC { namespace FTL { > >@@ -41,18 +42,6 @@ namespace JSC { namespace FTL { > // use this in situations where there is no good way to say what node the value came > // from. > >-// Note that this is awkwardly similar to DataFormat in other parts of JSC, except that >-// unlike DataFormat and like ValueRecovery, it distinguishes between UInt32 and Int32. >- >-enum ValueFormat { >- InvalidValueFormat, >- ValueFormatInt32, >- ValueFormatUInt32, >- ValueFormatBoolean, >- ValueFormatJSValue, >- ValueFormatDouble >-}; >- > class FormattedValue { > public: > FormattedValue() >@@ -81,6 +70,13 @@ private: > LValue m_value; > }; > >+static inline FormattedValue noValue() { return FormattedValue(); } >+static inline FormattedValue int32Value(LValue value) { return FormattedValue(ValueFormatInt32, value); } >+static inline FormattedValue uInt32Value(LValue value) { return FormattedValue(ValueFormatUInt32, value); } >+static inline FormattedValue booleanValue(LValue value) { return FormattedValue(ValueFormatBoolean, value); } >+static inline FormattedValue jsValueValue(LValue value) { return FormattedValue(ValueFormatJSValue, value); } >+static inline FormattedValue doubleValue(LValue value) { return FormattedValue(ValueFormatDouble, value); } >+ > } } // namespace JSC::FTL > > #endif // ENABLE(FTL_JIT) >Index: Source/JavaScriptCore/ftl/FTLJITCode.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLJITCode.cpp (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLJITCode.cpp (working copy) >@@ -42,6 +42,11 @@ JITCode::~JITCode() > LLVMDisposeExecutionEngine(m_engine); > } > >+void JITCode::initializeExitThunks(CodeRef exitThunks) >+{ >+ m_exitThunks = exitThunks; >+} >+ > void JITCode::initializeCode(LLVMExecutionEngineRef engine, CodeRef entrypoint) > { > m_engine = engine; >@@ -97,6 +102,11 @@ bool JITCode::contains(void*) > return false; > } > >+CodePtr JITCode::exitThunks() >+{ >+ return m_exitThunks.code(); >+} >+ > JITCode* JITCode::ftl() > { > return this; >Index: Source/JavaScriptCore/ftl/FTLJITCode.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLJITCode.h (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLJITCode.h (working copy) >@@ -48,12 +48,16 @@ public: > size_t size(); > bool contains(void*); > >+ void initializeExitThunks(CodeRef); > void initializeCode(LLVMExecutionEngineRef, CodeRef entrypoint); > >+ CodePtr exitThunks(); >+ > JITCode* ftl(); > DFG::CommonData* dfgCommon(); > > DFG::CommonData common; >+ SegmentedVector<OSRExit, 8> osrExit; > > private: > // FIXME: LLVM should use our own JIT memory allocator, and we shouldn't have to >@@ -61,6 +65,7 @@ private: > // https://bugs.webkit.org/show_bug.cgi?id=113619 > LLVMExecutionEngineRef m_engine; > CodeRef m_entrypoint; >+ CodeRef m_exitThunks; > }; > > } } // namespace JSC::FTL >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -30,8 +30,10 @@ > > #include "DFGAbstractState.h" > #include "FTLAbstractHeapRepository.h" >+#include "FTLExitThunkGenerator.h" > #include "FTLFormattedValue.h" > #include "FTLOutput.h" >+#include "FTLThunks.h" > #include "Operations.h" > > namespace JSC { namespace FTL { >@@ -41,7 +43,7 @@ using namespace DFG; > // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating > // significantly less dead code. > #define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \ >- LValue _ftc_lowValue = (lowValue); \ >+ FormattedValue _ftc_lowValue = (lowValue); \ > Edge _ftc_highValue = (highValue); \ > SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough); \ > if (!m_state.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \ >@@ -57,6 +59,8 @@ public: > , m_localsBoolean(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) > , m_locals32(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) > , m_locals64(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) >+ , m_valueSources(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) >+ , m_exitThunkGenerator(state) > , m_state(state.graph) > { > } >@@ -80,14 +84,14 @@ public: > m_locals64[index] = buildAlloca(m_out.m_builder, m_out.int64); > } > >+ m_initialization = appendBasicBlock(m_ftlState.function); >+ m_out.jump(m_initialization); >+ m_out.appendTo(m_initialization); >+ > m_callFrame = m_out.param(0); > m_tagTypeNumber = m_out.constInt64(TagTypeNumber); > m_tagMask = m_out.constInt64(TagMask); > >- m_abortFunction = constIntToPtr( >- m_out.constIntPtr(abort), >- pointerType(functionType(m_out.voidType))); >- > for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { > m_highBlock = m_graph.m_blocks[blockIndex].get(); > if (!m_highBlock) >@@ -98,14 +102,17 @@ public: > > closeOverFlushedLocalOps(); > >- m_out.appendTo(m_prologue, m_blocks.get(m_graph.m_blocks[0].get())); >+ m_out.appendTo(m_initialization, m_blocks.get(m_graph.m_blocks[0].get())); > > transferAndCheckArguments(); > >- m_out.jump(m_blocks.get(m_graph.m_blocks[0].get())); >+ // Leave the initialization block hanging, since we will add to it later. > > for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) > compileBlock(blockIndex); >+ >+ // And now complete the initialization block. >+ linkOSRExitsAndCompleteInitializationBlock(); > > if (verboseCompilationEnabled()) > m_ftlState.dumpState("after lowering"); >@@ -151,8 +158,9 @@ private: > > void transferAndCheckArguments() > { >- // FIXME: Set up the OSR story here. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ // While checking arguments, everything is in the stack. >+ for (unsigned i = size(); i--;) >+ m_valueSources[i] = ValueSource(ValueInJSStack); > > for (int i = 0; i < m_graph.m_codeBlock->numParameters(); ++i) { > Node* node = m_graph.m_arguments[i]; >@@ -170,21 +178,21 @@ private: > if (variable->shouldUnboxIfPossible()) { > RELEASE_ASSERT(!variable->shouldUseDoubleFormat()); > >- SpeculatedType prediction = variable->prediction(); >+ SpeculatedType prediction = variable->argumentAwarePrediction(); > > if (isInt32Speculation(prediction)) { >- speculateBackward(BadType, jsValue, node, isNotInt32(jsValue)); >+ speculateBackward(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue)); > m_out.set(unboxInt32(jsValue), m_locals32.operand(variable->local())); > continue; > } > > if (isCellSpeculation(prediction)) { >- speculateBackward(BadType, jsValue, node, isNotCell(jsValue)); >+ speculateBackward(BadType, jsValueValue(jsValue), node, isNotCell(jsValue)); > m_out.set(jsValue, m_locals64.operand(variable->local())); > continue; > } > if (isBooleanSpeculation(prediction)) { >- speculateBackward(BadType, jsValue, node, isNotBoolean(jsValue)); >+ speculateBackward(BadType, jsValueValue(jsValue), node, isNotBoolean(jsValue)); > m_out.set(unboxBoolean(jsValue), m_localsBoolean.operand(variable->local())); > continue; > } >@@ -216,18 +224,18 @@ private: > // make IR dumps easier to read. > m_out.appendTo(lowBlock, m_nextLowBlock); > >- // FIXME: We should track the OSR situation here. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ initializeOSRExitStateForBlock(); > > m_int32Values.clear(); > m_jsValueValues.clear(); > m_booleanValues.clear(); > m_storageValues.clear(); >+ m_timeToLive.clear(); > > m_state.reset(); > m_state.beginBasicBlock(m_highBlock); > >- for (unsigned nodeIndex = 0; nodeIndex < m_highBlock->size(); ++nodeIndex) >+ for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) > compileNode(nodeIndex); > } > >@@ -240,9 +248,6 @@ private: > > bool shouldExecuteEffects = m_state.startExecuting(m_node); > >- if (!m_node->shouldGenerate()) >- return; // FIXME: Implement OSR magic here. https://bugs.webkit.org/show_bug.cgi?id=113623 >- > m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation; > > switch (m_node->op()) { >@@ -258,6 +263,12 @@ private: > case SetLocal: > compileSetLocal(); > break; >+ case MovHint: >+ compileMovHint(); >+ break; >+ case ZombieHint: >+ compileZombieHint(); >+ break; > case MovHintAndCheck: > compileMovHintAndCheck(); > break; >@@ -352,6 +363,11 @@ private: > break; > } > >+ DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, use); >+ >+ if (m_node->hasResult()) >+ m_timeToLive.add(m_node, m_node->adjustedRefCount()); >+ > if (shouldExecuteEffects) > m_state.executeEffects(nodeIndex); > } >@@ -368,8 +384,12 @@ private: > > void compileGetLocal() > { >+ // GetLocal is one of the few nodes that may be left behind, with !shouldGenerate(). >+ if (!m_node->shouldGenerate()) >+ return; >+ > VariableAccessData* variable = m_node->variableAccessData(); >- SpeculatedType prediction = variable->prediction(); >+ SpeculatedType prediction = variable->argumentAwarePrediction(); > AbstractValue& value = m_state.variables().operand(variable->local()); > > if (prediction == SpecNone) { >@@ -420,13 +440,12 @@ private: > > void compileSetLocal() > { >+ observeMovHint(m_node); >+ > VariableAccessData* variable = m_node->variableAccessData(); >- SpeculatedType prediction = variable->prediction(); >+ SpeculatedType prediction = variable->argumentAwarePrediction(); > bool needsFlushing = m_flushedLocalOps.contains(m_node); > >- // FIXME: Handle the MovHint for OSR. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >- > if (variable->shouldUnboxIfPossible()) { > if (variable->shouldUseDoubleFormat()) { > // FIXME: implement doubles in FTL. >@@ -438,21 +457,27 @@ private: > if (isInt32Speculation(prediction)) { > LValue value = lowInt32(m_node->child1()); > m_out.set(value, m_locals32.operand(variable->local())); >- if (needsFlushing) >+ if (needsFlushing) { > m_out.store32(value, payloadFor(variable->local())); >+ m_valueSources[variable->local()] = ValueSource(Int32InJSStack); >+ } > return; > } > if (isCellSpeculation(prediction)) { > LValue value = lowCell(m_node->child1()); > m_out.set(value, m_locals64.operand(variable->local())); >- if (needsFlushing) >+ if (needsFlushing) { > m_out.store64(value, addressFor(variable->local())); >+ m_valueSources[variable->local()] = ValueSource(CellInJSStack); >+ } > return; > } > if (isBooleanSpeculation(prediction)) { > m_out.set(lowBoolean(m_node->child1()), m_localsBoolean.operand(variable->local())); >- if (needsFlushing) >+ if (needsFlushing) { > m_out.store64(lowJSValue(m_node->child1()), addressFor(variable->local())); >+ m_valueSources[variable->local()] = ValueSource(ValueInJSStack); >+ } > return; > } > } >@@ -460,18 +485,32 @@ private: > LValue value = lowJSValue(m_node->child1()); > if (variable->isCaptured()) { > m_out.store64(value, addressFor(variable->local())); >+ m_valueSources[variable->local()] = ValueSource(ValueInJSStack); > return; > } > > m_out.set(value, m_locals64.operand(variable->local())); >- if (needsFlushing) >+ if (needsFlushing) { > m_out.store64(value, addressFor(variable->local())); >+ m_valueSources[variable->local()] = ValueSource(ValueInJSStack); >+ } >+ } >+ >+ void compileMovHint() >+ { >+ observeMovHint(m_node); >+ } >+ >+ void compileZombieHint() >+ { >+ VariableAccessData* data = m_node->variableAccessData(); >+ m_lastSetOperand = data->local(); >+ m_valueSources[data->local()] = ValueSource(SourceIsDead); > } > > void compileMovHintAndCheck() > { >- // FIXME: Handle the MovHint for OSR. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ observeMovHint(m_node); > speculate(m_node->child1()); > } > >@@ -500,7 +539,7 @@ private: > } > > LValue result = m_out.addWithOverflow32(left, right); >- speculate(Overflow, 0, 0, m_out.extractValue(result, 1)); >+ speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); > m_int32Values.add(m_node, m_out.extractValue(result, 0)); > break; > } >@@ -524,7 +563,7 @@ private: > } > > LValue result = m_out.subWithOverflow32(left, right); >- speculate(Overflow, 0, 0, m_out.extractValue(result, 1)); >+ speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); > m_int32Values.add(m_node, m_out.extractValue(result, 0)); > break; > } >@@ -547,7 +586,7 @@ private: > result = m_out.mul(left, right); > else { > LValue overflowResult = m_out.mulWithOverflow32(left, right); >- speculate(Overflow, 0, 0, m_out.extractValue(overflowResult, 1)); >+ speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); > result = m_out.extractValue(overflowResult, 0); > } > >@@ -556,8 +595,8 @@ private: > LBasicBlock continuation = m_out.newBlock(); > > LBasicBlock lastNext = m_out.appendTo(slowCase, continuation); >- speculate(NegativeZero, 0, 0, m_out.lessThan(left, m_out.int32Zero)); >- speculate(NegativeZero, 0, 0, m_out.lessThan(right, m_out.int32Zero)); >+ speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int32Zero)); >+ speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int32Zero)); > m_out.jump(continuation); > m_out.appendTo(continuation, lastNext); > } >@@ -585,7 +624,7 @@ private: > // We don't have a negate-with-overflow intrinsic. Hopefully this > // does the trick, though. > LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value); >- speculate(Overflow, 0, 0, m_out.extractValue(overflowResult, 1)); >+ speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); > result = m_out.extractValue(overflowResult, 0); > } > >@@ -656,7 +695,7 @@ private: > > LValue value = lowInt32(m_node->child1()); > speculateForward( >- Overflow, 0, 0, m_out.lessThan(value, m_out.int32Zero), >+ Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero), > FormattedValue(ValueFormatUInt32, value)); > m_int32Values.add(m_node, value); > } >@@ -675,7 +714,7 @@ private: > > if (m_node->structureSet().size() == 1) { > speculate( >- exitKind, cell, 0, >+ exitKind, jsValueValue(cell), 0, > m_out.notEqual(structure, weakPointer(m_node->structureSet()[0]))); > return; > } >@@ -692,7 +731,7 @@ private: > } > > speculate( >- exitKind, cell, 0, >+ exitKind, jsValueValue(cell), 0, > m_out.notEqual(structure, weakPointer(m_node->structureSet().last()))); > > m_out.appendTo(continuation, lastNext); >@@ -755,7 +794,7 @@ private: > case Array::Contiguous: { > if (m_node->arrayMode().isInBounds()) { > speculate( >- OutOfBounds, 0, 0, >+ OutOfBounds, noValue(), 0, > m_out.aboveOrEqual( > index, m_out.load32(storage, m_heaps.Butterfly_publicLength))); > >@@ -764,7 +803,7 @@ private: > m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties, > storage, m_out.zeroExt(index, m_out.intPtr), > m_state.forNode(m_node->child2()).m_value)); >- speculate(LoadFromHole, 0, 0, m_out.isZero64(result)); >+ speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result)); > m_jsValueValues.add(m_node, result); > break; > } >@@ -865,32 +904,26 @@ private: > } > } > >- void speculateBackward(ExitKind, LValue, Node*, LValue failCondition) >+ void speculateBackward( >+ ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) > { >- LBasicBlock failCase = m_out.newBlock(); >- LBasicBlock continuation = m_out.newBlock(); >- >- m_out.branch(failCondition, failCase, continuation); >- LBasicBlock lastNext = m_out.appendTo(failCase, continuation); >- // FIXME: Implement OSR exit. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >- m_out.call(m_abortFunction); >- m_out.unreachable(); >- m_out.appendTo(continuation, lastNext); >+ appendOSRExit( >+ kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue()); > } > >- void speculateForward(ExitKind kind, LValue lowValue, Node* highValue, LValue failCondition, const FormattedValue&) >+ void speculateForward( >+ ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition, >+ const FormattedValue& recovery) > { >- speculateBackward(kind, lowValue, highValue, failCondition); >- // FIXME: Implement rewiring of OSR exit to forward. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ appendOSRExit( >+ kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery); > } > >- void speculate(ExitKind kind, LValue lowValue, Node* highValue, LValue failCondition) >+ void speculate( >+ ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) > { >- speculateBackward(kind, lowValue, highValue, failCondition); >- // FIXME: Implement rewiring the OSR exit to forward, if m_direction == ForwardDirection. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ appendOSRExit( >+ kind, lowValue, highValue, failCondition, m_direction, FormattedValue()); > } > > void terminate(ExitKind kind) >@@ -898,27 +931,42 @@ private: > speculate(kind, 0, 0, m_out.booleanTrue); > } > >- void backwardTypeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) >+ void backwardTypeCheck( >+ FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, >+ LValue failCondition) > { >- if (!m_state.needsTypeCheck(highValue, typesPassedThrough)) >- return; >- ASSERT(mayHaveTypeCheck(highValue.useKind())); >- speculateBackward(BadType, lowValue, highValue.node(), failCondition); >- m_state.forNode(highValue).filter(typesPassedThrough); >+ appendTypeCheck( >+ lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation, >+ FormattedValue()); > } > >- void forwardTypeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) >+ void forwardTypeCheck( >+ FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, >+ LValue failCondition) > { >- backwardTypeCheck(lowValue, highValue, typesPassedThrough, failCondition); >- // FIXME: Implement rewiring of OSR exit to forward. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ appendTypeCheck( >+ lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation, >+ FormattedValue()); > } > >- void typeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) >+ void typeCheck( >+ FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, >+ LValue failCondition) > { >- backwardTypeCheck(lowValue, highValue, typesPassedThrough, failCondition); >- // FIXME: Implement rewiring of OSR exit to forward, if m_direction == ForwardDirection. >- // https://bugs.webkit.org/show_bug.cgi?id=113623 >+ appendTypeCheck( >+ lowValue, highValue, typesPassedThrough, failCondition, m_direction, >+ FormattedValue()); >+ } >+ >+ void appendTypeCheck( >+ LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, >+ LValue failCondition, SpeculationDirection direction, FormattedValue recovery) >+ { >+ if (!m_state.needsTypeCheck(highValue, typesPassedThrough)) >+ return; >+ ASSERT(mayHaveTypeCheck(highValue.useKind())); >+ appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery); >+ m_state.forNode(highValue).filter(typesPassedThrough); > } > > LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) >@@ -929,7 +977,8 @@ private: > return result; > > if (LValue boxedResult = m_jsValueValues.get(edge.node())) { >- FTL_TYPE_CHECK(boxedResult, edge, SpecInt32, isNotInt32(boxedResult)); >+ FTL_TYPE_CHECK( >+ jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult)); > LValue result = unboxInt32(boxedResult); > m_int32Values.add(edge.node(), result); > return result; >@@ -945,7 +994,8 @@ private: > ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind())); > > if (LValue uncheckedResult = m_jsValueValues.get(edge.node())) { >- FTL_TYPE_CHECK(uncheckedResult, edge, SpecCell, isNotCell(uncheckedResult)); >+ FTL_TYPE_CHECK( >+ jsValueValue(uncheckedResult), edge, SpecCell, isNotCell(uncheckedResult)); > return uncheckedResult; > } > >@@ -971,7 +1021,8 @@ private: > return result; > > if (LValue unboxedResult = m_jsValueValues.get(edge.node())) { >- FTL_TYPE_CHECK(unboxedResult, edge, SpecBoolean, isNotBoolean(unboxedResult)); >+ FTL_TYPE_CHECK( >+ jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult)); > LValue result = unboxBoolean(unboxedResult); > m_booleanValues.add(edge.node(), result); > return result; >@@ -1094,7 +1145,7 @@ private: > void speculateObject(Edge edge, LValue cell) > { > FTL_TYPE_CHECK( >- cell, edge, SpecObject, >+ jsValueValue(cell), edge, SpecObject, > m_out.equal( > m_out.loadPtr(cell, m_heaps.JSCell_structure), > m_out.constIntPtr(globalData().stringStructure.get()))); >@@ -1105,6 +1156,357 @@ private: > speculateObject(edge, lowCell(edge)); > } > >+ bool isLive(Node* node) >+ { >+ HashMap<Node*, unsigned>::iterator iter = m_timeToLive->find(edge.node()); >+ ASSERT(iter != m_timeToLive->end()); >+ return !!iter->value; >+ } >+ >+ void use(Edge edge) >+ { >+ HashMap<Node*, unsigned>::iterator iter = m_timeToLive->find(edge.node()); >+ ASSERT(iter != m_timeToLive->end()); >+ ASSERT(iter->value); >+ iter->value--; >+ } >+ >+ // Wrapper used only for DFG_NODE_DO_TO_CHILDREN >+ void use(Node*, Edge edge) >+ { >+ use(edge); >+ } >+ >+ void initializeOSRExitStateForBlock() >+ { >+ for (unsigned i = m_valueSources.size(); i--;) { >+ Node* node = m_highBlock->variablesAtHead[i]; >+ if (!node) { >+ m_valueSources[i] = ValueSource(SourceIsDead); >+ continue; >+ } >+ >+ VariableAccessData* variable = node->variableAccessData(); >+ SpeculatedType prediction = variable->argumentAwarePrediction(); >+ >+ if (variable->isArgumentsAlias()) { >+ m_valueSources[i] = ValueSource(ArgumentsSource); >+ continue; >+ } >+ >+ if (!node->shouldGenerate()) { >+ m_valueSources[i] = ValueSource(SourceIsDead); >+ continue; >+ } >+ >+ if (m_flushedLocalOps.contains(node)) { >+ // This value will have been flushed to the JSStack in some form or >+ // another. >+ >+ if (variable->shouldUnboxIfPossible()) { >+ if (variable->shouldUseDoubleFormat()) { >+ m_valueSources[i] = ValueSource(DoubleInJSStack); >+ continue; >+ } >+ >+ if (isInt32Speculation(prediction)) { >+ m_valueSources[i] = ValueSource(Int32InJSStack); >+ continue; >+ } >+ } >+ >+ m_valueSources[i] = ValueSource(ValueInJSStack); >+ continue; >+ } >+ >+ if (variable->shouldUnboxIfPossible()) { >+ if (variable->shouldUseDoubleFormat()) { >+ m_valueSources[i] = ValueSource(ValueInLocals); >+ continue; >+ } >+ >+ if (isInt32Speculation(prediction)) { >+ m_valueSources[i] = ValueSource(Int32InLocals); >+ continue; >+ } >+ >+ if (isBooleanSpeculation(prediction)) { >+ m_valueSources[i] = ValueSource(BooleanInLocals); >+ continue; >+ } >+ } >+ >+ m_valueSources[i] = ValueSource(ValueInLocals); >+ } >+ } >+ >+ void appendOSRExit( >+ ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition, >+ SpeculationDirection direction, FormattedValue recovery) >+ { >+ m_ftlState.jitCode->osrExit.append( >+ OSRExit( >+ kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue), >+ m_node->codeOrigin, m_lastSetOperand, m_valueSources.numberOfArguments(), >+ m_valueSources.numberOfLocals())); >+ m_ftlState.osrExit.append(OSRExitCompilationInfo()); >+ >+ OSRExit& exit = m_ftlState.jitCode->osrExit.last(); >+ OSRExitCompilationInfo& info = m_ftlState.osrExit.last(); >+ >+ LBasicBlock failCase = m_out.newBlock(); >+ LBasicBlock continuation = m_out.newBlock(); >+ >+ m_out.branch(failCondition, failCase, continuation); >+ >+ m_out.appendTo(m_prologue); >+ info.m_thunkAddress = buildAlloca(m_out.m_builder, m_out.intPtr); >+ >+ LBasicBlock lastNext = m_out.appendTo(failCase, continuation); >+ >+ ExitArgumentList arguments; >+ arguments.append(m_callFrame); >+ if (lowValue) >+ arguments.append(arguments.value()); >+ >+ for (unsigned i = 0; i < exit.m_values.size(); ++i) { >+ ValueSource source = m_valueSources[i]; >+ >+ switch (source.kind()) { >+ case ValueInJSStack: >+ exit.m_values[i] = ExitValue::inJSStack(); >+ break; >+ case Int32InJSStack: >+ exit.m_values[i] = ExitValue::inJSStackAsIn32(); >+ break; >+ case DoubleInJSStack: >+ exit.m_values[i] = ExitValue::inJSStackAsDouble(); >+ break; >+ case ValueInLocals: >+ addExitArgument( >+ exit, arguments, i, ValueFormatJSValue, m_out.get(m_locals64[i])); >+ break; >+ case Int32InLocals: >+ addExitArgument( >+ exit, arguments, i, ValueFormatInt32, m_out.get(m_locals32[i])); >+ break; >+ case BooleanInLocals: >+ addExitArgument( >+ exit, arguments, i, ValueFormatBoolean, m_out.get(m_localsBoolean[i])); >+ break; >+ case DoubleInLocals: >+ // FIXME: implement doubles in FTL. >+ // https://bugs.webkit.org/show_bug.cgi?id=113624 >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ case ArgumentsSource: >+ // FIXME: implement PhantomArguments. >+ // https://bugs.webkit.org/show_bug.cgi?id=113986 >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ case SourceIsDead: >+ exit.m_values[i] = ExitValue::dead(); >+ break; >+ case HaveNode: >+ addExitArgumentForNode(exit, arguments, i, source.node()); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ } >+ >+ if (direction = ForwardSpeculation) >+ exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments); >+ >+ // So, the really lame thing here is that we have to build an LLVM function type. >+ // Booo. >+ Vector<LType, 16> argumentTypes; >+ for (unsigned i = 0; i < arguments.size(); ++i) >+ argumentTypes.append(typeOf(arguments[i])); >+ >+ m_out.call( >+ m_out.intToPtr( >+ m_out.get(info.m_thunkAddress), >+ pointerType(functionType(m_out.voidType, argumentTypes))), >+ arguments); >+ >+ m_out.appendTo(continuation, lastNext); >+ } >+ >+ void addExitArgumentForNode( >+ OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node) >+ { >+ ASSERT(node->shouldGenerate()); >+ ASSERT(node->hasResult()); >+ >+ if (tryToSetConstantExitArument(exit, arguments, index, node)) >+ return; >+ >+ if (!isLive(node)) { >+ bool found = false; >+ >+ if (needsOSRBackwardRewiring(node->op())) { >+ node = node->child1().node(); >+ if (tryToSetConstantExitArgument(exit, arguments, index, node)) >+ return; >+ if (isLive(node)) >+ found = true; >+ } >+ >+ if (!found) { >+ Node* int32ToDouble = 0; >+ Node* valueToInt32 = 0; >+ Node* uint32ToNumber = 0; >+ Node* doubleAsInt32 = 0; >+ >+ HashMap<Node*, unsigned>::iterator iter = m_timeToLive.begin(); >+ HashMap<Node*, unsigned>::iterator end = m_timeToLive.end(); >+ for (; iter != end; ++iter) { >+ if (!iter->value) >+ continue; >+ Node* candidate = iter->key; >+ if (!candidate->child1()) >+ continue; >+ if (candidate->child1() != node) >+ continue; >+ switch (candidate->op()) { >+ case Int32ToDouble: >+ case ForwardInt32ToDouble: >+ int32ToDouble = candidate; >+ break; >+ case ValueToInt32: >+ valueToInt32 = candidate; >+ break; >+ case UInt32ToNumber: >+ uint32ToNumber = candidate; >+ break; >+ case DoubleAsInt32: >+ uint32ToNumber = candidate; >+ break; >+ default: >+ ASSERT(!needsOSRForwardRewiring(candidate->op())); >+ break; >+ } >+ } >+ >+ if (doubleAsInt32) >+ node = doubleAsIn32; >+ else if (int32ToDouble) >+ node = int32ToDouble; >+ else if (valueToInt32) >+ node = valueToInt32; >+ else if (uint32ToNumber) >+ node = uint32ToNumber; >+ >+ if (isLive(node)) >+ found = true; >+ } >+ >+ if (!found) { >+ exit.m_values[index] = ExitValue::dead(); >+ return; >+ } >+ } >+ >+ ASSERT(isLive(node)); >+ >+ if (LValue result = m_int32Values.get(node)) { >+ addExitArgument(exit, arguments, index, ValueFormatInt32, result); >+ return; >+ } >+ >+ if (LValue result = m_booleanValues.get(node)) { >+ addExitArgument(exit, arguments, index, ValueFormatBoolean, result); >+ return; >+ } >+ >+ if (LValue result = m_jsValueValues.get(node)) { >+ addExitArgument(exit, arguments, index, ValueFormatJSValue, result); >+ return; >+ } >+ >+ // FIXME: Implement doubles in the FTL. >+ // https://bugs.webkit.org/show_bug.cgi?id=113624 >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ void tryToSetConstantExitArgument( >+ OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node) >+ { >+ if (!node) >+ return false; >+ >+ switch (node->op()) { >+ case JSConstant: >+ case WeakJSConstant: >+ exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node)); >+ return true; >+ case PhantomArguments: >+ // FIXME: implement PhantomArguments. >+ // https://bugs.webkit.org/show_bug.cgi?id=113986 >+ RELEASE_ASSERT_NOT_REACHED(); >+ return true; >+ default: >+ return false; >+ } >+ } >+ >+ void addExitArgument( >+ OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format, >+ LValue value) >+ { >+ exit.m_values[i] = ExitValue::exitArgument(ExitArgument(format, arguments.size())); >+ arguments.append(value); >+ } >+ >+ void linkOSRExitsAndCompleteInitializationBlock() >+ { >+ MacroAssemblerCodeRef osrExitThunk = >+ globalData().getCTIStub(osrExitGenerationThunkGenerator); >+ CodeLocationLabel target = CodeLocationLabel(osrExitThunk.code()); >+ >+ m_out.appendTo(m_initialization); >+ >+ LinkBuffer linkBuffer( >+ &globalData(), &m_exitThunkGenerator, m_ftlState.graph.m_codeBlock, >+ JITCompilationMustSucceed); >+ >+ ASSERT(m_ftlState.osrExit.size() == m_ftlState.jitCode->osrExit.size()); >+ >+ for (unsigned i = 0; i < m_ftlState.osrExit.size(); ++i) { >+ OSRExitCompilationInfo& info = m_ftlState.osrExit[i]; >+ OSRExit& exit = m_ftlState.jitCode->osrExit[i]; >+ >+ linkBuffer.link(info.m_thunkJump, target); >+ >+ m_out.set( >+ m_out.constIntPtr( >+ linkBuffer.locationOf(info.m_thunkLabel).executableAddress()), >+ info.m_thunkAddress); >+ >+ exit.m_patchableCodeOffset = linkBuffer.offsetOf(exit.m_thunkJump); >+ } >+ >+ state.jitCode->initializeExitThunks( >+ FINALIZE_DFG_CODE( >+ linkBuffer, >+ ("FTL exit thunks for %s", toCString(CodeBlockWithJITType(state.graph.m_codeBlock,JITCode::FTLJIT)).data()))); >+ >+ m_out.jump(m_blocks.get(m_graph.m_blocks[0].get())); >+ } >+ >+ void observeMovHint(Node* node) >+ { >+ ASSERT(node->containsMovHint()); >+ ASSERT(node->op() != ZombieHint); >+ >+ int operand = node->local(); >+ >+ m_lastSetOperand = operand; >+ m_valueSources[operand] = ValueSource(node->child1().node()); >+ } >+ > void addWeakReference(JSCell* target) > { > m_ftlState.jitCode->common.weakReferences.append( >@@ -1151,12 +1553,12 @@ private: > Output m_out; > > LBasicBlock m_prologue; >+ LBasicBlock m_initialization; > HashMap<BasicBlock*, LBasicBlock> m_blocks; > > LValue m_callFrame; > LValue m_tagTypeNumber; > LValue m_tagMask; >- LValue m_abortFunction; > > HashSet<Node*> m_flushedLocalOps; > Vector<Node*> m_flushedLocalOpWorklist; >@@ -1165,15 +1567,21 @@ private: > HashMap<Node*, LValue> m_jsValueValues; > HashMap<Node*, LValue> m_booleanValues; > HashMap<Node*, LValue> m_storageValues; >+ HashMap<Node*, unsigned> m_timeToLive; > > Operands<LValue> m_localsBoolean; > Operands<LValue> m_locals32; > Operands<LValue> m_locals64; > >+ Operands<ValueSource> m_valueSources; >+ int m_lastSetOperand; >+ ExitThunkGenerator m_exitThunkGenerator; >+ > AbstractState m_state; > BasicBlock* m_highBlock; > BasicBlock* m_nextHighBlock; > LBasicBlock m_nextLowBlock; >+ unsigned m_nodeIndex; > Node* m_node; > SpeculationDirection m_direction; > }; >Index: Source/JavaScriptCore/ftl/FTLOSRExit.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExit.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOSRExit.cpp (working copy) >@@ -0,0 +1,93 @@ >+/* >+ * 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 "FTLOSRExit.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+OSRExit::OSRExit( >+ ExitKind exitKind, ValueFormat profileValueFormat, >+ MethodOfGettingAValueProfile valueProfile, CodeOrigin codeOrigin, >+ int lastSetOperand, unsigned numberOfArguments, unsigned numberOfLocals) >+ : OSRExitBase(exitKind, codeOrigin) >+ , m_profileValueFormat(profileValueFormat) >+ , m_valueProfile(valueProfile) >+ , m_codeOrigin(codeOrigin) >+ , m_patchableCodeOffset(0) >+ , m_lastSetOperand(lastSetOperand) >+ , m_values(numberOfArguments, numberOfLocals) >+{ >+} >+ >+CodeLocationJump OSRExit::codeLocationForRepatch(CodeBlock* ftlCodeBlock) const >+{ >+ return CodeLocationJump( >+ reinterpret_cast<char*>( >+ ftlCodeBlock->getJITCode()->ftl()->exitThunks().dataLocation()) + >+ m_patchableCodeOffset); >+} >+ >+void OSRExit::convertToForward( >+ DFG::BasicBlock* block, DFG::Node* currentNode, unsigned nodeIndex, >+ const FormattedValue &value, ExitArgumentList& arguments) >+{ >+ Node* node; >+ Node* lastMovHint; >+ doSearchForForwardConversion(block, currentNode, nodeIndex, !!valueRecovery); >+ >+ ASSERT(node->codeOrigin != currentNode->codeOrigin); >+ >+ m_codeOrigin = node->codeOrigin; >+ >+ if (!value) >+ return; >+ >+ int overriddenOperand = lastMovHint->local(); >+ m_lastSetOperand = overriddenOperand; >+ >+ // Is the value for this operand being passed as an argument to the exit, or is >+ // it something else? If it's an argument already, then replace that argument; >+ // otherwise add another argument. >+ if (m_values[overriddenOperand].isArgument()) { >+ ExitArgument argument = m_values[overriddenOperand].exitArgument(); >+ arguments[exitArgument.argument()] = value.value(); >+ m_values[overriddenOperand] = ExitValue::exitArgument( >+ exitArgument.withFormat(value.format())); >+ return; >+ } >+ >+ unsigned argument = arguments.size(); >+ arguments.append(value.value()); >+ m_values[m_lastSetOperand] = ExitValue::exitArgument( >+ ExitArgument(value.format(), argument)); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLOSRExit.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExit.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOSRExit.h (working copy) >@@ -0,0 +1,180 @@ >+/* >+ * 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 FTLOSRExit_h >+#define FTLOSRExit_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "CodeOrigin.h" >+#include "DFGExitProfile.h" >+#include "DFGOSRExitBase.h" >+#include "FTLAbbreviations.h" >+#include "FTLExitArgumentList.h" >+#include "FTLExitValue.h" >+#include "MethodOfGettingAValueProfile.h" >+#include "Operands.h" >+#include "ValueProfile.h" >+ >+namespace JSC { namespace FTL { >+ >+// Tracks one OSR exit site within the FTL JIT. OSR exit in FTL works by deconstructing >+// the crazy that is OSR down to simple SSA CFG primitives that any compiler backend >+// (including of course LLVM) can grok and do meaningful things to. Except for >+// watchpoint-based exits, which haven't yet been implemented (see webkit.org/b/113647), >+// an exit is just a conditional branch in the emitted code where one destination is the >+// continuation and the other is a basic block that performs a no-return tail-call to an >+// exit thunk. This thunk takes as its arguments the live non-constant >+// not-already-accounted-for bytecode state. To appreciate how this works consider the >+// following JavaScript program, and its lowering down to LLVM IR including the relevant >+// exits: >+// >+// function foo(o) { >+// var a = o.a; // predicted int >+// var b = o.b; >+// var c = o.c; // NB this is dead >+// a = a | 5; // our example OSR exit: need to check if a is an int >+// return a + b; >+// } >+// >+// Just consider the "a | 5". In the DFG IR, this looks like: >+// >+// BitOr(Check:Int32:@a, Int32:5) >+// >+// Where @a is the node for the GetLocal node that gets the value of the 'a' variable. >+// Conceptually, this node can be further broken down to the following (note that this >+// particular lowering never actually happens - we skip this step and go straight to >+// LLVM IR - but it's still useful to see this): >+// >+// exitIf(@a is not int32); >+// continuation; >+// >+// Where 'exitIf()' is a function that will exit if the argument is true, and >+// 'continuation' is the stuff that we will do after the exitIf() check. (Note that >+// FTL refers to 'exitIf()' as 'speculate()', which is in line with DFG terminology.) >+// This then gets broken down to the following LLVM IR, assuming that %0 is the LLVM >+// value corresponding to variable 'a', and %1 is the LLVM value for variable 'b': >+// >+// %2 = ... // the predictate corresponding to '@a is not int32' >+// br i1 %2, label %3, label %4 >+// ; <label>:3 >+// call void exitThunk1(%0, %1) // pass 'a' and 'b', since they're both live-in-bytecode >+// unreachable >+// ; <label>:4 >+// ... // code for the continuation >+// >+// Where 'exitThunk1' is the IR to get the exit thunk for *this* OSR exit. Each OSR >+// exit will appear to LLVM to have a distinct exit thunk. >+// >+// Note that this didn't have to pass '5', 'o', or 'c' to the exit thunk. 5 is a >+// constant and the DFG already knows that, and can already tell the OSR exit machinery >+// what that contant is and which bytecode variables (if any) it needs to be dropped >+// into. This is conveyed to the exit statically, via the OSRExit data structure below. >+// See the code for ExitValue for details. 'o' is an argument, and arguments are always >+// "flushed" - if you never assign them then their values are still in the argument >+// stack slots, and if you do assign them then we eagerly store them into those slots. >+// 'c' is dead in bytecode, and the DFG knows this; we statically tell the exit thunk >+// that it's dead and don't have to pass anything. The exit thunk will "initialize" its >+// value to Undefined. >+// >+// This approach to OSR exit has a number of virtues: >+// >+// - It is an entirely unsurprising representation for a compiler that already groks >+// CFG-like IRs for C-like languages. All existing analyses and transformations just >+// work. >+// >+// - It lends itself naturally to modern approaches to code motion. For example, you >+// could sink operations from above the exit to below it, if you just duplicate the >+// operation into the OSR exit block. This is both legal and desirable. It works >+// because the backend sees the OSR exit block as being no different than any other, >+// and LLVM already supports sinking if it sees that a value is only partially used. >+// Hence there exists a value that dominates the exit but is only used by the exit >+// thunk and not by the continuation, sinking ought to kick in for that value. >+// Hoisting operations from below it to above it is also possible, for similar >+// reasons. >+// >+// - The no-return tail-call to the OSR exit thunk can be subjected to specialized >+// code-size reduction optimizations, though this is optional. For example, instead >+// of actually emitting a call along with all that goes with it (like placing the >+// arguments into argument position), the backend could choose to simply inform us >+// where it had placed the arguments and expect the callee (i.e. the exit thunk) to >+// figure it out from there. It could also tell us what we need to do to pop stack, >+// although again, it doesn't have to; it could just emit that code normally. Though >+// we don't support this yet, we could; the only thing that would change on our end >+// is that we'd need feedback from the backend about the location of the arguments >+// and a description of the things that need to be done to pop stack. This would >+// involve switching the m_values array to use something more akin to ValueRecovery >+// rather than the current ExitValue, albeit possibly with some hacks to better >+// understand the kinds of places where the LLVM backend would put values. >+// >+// - It could be extended to allow the backend to do its own exit hoisting, by using >+// intrinsics (or meta-data, or something) to inform the backend that it's safe to >+// make the predicate passed to 'exitIf()' more truthy. >+// >+// - It could be extended to support watchpoints (see webkit.org/b/113647) by making >+// the predicate passed to 'exitIf()' be an intrinsic that the backend knows to be >+// true at compile-time. The backend could then turn the conditional branch into a >+// replaceable jump, much like the DFG does. >+ >+struct OSRExit : public OSRExitBase { >+ OSRExit( >+ ExitKind, ValueFormat profileValueFormat, MethodOfGettingAValueProfile, >+ CodeOrigin, int lastSetOperand, unsigned numberOfArguments, >+ unsigned numberOfLocals); >+ >+ MacroAssemblerCodeRef m_code; >+ >+ // The first argument to the exit call may be a value we wish to profile. >+ // If that's the case, the format will be not Invalid and we'll have a >+ // method of getting a value profile. Note that all of the ExitArgument's >+ // are already aware of this possible off-by-one, so there is no need to >+ // correct them. >+ ValueFormat m_profileValueFormat; >+ MethodOfGettingAValueProfile m_valueProfile; >+ >+ CodeOrigin m_codeOrigin; >+ >+ // Offset within the exit stubs of the stub for this exit. >+ unsigned m_patchableCodeOffset; >+ >+ int m_lastSetOperand; >+ >+ Operands<ExitValue> m_values; >+ >+ CodeLocationJump codeLocationForRepatch(CodeBlock* ftlCodeBlock) const; >+ >+ void convertToForward( >+ DFG::BasicBlock*, DFG::Node* currentNode, unsigned nodeIndex, >+ const FormattedValue&, ExitArgumentList& arguments); >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLOSRExit_h >+ >Index: Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOSRExitCompilationInfo.h (working copy) >@@ -0,0 +1,54 @@ >+/* >+ * 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 FTLOSRExitCompilationInfo_h >+#define FTLOSRExitCompilationInfo_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "FTLAbbreviations.h" >+#include "MacroAssembler.h" >+ >+namespace JSC { namespace FTL { >+ >+struct OSRExitCompilationInfo { >+ OSRExitCompilationInfo() >+ : m_thunkAddress(0) >+ { >+ } >+ >+ MacroAssembler::Label m_thunkLabel; >+ MacroAssembler::PatchableJump m_thunkJump; >+ LValue m_thunkAddress; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLOSRExitCompilationInfo_h >+ >Index: Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (working copy) >@@ -0,0 +1,87 @@ >+/* >+ * 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 "FTLOSRExitCompiler.h" >+ >+#if ENABLE(FTL_JIT) >+ >+#include "DFGOSRExitCompilerCommon.h" >+#include "DFGOSRExitPreparation.h" >+#include "FTLCArgumentGetter.h" >+ >+namespace JSC { namespace FTL { >+ >+extern "C" void* compileFTLOSRExit(ExecState* exec, unsigned exitID) >+{ >+ SamplingRegion samplingRegion("FTL OSR Exit Compilation"); >+ >+ CodeBlock* codeBlock = exec->codeBlock(); >+ >+ ASSERT(codeBlock); >+ ASSERT(codeBlock->getJITType() == JITCode::FTLJIT); >+ >+ JSGlobalData* globalData = &exec->globalData(); >+ >+ OSRExit& exit = codeBlock->getJITCode()->ftl()->osrExit[exitID]; >+ >+ prepareCodeOriginForOSRExit(exit.m_codeOrigin); >+ >+ CCallHelpers jit(globalData, codeBlock); >+ >+ // This is actually fairly easy, even though it is horribly gross. We know that >+ // LLVM would have passes us all of the state via arguments. We know how to get >+ // the arguments. And, we know how to pop stack back to the JIT stack frame, sort >+ // of: we know that it's two frames beneath us. This is terrible and I feel >+ // ashamed of it, but it will work for now. >+ >+ CArgumentGetter arguments(jit); >+ >+ // First recover our call frame and tag thingies. >+ arguments.loadPtr(GPRInfo::callFrameRegister); >+ jit.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister); >+ jit.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister); >+ >+ // Do some value profiling. >+ >+ >+ // Start by dumping all argument exit values to the stack. >+ >+ Vector<ExitArgumentForOperand, 16> sortedArguments; >+ for (unsigned i = 0; i < exit.m_values.size(); ++i) { >+ ExitValue value = exit.m_values[i]; >+ if (!value.isArgument()) >+ continue; >+ sortedArguments.append(ExitArgumentForOperand( >+ value.exitArgument(), exit.m_values.operandForIndex(i))); >+ } >+ std::sort(sortedArguments.begin(), sortedArguments.end(), lesserArgumentIndex); >+ >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLOSRExitCompiler.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOSRExitCompiler.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLOSRExitCompiler.h (working copy) >@@ -0,0 +1,44 @@ >+/* >+ * 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 FTLOSRExitCompiler_h >+#define FTLOSRExitCompiler_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+// Takes the call frame and the index of the exit, and returns the address to >+// jump to. >+extern "C" void* DFG_OPERATION compileFTLOSRExit(ExecState*, unsigned exitID) WTF_INTERNAL; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLOSRExitCompiler_h >+ >Index: Source/JavaScriptCore/ftl/FTLOutput.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLOutput.h (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLOutput.h (working copy) >@@ -135,19 +135,20 @@ public: > LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); } > LValue intCast(LValue value, LType type) { return buildIntCast(m_builder, value, type); } > LValue castToInt32(LValue value) { return intCast(value, int32); } >+ LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); } > > LValue get(LValue reference) { return buildLoad(m_builder, reference); } > LValue set(LValue value, LValue reference) { return buildStore(m_builder, value, reference); } > > LValue load(TypedPointer pointer, LType refType) > { >- LValue result = get(buildIntToPtr(m_builder, pointer.value(), refType)); >+ LValue result = get(intToPtr(pointer.value(), refType)); > pointer.heap().decorateInstruction(result, *m_heaps); > return result; > } > void store(LValue value, TypedPointer pointer, LType refType) > { >- LValue result = set(value, buildIntToPtr(m_builder, pointer.value(), refType)); >+ LValue result = set(value, intToPtr(pointer.value(), refType)); > pointer.heap().decorateInstruction(result, *m_heaps); > } > >@@ -244,10 +245,18 @@ public: > LValue select(LValue value, LValue taken, LValue notTaken) { return buildSelect(m_builder, value, taken, notTaken); } > LValue extractValue(LValue aggVal, unsigned index) { return buildExtractValue(m_builder, aggVal, index); } > >+ template<typename VectorType> >+ LValue call(LValue function, const VectorType& vector) { return buildCall(m_builder, function, vector); } > LValue call(LValue function) { return buildCall(m_builder, function); } > LValue call(LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); } > LValue call(LValue function, LValue arg1, LValue arg2) { return buildCall(m_builder, function, arg1, arg2); } > >+ LValue convertToTailCall(LValue call) >+ { >+ setTailCall(call, IsTailCall); >+ return true; >+ } >+ > void jump(LBasicBlock destination) { buildBr(m_builder, destination); } > void branch(LValue condition, LBasicBlock taken, LBasicBlock notTaken) { buildCondBr(m_builder, condition, taken, notTaken); } > void ret(LValue value) { buildRet(m_builder, value); } >Index: Source/JavaScriptCore/ftl/FTLState.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLState.h (revision 148047) >+++ Source/JavaScriptCore/ftl/FTLState.h (working copy) >@@ -33,6 +33,7 @@ > #include "DFGGraph.h" > #include "FTLAbbreviations.h" > #include "FTLJITCode.h" >+#include "FTLOSRExitCompilationInfo.h" > #include <wtf/Noncopyable.h> > > namespace JSC { namespace FTL { >@@ -49,6 +50,7 @@ public: > LModule module; > LValue function; > RefPtr<JITCode> jitCode; >+ Vector<OSRExitCompilationInfo> osrExit; > > void dumpState(const char* when); > }; >Index: Source/JavaScriptCore/ftl/FTLThunks.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLThunks.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLThunks.cpp (working copy) >@@ -0,0 +1,76 @@ >+/* >+ * 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 "FTLThunks.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData) >+{ >+ MacroAssembler jit; >+ >+ size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfArgumentRegisters + FPRInfo::numberOfArgumentRegisters); >+ ScratchBuffer* scratchBuffer = globalData->scratchBufferForSize(scratchSize); >+ EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()); >+ >+ for (unsigned i = 0; i < GPRInfo::numberOfArgumentRegisters; ++i) >+ jit.store64(GPRInfo::toArgumentRegister(i), buffer + i); >+ for (unsigned i = 0; i < FPRInfo::numberOfArgumentRegisters; ++i) { >+ jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfArgumentRegisters + i), GPRInfo::nonArgGPR1); >+ jit.storeDouble(FPRInfo::toArgumentRegister(i), GPRInfo::nonArgGPR1); >+ } >+ >+ // Tell GC mark phase how much of the scratch buffer is active during call. >+ jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::nonArgGPR1); >+ jit.storePtr(MacroAssembler::TrustedImmPtr(scratchSize), GPRInfo::nonArgGPR1); >+ >+ // argument 0 is already the call frame. >+ jit.move(GPRInfo::nonArgGPR0, GPRInfo::argumentGPR1); >+ MacroAssembler::Call functionCall = jit.call(); >+ >+ jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::nonPreservedNonReturnGPR); >+ jit.storePtr(MacroAssembler::TrustedImmPtr(0), GPRInfo::nonPreservedNonReturnGPR); >+ >+ for (unsigned i = 0; i < FPRInfo::numberOfArgumentRegisters; ++i) { >+ jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfArgumentRegisters + i), GPRInfo::nonPreservedNonReturnGPR); >+ jit.loadDouble(GPRInfo::nonPreservedNonReturnGPR, FPRInfo::toArgumentRegister(i)); >+ } >+ for (unsigned i = 0; i < GPRInfo::numberOfArgumentRegisters; ++i) >+ jit.load64(buffer + i, GPRInfo::toArgumentRegister(i)); >+ >+ jit.jump(GPRInfo::returnValueGPR); >+ >+ LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID); >+ patchBuffer.link(functionCall, compileFTLOSRExit); >+ return FINALIZE_CODE(patchBuffer, ("FTL OSR exit generation thunk")); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLThunks.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLThunks.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLThunks.h (working copy) >@@ -0,0 +1,47 @@ >+/* >+ * 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 FTLThunks_h >+#define FTLThunks_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include "MacroAssemblerCodeRef.h" >+ >+namespace JSC { >+ >+class JSGlobalData; >+ >+namespace FTL { >+ >+MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData*); >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLTHunks_h >Index: Source/JavaScriptCore/ftl/FTLValueFormat.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueFormat.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLValueFormat.cpp (working copy) >@@ -0,0 +1,64 @@ >+/* >+ * 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 "FTLValueFormat.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace WTF { >+ >+using namespace JSC::FTL; >+ >+void printInternal(PrintStream& out, ValueFormat format) >+{ >+ switch (format) { >+ case InvalidValueFormat: >+ out.print("Invalid"); >+ return; >+ case ValueFormatInt32: >+ out.print("Int32"); >+ return; >+ case ValueFormatUInt32: >+ out.print("UInt32"); >+ return; >+ case ValueFormatBoolean: >+ out.print("Boolean"); >+ return; >+ case ValueFormatJSValue: >+ out.print("JSValue"); >+ return; >+ case ValueFormatDouble: >+ out.print("Double"); >+ return; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace WTF >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLValueFormat.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueFormat.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLValueFormat.h (working copy) >@@ -0,0 +1,60 @@ >+/* >+ * 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 FTLValueFormat_h >+#define FTLValueFormat_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace FTL { >+ >+// Note that this is awkwardly similar to DataFormat in other parts of JSC, except that >+// unlike DataFormat and like ValueRecovery, it distinguishes between UInt32 and Int32. >+ >+enum ValueFormat { >+ InvalidValueFormat, >+ ValueFormatInt32, >+ ValueFormatUInt32, >+ ValueFormatBoolean, >+ ValueFormatJSValue, >+ ValueFormatDouble >+}; >+ >+} } // namespace JSC::FTL >+ >+namespace WTF { >+ >+void printInternal(PrintStream&, JSC::FTL::ValueFormat); >+ >+} // namespace WTF >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLValueFormat_h >+ >Index: Source/JavaScriptCore/ftl/FTLValueSource.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueSource.cpp (revision 0) >+++ Source/JavaScriptCore/ftl/FTLValueSource.cpp (working copy) >@@ -0,0 +1,77 @@ >+/* >+ * 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 "FTLValueSource.h" >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+void ValueSource::dump(PrintStream& out) const >+{ >+ switch (kind()) { >+ case SourceNotSet: >+ out.print("SourceNotSet"); >+ return; >+ case ValueInJSStack: >+ out.print("ValueInJSStack"); >+ return; >+ case Int32InJSStack: >+ out.print("Int32InJSStack"); >+ return; >+ case DoubleInJSStack: >+ out.print("DoubleInJSStack"); >+ return; >+ case ValueInLocals: >+ out.print("ValueInLocals"); >+ return; >+ case Int32InLocals: >+ out.print("Int32InLocals"); >+ return; >+ case BooleanInLocals: >+ out.print("BooleanInLocals"); >+ return; >+ case DoubleInLocals: >+ out.print("DoubleInLocals"); >+ return; >+ case ArgumentsSource: >+ out.print("ArgumentsSource"); >+ return; >+ case SourceIsDead: >+ out.print("SourceIsDead"); >+ return; >+ case HaveNode: >+ out.print("Node(", node(), ")"); >+ return; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >Index: Source/JavaScriptCore/ftl/FTLValueSource.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLValueSource.h (revision 0) >+++ Source/JavaScriptCore/ftl/FTLValueSource.h (working copy) >@@ -0,0 +1,92 @@ >+/* >+ * 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 FTLValueSource_h >+#define FTLValueSource_h >+ >+#include <wtf/Platform.h> >+ >+#if ENABLE(FTL_JIT) >+ >+namespace JSC { namespace FTL { >+ >+enum ValueSourceKind { >+ SourceNotSet, >+ ValueInJSStack, >+ Int32InJSStack, >+ DoubleInJSStack, >+ ValueInLocals, >+ Int32InLocals, >+ BooleanInLocals, >+ DoubleInLocals, >+ ArgumentsSource, >+ SourceIsDead, >+ HaveNode >+}; >+ >+class ValueSource { >+public: >+ ValueSource() >+ : m_value(SourceNotSet) >+ { >+ } >+ >+ explicit ValueSource(ValueSourceKind kind) >+ : m_value(kind) >+ { >+ } >+ >+ explicit ValueSource(DFG::Node* node) >+ : m_value(bitwise_cast<uintptr_t>(node)) >+ { >+ } >+ >+ ValueSourceKind() kind() const >+ { >+ if (m_value < static_cast<uintptr_t>(HaveNode)) >+ return static_cast<ValueSourceKind>(m_value); >+ return HaveNode; >+ } >+ >+ bool operator!() const { return kind() != SourceNotSet; } >+ >+ DFG::Node* node() const >+ { >+ ASSERT(kind() == HaveNode); >+ return bitwise_cast<DFG::Node*>(m_value); >+ } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ uintptr_t m_value; >+}; >+ >+} } // namespace JSC::FTL >+ >+#endif // ENABLE(FTL_JIT) >+ >+#endif // FTLValueSource_h >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 113623
:
196508
|
196539
|
196562
|
196565
|
196700
|
196704
|
197166
|
197216
|
197373
|
197502
|
197706
|
197914
|
197920