Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (184746 => 184747)
--- trunk/Source/_javascript_Core/ChangeLog 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-05-22 02:39:25 UTC (rev 184747)
@@ -1,3 +1,47 @@
+2015-05-21 Saam Barati <saambara...@gmail.com>
+
+ Object allocation sinking phase should explicitly create bottom values for CreateActivation sink candidates and CreateActivation should have SymbolTable as a child node
+ https://bugs.webkit.org/show_bug.cgi?id=145192
+
+ Reviewed by Filip Pizlo.
+
+ When we sink CreateActivation and generate MaterializeCreateActivation
+ in the object allocation sinking phase, we now explictly add PutHints for
+ all variables on the activation setting those variables to their default value
+ (undefined for Function activations and soon to be JS Empty Value for block scope activations).
+ This allows us to remove code that fills FTL fast activation allocations with Undefined.
+
+ This patch also adds the constant SymbolTable as an OpInfo of CreateActivation and MaterializeCreateActivation
+ nodes. This is in preparation for ES6 block scoping which will introduce a new
+ op code that gets lowered to CreateActivation.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasCellOperand):
+ (JSC::DFG::Node::cellOperand):
+ * dfg/DFGObjectAllocationSinkingPhase.cpp:
+ (JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
+ (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+ (JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
+ (JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):
+ * dfg/DFGPromotedHeapLocation.cpp:
+ (WTF::printInternal):
+ * dfg/DFGPromotedHeapLocation.h:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileCreateActivation):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
+ (JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):
+ * ftl/FTLOperations.cpp:
+ (JSC::FTL::operationMaterializeObjectInOSR):
+ * tests/stress/activation-sink-default-value.js: Added.
+ (bar):
+ * tests/stress/activation-sink-osrexit-default-value.js: Added.
+ (foo.set result):
+
2015-05-21 Per Arne Vollan <pe...@outlook.com>
MSVC internal compiler error when compiling TemplateRegistryKey class.
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -3733,7 +3733,8 @@
}
case op_create_lexical_environment: {
- Node* lexicalEnvironment = addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[2].u.operand)));
+ FrozenValue* symbolTable = m_graph.freezeStrong(m_graph.symbolTableFor(currentNodeOrigin().semantic));
+ Node* lexicalEnvironment = addToGraph(CreateActivation, OpInfo(symbolTable), get(VirtualRegister(currentInstruction[2].u.operand)));
set(VirtualRegister(currentInstruction[1].u.operand), lexicalEnvironment);
set(VirtualRegister(currentInstruction[2].u.operand), lexicalEnvironment);
NEXT_OPCODE(op_create_lexical_environment);
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-05-22 02:39:25 UTC (rev 184747)
@@ -317,7 +317,7 @@
return;
case CreateActivation: {
- SymbolTable* table = graph.symbolTableFor(node->origin.semantic);
+ SymbolTable* table = node->castOperand<SymbolTable*>();
if (table->singletonScope()->isStillValid())
write(Watchpoint_fire);
read(HeapObjectCount);
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-05-22 02:39:25 UTC (rev 184747)
@@ -1282,6 +1282,8 @@
case NativeConstruct:
case NativeCall:
case NewFunction:
+ case CreateActivation:
+ case MaterializeCreateActivation:
return true;
default:
return false;
@@ -1291,7 +1293,13 @@
FrozenValue* cellOperand()
{
ASSERT(hasCellOperand());
- return reinterpret_cast<FrozenValue*>(m_opInfo);
+ switch (op()) {
+ case MaterializeCreateActivation:
+ return reinterpret_cast<FrozenValue*>(m_opInfo2);
+ default:
+ return reinterpret_cast<FrozenValue*>(m_opInfo);
+ }
+ RELEASE_ASSERT_NOT_REACHED();
}
template<typename T>
Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -586,6 +586,27 @@
nodeIndex + 1,
PromotedHeapLocation(ActivationScopePLoc, node).createHint(
m_graph, node->origin, node->child1().node()));
+ Node* symbolTableNode = m_insertionSet.insertConstant(
+ nodeIndex + 1, node->origin, node->cellOperand());
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
+ m_graph, node->origin, symbolTableNode));
+
+ {
+ SymbolTable* symbolTable = node->castOperand<SymbolTable*>();
+ Node* undefined = m_insertionSet.insertConstant(
+ nodeIndex + 1, node->origin, jsUndefined());
+ ConcurrentJITLocker locker(symbolTable->m_lock);
+ for (auto iter = symbolTable->begin(locker), end = symbolTable->end(locker); iter != end; ++iter) {
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(
+ ClosureVarPLoc, node, iter->value.scopeOffset().offset()).createHint(
+ m_graph, node->origin, undefined));
+ }
+ }
+
node->convertToPhantomCreateActivation();
}
break;
@@ -597,6 +618,12 @@
nodeIndex + 1,
PromotedHeapLocation(ActivationScopePLoc, node).createHint(
m_graph, node->origin, m_graph.varArgChild(node, 0).node()));
+ Node* symbolTableNode = m_insertionSet.insertConstant(
+ nodeIndex + 1, node->origin, node->cellOperand());
+ m_insertionSet.insert(
+ nodeIndex + 1,
+ PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
+ m_graph, node->origin, symbolTableNode));
ObjectMaterializationData& data = ""
for (unsigned i = 0; i < data.m_properties.size(); ++i) {
unsigned identifierNumber = data.m_properties[i].m_identifierNumber;
@@ -829,7 +856,7 @@
break;
case CreateActivation:
- if (!m_graph.symbolTableFor(node->origin.semantic)->singletonScope()->isStillValid())
+ if (!node->castOperand<SymbolTable*>()->singletonScope()->isStillValid())
sinkCandidate();
escape(node->child1().node());
break;
@@ -932,13 +959,13 @@
case CreateActivation:
case MaterializeCreateActivation: {
ObjectMaterializationData* data = ""
-
+ FrozenValue* symbolTable = escapee->cellOperand();
result = m_graph.addNode(
escapee->prediction(), Node::VarArg, MaterializeCreateActivation,
NodeOrigin(
escapee->origin.semantic,
where->origin.forExit),
- OpInfo(data), OpInfo(), 0, 0);
+ OpInfo(data), OpInfo(symbolTable), 0, 0);
break;
}
@@ -1009,6 +1036,7 @@
Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
PromotedHeapLocation scope(ActivationScopePLoc, escapee);
+ PromotedHeapLocation symbolTable(ActivationSymbolTablePLoc, escapee);
ASSERT(locations.contains(scope));
m_graph.m_varArgChildren.append(Edge(resolve(block, scope), KnownCellUse));
@@ -1020,6 +1048,11 @@
break;
}
+ case ActivationSymbolTablePLoc: {
+ ASSERT(locations[i] == symbolTable);
+ break;
+ }
+
case ClosureVarPLoc: {
Node* value = resolve(block, locations[i]);
if (value->op() == BottomValue)
Modified: trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -66,6 +66,10 @@
case StructurePLoc:
out.print("StructurePLoc");
return;
+
+ case ActivationSymbolTablePLoc:
+ out.print("ActivationSymbolTablePLoc");
+ return;
case NamedPropertyPLoc:
out.print("NamedPropertyPLoc");
Modified: trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGPromotedHeapLocation.h 2015-05-22 02:39:25 UTC (rev 184747)
@@ -37,6 +37,7 @@
InvalidPromotedLocationKind,
StructurePLoc,
+ ActivationSymbolTablePLoc,
NamedPropertyPLoc,
ArgumentPLoc,
ArgumentCountPLoc,
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -4521,7 +4521,7 @@
void SpeculativeJIT::compileCreateActivation(Node* node)
{
- SymbolTable* table = m_jit.graph().symbolTableFor(node->origin.semantic);
+ SymbolTable* table = node->castOperand<SymbolTable*>();
Structure* structure = m_jit.graph().globalObjectFor(
node->origin.semantic)->activationStructure();
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -2947,7 +2947,7 @@
void compileCreateActivation()
{
LValue scope = lowCell(m_node->child1());
- SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic);
+ SymbolTable* table = m_node->castOperand<SymbolTable*>();
Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
if (table->singletonScope()->isStillValid()) {
@@ -5264,7 +5264,7 @@
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);
+ SymbolTable* table = m_node->castOperand<SymbolTable*>();
Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MaterializeCreateActivation slow path"));
@@ -5278,11 +5278,6 @@
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);
@@ -5296,11 +5291,28 @@
m_out.appendTo(continuation, lastNext);
LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
+ RELEASE_ASSERT(data.m_properties.size() == table->scopeSize());
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]);
}
+
+ if (validationEnabled()) {
+ // Validate to make sure every slot in the scope has one value.
+ ConcurrentJITLocker locker(table->m_lock);
+ for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
+ bool found = false;
+ for (unsigned i = 0; i < data.m_properties.size(); ++i) {
+ if (iter->value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT(found);
+ }
+ }
+
setJSValue(activation);
}
Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (184746 => 184747)
--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2015-05-22 02:39:25 UTC (rev 184747)
@@ -115,21 +115,24 @@
case PhantomCreateActivation: {
// Figure out where the scope is
JSScope* scope = nullptr;
+ SymbolTable* table = 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]));
+ if (property.location() == PromotedLocationDescriptor(ActivationScopePLoc))
+ scope = jsCast<JSScope*>(JSValue::decode(values[i]));
+ else if (property.location() == PromotedLocationDescriptor(ActivationSymbolTablePLoc))
+ table = jsCast<SymbolTable*>(JSValue::decode(values[i]));
}
RELEASE_ASSERT(scope);
+ RELEASE_ASSERT(table);
CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
materialization->origin(), exec->codeBlock());
- SymbolTable* table = codeBlock->symbolTable();
Structure* structure = codeBlock->globalObject()->activationStructure();
JSLexicalEnvironment* result = JSLexicalEnvironment::create(vm, structure, scope, table);
+ RELEASE_ASSERT(materialization->properties().size() - 2 == table->scopeSize());
// Figure out what to populate the activation with
for (unsigned i = materialization->properties().size(); i--;) {
const ExitPropertyValue& property = materialization->properties()[i];
@@ -139,6 +142,31 @@
result->variableAt(ScopeOffset(property.location().info())).set(exec->vm(), result, JSValue::decode(values[i]));
}
+ if (validationEnabled()) {
+ // Validate to make sure every slot in the scope has one value.
+ ConcurrentJITLocker locker(table->m_lock);
+ for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
+ bool found = false;
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() != ClosureVarPLoc)
+ continue;
+ if (ScopeOffset(property.location().info()) == iter->value.scopeOffset()) {
+ found = true;
+ break;
+ }
+ }
+ ASSERT(found);
+ }
+ unsigned numberOfClosureVarPloc = 0;
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() == ClosureVarPLoc)
+ numberOfClosureVarPloc++;
+ }
+ ASSERT(numberOfClosureVarPloc == table->scopeSize());
+ }
+
return result;
}
Added: trunk/Source/_javascript_Core/tests/stress/activation-sink-default-value.js (0 => 184747)
--- trunk/Source/_javascript_Core/tests/stress/activation-sink-default-value.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/activation-sink-default-value.js 2015-05-22 02:39:25 UTC (rev 184747)
@@ -0,0 +1,31 @@
+var n = 10000000;
+
+function bar(f) { f(10); }
+
+function foo(b) {
+ var result = 0;
+ var imUndefined;
+ var baz;
+ var set = function (x) { result = x; return (imUndefined, baz); }
+ baz = 40;
+ if (b) {
+ bar(set);
+ if (result != 10)
+ throw "Error: bad: " + result;
+ if (baz !== 40)
+ throw "Error: bad: " + baz;
+ if (imUndefined !== void 0)
+ throw "Error: bad value: " + imUndefined;
+ 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-osrexit-default-value.js (0 => 184747)
--- trunk/Source/_javascript_Core/tests/stress/activation-sink-osrexit-default-value.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/activation-sink-osrexit-default-value.js 2015-05-22 02:39:25 UTC (rev 184747)
@@ -0,0 +1,37 @@
+var n = 10000000;
+
+function bar(set) {
+ var result = set(0);
+ if (result !== void 0)
+ throw "Error: bad value: " + result;
+}
+
+function foo(b) {
+ var result = 0;
+ var imUndefined;
+ var baz;
+ var set = function (x) {
+ result = x;
+ if (baz !== 50)
+ throw "Error: bad value: " + baz;
+ return imUndefined;
+ }
+ baz = 50;
+ 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;
+}