 Chromium Code Reviews
 Chromium Code Reviews Issue 1554073003:
  [turbofan] Improve caching in escape analysis.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1554073003:
  [turbofan] Improve caching in escape analysis.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| 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 "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" | 
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 CommonOperatorBuilder* common, Node* control); | 141 CommonOperatorBuilder* common, Node* control); | 
| 142 | 142 | 
| 143 size_t size() { return info_.size(); } | 143 size_t size() { return info_.size(); } | 
| 144 | 144 | 
| 145 private: | 145 private: | 
| 146 ZoneVector<VirtualObject*> info_; | 146 ZoneVector<VirtualObject*> info_; | 
| 147 Node* last_changed_; | 147 Node* last_changed_; | 
| 148 }; | 148 }; | 
| 149 | 149 | 
| 150 | 150 | 
| 151 class MergeCache : public ZoneObject { | |
| 152 public: | |
| 153 explicit MergeCache(Zone* zone) | |
| 154 : states_(zone), objects_(zone), fields_(zone), min_size_(SIZE_MAX) { | |
| 155 states_.reserve(4); | |
| 156 objects_.reserve(4); | |
| 157 fields_.reserve(4); | |
| 158 } | |
| 159 ZoneVector<VirtualState*>& states() { return states_; } | |
| 160 ZoneVector<VirtualObject*>& objects() { return objects_; } | |
| 161 ZoneVector<Node*>& fields() { return fields_; } | |
| 162 void Clear() { | |
| 163 states_.clear(); | |
| 164 objects_.clear(); | |
| 165 fields_.clear(); | |
| 166 min_size_ = SIZE_MAX; | |
| 167 } | |
| 168 void push_back(VirtualState* state) { | |
| 169 states_.push_back(state); | |
| 170 min_size_ = std::min(state->size(), min_size_); | |
| 171 } | |
| 172 size_t min_size() { return min_size_; } | |
| 173 | |
| 174 size_t GetVirtualObjects(NodeId id); | |
| 175 void GetVirtualObjects(VirtualState* state); | |
| 176 Node* GetFields(size_t pos); | |
| 177 | |
| 178 private: | |
| 179 ZoneVector<VirtualState*> states_; | |
| 180 ZoneVector<VirtualObject*> objects_; | |
| 181 ZoneVector<Node*> fields_; | |
| 182 size_t min_size_; | |
| 183 }; | |
| 184 | |
| 185 | |
| 186 size_t MergeCache::GetVirtualObjects(NodeId id) { | |
| 187 objects_.clear(); | |
| 188 DCHECK_GT(states_.size(), 0u); | |
| 189 size_t min = SIZE_MAX; | |
| 190 for (size_t i = 0; i < states_.size(); ++i) { | |
| 
Benedikt Meurer
2016/01/05 05:00:01
Nit: for (VirtualState* const state : states_) { .
 
sigurds
2016/01/05 09:52:53
Done.
 | |
| 191 if (VirtualObject* obj = states_[i]->GetVirtualObject(id)) { | |
| 192 objects_.push_back(obj); | |
| 193 min = std::min(obj->field_count(), min); | |
| 194 } | |
| 195 } | |
| 196 return min; | |
| 197 } | |
| 198 | |
| 199 | |
| 200 void MergeCache::GetVirtualObjects(VirtualState* state) { | |
| 
Benedikt Meurer
2016/01/05 05:00:01
This name is weird. This method doesn't really "ge
 
sigurds
2016/01/05 09:52:53
Done.
 | |
| 201 objects_.clear(); | |
| 202 for (size_t i = 0; i < fields_.size(); ++i) { | |
| 
Benedikt Meurer
2016/01/05 05:00:01
Nit: for (Node* const field : fields_) { ... }
 
sigurds
2016/01/05 09:52:53
Done.
 | |
| 203 if (VirtualObject* obj = state->GetVirtualObject(fields_[i])) { | |
| 204 objects_.push_back(obj); | |
| 205 } | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 | |
| 210 Node* MergeCache::GetFields(size_t pos) { | |
| 211 fields_.clear(); | |
| 212 Node* rep = objects_.front()->GetField(pos); | |
| 213 for (VirtualObject* obj : objects_) { | |
| 214 Node* field = obj->GetField(pos); | |
| 215 if (field) { | |
| 216 fields_.push_back(field); | |
| 217 } | |
| 218 if (field != rep) { | |
| 219 rep = nullptr; | |
| 220 } | |
| 221 } | |
| 222 return rep; | |
| 223 } | |
| 224 | |
| 225 | |
| 151 VirtualState::VirtualState(Zone* zone, size_t size) | 226 VirtualState::VirtualState(Zone* zone, size_t size) | 
| 152 : info_(zone), last_changed_(nullptr) { | 227 : info_(zone), last_changed_(nullptr) { | 
| 153 info_.resize(size); | 228 info_.resize(size); | 
| 154 } | 229 } | 
| 155 | 230 | 
| 156 | 231 | 
| 157 VirtualState::VirtualState(const VirtualState& state) | 232 VirtualState::VirtualState(const VirtualState& state) | 
| 158 : info_(state.info_.get_allocator().zone()), | 233 : info_(state.info_.get_allocator().zone()), | 
| 159 last_changed_(state.last_changed_) { | 234 last_changed_(state.last_changed_) { | 
| 160 info_.resize(state.info_.size()); | 235 info_.resize(state.info_.size()); | 
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 } | 320 } | 
| 246 | 321 | 
| 247 changed = ls->UpdateFrom(*rs) || changed; | 322 changed = ls->UpdateFrom(*rs) || changed; | 
| 248 } | 323 } | 
| 249 return false; | 324 return false; | 
| 250 } | 325 } | 
| 251 | 326 | 
| 252 | 327 | 
| 253 namespace { | 328 namespace { | 
| 254 | 329 | 
| 255 size_t min_size(ZoneVector<VirtualState*>& states) { | |
| 256 size_t min = SIZE_MAX; | |
| 257 for (VirtualState* state : states) { | |
| 258 min = std::min(state->size(), min); | |
| 259 } | |
| 260 return min; | |
| 261 } | |
| 262 | |
| 263 | |
| 264 size_t min_field_count(ZoneVector<VirtualObject*>& objs) { | |
| 265 size_t min = SIZE_MAX; | |
| 266 for (VirtualObject* obj : objs) { | |
| 267 min = std::min(obj->field_count(), min); | |
| 268 } | |
| 269 return min; | |
| 270 } | |
| 271 | |
| 272 | |
| 273 void GetVirtualObjects(ZoneVector<VirtualState*> states, | |
| 274 ZoneVector<VirtualObject*>& objs, NodeId id) { | |
| 275 objs.clear(); | |
| 276 for (VirtualState* state : states) { | |
| 277 if (VirtualObject* obj = state->GetVirtualObject(id)) { | |
| 278 objs.push_back(obj); | |
| 279 } | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 | |
| 284 void GetVirtualObjects(VirtualState* state, ZoneVector<Node*> nodes, | |
| 285 ZoneVector<VirtualObject*>& objs) { | |
| 286 objs.clear(); | |
| 287 for (Node* node : nodes) { | |
| 288 if (VirtualObject* obj = state->GetVirtualObject(node)) { | |
| 289 objs.push_back(obj); | |
| 290 } | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 | |
| 295 Node* GetFieldIfSame(size_t pos, ZoneVector<VirtualObject*>& objs) { | |
| 296 Node* rep = objs.front()->GetField(pos); | |
| 297 for (VirtualObject* obj : objs) { | |
| 298 if (obj->GetField(pos) != rep) { | |
| 299 return nullptr; | |
| 300 } | |
| 301 } | |
| 302 return rep; | |
| 303 } | |
| 304 | |
| 305 | |
| 306 void GetFields(ZoneVector<VirtualObject*>& objs, ZoneVector<Node*>& fields, | |
| 307 size_t pos) { | |
| 308 fields.clear(); | |
| 309 for (VirtualObject* obj : objs) { | |
| 310 if (Node* field = obj->GetField(pos)) { | |
| 311 fields.push_back(field); | |
| 312 } | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 | |
| 317 bool IsEquivalentPhi(Node* node1, Node* node2) { | 330 bool IsEquivalentPhi(Node* node1, Node* node2) { | 
| 318 if (node1 == node2) return true; | 331 if (node1 == node2) return true; | 
| 319 if (node1->opcode() != IrOpcode::kPhi || node2->opcode() != IrOpcode::kPhi || | 332 if (node1->opcode() != IrOpcode::kPhi || node2->opcode() != IrOpcode::kPhi || | 
| 320 node1->op()->ValueInputCount() != node2->op()->ValueInputCount()) { | 333 node1->op()->ValueInputCount() != node2->op()->ValueInputCount()) { | 
| 321 return false; | 334 return false; | 
| 322 } | 335 } | 
| 323 for (int i = 0; i < node1->op()->ValueInputCount(); ++i) { | 336 for (int i = 0; i < node1->op()->ValueInputCount(); ++i) { | 
| 324 Node* input1 = NodeProperties::GetValueInput(node1, i); | 337 Node* input1 = NodeProperties::GetValueInput(node1, i); | 
| 325 Node* input2 = NodeProperties::GetValueInput(node2, i); | 338 Node* input2 = NodeProperties::GetValueInput(node2, i); | 
| 326 if (!IsEquivalentPhi(input1, input2)) { | 339 if (!IsEquivalentPhi(input1, input2)) { | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 356 } | 369 } | 
| 357 } | 370 } | 
| 358 return rep; | 371 return rep; | 
| 359 } | 372 } | 
| 360 | 373 | 
| 361 | 374 | 
| 362 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 375 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 
| 363 CommonOperatorBuilder* common, Node* control) { | 376 CommonOperatorBuilder* common, Node* control) { | 
| 364 DCHECK_GT(cache->states().size(), 0u); | 377 DCHECK_GT(cache->states().size(), 0u); | 
| 365 bool changed = false; | 378 bool changed = false; | 
| 366 for (NodeId id = 0; id < min_size(cache->states()); ++id) { | 379 for (NodeId id = 0; id < cache->min_size(); ++id) { | 
| 367 GetVirtualObjects(cache->states(), cache->objects(), id); | 380 size_t fields = cache->GetVirtualObjects(id); | 
| 368 if (cache->objects().size() == cache->states().size()) { | 381 if (cache->objects().size() == cache->states().size()) { | 
| 369 // Don't process linked objects. | 382 // Don't process linked objects. | 
| 370 if (cache->objects()[0]->id() != id) continue; | 383 if (cache->objects()[0]->id() != id) continue; | 
| 371 if (FLAG_trace_turbo_escape) { | 384 if (FLAG_trace_turbo_escape) { | 
| 372 PrintF(" Merging virtual objects of #%d\n", id); | 385 PrintF(" Merging virtual objects of #%d\n", id); | 
| 373 } | 386 } | 
| 374 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); | 387 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); | 
| 375 size_t fields = min_field_count(cache->objects()); | |
| 376 changed = mergeObject->ResizeFields(fields) || changed; | 388 changed = mergeObject->ResizeFields(fields) || changed; | 
| 377 for (size_t i = 0; i < fields; ++i) { | 389 for (size_t i = 0; i < fields; ++i) { | 
| 378 if (Node* field = GetFieldIfSame(i, cache->objects())) { | 390 if (Node* field = cache->GetFields(i)) { | 
| 379 changed = mergeObject->SetField(i, field) || changed; | 391 changed = mergeObject->SetField(i, field) || changed; | 
| 380 if (FLAG_trace_turbo_escape) { | 392 if (FLAG_trace_turbo_escape) { | 
| 381 PrintF(" Field %zu agree on rep #%d\n", i, field->id()); | 393 PrintF(" Field %zu agree on rep #%d\n", i, field->id()); | 
| 382 } | 394 } | 
| 383 } else { | 395 } else { | 
| 384 GetFields(cache->objects(), cache->fields(), i); | 396 int value_input_count = static_cast<int>(cache->fields().size()); | 
| 385 if (cache->fields().size() == cache->objects().size()) { | 397 if (cache->fields().size() == cache->objects().size()) { | 
| 386 Node* rep = mergeObject->GetField(i); | 398 Node* rep = mergeObject->GetField(i); | 
| 387 if (!rep || !mergeObject->IsCreatedPhi(i)) { | 399 if (!rep || !mergeObject->IsCreatedPhi(i)) { | 
| 388 cache->fields().push_back(control); | 400 cache->fields().push_back(control); | 
| 389 Node* phi = | 401 Node* phi = graph->NewNode( | 
| 390 graph->NewNode(common->Phi(MachineRepresentation::kTagged, 2), | 402 common->Phi(MachineRepresentation::kTagged, | 
| 391 static_cast<int>(cache->fields().size()), | 403 value_input_count), | 
| 392 &cache->fields().front()); | 404 value_input_count + 1, &cache->fields().front()); | 
| 393 mergeObject->SetField(i, phi, true); | 405 mergeObject->SetField(i, phi, true); | 
| 394 if (FLAG_trace_turbo_escape) { | 406 if (FLAG_trace_turbo_escape) { | 
| 395 PrintF(" Creating Phi #%d as merge of", phi->id()); | 407 PrintF(" Creating Phi #%d as merge of", phi->id()); | 
| 396 for (size_t i = 0; i + 1 < cache->fields().size(); i++) { | 408 for (int i = 0; i < value_input_count; i++) { | 
| 397 PrintF(" #%d (%s)", cache->fields()[i]->id(), | 409 PrintF(" #%d (%s)", cache->fields()[i]->id(), | 
| 398 cache->fields()[i]->op()->mnemonic()); | 410 cache->fields()[i]->op()->mnemonic()); | 
| 399 } | 411 } | 
| 400 PrintF("\n"); | 412 PrintF("\n"); | 
| 401 } | 413 } | 
| 402 changed = true; | 414 changed = true; | 
| 403 } else { | 415 } else { | 
| 404 DCHECK(rep->opcode() == IrOpcode::kPhi); | 416 DCHECK(rep->opcode() == IrOpcode::kPhi); | 
| 405 for (size_t n = 0; n < cache->fields().size(); ++n) { | 417 for (int n = 0; n < value_input_count; ++n) { | 
| 406 Node* old = | 418 if (n < rep->op()->ValueInputCount()) { | 
| 407 NodeProperties::GetValueInput(rep, static_cast<int>(n)); | 419 Node* old = NodeProperties::GetValueInput(rep, n); | 
| 408 if (old != cache->fields()[n]) { | 420 if (old != cache->fields()[n]) { | 
| 421 changed = true; | |
| 422 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], | |
| 423 n); | |
| 424 } | |
| 425 } else { | |
| 409 changed = true; | 426 changed = true; | 
| 410 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], | 427 rep->InsertInput(graph->zone(), n, cache->fields()[n]); | 
| 411 static_cast<int>(n)); | |
| 412 } | 428 } | 
| 413 } | 429 } | 
| 430 if (rep->op()->ValueInputCount() != value_input_count) { | |
| 431 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(), | |
| 432 rep->op()->ValueInputCount(), value_input_count); | |
| 433 NodeProperties::ChangeOp( | |
| 434 rep, common->Phi(MachineRepresentation::kTagged, | |
| 435 value_input_count)); | |
| 436 } | |
| 414 } | 437 } | 
| 415 } else { | 438 } else { | 
| 416 changed = mergeObject->SetField(i, nullptr) || changed; | 439 changed = mergeObject->SetField(i, nullptr) || changed; | 
| 417 } | 440 } | 
| 418 } | 441 } | 
| 419 } | 442 } | 
| 420 | 443 | 
| 421 } else { | 444 } else { | 
| 422 SetVirtualObject(id, nullptr); | 445 SetVirtualObject(id, nullptr); | 
| 423 } | 446 } | 
| 424 } | 447 } | 
| 425 // Update linked objects. | 448 // Update linked objects. | 
| 426 for (NodeId id = 0; id < min_size(cache->states()); ++id) { | 449 for (NodeId id = 0; id < cache->min_size(); ++id) { | 
| 427 GetVirtualObjects(cache->states(), cache->objects(), id); | 450 if (VirtualObject* obj = cache->states().front()->GetVirtualObject(id)) { | 
| 428 if (cache->objects().size() == cache->states().size()) { | 451 if (obj->id() != id) { | 
| 429 if (cache->objects()[0]->id() != id) { | 452 SetVirtualObject(id, GetVirtualObject(obj->id())); | 
| 430 SetVirtualObject(id, GetVirtualObject(cache->objects()[0]->id())); | |
| 431 } | 453 } | 
| 432 } | 454 } | 
| 433 } | 455 } | 
| 434 return changed; | 456 return changed; | 
| 435 } | 457 } | 
| 436 | 458 | 
| 437 | 459 | 
| 438 // ------------------------------EscapeStatusAnalysis--------------------------- | 460 // ------------------------------EscapeStatusAnalysis--------------------------- | 
| 439 | 461 | 
| 440 | 462 | 
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 | 728 | 
| 707 | 729 | 
| 708 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, | 730 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, | 
| 709 Zone* zone) | 731 Zone* zone) | 
| 710 : graph_(graph), | 732 : graph_(graph), | 
| 711 common_(common), | 733 common_(common), | 
| 712 zone_(zone), | 734 zone_(zone), | 
| 713 virtual_states_(zone), | 735 virtual_states_(zone), | 
| 714 replacements_(zone), | 736 replacements_(zone), | 
| 715 escape_status_(this, graph, zone), | 737 escape_status_(this, graph, zone), | 
| 716 cache_(zone) {} | 738 cache_(new (zone) MergeCache(zone)) {} | 
| 717 | 739 | 
| 718 | 740 | 
| 719 EscapeAnalysis::~EscapeAnalysis() {} | 741 EscapeAnalysis::~EscapeAnalysis() {} | 
| 720 | 742 | 
| 721 | 743 | 
| 722 void EscapeAnalysis::Run() { | 744 void EscapeAnalysis::Run() { | 
| 723 replacements_.resize(graph()->NodeCount()); | 745 replacements_.resize(graph()->NodeCount()); | 
| 724 RunObjectAnalysis(); | 746 RunObjectAnalysis(); | 
| 725 escape_status_.Run(); | 747 escape_status_.Run(); | 
| 726 } | 748 } | 
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 926 virtual_states_[node->id()] = mergeState; | 948 virtual_states_[node->id()] = mergeState; | 
| 927 changed = true; | 949 changed = true; | 
| 928 if (FLAG_trace_turbo_escape) { | 950 if (FLAG_trace_turbo_escape) { | 
| 929 PrintF("Effect Phi #%d got new states map %p.\n", node->id(), | 951 PrintF("Effect Phi #%d got new states map %p.\n", node->id(), | 
| 930 static_cast<void*>(mergeState)); | 952 static_cast<void*>(mergeState)); | 
| 931 } | 953 } | 
| 932 } else if (mergeState->GetLastChanged() != node) { | 954 } else if (mergeState->GetLastChanged() != node) { | 
| 933 changed = true; | 955 changed = true; | 
| 934 } | 956 } | 
| 935 | 957 | 
| 936 cache_.Clear(); | 958 cache_->Clear(); | 
| 937 | 959 | 
| 938 if (FLAG_trace_turbo_escape) { | 960 if (FLAG_trace_turbo_escape) { | 
| 939 PrintF("At Effect Phi #%d, merging states into %p:", node->id(), | 961 PrintF("At Effect Phi #%d, merging states into %p:", node->id(), | 
| 940 static_cast<void*>(mergeState)); | 962 static_cast<void*>(mergeState)); | 
| 941 } | 963 } | 
| 942 | 964 | 
| 943 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { | 965 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { | 
| 944 Node* input = NodeProperties::GetEffectInput(node, i); | 966 Node* input = NodeProperties::GetEffectInput(node, i); | 
| 945 VirtualState* state = virtual_states_[input->id()]; | 967 VirtualState* state = virtual_states_[input->id()]; | 
| 946 if (state) { | 968 if (state) { | 
| 947 cache_.states().push_back(state); | 969 cache_->push_back(state); | 
| 948 } | 970 } | 
| 949 if (FLAG_trace_turbo_escape) { | 971 if (FLAG_trace_turbo_escape) { | 
| 950 PrintF(" %p (from %d %s)", static_cast<void*>(state), input->id(), | 972 PrintF(" %p (from %d %s)", static_cast<void*>(state), input->id(), | 
| 951 input->op()->mnemonic()); | 973 input->op()->mnemonic()); | 
| 952 } | 974 } | 
| 953 } | 975 } | 
| 954 if (FLAG_trace_turbo_escape) { | 976 if (FLAG_trace_turbo_escape) { | 
| 955 PrintF("\n"); | 977 PrintF("\n"); | 
| 956 } | 978 } | 
| 957 | 979 | 
| 958 if (cache_.states().size() == 0) { | 980 if (cache_->states().size() == 0) { | 
| 959 return changed; | 981 return changed; | 
| 960 } | 982 } | 
| 961 | 983 | 
| 962 changed = mergeState->MergeFrom(&cache_, zone(), graph(), common(), | 984 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(), | 
| 963 NodeProperties::GetControlInput(node)) || | 985 NodeProperties::GetControlInput(node)) || | 
| 964 changed; | 986 changed; | 
| 965 | 987 | 
| 966 if (FLAG_trace_turbo_escape) { | 988 if (FLAG_trace_turbo_escape) { | 
| 967 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); | 989 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); | 
| 968 } | 990 } | 
| 969 | 991 | 
| 970 if (changed) { | 992 if (changed) { | 
| 971 mergeState->LastChangedAt(node); | 993 mergeState->LastChangedAt(node); | 
| 972 escape_status_.Resize(); | 994 escape_status_.Resize(); | 
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 return OpParameter<FieldAccess>(node).offset / kPointerSize; | 1141 return OpParameter<FieldAccess>(node).offset / kPointerSize; | 
| 1120 } | 1142 } | 
| 1121 | 1143 | 
| 1122 | 1144 | 
| 1123 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, | 1145 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, | 
| 1124 VirtualState* state) { | 1146 VirtualState* state) { | 
| 1125 if (FLAG_trace_turbo_escape) { | 1147 if (FLAG_trace_turbo_escape) { | 
| 1126 PrintF("Load #%d from phi #%d", node->id(), from->id()); | 1148 PrintF("Load #%d from phi #%d", node->id(), from->id()); | 
| 1127 } | 1149 } | 
| 1128 | 1150 | 
| 1129 ZoneVector<Node*> inputs(zone()); | 1151 cache_->fields().clear(); | 
| 1130 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | 1152 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | 
| 1131 Node* input = NodeProperties::GetValueInput(node, i); | 1153 Node* input = NodeProperties::GetValueInput(node, i); | 
| 1132 inputs.push_back(input); | 1154 cache_->fields().push_back(input); | 
| 1133 } | 1155 } | 
| 1134 | 1156 | 
| 1135 GetVirtualObjects(state, inputs, cache_.objects()); | 1157 cache_->GetVirtualObjects(state); | 
| 1136 if (cache_.objects().size() == inputs.size()) { | 1158 if (cache_->objects().size() == cache_->fields().size()) { | 
| 1137 GetFields(cache_.objects(), cache_.fields(), offset); | 1159 cache_->GetFields(offset); | 
| 1138 if (cache_.fields().size() == cache_.objects().size()) { | 1160 if (cache_->fields().size() == cache_->objects().size()) { | 
| 1139 Node* rep = replacement(node); | 1161 Node* rep = replacement(node); | 
| 1140 if (!rep || !IsEquivalentPhi(rep, cache_.fields())) { | 1162 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { | 
| 1141 cache_.fields().push_back(NodeProperties::GetControlInput(from)); | 1163 int value_input_count = static_cast<int>(cache_->fields().size()); | 
| 1164 cache_->fields().push_back(NodeProperties::GetControlInput(from)); | |
| 1142 Node* phi = graph()->NewNode( | 1165 Node* phi = graph()->NewNode( | 
| 1143 common()->Phi(MachineRepresentation::kTagged, 2), | 1166 common()->Phi(MachineRepresentation::kTagged, value_input_count), | 
| 1144 static_cast<int>(cache_.fields().size()), &cache_.fields().front()); | 1167 value_input_count + 1, &cache_->fields().front()); | 
| 1145 escape_status_.Resize(); | 1168 escape_status_.Resize(); | 
| 1146 SetReplacement(node, phi); | 1169 SetReplacement(node, phi); | 
| 1147 state->LastChangedAt(node); | 1170 state->LastChangedAt(node); | 
| 1148 if (FLAG_trace_turbo_escape) { | 1171 if (FLAG_trace_turbo_escape) { | 
| 1149 PrintF(" got phi created.\n"); | 1172 PrintF(" got phi created.\n"); | 
| 1150 } | 1173 } | 
| 1151 } else if (FLAG_trace_turbo_escape) { | 1174 } else if (FLAG_trace_turbo_escape) { | 
| 1152 PrintF(" has already phi #%d.\n", rep->id()); | 1175 PrintF(" has already phi #%d.\n", rep->id()); | 
| 1153 } | 1176 } | 
| 1154 } else if (FLAG_trace_turbo_escape) { | 1177 } else if (FLAG_trace_turbo_escape) { | 
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1315 } | 1338 } | 
| 1316 } | 1339 } | 
| 1317 for (size_t n = 0; n < object_states.size(); n++) { | 1340 for (size_t n = 0; n < object_states.size(); n++) { | 
| 1318 DebugPrintState(object_states[n]); | 1341 DebugPrintState(object_states[n]); | 
| 1319 } | 1342 } | 
| 1320 } | 1343 } | 
| 1321 | 1344 | 
| 1322 } // namespace compiler | 1345 } // namespace compiler | 
| 1323 } // namespace internal | 1346 } // namespace internal | 
| 1324 } // namespace v8 | 1347 } // namespace v8 | 
| OLD | NEW |