Diff
Modified: trunk/LayoutTests/ChangeLog (183811 => 183812)
--- trunk/LayoutTests/ChangeLog 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/LayoutTests/ChangeLog 2015-05-05 16:34:21 UTC (rev 183812)
@@ -1,3 +1,16 @@
+2015-05-04 Basile Clement <[email protected]>
+
+ Allow CreateActivation sinking
+ https://bugs.webkit.org/show_bug.cgi?id=144300
+
+ Reviewed by Filip Pizlo.
+
+ Add a performance test for activation allocation sinking.
+
+ * js/regress/script-tests/sink-huge-activation.js: Added.
+ (bar):
+ (foo):
+
2015-05-05 Andreas Kling <[email protected]>
Fix up fast/performance/performance-now-crash-on-navigated-window.html after r183795.
Added: trunk/LayoutTests/js/regress/script-tests/sink-huge-activation.js (0 => 183812)
--- trunk/LayoutTests/js/regress/script-tests/sink-huge-activation.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/sink-huge-activation.js 2015-05-05 16:34:21 UTC (rev 183812)
@@ -0,0 +1,41 @@
+function bar() { }
+
+function foo(alpha) {
+ var x0 = 0;
+ var x1 = 0;
+ var x2 = 0;
+ var x3 = 0;
+ var x4 = 0;
+ var x5 = 0;
+ var x6 = 0;
+ var x7 = 0;
+ var x8 = 0;
+ var x9 = 0;
+ var x10 = 0;
+ var x11 = 0;
+ var x12 = 0;
+ var x13 = 0;
+ var x14 = 0;
+ var x15 = 0;
+ var x16 = 0;
+ var x17 = 0;
+ var x18 = 0;
+ var x19 = 0;
+ if (alpha) {
+ bar(function () {
+ return (x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 +
+ x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19);
+ });
+ return x17;
+ }
+ return x12;
+}
+
+noInline(bar);
+noInline(foo);
+
+for (var i = 0; i < 1000000; i++) {
+ var result = foo(!(i % 1000));
+ if (result !== 0)
+ throw "Error: expected undefined, got " + result;
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (183811 => 183812)
--- trunk/Source/_javascript_Core/ChangeLog 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-05-05 16:34:21 UTC (rev 183812)
@@ -1,3 +1,69 @@
+2015-05-04 Basile Clement <[email protected]>
+
+ Allow CreateActivation sinking
+ https://bugs.webkit.org/show_bug.cgi?id=144300
+
+ Reviewed by Filip Pizlo.
+
+ This pursues the work started in
+ https://bugs.webkit.org/show_bug.cgi?id=144016 to expand the set of
+ allocations we are able to sink by allowing sinking of CreateActivation
+ node.
+
+ This is achieved by following closely the way NewObject is currently
+ sunk: we add a new PhantomCreateActivation node to record the initial
+ position of the CreateActivation node, new ClosureVarPLoc promoted heap
+ locations to keep track of the variables put in the activation, and a
+ new MaterializeCreateActivation node to allocate and populate the sunk
+ activation.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNode.cpp:
+ (JSC::DFG::Node::convertToPutClosureVarHint):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToPhantomCreateActivation):
+ (JSC::DFG::Node::isActivationAllocation):
+ (JSC::DFG::Node::isPhantomActivationAllocation):
+ (JSC::DFG::Node::isPhantomAllocation):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGObjectAllocationSinkingPhase.cpp:
+ (JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
+ (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+ (JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
+ (JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGPromotedHeapLocation.cpp:
+ (WTF::printInternal):
+ * dfg/DFGPromotedHeapLocation.h:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGValidate.cpp:
+ (JSC::DFG::Validate::validateCPS):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):
+ * ftl/FTLOperations.cpp:
+ (JSC::FTL::operationMaterializeObjectInOSR):
+ * tests/stress/activation-sink-osrexit.js: Added.
+ (bar):
+ (foo.set result):
+ * tests/stress/activation-sink.js: Added.
+ (bar):
+
2015-05-04 Filip Pizlo <[email protected]>
Unreviewed, fix stale comment.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -1495,6 +1495,7 @@
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case BottomValue:
@@ -1517,8 +1518,9 @@
forNode(node).set(m_graph, set);
break;
}
-
+
case CreateActivation:
+ case MaterializeCreateActivation:
forNode(node).set(
m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -854,6 +854,8 @@
case PhantomNewObject:
case MaterializeNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
+ case MaterializeCreateActivation:
read(HeapObjectCount);
write(HeapObjectCount);
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -198,6 +198,7 @@
case BottomValue:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case GetMyArgumentByVal:
@@ -236,6 +237,7 @@
case GetEnumeratorGenericPname:
case ToIndexString:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
return true;
case MultiPutByOffset:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -1029,6 +1029,7 @@
case BooleanToNumber:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case ForwardVarargs:
@@ -1036,6 +1037,7 @@
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PutStack:
case KillStack:
case GetStack:
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGNode.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -158,6 +158,14 @@
child2().node(), child3().node());
}
+void Node::convertToPutClosureVarHint()
+{
+ ASSERT(m_op == PutClosureVar);
+ convertToPutHint(
+ PromotedLocationDescriptor(ClosureVarPLoc, scopeOffset().offset()),
+ child1().node(), child2().node());
+}
+
PromotedLocationDescriptor Node::promotedLocationDescriptor()
{
return PromotedLocationDescriptor(static_cast<PromotedLocationKind>(m_opInfo), m_opInfo2);
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -569,6 +569,7 @@
void convertToPutByOffsetHint();
void convertToPutStructureHint(Node* structure);
+ void convertToPutClosureVarHint();
void convertToPhantomNewObject()
{
@@ -591,6 +592,17 @@
children = AdjacencyList();
}
+ void convertToPhantomCreateActivation()
+ {
+ ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
+ m_op = PhantomCreateActivation;
+ m_flags &= ~NodeHasVarArgs;
+ m_flags |= NodeMustGenerate;
+ m_opInfo = 0;
+ m_opInfo2 = 0;
+ children = AdjacencyList();
+ }
+
void convertPhantomToPhantomLocal()
{
ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
@@ -1442,6 +1454,27 @@
}
}
+ bool isActivationAllocation()
+ {
+ switch (op()) {
+ case CreateActivation:
+ case MaterializeCreateActivation:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isPhantomActivationAllocation()
+ {
+ switch (op()) {
+ case PhantomCreateActivation:
+ return true;
+ default:
+ return false;
+ }
+ }
+
bool isPhantomAllocation()
{
switch (op()) {
@@ -1449,6 +1482,7 @@
case PhantomDirectArguments:
case PhantomClonedArguments:
case PhantomNewFunction:
+ case PhantomCreateActivation:
return true;
default:
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -254,6 +254,8 @@
macro(CheckStructureImmediate, NodeMustGenerate) \
macro(MaterializeNewObject, NodeResultJS | NodeHasVarArgs) \
macro(PhantomNewFunction, NodeResultJS | NodeMustGenerate) \
+ macro(PhantomCreateActivation, NodeResultJS | NodeMustGenerate) \
+ macro(MaterializeCreateActivation, NodeResultJS | NodeHasVarArgs) \
\
/* Nodes for misc operations. */\
macro(Breakpoint, NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -506,6 +506,15 @@
}
break;
}
+
+ case PutClosureVar: {
+ Node* target = node->child1().node();
+ if (m_sinkCandidates.contains(target)) {
+ ASSERT(target->isPhantomActivationAllocation());
+ node->convertToPutClosureVarHint();
+ }
+ break;
+ }
case PutStructure: {
Node* target = node->child1().node();
@@ -569,11 +578,43 @@
break;
}
+ case CreateActivation: {
+ if (m_sinkCandidates.contains(node)) {
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(ActivationScopePLoc, node).createHint(
+ m_graph, node->origin, node->child1().node()));
+ node->convertToPhantomCreateActivation();
+ }
+ break;
+ }
+
+ case MaterializeCreateActivation: {
+ if (m_sinkCandidates.contains(node)) {
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(ActivationScopePLoc, node).createHint(
+ m_graph, node->origin, m_graph.varArgChild(node, 0).node()));
+ ObjectMaterializationData& data = ""
+ for (unsigned i = 0; i < data.m_properties.size(); ++i) {
+ unsigned identifierNumber = data.m_properties[i].m_identifierNumber;
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(
+ ClosureVarPLoc, node, identifierNumber).createHint(
+ m_graph, node->origin,
+ m_graph.varArgChild(node, i + 1).node()));
+ }
+ node->convertToPhantomCreateActivation();
+ }
+ break;
+ }
+
case StoreBarrier:
case StoreBarrierWithNullCheck: {
Node* target = node->child1().node();
if (m_sinkCandidates.contains(target)) {
- ASSERT(target->isPhantomObjectAllocation());
+ ASSERT(target->isPhantomAllocation());
node->remove();
}
break;
@@ -775,6 +816,7 @@
switch (node->op()) {
case NewObject:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
sinkCandidate();
m_graph.doToChildren(
node,
@@ -793,18 +835,28 @@
});
break;
+ case CreateActivation:
+ if (!m_graph.symbolTableFor(node->origin.semantic)->singletonScope()->isStillValid())
+ sinkCandidate();
+ m_graph.doToChildren(
+ node,
+ [&] (Edge edge) {
+ escape(edge.node());
+ });
+ break;
+
case MovHint:
case Check:
case PutHint:
+ case StoreBarrier:
+ case StoreBarrierWithNullCheck:
break;
case PutStructure:
case CheckStructure:
case GetByOffset:
case MultiGetByOffset:
- case GetGetterSetterByOffset:
- case StoreBarrier:
- case StoreBarrierWithNullCheck: {
+ case GetGetterSetterByOffset: {
Node* target = node->child1().node();
if (!target->isObjectAllocation())
escape(target);
@@ -820,6 +872,14 @@
escape(node->child3().node());
break;
}
+
+ case PutClosureVar: {
+ Node* target = node->child1().node();
+ if (!target->isActivationAllocation())
+ escape(target);
+ escape(node->child2().node());
+ break;
+ }
case MultiPutByOffset:
// FIXME: In the future we should be able to handle this. It's just a matter of
@@ -869,6 +929,19 @@
escapee->child1());
break;
+ case CreateActivation:
+ case MaterializeCreateActivation: {
+ ObjectMaterializationData* data = ""
+
+ result = m_graph.addNode(
+ escapee->prediction(), Node::VarArg, MaterializeCreateActivation,
+ NodeOrigin(
+ escapee->origin.semantic,
+ where->origin.forExit),
+ OpInfo(data), OpInfo(), 0, 0);
+ break;
+ }
+
default:
DFG_CRASH(m_graph, escapee, "Bad escapee op");
break;
@@ -928,6 +1001,46 @@
break;
}
+ case MaterializeCreateActivation: {
+ ObjectMaterializationData& data = ""
+
+ unsigned firstChild = m_graph.m_varArgChildren.size();
+
+ Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
+
+ PromotedHeapLocation scope(ActivationScopePLoc, escapee);
+ ASSERT(locations.contains(scope));
+
+ m_graph.m_varArgChildren.append(Edge(resolve(block, scope), KnownCellUse));
+
+ for (unsigned i = 0; i < locations.size(); ++i) {
+ switch (locations[i].kind()) {
+ case ActivationScopePLoc: {
+ ASSERT(locations[i] == scope);
+ break;
+ }
+
+ case ClosureVarPLoc: {
+ Node* value = resolve(block, locations[i]);
+ if (value->op() == BottomValue)
+ break;
+
+ data.m_properties.append(PhantomPropertyValue(locations[i].info()));
+ m_graph.m_varArgChildren.append(value);
+ break;
+ }
+
+ default:
+ DFG_CRASH(m_graph, node, "Bad location kind");
+ }
+ }
+
+ node->children = AdjacencyList(
+ AdjacencyList::Variable,
+ firstChild, m_graph.m_varArgChildren.size() - firstChild);
+ break;
+ }
+
case NewFunction: {
if (!ASSERT_DISABLED) {
Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -543,6 +543,7 @@
case BooleanToNumber:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case GetMyArgumentByVal:
@@ -550,6 +551,7 @@
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PutStack:
case KillStack:
case GetStack: {
Modified: trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -90,6 +90,14 @@
case FunctionActivationPLoc:
out.print("FunctionActivationPLoc");
return;
+
+ case ActivationScopePLoc:
+ out.print("ActivationScopePLoc");
+ return;
+
+ case ClosureVarPLoc:
+ out.print("ClosureVarPLoc");
+ return;
}
RELEASE_ASSERT_NOT_REACHED();
Modified: trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -44,6 +44,8 @@
FunctionExecutablePLoc,
FunctionActivationPLoc,
+ ActivationScopePLoc,
+ ClosureVarPLoc,
};
class PromotedLocationDescriptor {
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-05-05 16:34:21 UTC (rev 183812)
@@ -273,9 +273,11 @@
case ToIndexString:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case GetMyArgumentByVal:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -4595,9 +4595,11 @@
case BottomValue:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PutStack:
case KillStack:
case GetStack:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -4691,10 +4691,12 @@
case BottomValue:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case GetMyArgumentByVal:
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PutStack:
case KillStack:
case GetStack:
Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -424,10 +424,12 @@
case CheckInBounds:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case GetMyArgumentByVal:
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PutStack:
case KillStack:
case GetStack:
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -181,9 +181,11 @@
case BottomValue:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case MaterializeCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case GetMyArgumentByVal:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -847,6 +847,9 @@
case MaterializeNewObject:
compileMaterializeNewObject();
break;
+ case MaterializeCreateActivation:
+ compileMaterializeCreateActivation();
+ break;
case PhantomLocal:
case LoopHint:
@@ -854,6 +857,7 @@
case ZombieHint:
case PhantomNewObject:
case PhantomNewFunction:
+ case PhantomCreateActivation:
case PhantomDirectArguments:
case PhantomClonedArguments:
case PutHint:
@@ -5209,6 +5213,55 @@
setJSValue(m_out.phi(m_out.intPtr, results));
}
+ void compileMaterializeCreateActivation()
+ {
+ ObjectMaterializationData& data = ""
+
+ Vector<LValue, 8> values;
+ for (unsigned i = 0; i < data.m_properties.size(); ++i)
+ values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
+
+ LValue scope = lowCell(m_graph.varArgChild(m_node, 0));
+ SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic);
+ Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
+
+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MaterializeCreateActivation slow path"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MaterializeCreateActivation continuation"));
+
+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
+
+ LValue fastObject = allocateObject<JSLexicalEnvironment>(
+ JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
+
+ m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
+ m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
+
+ for (unsigned i = 0; i < table->scopeSize(); ++i) {
+ m_out.store64(
+ m_out.constInt64(JSValue::encode(jsUndefined())),
+ fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
+ }
+
+ ValueFromBlock fastResult = m_out.anchor(fastObject);
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowPath, continuation);
+ LValue callResult = vmCall(
+ m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure),
+ scope, weakPointer(table));
+ ValueFromBlock slowResult = m_out.anchor(callResult);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
+ for (unsigned i = 0; i < data.m_properties.size(); ++i) {
+ m_out.store64(values[i],
+ activation,
+ m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]);
+ }
+ setJSValue(activation);
+ }
+
#if ENABLE(FTL_NATIVE_CALL_INLINING)
LValue getFunctionBySymbol(const CString symbol)
{
Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (183811 => 183812)
--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2015-05-05 16:27:39 UTC (rev 183811)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2015-05-05 16:34:21 UTC (rev 183812)
@@ -31,6 +31,7 @@
#include "ClonedArguments.h"
#include "DirectArguments.h"
#include "JSCInlines.h"
+#include "JSLexicalEnvironment.h"
namespace JSC { namespace FTL {
@@ -111,6 +112,36 @@
return result;
}
+ case PhantomCreateActivation: {
+ // Figure out where the scope is
+ JSScope* scope = nullptr;
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location() != PromotedLocationDescriptor(ActivationScopePLoc))
+ continue;
+ scope = jsCast<JSScope*>(JSValue::decode(values[i]));
+ }
+ RELEASE_ASSERT(scope);
+
+ CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
+ materialization->origin(), exec->codeBlock());
+ SymbolTable* table = codeBlock->symbolTable();
+ Structure* structure = codeBlock->globalObject()->activationStructure();
+
+ JSLexicalEnvironment* result = JSLexicalEnvironment::create(vm, structure, scope, table);
+
+ // Figure out what to populate the activation with
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() != ClosureVarPLoc)
+ continue;
+
+ result->variableAt(ScopeOffset(property.location().info())).set(exec->vm(), result, JSValue::decode(values[i]));
+ }
+
+ return result;
+ }
+
case PhantomDirectArguments:
case PhantomClonedArguments: {
if (!materialization->origin().inlineCallFrame) {
Added: trunk/Source/_javascript_Core/tests/stress/activation-sink-osrexit.js (0 => 183812)
--- trunk/Source/_javascript_Core/tests/stress/activation-sink-osrexit.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/activation-sink-osrexit.js 2015-05-05 16:34:21 UTC (rev 183812)
@@ -0,0 +1,25 @@
+var n = 10000000;
+
+function bar() { }
+
+function foo(b) {
+ var result = 0;
+ var set = function (x) { result = x; }
+ if (b) {
+ OSRExit();
+ if (b) {
+ bar(set);
+ }
+ return 0;
+ }
+ return result;
+}
+
+noInline(bar);
+noInline(foo);
+
+for (var i = 0; i < n; i++) {
+ var result = foo(!(i % 100));
+ if (result != 0)
+ throw "Error: bad result: " + result;
+}
Added: trunk/Source/_javascript_Core/tests/stress/activation-sink.js (0 => 183812)
--- trunk/Source/_javascript_Core/tests/stress/activation-sink.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/activation-sink.js 2015-05-05 16:34:21 UTC (rev 183812)
@@ -0,0 +1,24 @@
+var n = 10000000;
+
+function bar(f) { f(10); }
+
+function foo(b) {
+ var result = 0;
+ var set = function (x) { result = x; }
+ if (b) {
+ bar(set);
+ if (result != 10)
+ throw "Error: bad: " + result;
+ return 0;
+ }
+ return result;
+}
+
+noInline(bar);
+noInline(foo);
+
+for (var i = 0; i < n; i++) {
+ var result = foo(!(i % 100));
+ if (result != 0)
+ throw "Error: bad result: " + result;
+}