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

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

Issue 2000733002: [turbofan] Unify escape analysis offset calculation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix typo. 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 | « src/compiler/escape-analysis.h ('k') | 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 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { 1320 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
1321 DCHECK(IsVirtual(left) && IsVirtual(right)); 1321 DCHECK(IsVirtual(left) && IsVirtual(right));
1322 left = ResolveReplacement(left); 1322 left = ResolveReplacement(left);
1323 right = ResolveReplacement(right); 1323 right = ResolveReplacement(right);
1324 if (IsEquivalentPhi(left, right)) { 1324 if (IsEquivalentPhi(left, right)) {
1325 return true; 1325 return true;
1326 } 1326 }
1327 return false; 1327 return false;
1328 } 1328 }
1329 1329
1330 int EscapeAnalysis::OffsetFromAccess(Node* node) { 1330 namespace {
1331 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 1331
1332 return OpParameter<FieldAccess>(node).offset / kPointerSize; 1332 int OffsetForFieldAccess(Node* node) {
1333 FieldAccess access = FieldAccessOf(node->op());
1334 DCHECK_EQ(access.offset % kPointerSize, 0);
1335 return access.offset / kPointerSize;
1333 } 1336 }
1334 1337
1338 int OffsetForElementAccess(Node* node, int index) {
1339 ElementAccess access = ElementAccessOf(node->op());
1340 DCHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1341 kPointerSizeLog2);
1342 DCHECK_EQ(access.header_size % kPointerSize, 0);
1343 return access.header_size / kPointerSize + index;
1344 }
1345
1346 } // namespace
1347
1335 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load, 1348 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load,
1336 VirtualState* state) { 1349 VirtualState* state) {
1337 TRACE("Load #%d from phi #%d", load->id(), from->id()); 1350 TRACE("Load #%d from phi #%d", load->id(), from->id());
1338 1351
1339 cache_->fields().clear(); 1352 cache_->fields().clear();
1340 for (int i = 0; i < load->op()->ValueInputCount(); ++i) { 1353 for (int i = 0; i < load->op()->ValueInputCount(); ++i) {
1341 Node* input = NodeProperties::GetValueInput(load, i); 1354 Node* input = NodeProperties::GetValueInput(load, i);
1342 cache_->fields().push_back(input); 1355 cache_->fields().push_back(input);
1343 } 1356 }
1344 1357
(...skipping 22 matching lines...) Expand all
1367 TRACE(" has incomplete virtual object info.\n"); 1380 TRACE(" has incomplete virtual object info.\n");
1368 } 1381 }
1369 } 1382 }
1370 1383
1371 void EscapeAnalysis::ProcessLoadField(Node* node) { 1384 void EscapeAnalysis::ProcessLoadField(Node* node) {
1372 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1385 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1373 ForwardVirtualState(node); 1386 ForwardVirtualState(node);
1374 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1387 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1375 VirtualState* state = virtual_states_[node->id()]; 1388 VirtualState* state = virtual_states_[node->id()];
1376 if (VirtualObject* object = GetVirtualObject(state, from)) { 1389 if (VirtualObject* object = GetVirtualObject(state, from)) {
1377 int offset = OffsetFromAccess(node); 1390 int offset = OffsetForFieldAccess(node);
1378 if (!object->IsTracked() || 1391 if (!object->IsTracked() ||
1379 static_cast<size_t>(offset) >= object->field_count()) { 1392 static_cast<size_t>(offset) >= object->field_count()) {
1380 return; 1393 return;
1381 } 1394 }
1382 Node* value = object->GetField(offset); 1395 Node* value = object->GetField(offset);
1383 if (value) { 1396 if (value) {
1384 value = ResolveReplacement(value); 1397 value = ResolveReplacement(value);
1385 } 1398 }
1386 // Record that the load has this alias. 1399 // Record that the load has this alias.
1387 UpdateReplacement(state, node, value); 1400 UpdateReplacement(state, node, value);
1388 } else if (from->opcode() == IrOpcode::kPhi && 1401 } else if (from->opcode() == IrOpcode::kPhi &&
1389 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) { 1402 FieldAccessOf(node->op()).offset % kPointerSize == 0) {
1390 int offset = OffsetFromAccess(node); 1403 int offset = OffsetForFieldAccess(node);
1391 // Only binary phis are supported for now. 1404 // Only binary phis are supported for now.
1392 ProcessLoadFromPhi(offset, from, node, state); 1405 ProcessLoadFromPhi(offset, from, node, state);
1393 } else { 1406 } else {
1394 UpdateReplacement(state, node, nullptr); 1407 UpdateReplacement(state, node, nullptr);
1395 } 1408 }
1396 } 1409 }
1397 1410
1398 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1411 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1399 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1412 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1400 ForwardVirtualState(node); 1413 ForwardVirtualState(node);
1401 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1414 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1402 VirtualState* state = virtual_states_[node->id()]; 1415 VirtualState* state = virtual_states_[node->id()];
1403 Node* index_node = node->InputAt(1); 1416 Node* index_node = node->InputAt(1);
1404 NumberMatcher index(index_node); 1417 NumberMatcher index(index_node);
1405 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1418 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1406 index_node->opcode() != IrOpcode::kInt64Constant && 1419 index_node->opcode() != IrOpcode::kInt64Constant &&
1407 index_node->opcode() != IrOpcode::kFloat32Constant && 1420 index_node->opcode() != IrOpcode::kFloat32Constant &&
1408 index_node->opcode() != IrOpcode::kFloat64Constant); 1421 index_node->opcode() != IrOpcode::kFloat64Constant);
1409 ElementAccess access = OpParameter<ElementAccess>(node);
1410 if (index.HasValue()) { 1422 if (index.HasValue()) {
1411 int offset = index.Value() + access.header_size / kPointerSize;
1412 if (VirtualObject* object = GetVirtualObject(state, from)) { 1423 if (VirtualObject* object = GetVirtualObject(state, from)) {
1413 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1424 int offset = OffsetForElementAccess(node, index.Value());
1414 kPointerSizeLog2);
1415 CHECK_EQ(access.header_size % kPointerSize, 0);
1416
1417 if (!object->IsTracked() || 1425 if (!object->IsTracked() ||
1418 static_cast<size_t>(offset) >= object->field_count()) { 1426 static_cast<size_t>(offset) >= object->field_count()) {
1419 return; 1427 return;
1420 } 1428 }
1421
1422 Node* value = object->GetField(offset); 1429 Node* value = object->GetField(offset);
1423 if (value) { 1430 if (value) {
1424 value = ResolveReplacement(value); 1431 value = ResolveReplacement(value);
1425 } 1432 }
1426 // Record that the load has this alias. 1433 // Record that the load has this alias.
1427 UpdateReplacement(state, node, value); 1434 UpdateReplacement(state, node, value);
1428 } else if (from->opcode() == IrOpcode::kPhi) { 1435 } else if (from->opcode() == IrOpcode::kPhi) {
1429 ElementAccess access = OpParameter<ElementAccess>(node); 1436 int offset = OffsetForElementAccess(node, index.Value());
1430 int offset = index.Value() + access.header_size / kPointerSize;
1431 ProcessLoadFromPhi(offset, from, node, state); 1437 ProcessLoadFromPhi(offset, from, node, state);
1432 } else { 1438 } else {
1433 UpdateReplacement(state, node, nullptr); 1439 UpdateReplacement(state, node, nullptr);
1434 } 1440 }
1435 } else { 1441 } else {
1436 // We have a load from a non-const index, cannot eliminate object. 1442 // We have a load from a non-const index, cannot eliminate object.
1437 if (status_analysis_->SetEscaped(from)) { 1443 if (status_analysis_->SetEscaped(from)) {
1438 TRACE( 1444 TRACE(
1439 "Setting #%d (%s) to escaped because load element #%d from non-const " 1445 "Setting #%d (%s) to escaped because load element #%d from non-const "
1440 "index #%d (%s)\n", 1446 "index #%d (%s)\n",
1441 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1447 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1442 index_node->op()->mnemonic()); 1448 index_node->op()->mnemonic());
1443 } 1449 }
1444 } 1450 }
1445 } 1451 }
1446 1452
1447 void EscapeAnalysis::ProcessStoreField(Node* node) { 1453 void EscapeAnalysis::ProcessStoreField(Node* node) {
1448 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1454 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1449 ForwardVirtualState(node); 1455 ForwardVirtualState(node);
1450 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1456 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1451 VirtualState* state = virtual_states_[node->id()]; 1457 VirtualState* state = virtual_states_[node->id()];
1452 VirtualObject* obj = GetVirtualObject(state, to); 1458 VirtualObject* obj = GetVirtualObject(state, to);
1453 int offset = OffsetFromAccess(node); 1459 int offset = OffsetForFieldAccess(node);
1454 if (obj && obj->IsTracked() && 1460 if (obj && obj->IsTracked() &&
1455 static_cast<size_t>(offset) < obj->field_count()) { 1461 static_cast<size_t>(offset) < obj->field_count()) {
1456 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1)); 1462 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
1457 if (obj->GetField(offset) != val) { 1463 if (obj->GetField(offset) != val) {
1458 obj = CopyForModificationAt(obj, state, node); 1464 obj = CopyForModificationAt(obj, state, node);
1459 obj->SetField(offset, val); 1465 obj->SetField(offset, val);
1460 } 1466 }
1461 } 1467 }
1462 } 1468 }
1463 1469
1464 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1470 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1465 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1471 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1466 ForwardVirtualState(node); 1472 ForwardVirtualState(node);
1467 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1473 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1468 Node* index_node = node->InputAt(1); 1474 Node* index_node = node->InputAt(1);
1469 NumberMatcher index(index_node); 1475 NumberMatcher index(index_node);
1470 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1476 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1471 index_node->opcode() != IrOpcode::kInt64Constant && 1477 index_node->opcode() != IrOpcode::kInt64Constant &&
1472 index_node->opcode() != IrOpcode::kFloat32Constant && 1478 index_node->opcode() != IrOpcode::kFloat32Constant &&
1473 index_node->opcode() != IrOpcode::kFloat64Constant); 1479 index_node->opcode() != IrOpcode::kFloat64Constant);
1474 ElementAccess access = OpParameter<ElementAccess>(node);
1475 VirtualState* state = virtual_states_[node->id()]; 1480 VirtualState* state = virtual_states_[node->id()];
1476 VirtualObject* obj = GetVirtualObject(state, to); 1481 VirtualObject* obj = GetVirtualObject(state, to);
1477 if (index.HasValue()) { 1482 if (index.HasValue()) {
1478 int offset = index.Value() + access.header_size / kPointerSize; 1483 int offset = OffsetForElementAccess(node, index.Value());
1479 if (obj && obj->IsTracked() && 1484 if (obj && obj->IsTracked() &&
1480 static_cast<size_t>(offset) < obj->field_count()) { 1485 static_cast<size_t>(offset) < obj->field_count()) {
1481 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1482 kPointerSizeLog2);
1483 CHECK_EQ(access.header_size % kPointerSize, 0);
1484 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2)); 1486 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
1485 if (obj->GetField(offset) != val) { 1487 if (obj->GetField(offset) != val) {
1486 obj = CopyForModificationAt(obj, state, node); 1488 obj = CopyForModificationAt(obj, state, node);
1487 obj->SetField(offset, val); 1489 obj->SetField(offset, val);
1488 } 1490 }
1489 } 1491 }
1490 } else { 1492 } else {
1491 // We have a store to a non-const index, cannot eliminate object. 1493 // We have a store to a non-const index, cannot eliminate object.
1492 if (status_analysis_->SetEscaped(to)) { 1494 if (status_analysis_->SetEscaped(to)) {
1493 TRACE( 1495 TRACE(
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 } 1599 }
1598 } 1600 }
1599 return false; 1601 return false;
1600 } 1602 }
1601 1603
1602 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } 1604 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); }
1603 1605
1604 } // namespace compiler 1606 } // namespace compiler
1605 } // namespace internal 1607 } // namespace internal
1606 } // namespace v8 1608 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698