Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: src/compiler/escape-analysis.cc

Issue 2008883002: [turbofan] Fix escape analysis of sub-word element access. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/escape-analysis.h" 5 #include "src/compiler/escape-analysis.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "src/base/flags.h" 9 #include "src/base/flags.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 TRACE(" has incomplete virtual object info.\n"); 1381 TRACE(" has incomplete virtual object info.\n");
1382 } 1382 }
1383 } 1383 }
1384 1384
1385 void EscapeAnalysis::ProcessLoadField(Node* node) { 1385 void EscapeAnalysis::ProcessLoadField(Node* node) {
1386 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1386 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1387 ForwardVirtualState(node); 1387 ForwardVirtualState(node);
1388 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1388 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1389 VirtualState* state = virtual_states_[node->id()]; 1389 VirtualState* state = virtual_states_[node->id()];
1390 if (VirtualObject* object = GetVirtualObject(state, from)) { 1390 if (VirtualObject* object = GetVirtualObject(state, from)) {
1391 if (!object->IsTracked()) return;
1391 int offset = OffsetForFieldAccess(node); 1392 int offset = OffsetForFieldAccess(node);
1392 if (!object->IsTracked() || 1393 if (static_cast<size_t>(offset) >= object->field_count()) return;
1393 static_cast<size_t>(offset) >= object->field_count()) {
1394 return;
1395 }
1396 Node* value = object->GetField(offset); 1394 Node* value = object->GetField(offset);
1397 if (value) { 1395 if (value) {
1398 value = ResolveReplacement(value); 1396 value = ResolveReplacement(value);
1399 } 1397 }
1400 // Record that the load has this alias. 1398 // Record that the load has this alias.
1401 UpdateReplacement(state, node, value); 1399 UpdateReplacement(state, node, value);
1402 } else if (from->opcode() == IrOpcode::kPhi && 1400 } else if (from->opcode() == IrOpcode::kPhi &&
1403 FieldAccessOf(node->op()).offset % kPointerSize == 0) { 1401 FieldAccessOf(node->op()).offset % kPointerSize == 0) {
1404 int offset = OffsetForFieldAccess(node); 1402 int offset = OffsetForFieldAccess(node);
1405 // Only binary phis are supported for now. 1403 // Only binary phis are supported for now.
1406 ProcessLoadFromPhi(offset, from, node, state); 1404 ProcessLoadFromPhi(offset, from, node, state);
1407 } else { 1405 } else {
1408 UpdateReplacement(state, node, nullptr); 1406 UpdateReplacement(state, node, nullptr);
1409 } 1407 }
1410 } 1408 }
1411 1409
1412 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1410 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1413 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1411 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1414 ForwardVirtualState(node); 1412 ForwardVirtualState(node);
1415 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1413 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1416 VirtualState* state = virtual_states_[node->id()]; 1414 VirtualState* state = virtual_states_[node->id()];
1417 Node* index_node = node->InputAt(1); 1415 Node* index_node = node->InputAt(1);
1418 NumberMatcher index(index_node); 1416 NumberMatcher index(index_node);
1419 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1417 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1420 index_node->opcode() != IrOpcode::kInt64Constant && 1418 index_node->opcode() != IrOpcode::kInt64Constant &&
1421 index_node->opcode() != IrOpcode::kFloat32Constant && 1419 index_node->opcode() != IrOpcode::kFloat32Constant &&
1422 index_node->opcode() != IrOpcode::kFloat64Constant); 1420 index_node->opcode() != IrOpcode::kFloat64Constant);
1423 if (index.HasValue()) { 1421 if (index.HasValue()) {
1424 if (VirtualObject* object = GetVirtualObject(state, from)) { 1422 if (VirtualObject* object = GetVirtualObject(state, from)) {
1423 if (!object->IsTracked()) return;
1425 int offset = OffsetForElementAccess(node, index.Value()); 1424 int offset = OffsetForElementAccess(node, index.Value());
1426 if (!object->IsTracked() || 1425 if (static_cast<size_t>(offset) >= object->field_count()) return;
1427 static_cast<size_t>(offset) >= object->field_count()) {
1428 return;
1429 }
1430 Node* value = object->GetField(offset); 1426 Node* value = object->GetField(offset);
1431 if (value) { 1427 if (value) {
1432 value = ResolveReplacement(value); 1428 value = ResolveReplacement(value);
1433 } 1429 }
1434 // Record that the load has this alias. 1430 // Record that the load has this alias.
1435 UpdateReplacement(state, node, value); 1431 UpdateReplacement(state, node, value);
1436 } else if (from->opcode() == IrOpcode::kPhi) { 1432 } else if (from->opcode() == IrOpcode::kPhi) {
1437 int offset = OffsetForElementAccess(node, index.Value()); 1433 int offset = OffsetForElementAccess(node, index.Value());
1438 ProcessLoadFromPhi(offset, from, node, state); 1434 ProcessLoadFromPhi(offset, from, node, state);
1439 } else { 1435 } else {
1440 UpdateReplacement(state, node, nullptr); 1436 UpdateReplacement(state, node, nullptr);
1441 } 1437 }
1442 } else { 1438 } else {
1443 // We have a load from a non-const index, cannot eliminate object. 1439 // We have a load from a non-const index, cannot eliminate object.
1444 if (status_analysis_->SetEscaped(from)) { 1440 if (status_analysis_->SetEscaped(from)) {
1445 TRACE( 1441 TRACE(
1446 "Setting #%d (%s) to escaped because load element #%d from non-const " 1442 "Setting #%d (%s) to escaped because load element #%d from non-const "
1447 "index #%d (%s)\n", 1443 "index #%d (%s)\n",
1448 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1444 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1449 index_node->op()->mnemonic()); 1445 index_node->op()->mnemonic());
1450 } 1446 }
1451 } 1447 }
1452 } 1448 }
1453 1449
1454 void EscapeAnalysis::ProcessStoreField(Node* node) { 1450 void EscapeAnalysis::ProcessStoreField(Node* node) {
1455 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1451 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1456 ForwardVirtualState(node); 1452 ForwardVirtualState(node);
1457 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1453 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1458 VirtualState* state = virtual_states_[node->id()]; 1454 VirtualState* state = virtual_states_[node->id()];
1459 VirtualObject* obj = GetVirtualObject(state, to); 1455 if (VirtualObject* object = GetVirtualObject(state, to)) {
1460 int offset = OffsetForFieldAccess(node); 1456 if (!object->IsTracked()) return;
1461 if (obj && obj->IsTracked() && 1457 int offset = OffsetForFieldAccess(node);
1462 static_cast<size_t>(offset) < obj->field_count()) { 1458 if (static_cast<size_t>(offset) >= object->field_count()) return;
1463 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1)); 1459 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
1464 // TODO(mstarzinger): The following is a workaround to not track the code 1460 // TODO(mstarzinger): The following is a workaround to not track the code
1465 // entry field in virtual JSFunction objects. We only ever store the inner 1461 // entry field in virtual JSFunction objects. We only ever store the inner
1466 // pointer into the compile lazy stub in this field and the deoptimizer has 1462 // pointer into the compile lazy stub in this field and the deoptimizer has
1467 // this assumption hard-coded in {TranslatedState::MaterializeAt} as well. 1463 // this assumption hard-coded in {TranslatedState::MaterializeAt} as well.
1468 if (val->opcode() == IrOpcode::kInt32Constant || 1464 if (val->opcode() == IrOpcode::kInt32Constant ||
1469 val->opcode() == IrOpcode::kInt64Constant) { 1465 val->opcode() == IrOpcode::kInt64Constant) {
1470 DCHECK_EQ(JSFunction::kCodeEntryOffset, FieldAccessOf(node->op()).offset); 1466 DCHECK_EQ(JSFunction::kCodeEntryOffset, FieldAccessOf(node->op()).offset);
1471 val = slot_not_analyzed_; 1467 val = slot_not_analyzed_;
1472 } 1468 }
1473 if (obj->GetField(offset) != val) { 1469 if (object->GetField(offset) != val) {
1474 obj = CopyForModificationAt(obj, state, node); 1470 object = CopyForModificationAt(object, state, node);
1475 obj->SetField(offset, val); 1471 object->SetField(offset, val);
1476 } 1472 }
1477 } 1473 }
1478 } 1474 }
1479 1475
1480 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1476 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1481 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1477 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1482 ForwardVirtualState(node); 1478 ForwardVirtualState(node);
1483 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1479 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1484 Node* index_node = node->InputAt(1); 1480 Node* index_node = node->InputAt(1);
1485 NumberMatcher index(index_node); 1481 NumberMatcher index(index_node);
1486 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1482 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1487 index_node->opcode() != IrOpcode::kInt64Constant && 1483 index_node->opcode() != IrOpcode::kInt64Constant &&
1488 index_node->opcode() != IrOpcode::kFloat32Constant && 1484 index_node->opcode() != IrOpcode::kFloat32Constant &&
1489 index_node->opcode() != IrOpcode::kFloat64Constant); 1485 index_node->opcode() != IrOpcode::kFloat64Constant);
1490 VirtualState* state = virtual_states_[node->id()]; 1486 VirtualState* state = virtual_states_[node->id()];
1491 VirtualObject* obj = GetVirtualObject(state, to);
1492 if (index.HasValue()) { 1487 if (index.HasValue()) {
1493 int offset = OffsetForElementAccess(node, index.Value()); 1488 if (VirtualObject* object = GetVirtualObject(state, to)) {
1494 if (obj && obj->IsTracked() && 1489 if (!object->IsTracked()) return;
1495 static_cast<size_t>(offset) < obj->field_count()) { 1490 int offset = OffsetForElementAccess(node, index.Value());
1491 if (static_cast<size_t>(offset) >= object->field_count()) return;
1496 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2)); 1492 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
1497 if (obj->GetField(offset) != val) { 1493 if (object->GetField(offset) != val) {
1498 obj = CopyForModificationAt(obj, state, node); 1494 object = CopyForModificationAt(object, state, node);
1499 obj->SetField(offset, val); 1495 object->SetField(offset, val);
1500 } 1496 }
1501 } 1497 }
1502 } else { 1498 } else {
1503 // We have a store to a non-const index, cannot eliminate object. 1499 // We have a store to a non-const index, cannot eliminate object.
1504 if (status_analysis_->SetEscaped(to)) { 1500 if (status_analysis_->SetEscaped(to)) {
1505 TRACE( 1501 TRACE(
1506 "Setting #%d (%s) to escaped because store element #%d to non-const " 1502 "Setting #%d (%s) to escaped because store element #%d to non-const "
1507 "index #%d (%s)\n", 1503 "index #%d (%s)\n",
1508 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), 1504 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1509 index_node->op()->mnemonic()); 1505 index_node->op()->mnemonic());
1510 } 1506 }
1511 if (obj && obj->IsTracked()) { 1507 if (VirtualObject* object = GetVirtualObject(state, to)) {
1512 if (!obj->AllFieldsClear()) { 1508 if (!object->IsTracked()) return;
1513 obj = CopyForModificationAt(obj, state, node); 1509 if (!object->AllFieldsClear()) {
1514 obj->ClearAllFields(); 1510 object = CopyForModificationAt(object, state, node);
1511 object->ClearAllFields();
1515 TRACE("Cleared all fields of @%d:#%d\n", 1512 TRACE("Cleared all fields of @%d:#%d\n",
1516 status_analysis_->GetAlias(obj->id()), obj->id()); 1513 status_analysis_->GetAlias(object->id()), object->id());
1517 } 1514 }
1518 } 1515 }
1519 } 1516 }
1520 } 1517 }
1521 1518
1522 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { 1519 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
1523 if ((node->opcode() == IrOpcode::kFinishRegion || 1520 if ((node->opcode() == IrOpcode::kFinishRegion ||
1524 node->opcode() == IrOpcode::kAllocate) && 1521 node->opcode() == IrOpcode::kAllocate) &&
1525 IsVirtual(node)) { 1522 IsVirtual(node)) {
1526 if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()], 1523 if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()],
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 } 1606 }
1610 } 1607 }
1611 return false; 1608 return false;
1612 } 1609 }
1613 1610
1614 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } 1611 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); }
1615 1612
1616 } // namespace compiler 1613 } // namespace compiler
1617 } // namespace internal 1614 } // namespace internal
1618 } // namespace v8 1615 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698