OLD | NEW |
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 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 } | 1392 } |
1393 | 1393 |
1394 void EscapeAnalysis::ProcessLoadField(Node* node) { | 1394 void EscapeAnalysis::ProcessLoadField(Node* node) { |
1395 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); | 1395 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); |
1396 ForwardVirtualState(node); | 1396 ForwardVirtualState(node); |
1397 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); | 1397 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); |
1398 VirtualState* state = virtual_states_[node->id()]; | 1398 VirtualState* state = virtual_states_[node->id()]; |
1399 if (VirtualObject* object = GetVirtualObject(state, from)) { | 1399 if (VirtualObject* object = GetVirtualObject(state, from)) { |
1400 if (!object->IsTracked()) return; | 1400 if (!object->IsTracked()) return; |
1401 int offset = OffsetForFieldAccess(node); | 1401 int offset = OffsetForFieldAccess(node); |
1402 if (static_cast<size_t>(offset) >= object->field_count()) return; | 1402 if (static_cast<size_t>(offset) >= object->field_count()) { |
| 1403 // We have a load from a field that is not inside the {object}. This |
| 1404 // can only happen with conflicting type feedback and for dead {node}s. |
| 1405 // For now, we just mark the {object} as escaping. |
| 1406 // TODO(turbofan): Consider introducing an Undefined or None operator |
| 1407 // that we can replace this load with, since we know it's dead code. |
| 1408 if (status_analysis_->SetEscaped(from)) { |
| 1409 TRACE( |
| 1410 "Setting #%d (%s) to escaped because load field #%d from " |
| 1411 "offset %d outside of object\n", |
| 1412 from->id(), from->op()->mnemonic(), node->id(), offset); |
| 1413 } |
| 1414 return; |
| 1415 } |
1403 Node* value = object->GetField(offset); | 1416 Node* value = object->GetField(offset); |
1404 if (value) { | 1417 if (value) { |
1405 value = ResolveReplacement(value); | 1418 value = ResolveReplacement(value); |
1406 } | 1419 } |
1407 // Record that the load has this alias. | 1420 // Record that the load has this alias. |
1408 UpdateReplacement(state, node, value); | 1421 UpdateReplacement(state, node, value); |
1409 } else if (from->opcode() == IrOpcode::kPhi && | 1422 } else if (from->opcode() == IrOpcode::kPhi && |
1410 FieldAccessOf(node->op()).offset % kPointerSize == 0) { | 1423 FieldAccessOf(node->op()).offset % kPointerSize == 0) { |
1411 int offset = OffsetForFieldAccess(node); | 1424 int offset = OffsetForFieldAccess(node); |
1412 // Only binary phis are supported for now. | 1425 // Only binary phis are supported for now. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 } | 1470 } |
1458 | 1471 |
1459 void EscapeAnalysis::ProcessStoreField(Node* node) { | 1472 void EscapeAnalysis::ProcessStoreField(Node* node) { |
1460 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); | 1473 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); |
1461 ForwardVirtualState(node); | 1474 ForwardVirtualState(node); |
1462 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); | 1475 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); |
1463 VirtualState* state = virtual_states_[node->id()]; | 1476 VirtualState* state = virtual_states_[node->id()]; |
1464 if (VirtualObject* object = GetVirtualObject(state, to)) { | 1477 if (VirtualObject* object = GetVirtualObject(state, to)) { |
1465 if (!object->IsTracked()) return; | 1478 if (!object->IsTracked()) return; |
1466 int offset = OffsetForFieldAccess(node); | 1479 int offset = OffsetForFieldAccess(node); |
1467 if (static_cast<size_t>(offset) >= object->field_count()) return; | 1480 if (static_cast<size_t>(offset) >= object->field_count()) { |
| 1481 // We have a store to a field that is not inside the {object}. This |
| 1482 // can only happen with conflicting type feedback and for dead {node}s. |
| 1483 // For now, we just mark the {object} as escaping. |
| 1484 // TODO(turbofan): Consider just eliminating the store in the reducer |
| 1485 // pass, as it's dead code anyways. |
| 1486 if (status_analysis_->SetEscaped(to)) { |
| 1487 TRACE( |
| 1488 "Setting #%d (%s) to escaped because store field #%d to " |
| 1489 "offset %d outside of object\n", |
| 1490 to->id(), to->op()->mnemonic(), node->id(), offset); |
| 1491 } |
| 1492 return; |
| 1493 } |
1468 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1)); | 1494 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1)); |
1469 // TODO(mstarzinger): The following is a workaround to not track some well | 1495 // TODO(mstarzinger): The following is a workaround to not track some well |
1470 // known raw fields. We only ever store default initial values into these | 1496 // known raw fields. We only ever store default initial values into these |
1471 // fields which are hard-coded in {TranslatedState::MaterializeAt} as well. | 1497 // fields which are hard-coded in {TranslatedState::MaterializeAt} as well. |
1472 if (val->opcode() == IrOpcode::kInt32Constant || | 1498 if (val->opcode() == IrOpcode::kInt32Constant || |
1473 val->opcode() == IrOpcode::kInt64Constant) { | 1499 val->opcode() == IrOpcode::kInt64Constant) { |
1474 DCHECK(FieldAccessOf(node->op()).offset == JSFunction::kCodeEntryOffset || | 1500 DCHECK(FieldAccessOf(node->op()).offset == JSFunction::kCodeEntryOffset || |
1475 FieldAccessOf(node->op()).offset == Name::kHashFieldOffset); | 1501 FieldAccessOf(node->op()).offset == Name::kHashFieldOffset); |
1476 val = slot_not_analyzed_; | 1502 val = slot_not_analyzed_; |
1477 } | 1503 } |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1636 } | 1662 } |
1637 } | 1663 } |
1638 return false; | 1664 return false; |
1639 } | 1665 } |
1640 | 1666 |
1641 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } | 1667 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } |
1642 | 1668 |
1643 } // namespace compiler | 1669 } // namespace compiler |
1644 } // namespace internal | 1670 } // namespace internal |
1645 } // namespace v8 | 1671 } // namespace v8 |
OLD | NEW |