Commit 9e922895 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[turbofan] Escape analysis no longer introduces Dead nodes in unreachable code.

Bug: chromium:780658
Change-Id: Ie1252a4e4e8ae8621817ab8c058715dcc3cef7d9
Reviewed-on: https://chromium-review.googlesource.com/769507
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49377}
parent 2f5d90a8
......@@ -125,7 +125,18 @@ class VariableTracker {
public:
Scope(VariableTracker* tracker, Node* node, Reduction* reduction);
~Scope();
Node* Get(Variable var) { return current_state_.Get(var); }
Maybe<Node*> Get(Variable var) {
Node* node = current_state_.Get(var);
if (node && node->opcode() == IrOpcode::kDead) {
// TODO(tebbi): We use {Dead} as a sentinel for uninitialized memory.
// Reading uninitialized memory can only happen in unreachable code. In
// this case, we have to mark the object as escaping to avoid dead nodes
// in the graph. This is a workaround that should be removed once we can
// handle dead nodes everywhere.
return Nothing<Node*>();
}
return Just(node);
}
void Set(Variable var, Node* node) { current_state_.Set(var, node); }
private:
......@@ -585,14 +596,12 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
Node* object = current->ValueInput(0);
const VirtualObject* vobject = current->GetVirtualObject(object);
Variable var;
Node* value;
if (vobject && !vobject->HasEscaped() &&
vobject->FieldAt(OffsetOfFieldAccess(op)).To(&var)) {
current->SetReplacement(current->Get(var));
vobject->FieldAt(OffsetOfFieldAccess(op)).To(&var) &&
current->Get(var).To(&value)) {
current->SetReplacement(value);
} else {
// TODO(tebbi): At the moment, we mark objects as escaping if there
// is a load from an invalid location to avoid dead nodes. This is a
// workaround that should be removed once we can handle dead nodes
// everywhere.
current->SetEscaped(object);
}
break;
......@@ -603,10 +612,11 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
const VirtualObject* vobject = current->GetVirtualObject(object);
int offset;
Variable var;
Node* value;
if (vobject && !vobject->HasEscaped() &&
OffsetOfElementsAccess(op, index).To(&offset) &&
vobject->FieldAt(offset).To(&var)) {
current->SetReplacement(current->Get(var));
vobject->FieldAt(offset).To(&var) && current->Get(var).To(&value)) {
current->SetReplacement(value);
} else {
current->SetEscaped(object);
}
......@@ -656,9 +666,11 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
Node* checked = current->ValueInput(0);
const VirtualObject* vobject = current->GetVirtualObject(checked);
Variable map_field;
Node* map;
if (vobject && !vobject->HasEscaped() &&
vobject->FieldAt(HeapObject::kMapOffset).To(&map_field)) {
if (Node* map = current->Get(map_field)) {
vobject->FieldAt(HeapObject::kMapOffset).To(&map_field) &&
current->Get(map_field).To(&map)) {
if (map) {
Type* const map_type = NodeProperties::GetType(map);
if (map_type->IsHeapConstant() &&
params.maps().contains(
......@@ -679,9 +691,11 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
Node* object = current->ValueInput(0);
const VirtualObject* vobject = current->GetVirtualObject(object);
Variable map_field;
Node* object_map;
if (vobject && !vobject->HasEscaped() &&
vobject->FieldAt(HeapObject::kMapOffset).To(&map_field)) {
if (Node* object_map = current->Get(map_field)) {
vobject->FieldAt(HeapObject::kMapOffset).To(&map_field) &&
current->Get(map_field).To(&object_map)) {
if (object_map) {
current->SetReplacement(LowerCompareMapsWithoutLoad(
object_map, CompareMapsParametersOf(op).maps(), jsgraph));
break;
......
......@@ -130,7 +130,10 @@ class VirtualObject : public Dependable {
}
CHECK(!HasEscaped());
if (offset >= size()) {
// This can only happen in unreachable code.
// TODO(tebbi): Reading out-of-bounds can only happen in unreachable
// code. In this case, we have to mark the object as escaping to avoid
// dead nodes in the graph. This is a workaround that should be removed
// once we can handle dead nodes everywhere.
return Nothing<Variable>();
}
return Just(fields_.at(offset / kPointerSize));
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-escape
function get1(l, b) {
return l[1];
}
function with_double(x) {
var o = {a: [x,x,x]};
o.a.some_property = 1;
return get1(o.a);
}
function with_tagged(x) {
var l = [{}, x,x];
return get1(l);
}
with_double(.5);
with_tagged({});
with_double(.6);
with_tagged(null);
with_double(.5);
with_tagged({});
%OptimizeFunctionOnNextCall(with_double);
with_double(.7);
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