diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-17 16:21:14 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-17 16:21:14 +0200 |
commit | 8995b83bcbfbb68245f779b64e5517627c6cc6ea (patch) | |
tree | 17985605dab9263cc2444bd4d45f189e142cca7c /Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp | |
parent | b9c9652036d5e9f1e29c574f40bc73a35c81ace6 (diff) | |
download | qtwebkit-8995b83bcbfbb68245f779b64e5517627c6cc6ea.tar.gz |
Imported WebKit commit cf4f8fc6f19b0629f51860cb2d4b25e139d07e00 (http://svn.webkit.org/repository/webkit/trunk@131592)
New snapshot that includes the build fixes for Mac OS X 10.6 and earlier as well
as the previously cherry-picked changes
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp | 140 |
1 files changed, 120 insertions, 20 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 6d5f68200..dc668d93e 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -43,6 +43,76 @@ namespace JSC { namespace DFG { +class ConstantBufferKey { +public: + ConstantBufferKey() + : m_codeBlock(0) + , m_index(0) + { + } + + ConstantBufferKey(WTF::HashTableDeletedValueType) + : m_codeBlock(0) + , m_index(1) + { + } + + ConstantBufferKey(CodeBlock* codeBlock, unsigned index) + : m_codeBlock(codeBlock) + , m_index(index) + { + } + + bool operator==(const ConstantBufferKey& other) const + { + return m_codeBlock == other.m_codeBlock + && m_index == other.m_index; + } + + unsigned hash() const + { + return WTF::PtrHash<CodeBlock*>::hash(m_codeBlock) ^ m_index; + } + + bool isHashTableDeletedValue() const + { + return !m_codeBlock && m_index; + } + + CodeBlock* codeBlock() const { return m_codeBlock; } + unsigned index() const { return m_index; } + +private: + CodeBlock* m_codeBlock; + unsigned m_index; +}; + +struct ConstantBufferKeyHash { + static unsigned hash(const ConstantBufferKey& key) { return key.hash(); } + static bool equal(const ConstantBufferKey& a, const ConstantBufferKey& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} } // namespace JSC::DFG + +namespace WTF { + +template<typename T> struct DefaultHash; +template<> struct DefaultHash<JSC::DFG::ConstantBufferKey> { + typedef JSC::DFG::ConstantBufferKeyHash Hash; +}; + +template<typename T> struct HashTraits; +template<> struct HashTraits<JSC::DFG::ConstantBufferKey> : SimpleClassHashTraits<JSC::DFG::ConstantBufferKey> { }; + +} // namespace WTF + +namespace JSC { namespace DFG { + // === ByteCodeParser === // // This class is used to compile the dataflow graph from a CodeBlock. @@ -142,7 +212,7 @@ private: return getJSConstant(constant); } - if (operand == RegisterFile::Callee) + if (operand == JSStack::Callee) return getCallee(); // Is this an argument? @@ -227,7 +297,10 @@ private: if (nodePtr->op() == GetLocal) nodeIndex = nodePtr->child1().index(); - return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); + NodeIndex newGetLocal = injectLazyOperandSpeculation( + addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); + m_currentBlock->variablesAtTail.local(operand) = newGetLocal; + return newGetLocal; } if (nodePtr->op() == GetLocal) @@ -366,11 +439,11 @@ private: InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame; if (!inlineCallFrame) break; - if (operand >= static_cast<int>(inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize)) + if (operand >= static_cast<int>(inlineCallFrame->stackOffset - JSStack::CallFrameHeaderSize)) continue; if (operand == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset()) continue; - if (operand < static_cast<int>(inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size())) + if (operand < static_cast<int>(inlineCallFrame->stackOffset - JSStack::CallFrameHeaderSize - inlineCallFrame->arguments.size())) continue; int argument = operandToArgument(operand - inlineCallFrame->stackOffset); return stack->m_argumentPositions[argument]; @@ -669,9 +742,9 @@ private: { HashMap<JSCell*, NodeIndex>::AddResult result = m_cellConstantNodes.add(cell, NoNode); if (result.isNewEntry) - result.iterator->second = addToGraph(WeakJSConstant, OpInfo(cell)); + result.iterator->value = addToGraph(WeakJSConstant, OpInfo(cell)); - return result.iterator->second; + return result.iterator->value; } CodeOrigin currentCodeOrigin() @@ -758,8 +831,8 @@ private: addVarArgChild(get(currentInstruction[1].u.operand)); int argCount = currentInstruction[2].u.operand; - if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots) - m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount; + if (JSStack::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots) + m_parameterSlots = JSStack::CallFrameHeaderSize + argCount; int registerOffset = currentInstruction[3].u.operand; int dummyThisArgument = op == Call ? 0 : 1; @@ -1049,6 +1122,8 @@ private: Vector<PhiStackEntry, 16> m_argumentPhiStack; Vector<PhiStackEntry, 16> m_localPhiStack; + HashMap<ConstantBufferKey, unsigned> m_constantBufferCache; + struct InlineStackEntry { ByteCodeParser* m_byteCodeParser; @@ -1067,6 +1142,7 @@ private: // direct, caller). Vector<unsigned> m_identifierRemap; Vector<unsigned> m_constantRemap; + Vector<unsigned> m_constantBufferRemap; // Blocks introduced by this code block, which need successor linking. // May include up to one basic block that includes the continuation after @@ -1139,7 +1215,7 @@ private: return result; } - if (operand == RegisterFile::Callee) + if (operand == JSStack::Callee) return m_calleeVR; return operand + m_inlineCallFrame->stackOffset; @@ -1361,14 +1437,14 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c // FIXME: Don't flush constants! - int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize; + int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - JSStack::CallFrameHeaderSize; // Make sure that the area used by the call frame is reserved. - for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;) + for (int arg = inlineCallFrameStart + JSStack::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;) m_preservedVars.set(arg); // Make sure that we have enough locals. - unsigned newNumLocals = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; + unsigned newNumLocals = inlineCallFrameStart + JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; if (newNumLocals > m_numLocals) { m_numLocals = newNumLocals; for (size_t i = 0; i < m_graph.m_blocks.size(); ++i) @@ -1571,6 +1647,8 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins case Array::ArrayWithArrayStorageToHole: ASSERT_NOT_REACHED(); + case Array::ArrayWithContiguous: + case Array::ArrayWithContiguousOutOfBounds: case Array::ArrayWithArrayStorage: case Array::ArrayWithArrayStorageOutOfBounds: { NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); @@ -1594,6 +1672,8 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins case Array::ArrayWithArrayStorageToHole: ASSERT_NOT_REACHED(); + case Array::ArrayWithContiguous: + case Array::ArrayWithContiguousOutOfBounds: case Array::ArrayWithArrayStorage: case Array::ArrayWithArrayStorageOutOfBounds: { NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); @@ -1868,7 +1948,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) } case op_create_this: { - set(currentInstruction[1].u.operand, addToGraph(CreateThis, get(RegisterFile::Callee))); + set(currentInstruction[1].u.operand, addToGraph(CreateThis, get(JSStack::Callee))); NEXT_OPCODE(op_create_this); } @@ -1889,7 +1969,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_new_array_buffer: { int startConstant = currentInstruction[2].u.operand; int numConstants = currentInstruction[3].u.operand; - set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(startConstant), OpInfo(numConstants))); + set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(m_inlineStackTop->m_constantBufferRemap[startConstant]), OpInfo(numConstants))); NEXT_OPCODE(op_new_array_buffer); } @@ -2753,8 +2833,8 @@ bool ByteCodeParser::parseBlock(unsigned limit) addToGraph(CheckArgumentsNotCreated); unsigned argCount = m_inlineStackTop->m_inlineCallFrame->arguments.size(); - if (RegisterFile::CallFrameHeaderSize + argCount > m_parameterSlots) - m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount; + if (JSStack::CallFrameHeaderSize + argCount > m_parameterSlots) + m_parameterSlots = JSStack::CallFrameHeaderSize + argCount; addVarArgChild(get(currentInstruction[1].u.operand)); // callee addVarArgChild(get(currentInstruction[2].u.operand)); // this @@ -2775,8 +2855,10 @@ bool ByteCodeParser::parseBlock(unsigned limit) // Statically speculate for now. It makes sense to let speculate-only jneq_ptr // support simmer for a while before making it more general, since it's // already gnarly enough as it is. + ASSERT(pointerIsFunction(currentInstruction[2].u.specialPointer)); addToGraph( - CheckFunction, OpInfo(currentInstruction[2].u.jsCell.get()), + CheckFunction, + OpInfo(actualPointerFor(m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)), get(currentInstruction[1].u.operand)); addToGraph(Jump, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_ptr))); LAST_OPCODE(op_jneq_ptr); @@ -3205,7 +3287,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry( InlineCallFrame inlineCallFrame; inlineCallFrame.executable.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), codeBlock->ownerExecutable()); - inlineCallFrame.stackOffset = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize; + inlineCallFrame.stackOffset = inlineCallFrameStart + JSStack::CallFrameHeaderSize; inlineCallFrame.callee.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), callee); inlineCallFrame.caller = byteCodeParser->currentCodeOrigin(); inlineCallFrame.arguments.resize(argumentCountIncludingThis); // Set the number of arguments including this, but don't configure the value recoveries, yet. @@ -3242,13 +3324,14 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry( m_identifierRemap.resize(codeBlock->numberOfIdentifiers()); m_constantRemap.resize(codeBlock->numberOfConstantRegisters()); + m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers()); for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) { StringImpl* rep = codeBlock->identifier(i).impl(); IdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_codeBlock->numberOfIdentifiers()); if (result.isNewEntry) byteCodeParser->m_codeBlock->addIdentifier(Identifier(byteCodeParser->m_globalData, rep)); - m_identifierRemap[i] = result.iterator->second; + m_identifierRemap[i] = result.iterator->value; } for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) { JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex); @@ -3266,10 +3349,24 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry( byteCodeParser->m_codeBlock->addConstant(value); byteCodeParser->m_constants.append(ConstantRecord()); } - m_constantRemap[i] = result.iterator->second; + m_constantRemap[i] = result.iterator->value; } for (unsigned i = 0; i < codeBlock->numberOfGlobalResolveInfos(); ++i) byteCodeParser->m_codeBlock->addGlobalResolveInfo(std::numeric_limits<unsigned>::max()); + for (unsigned i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) { + // If we inline the same code block multiple times, we don't want to needlessly + // duplicate its constant buffers. + HashMap<ConstantBufferKey, unsigned>::iterator iter = + byteCodeParser->m_constantBufferCache.find(ConstantBufferKey(codeBlock, i)); + if (iter != byteCodeParser->m_constantBufferCache.end()) { + m_constantBufferRemap[i] = iter->value; + continue; + } + Vector<JSValue>& buffer = codeBlock->constantBufferAsVector(i); + unsigned newIndex = byteCodeParser->m_codeBlock->addConstantBuffer(buffer); + m_constantBufferRemap[i] = newIndex; + byteCodeParser->m_constantBufferCache.add(ConstantBufferKey(codeBlock, i), newIndex); + } m_callsiteBlockHeadNeedsLinking = true; } else { @@ -3285,11 +3382,14 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry( m_identifierRemap.resize(codeBlock->numberOfIdentifiers()); m_constantRemap.resize(codeBlock->numberOfConstantRegisters()); + m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers()); for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) m_identifierRemap[i] = i; for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) m_constantRemap[i] = i + FirstConstantRegisterIndex; + for (size_t i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) + m_constantBufferRemap[i] = i; m_callsiteBlockHeadNeedsLinking = false; } |