diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp index 4ee723d84..e69de29bb 100644 --- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2012 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 "DFGStructureCheckHoistingPhase.h" - -#if ENABLE(DFG_JIT) - -#include "DFGBasicBlock.h" -#include "DFGGraph.h" -#include "DFGInsertionSet.h" -#include "DFGPhase.h" -#include <wtf/HashMap.h> - -namespace JSC { namespace DFG { - -enum CheckBallot { VoteOther, VoteStructureCheck }; - -class StructureCheckHoistingPhase : public Phase { -public: - StructureCheckHoistingPhase(Graph& graph) - : Phase(graph, "structure check hoisting") - { - } - - bool run() - { - for (unsigned i = m_graph.m_variableAccessData.size(); i--;) { - VariableAccessData* variable = &m_graph.m_variableAccessData[i]; - if (!variable->isRoot()) - continue; - variable->clearVotes(); - } - - // Identify the set of variables that are always subject to the same structure - // checks. For now, only consider monomorphic structure checks (one structure). - - for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { - BasicBlock* block = m_graph.m_blocks[blockIndex].get(); - if (!block) - continue; - for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { - NodeIndex nodeIndex = block->at(indexInBlock); - Node& node = m_graph[nodeIndex]; - if (!node.shouldGenerate()) - continue; - switch (node.op()) { - case CheckStructure: - case StructureTransitionWatchpoint: { - Node& child = m_graph[node.child1()]; - if (child.op() != GetLocal) - break; - VariableAccessData* variable = child.variableAccessData(); - variable->vote(VoteStructureCheck); - if (variable->isCaptured() || variable->structureCheckHoistingFailed()) - break; - if (!isCellSpeculation(variable->prediction())) - break; - noticeStructureCheck(variable, node.structureSet()); - break; - } - - case ForwardCheckStructure: - case ForwardStructureTransitionWatchpoint: - // We currently rely on the fact that we're the only ones who would - // insert this node. - ASSERT_NOT_REACHED(); - break; - - case GetByOffset: - case PutByOffset: - case PutStructure: - case AllocatePropertyStorage: - case ReallocatePropertyStorage: - case GetButterfly: - case GetByVal: - case PutByVal: - case PutByValAlias: - case GetArrayLength: - case CheckArray: - case GetIndexedPropertyStorage: - case Phantom: - // Don't count these uses. - break; - - case SetLocal: { - // Find all uses of the source of the SetLocal. If any of them are a - // kind of CheckStructure, then we should notice them to ensure that - // we're not hoisting a check that would contravene checks that are - // already being performed. - VariableAccessData* variable = node.variableAccessData(); - if (variable->isCaptured() || variable->structureCheckHoistingFailed()) - break; - if (!isCellSpeculation(variable->prediction())) - break; - NodeIndex source = node.child1().index(); - for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) { - NodeIndex subNodeIndex = block->at(subIndexInBlock); - Node& subNode = m_graph[subNodeIndex]; - if (!subNode.shouldGenerate()) - continue; - switch (subNode.op()) { - case CheckStructure: { - if (subNode.child1().index() != source) - break; - - noticeStructureCheck(variable, subNode.structureSet()); - break; - } - case StructureTransitionWatchpoint: { - if (subNode.child1().index() != source) - break; - - noticeStructureCheck(variable, subNode.structure()); - break; - } - default: - break; - } - } - - m_graph.vote(node, VoteOther); - break; - } - case GarbageValue: - break; - - default: - m_graph.vote(node, VoteOther); - break; - } - } - } - - // Disable structure hoisting on variables that appear to mostly be used in - // contexts where it doesn't make sense. - - for (unsigned i = m_graph.m_variableAccessData.size(); i--;) { - VariableAccessData* variable = &m_graph.m_variableAccessData[i]; - if (!variable->isRoot()) - continue; - if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting()) - continue; - HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); - if (iter == m_map.end()) - continue; -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF("Zeroing the structure to hoist for %s because the ratio is %lf.\n", - m_graph.nameOfVariableAccessData(variable), variable->voteRatio()); -#endif - iter->value.m_structure = 0; - } - - // Disable structure check hoisting for variables that cross the OSR entry that - // we're currently taking, and where the value currently does not have the - // structure we want. - - for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { - BasicBlock* block = m_graph.m_blocks[blockIndex].get(); - if (!block) - continue; - ASSERT(block->isReachable); - if (!block->isOSRTarget) - continue; - if (block->bytecodeBegin != m_graph.m_osrEntryBytecodeIndex) - continue; - for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) { - int operand = m_graph.m_mustHandleValues.operandForIndex(i); - NodeIndex nodeIndex = block->variablesAtHead.operand(operand); - if (nodeIndex == NoNode) - continue; - VariableAccessData* variable = m_graph[nodeIndex].variableAccessData(); - HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); - if (iter == m_map.end()) - continue; - if (!iter->value.m_structure) - continue; - JSValue value = m_graph.m_mustHandleValues[i]; - if (!value || !value.isCell()) { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF("Zeroing the structure to hoist for %s because the OSR entry value is not a cell: %s.\n", - m_graph.nameOfVariableAccessData(variable), value); -#endif - iter->value.m_structure = 0; - continue; - } - if (value.asCell()->structure() != iter->value.m_structure) { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF("Zeroing the structure to hoist for %s because the OSR entry value has structure %p and we wanted %p.\n", - m_graph.nameOfVariableAccessData(variable), value.asCell()->structure(), iter->value.m_structure); -#endif - iter->value.m_structure = 0; - continue; - } - } - } - - bool changed = false; - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin(); - it != m_map.end(); ++it) { - if (!it->value.m_structure) { - dataLogF("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->key)); - continue; - } - dataLogF("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->key)); - } -#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - - // Place CheckStructure's at SetLocal sites. - - InsertionSet<NodeIndex> insertionSet; - for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { - BasicBlock* block = m_graph.m_blocks[blockIndex].get(); - if (!block) - continue; - for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { - NodeIndex nodeIndex = block->at(indexInBlock); - Node& node = m_graph[nodeIndex]; - // Be careful not to use 'node' after appending to the graph. In those switch - // cases where we need to append, we first carefully extract everything we need - // from the node, before doing any appending. - if (!node.shouldGenerate()) - continue; - switch (node.op()) { - case SetArgument: { - ASSERT(!blockIndex); - // Insert a GetLocal and a CheckStructure immediately following this - // SetArgument, if the variable was a candidate for structure hoisting. - // If the basic block previously only had the SetArgument as its - // variable-at-tail, then replace it with this GetLocal. - VariableAccessData* variable = node.variableAccessData(); - HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); - if (iter == m_map.end()) - break; - if (!iter->value.m_structure) - break; - - node.ref(); - - CodeOrigin codeOrigin = node.codeOrigin; - - Node getLocal(GetLocal, codeOrigin, OpInfo(variable), nodeIndex); - getLocal.predict(variable->prediction()); - getLocal.ref(); - NodeIndex getLocalIndex = m_graph.size(); - m_graph.append(getLocal); - insertionSet.append(indexInBlock + 1, getLocalIndex); - - Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), getLocalIndex); - checkStructure.ref(); - NodeIndex checkStructureIndex = m_graph.size(); - m_graph.append(checkStructure); - insertionSet.append(indexInBlock + 1, checkStructureIndex); - - if (block->variablesAtTail.operand(variable->local()) == nodeIndex) - block->variablesAtTail.operand(variable->local()) = getLocalIndex; - - m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocalIndex); - - changed = true; - break; - } - - case SetLocal: { - VariableAccessData* variable = node.variableAccessData(); - HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable); - if (iter == m_map.end()) - break; - if (!iter->value.m_structure) - break; - - // First insert a dead SetLocal to tell OSR that the child's value should - // be dropped into this bytecode variable if the CheckStructure decides - // to exit. - - CodeOrigin codeOrigin = node.codeOrigin; - NodeIndex child1 = node.child1().index(); - - Node setLocal(SetLocal, codeOrigin, OpInfo(variable), child1); - NodeIndex setLocalIndex = m_graph.size(); - m_graph.append(setLocal); - insertionSet.append(indexInBlock, setLocalIndex); - m_graph[child1].ref(); - // Use a ForwardCheckStructure to indicate that we should exit to the - // next bytecode instruction rather than reexecuting the current one. - Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), child1); - checkStructure.ref(); - NodeIndex checkStructureIndex = m_graph.size(); - m_graph.append(checkStructure); - insertionSet.append(indexInBlock, checkStructureIndex); - changed = true; - break; - } - - default: - break; - } - } - insertionSet.execute(*block); - } - - return changed; - } - -private: - void noticeStructureCheck(VariableAccessData* variable, Structure* structure) - { - HashMap<VariableAccessData*, CheckData>::AddResult result = - m_map.add(variable, CheckData(structure)); - if (result.isNewEntry) - return; - if (result.iterator->value.m_structure == structure) - return; - result.iterator->value.m_structure = 0; - } - - void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set) - { - if (set.size() != 1) { - noticeStructureCheck(variable, 0); - return; - } - noticeStructureCheck(variable, set.singletonStructure()); - } - - struct CheckData { - Structure* m_structure; - - CheckData() - : m_structure(0) - { - } - - CheckData(Structure* structure) - : m_structure(structure) - { - } - }; - - HashMap<VariableAccessData*, CheckData> m_map; -}; - -bool performStructureCheckHoisting(Graph& graph) -{ - SamplingRegion samplingRegion("DFG Structure Check Hoisting Phase"); - return runPhase<StructureCheckHoistingPhase>(graph); -} - -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) - - |