Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (183306 => 183307)
--- trunk/Source/_javascript_Core/ChangeLog 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-04-25 05:19:07 UTC (rev 183307)
@@ -1,3 +1,34 @@
+2015-04-24 Filip Pizlo <[email protected]>
+
+ CRASH in operationCreateDirectArgumentsDuringExit()
+ https://bugs.webkit.org/show_bug.cgi?id=143962
+
+ Reviewed by Geoffrey Garen.
+
+ We shouldn't assume that constant-like OSR exit values are always recoverable. They are only
+ recoverable so long as they are live. Therefore, OSR exit should track liveness of
+ constants instead of assuming that they are always live.
+
+ * dfg/DFGGenerationInfo.h:
+ (JSC::DFG::GenerationInfo::noticeOSRBirth):
+ (JSC::DFG::GenerationInfo::appendBirth):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+ * dfg/DFGVariableEvent.cpp:
+ (JSC::DFG::VariableEvent::dump):
+ * dfg/DFGVariableEvent.h:
+ (JSC::DFG::VariableEvent::birth):
+ (JSC::DFG::VariableEvent::id):
+ (JSC::DFG::VariableEvent::dataFormat):
+ * dfg/DFGVariableEventStream.cpp:
+ (JSC::DFG::VariableEventStream::reconstruct):
+ * tests/stress/phantom-direct-arguments-clobber-argument-count.js: Added.
+ (foo):
+ (bar):
+ * tests/stress/phantom-direct-arguments-clobber-callee.js: Added.
+ (foo):
+ (bar):
+
2015-04-24 Benjamin Poulain <[email protected]>
[JSC] When inserting a NaN into a Int32 array, we convert it to DoubleArray then to ContiguousArray
Modified: trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h (183306 => 183307)
--- trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGGenerationInfo.h 2015-04-25 05:19:07 UTC (rev 183307)
@@ -153,8 +153,6 @@
void noticeOSRBirth(VariableEventStream& stream, Node* node, VirtualRegister virtualRegister)
{
- if (m_isConstant)
- return;
if (m_node != node)
return;
if (!alive())
@@ -164,7 +162,9 @@
m_bornForOSR = true;
- if (m_registerFormat != DataFormatNone)
+ if (m_isConstant)
+ appendBirth(stream);
+ else if (m_registerFormat != DataFormatNone)
appendFill(BirthToFill, stream);
else if (m_spillFormat != DataFormatNone)
appendSpill(BirthToSpill, stream, virtualRegister);
@@ -379,6 +379,11 @@
}
private:
+ void appendBirth(VariableEventStream& stream)
+ {
+ stream.appendAndLog(VariableEvent::birth(MinifiedID(m_node)));
+ }
+
void appendFill(VariableEventKind kind, VariableEventStream& stream)
{
ASSERT(m_bornForOSR);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (183306 => 183307)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-04-25 05:19:07 UTC (rev 183307)
@@ -1428,33 +1428,29 @@
m_codeOriginForExitTarget = m_currentNode->origin.forExit;
m_codeOriginForExitProfile = m_currentNode->origin.semantic;
m_lastGeneratedNode = m_currentNode->op();
- if (!m_currentNode->shouldGenerate()) {
- if (belongsInMinifiedGraph(m_currentNode->op()))
- m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
- } else {
- if (verboseCompilationEnabled()) {
- dataLogF(
- "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
- (int)m_currentNode->index(),
- m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
- dataLog("\n");
- }
-
- compile(m_currentNode);
-
+
+ ASSERT(m_currentNode->shouldGenerate());
+
+ if (verboseCompilationEnabled()) {
+ dataLogF(
+ "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
+ (int)m_currentNode->index(),
+ m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
+ dataLog("\n");
+ }
+
+ compile(m_currentNode);
+
+ if (belongsInMinifiedGraph(m_currentNode->op()))
+ m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
+
#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
- m_jit.clearRegisterAllocationOffsets();
+ m_jit.clearRegisterAllocationOffsets();
#endif
-
- if (!m_compileOkay) {
- bail(DFGBailedAtEndOfNode);
- return;
- }
-
- if (belongsInMinifiedGraph(m_currentNode->op())) {
- m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
- noticeOSRBirth(m_currentNode);
- }
+
+ if (!m_compileOkay) {
+ bail(DFGBailedAtEndOfNode);
+ return;
}
// Make sure that the abstract state is rematerialized for the next node.
Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp (183306 => 183307)
--- trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEvent.cpp 2015-04-25 05:19:07 UTC (rev 183307)
@@ -46,6 +46,9 @@
case BirthToSpill:
dumpSpillInfo("BirthToSpill", out);
break;
+ case Birth:
+ out.print("Birth(", id(), ")");
+ break;
case Fill:
dumpFillInfo("Fill", out);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h (183306 => 183307)
--- trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEvent.h 2015-04-25 05:19:07 UTC (rev 183307)
@@ -47,6 +47,7 @@
// that we start to care about this node.
BirthToFill,
BirthToSpill,
+ Birth,
// Events related to how a node is represented.
Fill,
@@ -133,6 +134,14 @@
return event;
}
+ static VariableEvent birth(MinifiedID id)
+ {
+ VariableEvent event;
+ event.m_which.id = id.bits();
+ event.m_kind = Birth;
+ return event;
+ }
+
static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
{
ASSERT(kind == BirthToSpill || kind == Spill);
@@ -179,17 +188,17 @@
MinifiedID id() const
{
- ASSERT(m_kind == BirthToFill || m_kind == Fill
- || m_kind == BirthToSpill || m_kind == Spill
- || m_kind == Death || m_kind == MovHintEvent);
+ ASSERT(
+ m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+ || m_kind == Death || m_kind == MovHintEvent || m_kind == Birth);
return MinifiedID::fromBits(m_which.id);
}
DataFormat dataFormat() const
{
- ASSERT(m_kind == BirthToFill || m_kind == Fill
- || m_kind == BirthToSpill || m_kind == Spill
- || m_kind == SetLocalEvent);
+ ASSERT(
+ m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+ || m_kind == SetLocalEvent);
return static_cast<DataFormat>(m_dataFormat);
}
Modified: trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp (183306 => 183307)
--- trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp 2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableEventStream.cpp 2015-04-25 05:19:07 UTC (rev 183307)
@@ -48,11 +48,14 @@
struct MinifiedGenerationInfo {
bool filled; // true -> in gpr/fpr/pair, false -> spilled
+ bool alive;
VariableRepresentation u;
DataFormat format;
MinifiedGenerationInfo()
- : format(DataFormatNone)
+ : filled(false)
+ , alive(false)
+ , format(DataFormatNone)
{
}
@@ -62,13 +65,19 @@
case BirthToFill:
case Fill:
filled = true;
+ alive = true;
break;
case BirthToSpill:
case Spill:
filled = false;
+ alive = true;
break;
+ case Birth:
+ alive = true;
+ return;
case Death:
format = DataFormatNone;
+ alive = false;
return;
default:
return;
@@ -146,7 +155,8 @@
// nothing to do.
break;
case BirthToFill:
- case BirthToSpill: {
+ case BirthToSpill:
+ case Birth: {
MinifiedGenerationInfo info;
info.update(event);
generationInfos.add(event.id(), info);
@@ -185,14 +195,14 @@
ASSERT(source.kind() == HaveNode);
MinifiedNode* node = graph.at(source.id());
- if (tryToSetConstantRecovery(valueRecoveries[i], node))
- continue;
-
MinifiedGenerationInfo info = generationInfos.get(source.id());
- if (info.format == DataFormatNone) {
+ if (!info.alive) {
valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
continue;
}
+
+ if (tryToSetConstantRecovery(valueRecoveries[i], node))
+ continue;
ASSERT(info.format != DataFormatNone);
Added: trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js (0 => 183307)
--- trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-argument-count.js 2015-04-25 05:19:07 UTC (rev 183307)
@@ -0,0 +1,20 @@
+function foo() {
+ return effectful42.apply(this, arguments);
+}
+
+function bar(a, b) {
+ var result = foo.apply(this, b);
+ return [a, a, a, a, a, a, a, a, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = "" + bar(1, []);
+ if (result != "1,1,1,1,1,1,1,1,43")
+ throw "Error: bad result: " + result;
+}
+
+var result = "" + bar(2147483647, []);
+if (result != "2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483689")
+ throw "Error: bad result at end: " + result;
Added: trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js (0 => 183307)
--- trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/phantom-direct-arguments-clobber-callee.js 2015-04-25 05:19:07 UTC (rev 183307)
@@ -0,0 +1,21 @@
+function foo() {
+ return function() { return effectful42.apply(this, arguments) };
+}
+noInline(foo);
+
+function bar(a) {
+ var result = foo()();
+ return [result, result, result, result, result, result, result, result, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = "" + bar(1);
+ if (result != "42,42,42,42,42,42,42,42,43")
+ throw "Error: bad result: " + result;
+}
+
+var result = "" + bar(2147483647);
+if (result != "42,42,42,42,42,42,42,42,2147483689")
+ throw "Error: bad result at end: " + result;