Commit f6849d9e authored by Benedikt Meurer's avatar Benedikt Meurer

[turbofan] Fix cycles introduced by pushing ToNumbers into phis.

TEST=cctest
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/790123002

Cr-Commit-Position: refs/heads/master@{#25743}
parent 59753fb9
......@@ -232,6 +232,12 @@ void JSGenericLowering::LowerJSToBoolean(Node* node) {
void JSGenericLowering::LowerJSToNumber(Node* node) {
Callable callable = CodeFactory::ToNumber(isolate());
// TODO(mstarzinger): Embedding the context this way prevents sharing of code
// across native contexts.
if (!info_context_constant_.is_set()) {
info_context_constant_.set(jsgraph()->HeapConstant(info()->context()));
}
node->ReplaceInput(1, info_context_constant_.get());
ReplaceWithStubCall(node, callable, FlagsForNode(node));
}
......
......@@ -60,6 +60,7 @@ class JSGenericLowering : public Reducer {
private:
CompilationInfo* info_;
SetOncePointer<Node> info_context_constant_;
JSGraph* jsgraph_;
Linkage* linkage_;
};
......
......@@ -528,40 +528,43 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
return reduction;
}
Type* const input_type = NodeProperties::GetBounds(input).upper;
if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) {
Node* const context = node->InputAt(1);
// JSToNumber(phi(x1,...,xn,control):primitive)
// => phi(JSToNumber(x1),...,JSToNumber(xn),control):number
if (input_type->Is(Type::PlainPrimitive())) {
// Converting a plain primitive to a number has no observable side effects.
RelaxEffects(node);
int const input_count = input->InputCount() - 1;
Node* const control = input->InputAt(input_count);
DCHECK_LE(0, input_count);
DCHECK(NodeProperties::IsControl(control));
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number()));
node->set_op(common()->Phi(kMachAnyTagged, input_count));
for (int i = 0; i < input_count; ++i) {
Node* value = input->InputAt(i);
// Recursively try to reduce the value first.
Reduction reduction = ReduceJSToNumberInput(value);
if (reduction.Changed()) {
value = reduction.replacement();
} else {
value = graph()->NewNode(javascript()->ToNumber(), value, context,
graph()->start(), graph()->start());
// JSToNumber(phi(x1,...,xn,control):plain-primitive,context)
// => phi(JSToNumber(x1,no-context),...,JSToNumber(xn,no-context),control)
if (input->opcode() == IrOpcode::kPhi) {
int const input_count = input->InputCount() - 1;
Node* const control = input->InputAt(input_count);
DCHECK_LE(0, input_count);
DCHECK(NodeProperties::IsControl(control));
DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number()));
DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number()));
node->set_op(common()->Phi(kMachAnyTagged, input_count));
for (int i = 0; i < input_count; ++i) {
Node* value = input->InputAt(i);
// Recursively try to reduce the value first.
Reduction reduction = ReduceJSToNumberInput(value);
if (reduction.Changed()) {
value = reduction.replacement();
} else {
value = graph()->NewNode(javascript()->ToNumber(), value,
jsgraph()->NoContextConstant(),
graph()->start(), graph()->start());
}
if (i < node->InputCount()) {
node->ReplaceInput(i, value);
} else {
node->AppendInput(graph()->zone(), value);
}
}
if (i < node->InputCount()) {
node->ReplaceInput(i, value);
if (input_count < node->InputCount()) {
node->ReplaceInput(input_count, control);
} else {
node->AppendInput(graph()->zone(), value);
node->AppendInput(graph()->zone(), control);
}
node->TrimInputCount(input_count + 1);
}
if (input_count < node->InputCount()) {
node->ReplaceInput(input_count, control);
} else {
node->AppendInput(graph()->zone(), control);
}
node->TrimInputCount(input_count + 1);
return Changed(node);
}
return NoChange();
......
......@@ -213,7 +213,8 @@ namespace internal {
V(UniqueName, kSymbol | kInternalizedString) \
V(Name, kSymbol | kString) \
V(NumberOrString, kNumber | kString) \
V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \
V(PlainPrimitive, kNumberOrString | kBoolean | kNull | kUndefined) \
V(Primitive, kSymbol | kPlainPrimitive) \
V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \
V(DetectableReceiver, kDetectableObject | kProxy) \
V(Detectable, kDetectableReceiver | kNumber | kName) \
......
......@@ -114,10 +114,6 @@
'test-debug/NoDebugBreakInAfterCompileMessageHandler': [PASS, NO_VARIANTS],
'test-debug/RegExpDebugBreak': [PASS, NO_VARIANTS],
# TODO(mstarzinger): Investigate these failures.
'test-run-inlining/InlineTwiceDependentDiamond': [SKIP],
'test-run-inlining/InlineTwiceDependentDiamondDifferent': [SKIP],
# TODO(titzer): Triggers bug in late control reduction.
'test-run-inlining/InlineLoopGuardedEmpty': [SKIP],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment