Diff
Modified: branches/dfgopt/Source/_javascript_Core/ChangeLog (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/ChangeLog 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/ChangeLog 2012-05-23 06:07:53 UTC (rev 118126)
@@ -1,5 +1,40 @@
2012-05-22 Filip Pizlo <[email protected]>
+ Unreviewed, rollout http://trac.webkit.org/changeset/118108
+ https://bugs.webkit.org/show_bug.cgi?id=87161
+
+ The redundant store elimination is overzealous in some cases, because
+ it fails to catch implicit reads of captured local variables.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUse):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUses):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeProperArgumentsUse):
+ * dfg/DFGCSEPhase.cpp:
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::setReplacement):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGNode.h:
+ (Node):
+ (JSC::DFG::Node::hasConstant):
+ (JSC::DFG::Node::valueOfJSConstant):
+ (JSC::DFG::Node::hasStructureTransitionData):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-05-22 Filip Pizlo <[email protected]>
+
DFG CSE should do redundant store elimination
https://bugs.webkit.org/show_bug.cgi?id=87161
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGAbstractState.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -264,8 +264,7 @@
switch (node.op()) {
case JSConstant:
- case WeakJSConstant:
- case PhantomArguments: {
+ case WeakJSConstant: {
forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
node.setCanExit(false);
break;
@@ -1412,7 +1411,6 @@
}
case PutStructure:
- case PhantomPutStructure:
node.setCanExit(false);
clobberStructures(indexInBlock);
forNode(node.child1()).set(node.structureTransitionData().newStructure);
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -178,7 +178,7 @@
// a variable that we think is aliased to the arguments, then it
// may escape at this point. In future, we could track transitive
// aliasing. But not yet.
- observeBadArgumentsUse(node, node.child1());
+ observeBadArgumentsUse(node.child1());
if (variableAccessData->isCaptured())
break;
@@ -269,7 +269,7 @@
// That's so awful and pretty much impossible since it would
// imply that the arguments were predicted integer, but it's
// good to be defensive and thorough.
- observeBadArgumentsUse(node, node.child2());
+ observeBadArgumentsUse(node.child2());
observeProperArgumentsUse(node, node.child1());
break;
}
@@ -392,6 +392,31 @@
VariableAccessData* variableAccessData = node.variableAccessData();
+ // If this is a store into the arguments register for an InlineCallFrame*
+ // that does not create arguments, then kill it.
+ int argumentsRegister =
+ m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
+ if ((variableAccessData->local() == argumentsRegister
+ || variableAccessData->local()
+ == unmodifiedArgumentsRegister(argumentsRegister))
+ && !m_createsArguments.contains(source.codeOrigin.inlineCallFrame)) {
+ // Find the Flush. It should be the next instruction.
+ Node& flush = m_graph[block->at(indexInBlock + 1)];
+ ASSERT(flush.op() == Flush);
+ ASSERT(flush.variableAccessData() == variableAccessData);
+ ASSERT(flush.child1() == nodeIndex);
+ // Be defensive in release mode.
+ if (flush.op() != Flush
+ || flush.variableAccessData() != variableAccessData
+ || flush.child1() != nodeIndex)
+ break;
+ flush.setOpAndDefaultFlags(Nop);
+ m_graph.clearAndDerefChild1(flush);
+ flush.setRefCount(0);
+ changed = true;
+ break;
+ }
+
if (variableAccessData->isCaptured())
break;
@@ -558,35 +583,6 @@
insertionSet.execute(*block);
}
- 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;
- if (node.op() != CreateArguments)
- continue;
- // If this is a CreateArguments for an InlineCallFrame* that does
- // not create arguments, then replace it with a PhantomArguments.
- // PhantomArguments is a constant that represents JSValue() (the
- // empty value) in DFG and arguments creation for OSR exit.
- if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
- continue;
- Node phantom(Phantom, node.codeOrigin);
- phantom.children = node.children;
- phantom.ref();
- node.setOpAndDefaultFlags(PhantomArguments);
- node.children.reset();
- NodeIndex phantomNodeIndex = m_graph.size();
- m_graph.append(phantom);
- insertionSet.append(indexInBlock, phantomNodeIndex);
- }
- insertionSet.execute(*block);
- }
-
if (changed)
m_graph.collectGarbage();
@@ -601,43 +597,32 @@
DefaultHash<VariableAccessData*>::Hash,
NullableHashTraits<VariableAccessData*> > m_argumentsAliasing;
- void observeBadArgumentsUse(Node& node, Edge edge)
+ void observeBadArgumentsUse(Edge edge)
{
if (!edge)
return;
Node& child = m_graph[edge];
- switch (child.op()) {
- case CreateArguments: {
- if (node.codeOrigin.inlineCallFrame != child.codeOrigin.inlineCallFrame)
- m_createsArguments.add(child.codeOrigin.inlineCallFrame);
- break;
+ if (child.op() != GetLocal)
+ return;
+
+ if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)) {
+ m_createsArguments.add(child.codeOrigin.inlineCallFrame);
+ return;
}
-
- case GetLocal: {
- if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)) {
- m_createsArguments.add(child.codeOrigin.inlineCallFrame);
- return;
- }
-
- VariableAccessData* variableAccessData = child.variableAccessData();
- if (variableAccessData->isCaptured())
- return;
-
- ArgumentsAliasingData& data = ""
- data.escapes = true;
- break;
- }
-
- default:
- break;
- }
+
+ VariableAccessData* variableAccessData = child.variableAccessData();
+ if (variableAccessData->isCaptured())
+ return;
+
+ ArgumentsAliasingData& data = ""
+ data.escapes = true;
}
void observeBadArgumentsUses(Node& node)
{
for (unsigned i = m_graph.numChildren(node); i--;)
- observeBadArgumentsUse(node, m_graph.child(node, i));
+ observeBadArgumentsUse(m_graph.child(node, i));
}
void observeProperArgumentsUse(Node& node, Edge edge)
@@ -664,13 +649,9 @@
}
VariableAccessData* variableAccessData = child.variableAccessData();
- if (variableAccessData->isCaptured()) {
- if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)
- && node.codeOrigin.inlineCallFrame != child.codeOrigin.inlineCallFrame)
- m_createsArguments.add(child.codeOrigin.inlineCallFrame);
+ if (variableAccessData->isCaptured())
return;
- }
-
+
ArgumentsAliasingData& data = ""
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
}
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -199,33 +199,6 @@
return NoNode;
}
- NodeIndex globalVarStoreElimination(unsigned varNumber, JSGlobalObject* globalObject)
- {
- for (unsigned i = m_indexInBlock; i--;) {
- NodeIndex index = m_currentBlock->at(i);
- Node& node = m_graph[index];
- if (!node.shouldGenerate())
- continue;
- switch (node.op()) {
- case PutGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
- return index;
- break;
-
- case GetGlobalVar:
- if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
- return NoNode;
- break;
-
- default:
- break;
- }
- if (m_graph.clobbersWorld(index) || node.canExit())
- return NoNode;
- }
- return NoNode;
- }
-
NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -330,56 +303,6 @@
return false;
}
- NodeIndex putStructureStoreElimination(NodeIndex child1)
- {
- for (unsigned i = m_indexInBlock; i--;) {
- NodeIndex index = m_currentBlock->at(i);
- if (index == child1)
- break;
- Node& node = m_graph[index];
- if (!node.shouldGenerate())
- break;
- switch (node.op()) {
- case CheckStructure:
- return NoNode;
-
- case PhantomPutStructure:
- if (node.child1() == child1) // No need to retrace our steps.
- return NoNode;
- break;
-
- case PutStructure:
- if (node.child1() == child1)
- return index;
- break;
-
- // PutStructure needs to execute if we GC. Hence this needs to
- // be careful with respect to nodes that GC.
- case CreateArguments:
- case TearOffArguments:
- case NewFunctionNoCheck:
- case NewFunction:
- case NewFunctionExpression:
- case CreateActivation:
- case TearOffActivation:
- case StrCat:
- case ToPrimitive:
- case NewRegexp:
- case NewArrayBuffer:
- case NewArray:
- case NewObject:
- case CreateThis:
- return NoNode;
-
- default:
- break;
- }
- if (m_graph.clobbersWorld(index) || node.canExit())
- return NoNode;
- }
- return NoNode;
- }
-
NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -426,52 +349,6 @@
return NoNode;
}
- NodeIndex putByOffsetStoreElimination(unsigned identifierNumber, NodeIndex child1)
- {
- for (unsigned i = m_indexInBlock; i--;) {
- NodeIndex index = m_currentBlock->at(i);
- if (index == child1)
- break;
-
- Node& node = m_graph[index];
- if (!node.shouldGenerate())
- continue;
- switch (node.op()) {
- case GetByOffset:
- if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
- return NoNode;
- break;
-
- case PutByOffset:
- if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) {
- if (node.child1() == child1) // Must be same property storage.
- return index;
- return NoNode;
- }
- break;
-
- case PutByVal:
- case PutByValAlias:
- case GetByVal:
- if (m_graph.byValIsPure(node)) {
- // If PutByVal speculates that it's accessing an array with an
- // integer index, then it's impossible for it to cause a structure
- // change.
- break;
- }
- return NoNode;
-
- default:
- if (m_graph.clobbersWorld(index))
- return NoNode;
- break;
- }
- if (node.canExit())
- return NoNode;
- }
- return NoNode;
- }
-
NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -602,53 +479,6 @@
return NoNode;
}
- // This returns the Flush node that is keeping a SetLocal alive.
- NodeIndex setLocalStoreElimination(VirtualRegister local)
- {
- for (unsigned i = m_indexInBlock; i--;) {
- NodeIndex index = m_currentBlock->at(i);
- Node& node = m_graph[index];
- if (!node.shouldGenerate())
- continue;
- switch (node.op()) {
- case GetLocal:
- case SetLocal:
- if (node.local() == local)
- return NoNode;
- break;
-
- case GetLocalUnlinked:
- if (node.unlinkedLocal() == local)
- return NoNode;
- break;
-
- case Flush: {
- if (node.local() != local)
- break;
- if (!i)
- break;
- NodeIndex prevIndex = m_currentBlock->at(i - 1);
- if (prevIndex != node.child1().index())
- break;
- ASSERT(m_graph[prevIndex].local() == local);
- ASSERT(m_graph[prevIndex].variableAccessData() == node.variableAccessData());
- ASSERT(m_graph[prevIndex].shouldGenerate());
- if (m_graph[prevIndex].refCount() > 1)
- break;
- return index;
- }
-
- default:
- if (m_graph.clobbersWorld(index))
- return NoNode;
- break;
- }
- if (node.canExit())
- return NoNode;
- }
- return NoNode;
- }
-
void performSubstitution(Edge& child, bool addRef = true)
{
// Check if this operand is actually unused.
@@ -670,16 +500,14 @@
m_graph[child].ref();
}
- enum PredictionHandlingMode { RequireSamePrediction, AllowPredictionMismatch };
- bool setReplacement(NodeIndex replacement, PredictionHandlingMode predictionHandlingMode = RequireSamePrediction)
+ bool setReplacement(NodeIndex replacement)
{
if (replacement == NoNode)
return false;
// Be safe. Don't try to perform replacements if the predictions don't
// agree.
- if (predictionHandlingMode == RequireSamePrediction
- && m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
+ if (m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
return false;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
@@ -708,17 +536,6 @@
node.setOpAndDefaultFlags(Phantom);
}
- void eliminate(NodeIndex nodeIndex, NodeType phantomType = Phantom)
- {
- if (nodeIndex == NoNode)
- return;
- Node& node = m_graph[nodeIndex];
- if (node.refCount() != 1)
- return;
- ASSERT(node.mustGenerate());
- node.setOpAndDefaultFlags(phantomType);
- }
-
void performNodeCSE(Node& node)
{
bool shouldGenerate = node.shouldGenerate();
@@ -804,12 +621,6 @@
NodeIndex phiIndex = node.child1().index();
if (!setReplacement(possibleReplacement))
break;
- // If the GetLocal we replaced used to refer to a SetLocal, then it now
- // should refer to the child of the SetLocal instead.
- if (m_graph[phiIndex].op() == SetLocal) {
- ASSERT(node.child1().index() == phiIndex);
- m_graph.changeEdge(node.children.child1(), m_graph[phiIndex].child1());
- }
NodeIndex oldTailIndex = m_currentBlock->variablesAtTail.operand(
variableAccessData->local());
if (oldTailIndex == m_compileIndex) {
@@ -833,32 +644,10 @@
break;
}
- case SetLocal: {
- VariableAccessData* variableAccessData = node.variableAccessData();
- if (!variableAccessData->isCaptured())
- break;
- VirtualRegister local = variableAccessData->local();
- NodeIndex replacementIndex = setLocalStoreElimination(local);
- if (replacementIndex == NoNode)
- break;
- Node& replacement = m_graph[replacementIndex];
- ASSERT(replacement.op() == Flush);
- ASSERT(replacement.refCount() == 1);
- ASSERT(replacement.shouldGenerate());
- ASSERT(replacement.mustGenerate());
- replacement.setOpAndDefaultFlags(Phantom);
- NodeIndex setLocalIndex = replacement.child1().index();
- ASSERT(m_graph[setLocalIndex].op() == SetLocal);
- m_graph.clearAndDerefChild1(replacement);
- replacement.children.child1() = m_graph[setLocalIndex].child1();
- m_graph.ref(replacement.child1());
- break;
- }
-
case JSConstant:
// This is strange, but necessary. Some phases will convert nodes to constants,
// which may result in duplicated constants. We use CSE to clean this up.
- setReplacement(constantCSE(node), AllowPredictionMismatch);
+ setReplacement(constantCSE(node));
break;
case GetArrayLength:
@@ -891,10 +680,6 @@
setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
break;
- case PutGlobalVar:
- eliminate(globalVarStoreElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
- break;
-
case GetByVal:
if (m_graph.byValIsPure(node))
setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index()));
@@ -911,10 +696,6 @@
if (checkStructureLoadElimination(node.structureSet(), node.child1().index()))
eliminate();
break;
-
- case PutStructure:
- eliminate(putStructureStoreElimination(node.child1().index()), PhantomPutStructure);
- break;
case CheckFunction:
if (checkFunctionElimination(node.function(), node.child1().index()))
@@ -936,10 +717,6 @@
setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
break;
- case PutByOffset:
- eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
- break;
-
default:
// do nothing.
break;
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGNode.h (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGNode.h 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGNode.h 2012-05-23 06:07:53 UTC (rev 118126)
@@ -201,21 +201,9 @@
return op() == WeakJSConstant;
}
- bool isPhantomArguments()
- {
- return op() == PhantomArguments;
- }
-
bool hasConstant()
{
- switch (op()) {
- case JSConstant:
- case WeakJSConstant:
- case PhantomArguments:
- return true;
- default:
- return false;
- }
+ return isConstant() || isWeakConstant();
}
unsigned constantNumber()
@@ -251,17 +239,9 @@
JSValue valueOfJSConstant(CodeBlock* codeBlock)
{
- switch (op()) {
- case WeakJSConstant:
+ if (op() == WeakJSConstant)
return JSValue(weakConstant());
- case JSConstant:
- return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
- case PhantomArguments:
- return JSValue();
- default:
- ASSERT_NOT_REACHED();
- return JSValue(); // Have to return something in release mode.
- }
+ return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
}
bool isInt32Constant(CodeBlock* codeBlock)
@@ -609,7 +589,7 @@
bool hasStructureTransitionData()
{
- return op() == PutStructure || op() == PhantomPutStructure;
+ return op() == PutStructure;
}
StructureTransitionData& structureTransitionData()
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGNodeType.h (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGNodeType.h 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGNodeType.h 2012-05-23 06:07:53 UTC (rev 118126)
@@ -37,11 +37,11 @@
// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
#define FOR_EACH_DFG_OP(macro) \
/* A constant in the CodeBlock's constant pool. */\
- macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
+ macro(JSConstant, NodeResultJS) \
\
/* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
/* code block. */\
- macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
+ macro(WeakJSConstant, NodeResultJS) \
\
/* Nodes for handling functions (both as call and as construct). */\
macro(ConvertThis, NodeResultJS) \
@@ -53,10 +53,10 @@
/* VariableAccessData, and thus will share predictions. */\
macro(GetLocal, NodeResultJS) \
macro(SetLocal, 0) \
- macro(Phantom, NodeMustGenerate | NodeDoesNotExit) \
- macro(Nop, 0 | NodeDoesNotExit) \
- macro(Phi, 0 | NodeDoesNotExit) \
- macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
+ macro(Phantom, NodeMustGenerate) \
+ macro(Nop, 0) \
+ macro(Phi, 0) \
+ macro(Flush, NodeMustGenerate) \
\
/* Get the value of a local variable, without linking into the VariableAccessData */\
/* network. This is only valid for variable accesses whose predictions originated */\
@@ -64,12 +64,12 @@
macro(GetLocalUnlinked, NodeResultJS) \
\
/* Marker for an argument being set at the prologue of a function. */\
- macro(SetArgument, 0 | NodeDoesNotExit) \
+ macro(SetArgument, 0) \
\
/* Hint that inlining begins here. No code is generated for this node. It's only */\
/* used for copying OSR data into inline frame data, to support reification of */\
/* call frames of inlined functions. */\
- macro(InlineStart, 0 | NodeDoesNotExit) \
+ macro(InlineStart, 0) \
\
/* Nodes for bitwise operations. */\
macro(BitAnd, NodeResultInt32) \
@@ -113,12 +113,11 @@
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
- macro(PutStructure, NodeMustGenerate) \
- macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
+ macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
macro(GetPropertyStorage, NodeResultStorage) \
macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \
macro(GetByOffset, NodeResultJS) \
- macro(PutByOffset, NodeMustGenerate) \
+ macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
macro(GetArrayLength, NodeResultInt32) \
macro(GetArgumentsLength, NodeResultInt32) \
macro(GetStringLength, NodeResultInt32) \
@@ -136,7 +135,7 @@
macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
- macro(PutGlobalVar, NodeMustGenerate) \
+ macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckFunction, NodeMustGenerate) \
\
/* Optimizations for array mutation. */\
@@ -198,7 +197,6 @@
/* Nodes used for arguments. Similar to activation support, only it makes even less */\
/* sense. */\
macro(CreateArguments, NodeResultJS) \
- macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
macro(TearOffArguments, NodeMustGenerate) \
macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -618,9 +618,7 @@
case Int32ToDouble:
case GetLocalUnlinked:
case GetMyArgumentsLength:
- case GetMyArgumentByVal:
- case PhantomPutStructure:
- case PhantomArguments: {
+ case GetMyArgumentByVal: {
// This node should never be visible at this stage of compilation. It is
// inserted by fixup(), which follows this phase.
ASSERT_NOT_REACHED();
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -1358,15 +1358,13 @@
return ValueRecovery::argumentsThatWereNotCreated();
case HaveNode: {
- Node* nodePtr = &at(valueSource.nodeIndex());
-
- if (nodePtr->isPhantomArguments())
- return ValueRecovery::argumentsThatWereNotCreated();
-
- if (nodePtr->hasConstant())
+ if (isConstant(valueSource.nodeIndex()))
return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
+ Node* nodePtr = &at(valueSource.nodeIndex());
if (!nodePtr->shouldGenerate()) {
+ if (nodePtr->op() == CreateArguments)
+ return ValueRecovery::argumentsThatWereNotCreated();
// It's legitimately dead. As in, nobody will ever use this node, or operand,
// ever. Set it to Undefined to make the GC happy after the OSR.
return ValueRecovery::constant(jsUndefined());
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -1853,7 +1853,6 @@
switch (op) {
case JSConstant:
- case PhantomArguments:
initConstantInfo(m_compileIndex);
break;
@@ -3488,15 +3487,6 @@
break;
}
- case PhantomPutStructure: {
- m_jit.addWeakReferenceTransition(
- node.codeOrigin.codeOriginOwner(),
- node.structureTransitionData().previousStructure,
- node.structureTransitionData().newStructure);
- noResult(m_compileIndex);
- break;
- }
-
case PutStructure: {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
Modified: branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (118125 => 118126)
--- branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-05-23 05:40:20 UTC (rev 118125)
+++ branches/dfgopt/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-05-23 06:07:53 UTC (rev 118126)
@@ -1924,7 +1924,6 @@
switch (op) {
case JSConstant:
- case PhantomArguments:
initConstantInfo(m_compileIndex);
break;
@@ -3495,15 +3494,6 @@
break;
}
- case PhantomPutStructure: {
- m_jit.addWeakReferenceTransition(
- node.codeOrigin.codeOriginOwner(),
- node.structureTransitionData().previousStructure,
- node.structureTransitionData().newStructure);
- noResult(m_compileIndex);
- break;
- }
-
case PutStructure: {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();