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

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

Issue 1485183002: [turbofan] Deopt support for escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@ea-local
Patch Set: Rebase Created 4 years, 11 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') | src/compiler/escape-analysis-reducer.h » ('j') | 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 "src/base/flags.h" 7 #include "src/base/flags.h"
8 #include "src/bootstrapper.h" 8 #include "src/bootstrapper.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/common-operator.h" 10 #include "src/compiler/common-operator.h"
11 #include "src/compiler/graph-reducer.h" 11 #include "src/compiler/graph-reducer.h"
12 #include "src/compiler/js-operator.h" 12 #include "src/compiler/js-operator.h"
13 #include "src/compiler/node.h" 13 #include "src/compiler/node.h"
14 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties.h" 15 #include "src/compiler/node-properties.h"
16 #include "src/compiler/simplified-operator.h" 16 #include "src/compiler/simplified-operator.h"
17 #include "src/objects-inl.h" 17 #include "src/objects-inl.h"
18 #include "src/type-cache.h" 18 #include "src/type-cache.h"
19 19
20 namespace v8 { 20 namespace v8 {
21 namespace internal { 21 namespace internal {
22 namespace compiler { 22 namespace compiler {
23 23
24
25 // ------------------------------VirtualObject----------------------------------
26
27
28 class VirtualObject : public ZoneObject { 24 class VirtualObject : public ZoneObject {
29 public: 25 public:
30 enum Status { kUntracked = 0, kTracked = 1 }; 26 enum Status { kUntracked = 0, kTracked = 1 };
31 VirtualObject(NodeId id, Zone* zone) 27 VirtualObject(NodeId id, Zone* zone)
32 : id_(id), status_(kUntracked), fields_(zone), phi_(zone) {} 28 : id_(id),
29 status_(kUntracked),
30 fields_(zone),
31 phi_(zone),
32 object_state_(nullptr) {}
33 33
34 VirtualObject(const VirtualObject& other) 34 VirtualObject(const VirtualObject& other)
35 : id_(other.id_), 35 : id_(other.id_),
36 status_(other.status_), 36 status_(other.status_),
37 fields_(other.fields_), 37 fields_(other.fields_),
38 phi_(other.phi_) {} 38 phi_(other.phi_),
39 object_state_(other.object_state_) {}
39 40
40 VirtualObject(NodeId id, Zone* zone, size_t field_number) 41 VirtualObject(NodeId id, Zone* zone, size_t field_number)
41 : id_(id), status_(kTracked), fields_(zone), phi_(zone) { 42 : id_(id),
43 status_(kTracked),
44 fields_(zone),
45 phi_(zone),
46 object_state_(nullptr) {
42 fields_.resize(field_number); 47 fields_.resize(field_number);
43 phi_.resize(field_number, false); 48 phi_.resize(field_number, false);
44 } 49 }
45 50
46 Node* GetField(size_t offset) { 51 Node* GetField(size_t offset) {
47 if (offset < fields_.size()) { 52 if (offset < fields_.size()) {
48 return fields_[offset]; 53 return fields_[offset];
49 } 54 }
50 return nullptr; 55 return nullptr;
51 } 56 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 for (size_t i = 0; i < fields_.size(); ++i) { 90 for (size_t i = 0; i < fields_.size(); ++i) {
86 if (fields_[i] != nullptr) { 91 if (fields_[i] != nullptr) {
87 fields_[i] = nullptr; 92 fields_[i] = nullptr;
88 changed = true; 93 changed = true;
89 } 94 }
90 phi_[i] = false; 95 phi_[i] = false;
91 } 96 }
92 return changed; 97 return changed;
93 } 98 }
94 bool UpdateFrom(const VirtualObject& other); 99 bool UpdateFrom(const VirtualObject& other);
100 void SetObjectState(Node* node) { object_state_ = node; }
101 Node* GetObjectState() { return object_state_; }
95 102
96 NodeId id() { return id_; } 103 NodeId id() { return id_; }
97 void id(NodeId id) { id_ = id; } 104 void id(NodeId id) { id_ = id; }
98 105
99 private: 106 private:
100 NodeId id_; 107 NodeId id_;
101 Status status_; 108 Status status_;
102 ZoneVector<Node*> fields_; 109 ZoneVector<Node*> fields_;
103 ZoneVector<bool> phi_; 110 ZoneVector<bool> phi_;
111 Node* object_state_;
104 }; 112 };
105 113
106 114
107 bool VirtualObject::UpdateFrom(const VirtualObject& other) { 115 bool VirtualObject::UpdateFrom(const VirtualObject& other) {
108 bool changed = status_ != other.status_; 116 bool changed = status_ != other.status_;
109 status_ = other.status_; 117 status_ = other.status_;
110 if (fields_.size() != other.fields_.size()) { 118 if (fields_.size() != other.fields_.size()) {
111 fields_ = other.fields_; 119 fields_ = other.fields_;
112 return true; 120 return true;
113 } 121 }
114 for (size_t i = 0; i < fields_.size(); ++i) { 122 for (size_t i = 0; i < fields_.size(); ++i) {
115 if (fields_[i] != other.fields_[i]) { 123 if (fields_[i] != other.fields_[i]) {
116 changed = true; 124 changed = true;
117 fields_[i] = other.fields_[i]; 125 fields_[i] = other.fields_[i];
118 } 126 }
119 } 127 }
120 return changed; 128 return changed;
121 } 129 }
122 130
123 131
124 // ------------------------------VirtualState-----------------------------------
125
126
127 class VirtualState : public ZoneObject { 132 class VirtualState : public ZoneObject {
128 public: 133 public:
129 VirtualState(Zone* zone, size_t size); 134 VirtualState(Zone* zone, size_t size);
130 VirtualState(const VirtualState& states); 135 VirtualState(const VirtualState& states);
131 136
132 VirtualObject* GetVirtualObject(Node* node); 137 VirtualObject* GetVirtualObject(Node* node);
133 VirtualObject* GetVirtualObject(size_t id); 138 VirtualObject* GetVirtualObject(size_t id);
134 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone); 139 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone);
135 void SetVirtualObject(NodeId id, VirtualObject* state); 140 void SetVirtualObject(NodeId id, VirtualObject* state);
136 void LastChangedAt(Node* node) { last_changed_ = node; } 141 void LastChangedAt(Node* node) { last_changed_ = node; }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 } 222 }
218 if (field != rep) { 223 if (field != rep) {
219 rep = nullptr; 224 rep = nullptr;
220 } 225 }
221 } 226 }
222 return rep; 227 return rep;
223 } 228 }
224 229
225 230
226 VirtualState::VirtualState(Zone* zone, size_t size) 231 VirtualState::VirtualState(Zone* zone, size_t size)
227 : info_(zone), last_changed_(nullptr) { 232 : info_(size, nullptr, zone), last_changed_(nullptr) {}
228 info_.resize(size);
229 }
230 233
231 234
232 VirtualState::VirtualState(const VirtualState& state) 235 VirtualState::VirtualState(const VirtualState& state)
233 : info_(state.info_.get_allocator().zone()), 236 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()),
234 last_changed_(state.last_changed_) { 237 last_changed_(state.last_changed_) {
235 info_.resize(state.info_.size());
236 for (size_t i = 0; i < state.info_.size(); ++i) { 238 for (size_t i = 0; i < state.info_.size(); ++i) {
237 if (state.info_[i] && state.info_[i]->id() == i) { 239 if (state.info_[i] && state.info_[i]->id() == i) {
238 info_[i] = new (state.info_.get_allocator().zone()) 240 info_[i] = new (state.info_.get_allocator().zone())
239 VirtualObject(*state.info_[i]); 241 VirtualObject(*state.info_[i]);
240 } 242 }
241 } 243 }
242 for (size_t i = 0; i < state.info_.size(); ++i) { 244 for (size_t i = 0; i < state.info_.size(); ++i) {
243 if (state.info_[i] && state.info_[i]->id() != i) { 245 if (state.info_[i] && state.info_[i]->id() != i) {
244 info_[i] = info_[state.info_[i]->id()]; 246 info_[i] = info_[state.info_[i]->id()];
245 } 247 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 changed = true; 423 changed = true;
422 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], 424 NodeProperties::ReplaceValueInput(rep, cache->fields()[n],
423 n); 425 n);
424 } 426 }
425 } else { 427 } else {
426 changed = true; 428 changed = true;
427 rep->InsertInput(graph->zone(), n, cache->fields()[n]); 429 rep->InsertInput(graph->zone(), n, cache->fields()[n]);
428 } 430 }
429 } 431 }
430 if (rep->op()->ValueInputCount() != value_input_count) { 432 if (rep->op()->ValueInputCount() != value_input_count) {
431 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(), 433 if (FLAG_trace_turbo_escape) {
432 rep->op()->ValueInputCount(), value_input_count); 434 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(),
435 rep->op()->ValueInputCount(), value_input_count);
436 }
433 NodeProperties::ChangeOp( 437 NodeProperties::ChangeOp(
434 rep, common->Phi(MachineRepresentation::kTagged, 438 rep, common->Phi(MachineRepresentation::kTagged,
435 value_input_count)); 439 value_input_count));
436 } 440 }
437 } 441 }
438 } else { 442 } else {
439 changed = mergeObject->SetField(i, nullptr) || changed; 443 changed = mergeObject->SetField(i, nullptr) || changed;
440 } 444 }
441 } 445 }
442 } 446 }
443
444 } else { 447 } else {
445 SetVirtualObject(id, nullptr); 448 SetVirtualObject(id, nullptr);
446 } 449 }
447 } 450 }
448 // Update linked objects. 451 // Update linked objects.
449 for (NodeId id = 0; id < cache->min_size(); ++id) { 452 for (NodeId id = 0; id < cache->min_size(); ++id) {
450 if (VirtualObject* obj = cache->states().front()->GetVirtualObject(id)) { 453 if (VirtualObject* obj = cache->states().front()->GetVirtualObject(id)) {
451 if (obj->id() != id) { 454 if (obj->id() != id) {
452 SetVirtualObject(id, GetVirtualObject(obj->id())); 455 SetVirtualObject(id, GetVirtualObject(obj->id()));
453 } 456 }
454 } 457 }
455 } 458 }
456 return changed; 459 return changed;
457 } 460 }
458 461
459 462
460 // ------------------------------EscapeStatusAnalysis---------------------------
461
462
463 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, 463 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis,
464 Graph* graph, Zone* zone) 464 Graph* graph, Zone* zone)
465 : object_analysis_(object_analysis), 465 : object_analysis_(object_analysis),
466 graph_(graph), 466 graph_(graph),
467 zone_(zone), 467 zone_(zone),
468 info_(graph->NodeCount(), kUnknown, zone), 468 info_(graph->NodeCount(), kUnknown, zone),
469 queue_(zone) {} 469 queue_(zone) {}
470 470
471 471
472 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} 472 EscapeStatusAnalysis::~EscapeStatusAnalysis() {}
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 if (IsAllocation(rep) && CheckUsesForEscape(node, rep)) { 564 if (IsAllocation(rep) && CheckUsesForEscape(node, rep)) {
565 RevisitInputs(rep); 565 RevisitInputs(rep);
566 RevisitUses(rep); 566 RevisitUses(rep);
567 } 567 }
568 } 568 }
569 break; 569 break;
570 } 570 }
571 case IrOpcode::kPhi: 571 case IrOpcode::kPhi:
572 if (!HasEntry(node)) { 572 if (!HasEntry(node)) {
573 info_[node->id()] = kVirtual; 573 info_[node->id()] = kVirtual;
574 if (!IsAllocationPhi(node)) {
575 SetEscaped(node);
576 RevisitUses(node);
577 }
574 } 578 }
575 CheckUsesForEscape(node); 579 CheckUsesForEscape(node);
576 default: 580 default:
577 break; 581 break;
578 } 582 }
579 } 583 }
580 584
581 585
586 bool EscapeStatusAnalysis::IsAllocationPhi(Node* node) {
587 for (Edge edge : node->input_edges()) {
588 Node* input = edge.to();
589 if (input->opcode() == IrOpcode::kPhi && !IsEscaped(input)) continue;
590 if (IsAllocation(input)) continue;
591 return false;
592 }
593 return true;
594 }
595
596
582 void EscapeStatusAnalysis::ProcessStoreField(Node* node) { 597 void EscapeStatusAnalysis::ProcessStoreField(Node* node) {
583 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 598 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
584 Node* to = NodeProperties::GetValueInput(node, 0); 599 Node* to = NodeProperties::GetValueInput(node, 0);
585 Node* val = NodeProperties::GetValueInput(node, 1); 600 Node* val = NodeProperties::GetValueInput(node, 1);
586 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) { 601 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) {
587 RevisitUses(val); 602 RevisitUses(val);
588 RevisitInputs(val); 603 RevisitInputs(val);
589 if (FLAG_trace_turbo_escape) { 604 if (FLAG_trace_turbo_escape) {
590 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n", 605 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n",
591 val->id(), val->op()->mnemonic(), to->id()); 606 val->id(), val->op()->mnemonic(), to->id());
(...skipping 19 matching lines...) Expand all
611 626
612 void EscapeStatusAnalysis::ProcessAllocate(Node* node) { 627 void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
613 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 628 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
614 if (!HasEntry(node)) { 629 if (!HasEntry(node)) {
615 info_[node->id()] = kVirtual; 630 info_[node->id()] = kVirtual;
616 if (FLAG_trace_turbo_escape) { 631 if (FLAG_trace_turbo_escape) {
617 PrintF("Created status entry for node #%d (%s)\n", node->id(), 632 PrintF("Created status entry for node #%d (%s)\n", node->id(),
618 node->op()->mnemonic()); 633 node->op()->mnemonic());
619 } 634 }
620 NumberMatcher size(node->InputAt(0)); 635 NumberMatcher size(node->InputAt(0));
636 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
637 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
638 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
639 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
621 if (!size.HasValue() && SetEscaped(node)) { 640 if (!size.HasValue() && SetEscaped(node)) {
622 RevisitUses(node); 641 RevisitUses(node);
623 if (FLAG_trace_turbo_escape) { 642 if (FLAG_trace_turbo_escape) {
624 PrintF("Setting #%d to escaped because of non-const alloc\n", 643 PrintF("Setting #%d to escaped because of non-const alloc\n",
625 node->id()); 644 node->id());
626 } 645 }
627 // This node is known to escape, uses do not have to be checked. 646 // This node is known to escape, uses do not have to be checked.
628 return; 647 return;
629 } 648 }
630 } 649 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 void EscapeStatusAnalysis::DebugPrint() { 736 void EscapeStatusAnalysis::DebugPrint() {
718 for (NodeId id = 0; id < info_.size(); id++) { 737 for (NodeId id = 0; id < info_.size(); id++) {
719 if (info_[id] != kUnknown) { 738 if (info_[id] != kUnknown) {
720 PrintF("Node #%d is %s\n", id, 739 PrintF("Node #%d is %s\n", id,
721 info_[id] == kEscaped ? "escaping" : "virtual"); 740 info_[id] == kEscaped ? "escaping" : "virtual");
722 } 741 }
723 } 742 }
724 } 743 }
725 744
726 745
727 // -----------------------------EscapeAnalysis----------------------------------
728
729
730 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, 746 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
731 Zone* zone) 747 Zone* zone)
732 : graph_(graph), 748 : graph_(graph),
733 common_(common), 749 common_(common),
734 zone_(zone), 750 zone_(zone),
735 virtual_states_(zone), 751 virtual_states_(zone),
736 replacements_(zone), 752 replacements_(zone),
737 escape_status_(this, graph, zone), 753 escape_status_(this, graph, zone),
738 cache_(new (zone) MergeCache(zone)) {} 754 cache_(new (zone) MergeCache(zone)) {}
739 755
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 1014
999 1015
1000 void EscapeAnalysis::ProcessAllocation(Node* node) { 1016 void EscapeAnalysis::ProcessAllocation(Node* node) {
1001 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 1017 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
1002 ForwardVirtualState(node); 1018 ForwardVirtualState(node);
1003 1019
1004 // Check if we have already processed this node. 1020 // Check if we have already processed this node.
1005 if (virtual_states_[node->id()]->GetVirtualObject(node)) return; 1021 if (virtual_states_[node->id()]->GetVirtualObject(node)) return;
1006 1022
1007 NumberMatcher size(node->InputAt(0)); 1023 NumberMatcher size(node->InputAt(0));
1024 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
1025 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
1026 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
1027 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
1008 if (size.HasValue()) { 1028 if (size.HasValue()) {
1009 virtual_states_[node->id()]->SetVirtualObject( 1029 virtual_states_[node->id()]->SetVirtualObject(
1010 node->id(), new (zone()) VirtualObject(node->id(), zone(), 1030 node->id(), new (zone()) VirtualObject(node->id(), zone(),
1011 size.Value() / kPointerSize)); 1031 size.Value() / kPointerSize));
1012 } else { 1032 } else {
1013 virtual_states_[node->id()]->SetVirtualObject( 1033 virtual_states_[node->id()]->SetVirtualObject(
1014 node->id(), new (zone()) VirtualObject(node->id(), zone())); 1034 node->id(), new (zone()) VirtualObject(node->id(), zone()));
1015 } 1035 }
1016 virtual_states_[node->id()]->LastChangedAt(node); 1036 virtual_states_[node->id()]->LastChangedAt(node);
1017 } 1037 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 Node* node) { 1149 Node* node) {
1130 VirtualObject* obj = state->GetVirtualObject(ResolveReplacement(node)); 1150 VirtualObject* obj = state->GetVirtualObject(ResolveReplacement(node));
1131 while (obj && replacement(obj->id()) && 1151 while (obj && replacement(obj->id()) &&
1132 state->GetVirtualObject(replacement(obj->id()))) { 1152 state->GetVirtualObject(replacement(obj->id()))) {
1133 obj = state->GetVirtualObject(replacement(obj->id())); 1153 obj = state->GetVirtualObject(replacement(obj->id()));
1134 } 1154 }
1135 return obj; 1155 return obj;
1136 } 1156 }
1137 1157
1138 1158
1159 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
1160 DCHECK(IsVirtual(left) && IsVirtual(right));
1161 left = ResolveReplacement(left);
1162 right = ResolveReplacement(right);
1163 if (IsEquivalentPhi(left, right)) {
1164 return true;
1165 }
1166 return false;
1167 }
1168
1169
1139 int EscapeAnalysis::OffsetFromAccess(Node* node) { 1170 int EscapeAnalysis::OffsetFromAccess(Node* node) {
1140 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 1171 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
1141 return OpParameter<FieldAccess>(node).offset / kPointerSize; 1172 return OpParameter<FieldAccess>(node).offset / kPointerSize;
1142 } 1173 }
1143 1174
1144 1175
1145 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, 1176 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
1146 VirtualState* state) { 1177 VirtualState* state) {
1147 if (FLAG_trace_turbo_escape) { 1178 if (FLAG_trace_turbo_escape) {
1148 PrintF("Load #%d from phi #%d", node->id(), from->id()); 1179 PrintF("Load #%d from phi #%d", node->id(), from->id());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 } 1239 }
1209 1240
1210 1241
1211 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1242 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1212 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1243 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1213 ForwardVirtualState(node); 1244 ForwardVirtualState(node);
1214 Node* from = NodeProperties::GetValueInput(node, 0); 1245 Node* from = NodeProperties::GetValueInput(node, 0);
1215 VirtualState* state = virtual_states_[node->id()]; 1246 VirtualState* state = virtual_states_[node->id()];
1216 Node* index_node = node->InputAt(1); 1247 Node* index_node = node->InputAt(1);
1217 NumberMatcher index(index_node); 1248 NumberMatcher index(index_node);
1249 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1250 index_node->opcode() != IrOpcode::kInt64Constant &&
1251 index_node->opcode() != IrOpcode::kFloat32Constant &&
1252 index_node->opcode() != IrOpcode::kFloat64Constant);
1218 ElementAccess access = OpParameter<ElementAccess>(node); 1253 ElementAccess access = OpParameter<ElementAccess>(node);
1219 if (index.HasValue()) { 1254 if (index.HasValue()) {
1220 int offset = index.Value() + access.header_size / kPointerSize; 1255 int offset = index.Value() + access.header_size / kPointerSize;
1221 if (VirtualObject* object = ResolveVirtualObject(state, from)) { 1256 if (VirtualObject* object = ResolveVirtualObject(state, from)) {
1222 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1257 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1223 kPointerSizeLog2); 1258 kPointerSizeLog2);
1224 CHECK_EQ(access.header_size % kPointerSize, 0); 1259 CHECK_EQ(access.header_size % kPointerSize, 0);
1225 1260
1226 if (!object->IsTracked()) return; 1261 if (!object->IsTracked()) return;
1227 Node* value = object->GetField(offset); 1262 Node* value = object->GetField(offset);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 } 1301 }
1267 } 1302 }
1268 1303
1269 1304
1270 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1305 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1271 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1306 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1272 ForwardVirtualState(node); 1307 ForwardVirtualState(node);
1273 Node* to = NodeProperties::GetValueInput(node, 0); 1308 Node* to = NodeProperties::GetValueInput(node, 0);
1274 Node* index_node = node->InputAt(1); 1309 Node* index_node = node->InputAt(1);
1275 NumberMatcher index(index_node); 1310 NumberMatcher index(index_node);
1311 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1312 index_node->opcode() != IrOpcode::kInt64Constant &&
1313 index_node->opcode() != IrOpcode::kFloat32Constant &&
1314 index_node->opcode() != IrOpcode::kFloat64Constant);
1276 ElementAccess access = OpParameter<ElementAccess>(node); 1315 ElementAccess access = OpParameter<ElementAccess>(node);
1277 Node* val = NodeProperties::GetValueInput(node, 2); 1316 Node* val = NodeProperties::GetValueInput(node, 2);
1278 if (index.HasValue()) { 1317 if (index.HasValue()) {
1279 int offset = index.Value() + access.header_size / kPointerSize; 1318 int offset = index.Value() + access.header_size / kPointerSize;
1280 VirtualState* states = virtual_states_[node->id()]; 1319 VirtualState* states = virtual_states_[node->id()];
1281 if (VirtualObject* obj = ResolveVirtualObject(states, to)) { 1320 if (VirtualObject* obj = ResolveVirtualObject(states, to)) {
1282 if (!obj->IsTracked()) return; 1321 if (!obj->IsTracked()) return;
1283 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1322 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1284 kPointerSizeLog2); 1323 kPointerSizeLog2);
1285 CHECK_EQ(access.header_size % kPointerSize, 0); 1324 CHECK_EQ(access.header_size % kPointerSize, 0);
(...skipping 10 matching lines...) Expand all
1296 "non-const " 1335 "non-const "
1297 "index #%d (%s)\n", 1336 "index #%d (%s)\n",
1298 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), 1337 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1299 index_node->op()->mnemonic()); 1338 index_node->op()->mnemonic());
1300 } 1339 }
1301 } 1340 }
1302 } 1341 }
1303 } 1342 }
1304 1343
1305 1344
1345 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
1346 if ((node->opcode() == IrOpcode::kFinishRegion ||
1347 node->opcode() == IrOpcode::kAllocate) &&
1348 IsVirtual(node)) {
1349 if (VirtualObject* vobj =
1350 ResolveVirtualObject(virtual_states_[effect->id()], node)) {
1351 if (Node* object_state = vobj->GetObjectState()) {
1352 return object_state;
1353 } else {
1354 cache_->fields().clear();
1355 for (size_t i = 0; i < vobj->field_count(); ++i) {
1356 if (Node* field = vobj->GetField(i)) {
1357 cache_->fields().push_back(field);
1358 }
1359 }
1360 int input_count = static_cast<int>(cache_->fields().size());
1361 Node* new_object_state =
1362 graph()->NewNode(common()->ObjectState(input_count, vobj->id()),
1363 input_count, &cache_->fields().front());
1364 vobj->SetObjectState(new_object_state);
1365 if (FLAG_trace_turbo_escape) {
1366 PrintF(
1367 "Creating object state #%d for vobj %p (from node #%d) at effect "
1368 "#%d\n",
1369 new_object_state->id(), static_cast<void*>(vobj), node->id(),
1370 effect->id());
1371 }
1372 // Now fix uses of other objects.
1373 for (size_t i = 0; i < vobj->field_count(); ++i) {
1374 if (Node* field = vobj->GetField(i)) {
1375 if (Node* field_object_state =
1376 GetOrCreateObjectState(effect, field)) {
1377 NodeProperties::ReplaceValueInput(
1378 new_object_state, field_object_state, static_cast<int>(i));
1379 }
1380 }
1381 }
1382 return new_object_state;
1383 }
1384 }
1385 }
1386 return nullptr;
1387 }
1388
1389
1306 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) { 1390 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) {
1307 PrintF(" Object #%d with %zu fields\n", id, object->field_count()); 1391 PrintF(" Object #%d with %zu fields\n", id, object->field_count());
1308 for (size_t i = 0; i < object->field_count(); ++i) { 1392 for (size_t i = 0; i < object->field_count(); ++i) {
1309 if (Node* f = object->GetField(i)) { 1393 if (Node* f = object->GetField(i)) {
1310 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); 1394 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
1311 } 1395 }
1312 } 1396 }
1313 } 1397 }
1314 1398
1315 1399
(...skipping 22 matching lines...) Expand all
1338 } 1422 }
1339 } 1423 }
1340 for (size_t n = 0; n < object_states.size(); n++) { 1424 for (size_t n = 0; n < object_states.size(); n++) {
1341 DebugPrintState(object_states[n]); 1425 DebugPrintState(object_states[n]);
1342 } 1426 }
1343 } 1427 }
1344 1428
1345 } // namespace compiler 1429 } // namespace compiler
1346 } // namespace internal 1430 } // namespace internal
1347 } // namespace v8 1431 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698