Commit ddba89c4 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Also utilize the string length protector.

Utilize the string length protector to deoptimize if the resulting
string length for string addition overflows. This way we generate
less code here and avoid holding on to the lazy frame state, and
thus potentially reduce the number live ranges.

BUG=v8:5267,v8:5404
R=yangguo@chromium.org

Review-Url: https://codereview.chromium.org/2491943004
Cr-Commit-Position: refs/heads/master@{#40909}
parent 4ee6fdf3
......@@ -626,33 +626,44 @@ Reduction JSTypedLowering::ReduceCreateConsString(Node* node) {
// Check if we would overflow the allowed maximum string length.
Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
jsgraph()->Constant(String::kMaxLength));
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
{
// Throw a RangeError in case of overflow.
Node* vfalse = efalse = graph()->NewNode(
javascript()->CallRuntime(Runtime::kThrowInvalidStringLength), context,
frame_state, efalse, if_false);
if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
if_false = graph()->NewNode(common()->Throw(), vfalse, efalse, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), if_false);
Revisit(graph()->end());
// Update potential {IfException} uses of {node} to point to the
// %ThrowInvalidStringLength runtime call node instead.
for (Edge edge : node->use_edges()) {
if (edge.from()->opcode() == IrOpcode::kIfException) {
DCHECK(NodeProperties::IsControlEdge(edge) ||
NodeProperties::IsEffectEdge(edge));
edge.UpdateTo(vfalse);
Revisit(edge.from());
if (isolate()->IsStringLengthOverflowIntact()) {
// Add a code dependency on the string length overflow protector.
dependencies()->AssumePropertyCell(factory()->string_length_protector());
// We can just deoptimize if the {check} fails. Besides generating a
// shorter code sequence than the version below, this has the additional
// benefit of not holding on to the lazy {frame_state} and thus potentially
// reduces the number of live ranges and allows for more truncations.
effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
} else {
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
{
// Throw a RangeError in case of overflow.
Node* vfalse = efalse = graph()->NewNode(
javascript()->CallRuntime(Runtime::kThrowInvalidStringLength),
context, frame_state, efalse, if_false);
if_false = graph()->NewNode(common()->IfSuccess(), vfalse);
if_false = graph()->NewNode(common()->Throw(), vfalse, efalse, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), if_false);
Revisit(graph()->end());
// Update potential {IfException} uses of {node} to point to the
// %ThrowInvalidStringLength runtime call node instead.
for (Edge edge : node->use_edges()) {
if (edge.from()->opcode() == IrOpcode::kIfException) {
DCHECK(NodeProperties::IsControlEdge(edge) ||
NodeProperties::IsEffectEdge(edge));
edge.UpdateTo(vfalse);
Revisit(edge.from());
}
}
}
control = graph()->NewNode(common()->IfTrue(), branch);
}
control = graph()->NewNode(common()->IfTrue(), branch);
// Figure out the map for the resulting ConsString.
// TODO(turbofan): We currently just use the cons_string_map here for
......
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