summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-15 16:08:57 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-15 16:08:57 +0200
commit5466563f4b5b6b86523e3f89bb7f77e5b5270c78 (patch)
tree8caccf7cd03a15207cde3ba282c88bf132482a91 /Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
parent33b26980cb24288b5a9f2590ccf32a949281bb79 (diff)
downloadqtwebkit-5466563f4b5b6b86523e3f89bb7f77e5b5270c78.tar.gz
Imported WebKit commit 0dc6cd75e1d4836eaffbb520be96fac4847cc9d2 (http://svn.webkit.org/repository/webkit/trunk@131300)
WebKit update which introduces the QtWebKitWidgets module that contains the WK1 widgets based API. (In fact it renames QtWebKit to QtWebKitWidgets while we're working on completing the entire split as part of https://bugs.webkit.org/show_bug.cgi?id=99314
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp222
1 files changed, 26 insertions, 196 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
index 5b0b22963..2e44af2d7 100644
--- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
@@ -122,14 +122,20 @@ public:
if (!subNode.shouldGenerate())
continue;
switch (subNode.op()) {
- case CheckStructure:
- case StructureTransitionWatchpoint: {
+ 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;
}
@@ -162,7 +168,7 @@ public:
dataLog("Zeroing the structure to hoist for %s because the ratio is %lf.\n",
m_graph.nameOfVariableAccessData(variable), variable->voteRatio());
#endif
- iter->second.m_structure = 0;
+ iter->value.m_structure = 0;
}
// Disable structure check hoisting for variables that cross the OSR entry that
@@ -187,7 +193,7 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
continue;
- if (!iter->second.m_structure)
+ if (!iter->value.m_structure)
continue;
JSValue value = m_graph.m_mustHandleValues[i];
if (!value || !value.isCell()) {
@@ -195,162 +201,34 @@ public:
dataLog("Zeroing the structure to hoist for %s because the OSR entry value is not a cell: %s.\n",
m_graph.nameOfVariableAccessData(variable), value.description());
#endif
- iter->second.m_structure = 0;
+ iter->value.m_structure = 0;
continue;
}
- if (value.asCell()->structure() != iter->second.m_structure) {
+ if (value.asCell()->structure() != iter->value.m_structure) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog("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->second.m_structure);
+ m_graph.nameOfVariableAccessData(variable), value.asCell()->structure(), iter->value.m_structure);
#endif
- iter->second.m_structure = 0;
+ iter->value.m_structure = 0;
continue;
}
}
}
- // Identify the set of variables that are live across a structure clobber.
-
- Operands<VariableAccessData*> live(
- m_graph.m_blocks[0]->variablesAtTail.numberOfArguments(),
- m_graph.m_blocks[0]->variablesAtTail.numberOfLocals());
- for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
- BasicBlock* block = m_graph.m_blocks[blockIndex].get();
- if (!block)
- continue;
- ASSERT(live.numberOfArguments() == block->variablesAtTail.numberOfArguments());
- ASSERT(live.numberOfLocals() == block->variablesAtTail.numberOfLocals());
- for (unsigned i = live.size(); i--;) {
- NodeIndex indexAtTail = block->variablesAtTail[i];
- VariableAccessData* variable;
- if (indexAtTail == NoNode)
- variable = 0;
- else
- variable = m_graph[indexAtTail].variableAccessData();
- live[i] = variable;
- }
- for (unsigned indexInBlock = block->size(); indexInBlock--;) {
- NodeIndex nodeIndex = block->at(indexInBlock);
- Node& node = m_graph[nodeIndex];
- if (!node.shouldGenerate())
- continue;
- switch (node.op()) {
- case GetLocal:
- case Flush:
- // This is a birth.
- live.operand(node.local()) = node.variableAccessData();
- break;
-
- case SetLocal:
- case SetArgument:
- ASSERT(live.operand(node.local())); // Must be live.
- ASSERT(live.operand(node.local()) == node.variableAccessData()); // Must have the variable we expected.
- // This is a death.
- live.operand(node.local()) = 0;
- break;
-
- // Use the CFA's notion of what clobbers the world.
- case ValueAdd:
- if (m_graph.addShouldSpeculateInteger(node))
- break;
- if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
- break;
- clobber(live);
- break;
-
- case CompareLess:
- case CompareLessEq:
- case CompareGreater:
- case CompareGreaterEq:
- case CompareEq: {
- Node& left = m_graph[node.child1()];
- Node& right = m_graph[node.child2()];
- if (Node::shouldSpeculateInteger(left, right))
- break;
- if (Node::shouldSpeculateNumber(left, right))
- break;
- if (node.op() == CompareEq) {
- if ((m_graph.isConstant(node.child1().index())
- && m_graph.valueOfJSConstant(node.child1().index()).isNull())
- || (m_graph.isConstant(node.child2().index())
- && m_graph.valueOfJSConstant(node.child2().index()).isNull()))
- break;
-
- if (Node::shouldSpeculateFinalObject(left, right))
- break;
- if (Node::shouldSpeculateArray(left, right))
- break;
- if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther())
- break;
- if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther())
- break;
- if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther())
- break;
- if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther())
- break;
- }
- clobber(live);
- break;
- }
-
- case GetByVal:
- case PutByVal:
- case PutByValAlias:
- if (m_graph.byValIsPure(node))
- break;
- clobber(live);
- break;
-
- case GetMyArgumentsLengthSafe:
- case GetMyArgumentByValSafe:
- case GetById:
- case GetByIdFlush:
- case PutStructure:
- case PhantomPutStructure:
- case PutById:
- case PutByIdDirect:
- case Call:
- case Construct:
- case Resolve:
- case ResolveBase:
- case ResolveBaseStrictPut:
- case ResolveGlobal:
- case ArrayPush:
- case ArrayPop:
- case Arrayify:
- clobber(live);
- break;
-
- default:
- ASSERT(node.op() != Phi);
- break;
- }
- }
- }
-
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->second.m_structure) {
- dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->first));
- continue;
- }
- if (it->second.m_isClobbered && !it->second.m_structure->transitionWatchpointSetIsStillValid()) {
- dataLog("Not hoisting checks for %s because the structure is clobbered and has an invalid watchpoint set.\n", m_graph.nameOfVariableAccessData(it->first));
+ if (!it->value.m_structure) {
+ dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->key));
continue;
}
- dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->first));
+ dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->key));
}
#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- // Make changes:
- // 1) If a variable's live range does not span a clobber, then inject structure
- // checks before the SetLocal.
- // 2) If a variable's live range spans a clobber but is watchpointable, then
- // inject structure checks before the SetLocal and replace all other structure
- // checks on that variable with structure transition watchpoints.
+ // Place CheckStructure's at SetLocal sites.
InsertionSet<NodeIndex> insertionSet;
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
@@ -376,9 +254,7 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
break;
- if (!iter->second.m_structure)
- break;
- if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
+ if (!iter->value.m_structure)
break;
node.ref();
@@ -392,7 +268,7 @@ public:
m_graph.append(getLocal);
insertionSet.append(indexInBlock + 1, getLocalIndex);
- Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), 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);
@@ -412,9 +288,7 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
break;
- if (!iter->second.m_structure)
- break;
- if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
+ if (!iter->value.m_structure)
break;
// First insert a dead SetLocal to tell OSR that the child's value should
@@ -431,7 +305,7 @@ public:
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->second.m_structure)), child1);
+ Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), child1);
checkStructure.ref();
NodeIndex checkStructureIndex = m_graph.size();
m_graph.append(checkStructure);
@@ -440,28 +314,6 @@ public:
break;
}
- case CheckStructure: {
- Node& child = m_graph[node.child1()];
- if (child.op() != GetLocal)
- break;
- HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(child.variableAccessData());
- if (iter == m_map.end())
- break;
- if (!iter->second.m_structure)
- break;
- if (!iter->second.m_isClobbered) {
- node.setOpAndDefaultFlags(Phantom);
- ASSERT(node.refCount() == 1);
- break;
- }
- if (!iter->second.m_structure->transitionWatchpointSetIsStillValid())
- break;
- ASSERT(iter->second.m_structure == node.structureSet().singletonStructure());
- node.convertToStructureTransitionWatchpoint();
- changed = true;
- break;
- }
-
default:
break;
}
@@ -476,12 +328,12 @@ private:
void noticeStructureCheck(VariableAccessData* variable, Structure* structure)
{
HashMap<VariableAccessData*, CheckData>::AddResult result =
- m_map.add(variable, CheckData(structure, false));
+ m_map.add(variable, CheckData(structure));
if (result.isNewEntry)
return;
- if (result.iterator->second.m_structure == structure)
+ if (result.iterator->value.m_structure == structure)
return;
- result.iterator->second.m_structure = 0;
+ result.iterator->value.m_structure = 0;
}
void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set)
@@ -493,38 +345,16 @@ private:
noticeStructureCheck(variable, set.singletonStructure());
}
- void noticeClobber(VariableAccessData* variable)
- {
- HashMap<VariableAccessData*, CheckData>::iterator iter =
- m_map.find(variable);
- if (iter == m_map.end())
- return;
- iter->second.m_isClobbered = true;
- }
-
- void clobber(const Operands<VariableAccessData*>& live)
- {
- for (size_t i = live.size(); i--;) {
- VariableAccessData* variable = live[i];
- if (!variable)
- continue;
- noticeClobber(variable);
- }
- }
-
struct CheckData {
Structure* m_structure;
- bool m_isClobbered;
CheckData()
: m_structure(0)
- , m_isClobbered(false)
{
}
- CheckData(Structure* structure, bool isClobbered)
+ CheckData(Structure* structure)
: m_structure(structure)
- , m_isClobbered(isClobbered)
{
}
};