| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   109   } |   109   } | 
|   110   bool AllFieldsClear() { |   110   bool AllFieldsClear() { | 
|   111     for (size_t i = 0; i < fields_.size(); ++i) { |   111     for (size_t i = 0; i < fields_.size(); ++i) { | 
|   112       if (fields_[i] != nullptr) { |   112       if (fields_[i] != nullptr) { | 
|   113         return false; |   113         return false; | 
|   114       } |   114       } | 
|   115     } |   115     } | 
|   116     return true; |   116     return true; | 
|   117   } |   117   } | 
|   118   bool UpdateFrom(const VirtualObject& other); |   118   bool UpdateFrom(const VirtualObject& other); | 
 |   119   bool MergeFrom(MergeCache* cache, Node* at, Graph* graph, | 
 |   120                  CommonOperatorBuilder* common); | 
|   119   void SetObjectState(Node* node) { object_state_ = node; } |   121   void SetObjectState(Node* node) { object_state_ = node; } | 
|   120   Node* GetObjectState() const { return object_state_; } |   122   Node* GetObjectState() const { return object_state_; } | 
|   121   bool IsCopyRequired() const { return status_ & kCopyRequired; } |   123   bool IsCopyRequired() const { return status_ & kCopyRequired; } | 
|   122   void SetCopyRequired() { status_ |= kCopyRequired; } |   124   void SetCopyRequired() { status_ |= kCopyRequired; } | 
|   123   bool NeedCopyForModification() { |   125   bool NeedCopyForModification() { | 
|   124     if (!IsCopyRequired() || !IsInitialized()) { |   126     if (!IsCopyRequired() || !IsInitialized()) { | 
|   125       return false; |   127       return false; | 
|   126     } |   128     } | 
|   127     return true; |   129     return true; | 
|   128   } |   130   } | 
|   129  |   131  | 
|   130   NodeId id() const { return id_; } |   132   NodeId id() const { return id_; } | 
|   131   void id(NodeId id) { id_ = id; } |   133   void id(NodeId id) { id_ = id; } | 
|   132  |   134  | 
|   133  private: |   135  private: | 
 |   136   bool MergeFields(size_t i, Node* at, MergeCache* cache, Graph* graph, | 
 |   137                    CommonOperatorBuilder* common); | 
 |   138  | 
|   134   NodeId id_; |   139   NodeId id_; | 
|   135   StatusFlags status_; |   140   StatusFlags status_; | 
|   136   ZoneVector<Node*> fields_; |   141   ZoneVector<Node*> fields_; | 
|   137   ZoneVector<bool> phi_; |   142   ZoneVector<bool> phi_; | 
|   138   Node* object_state_; |   143   Node* object_state_; | 
|   139   VirtualState* owner_; |   144   VirtualState* owner_; | 
|   140  |   145  | 
|   141   DISALLOW_COPY_AND_ASSIGN(VirtualObject); |   146   DISALLOW_COPY_AND_ASSIGN(VirtualObject); | 
|   142 }; |   147 }; | 
|   143  |   148  | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   169       : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()), |   174       : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()), | 
|   170         owner_(owner) { |   175         owner_(owner) { | 
|   171     for (size_t i = 0; i < info_.size(); ++i) { |   176     for (size_t i = 0; i < info_.size(); ++i) { | 
|   172       if (state.info_[i]) { |   177       if (state.info_[i]) { | 
|   173         info_[i] = state.info_[i]; |   178         info_[i] = state.info_[i]; | 
|   174       } |   179       } | 
|   175     } |   180     } | 
|   176   } |   181   } | 
|   177  |   182  | 
|   178   VirtualObject* VirtualObjectFromAlias(size_t alias); |   183   VirtualObject* VirtualObjectFromAlias(size_t alias); | 
|   179   VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id, |  | 
|   180                                                  size_t fields, |  | 
|   181                                                  bool initialized, Zone* zone, |  | 
|   182                                                  bool force_copy); |  | 
|   183   void SetVirtualObject(Alias alias, VirtualObject* state); |   184   void SetVirtualObject(Alias alias, VirtualObject* state); | 
|   184   bool UpdateFrom(VirtualState* state, Zone* zone); |   185   bool UpdateFrom(VirtualState* state, Zone* zone); | 
|   185   bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, |   186   bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 
|   186                  CommonOperatorBuilder* common, Node* control, int arity); |   187                  CommonOperatorBuilder* common, Node* at); | 
|   187   size_t size() const { return info_.size(); } |   188   size_t size() const { return info_.size(); } | 
|   188   Node* owner() const { return owner_; } |   189   Node* owner() const { return owner_; } | 
|   189   VirtualObject* Copy(VirtualObject* obj, Alias alias); |   190   VirtualObject* Copy(VirtualObject* obj, Alias alias); | 
|   190   void SetCopyRequired() { |   191   void SetCopyRequired() { | 
|   191     for (VirtualObject* obj : info_) { |   192     for (VirtualObject* obj : info_) { | 
|   192       if (obj) obj->SetCopyRequired(); |   193       if (obj) obj->SetCopyRequired(); | 
|   193     } |   194     } | 
|   194   } |   195   } | 
|   195  |   196  | 
|   196  private: |   197  private: | 
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   281         static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj), |   282         static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj), | 
|   282         static_cast<void*>(new_obj)); |   283         static_cast<void*>(new_obj)); | 
|   283   info_[alias] = new_obj; |   284   info_[alias] = new_obj; | 
|   284   return new_obj; |   285   return new_obj; | 
|   285 } |   286 } | 
|   286  |   287  | 
|   287 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { |   288 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { | 
|   288   return info_[alias]; |   289   return info_[alias]; | 
|   289 } |   290 } | 
|   290  |   291  | 
|   291 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject( |  | 
|   292     Alias alias, NodeId id, size_t field_number, bool initialized, Zone* zone, |  | 
|   293     bool force_copy) { |  | 
|   294   if (!force_copy) { |  | 
|   295     if (VirtualObject* obj = VirtualObjectFromAlias(alias)) { |  | 
|   296       return obj; |  | 
|   297     } |  | 
|   298   } |  | 
|   299   VirtualObject* obj = new (zone) VirtualObject(id, this, zone, 0, initialized); |  | 
|   300   SetVirtualObject(alias, obj); |  | 
|   301   return obj; |  | 
|   302 } |  | 
|   303  |  | 
|   304 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) { |   292 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) { | 
|   305   info_[alias] = obj; |   293   info_[alias] = obj; | 
|   306 } |   294 } | 
|   307  |   295  | 
|   308 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) { |   296 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) { | 
|   309   if (from == this) return false; |   297   if (from == this) return false; | 
|   310   bool changed = false; |   298   bool changed = false; | 
|   311   for (Alias alias = 0; alias < size(); ++alias) { |   299   for (Alias alias = 0; alias < size(); ++alias) { | 
|   312     VirtualObject* ls = VirtualObjectFromAlias(alias); |   300     VirtualObject* ls = VirtualObjectFromAlias(alias); | 
|   313     VirtualObject* rs = from->VirtualObjectFromAlias(alias); |   301     VirtualObject* rs = from->VirtualObjectFromAlias(alias); | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   355     Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); |   343     Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); | 
|   356     if (!IsEquivalentPhi(input, inputs[i])) { |   344     if (!IsEquivalentPhi(input, inputs[i])) { | 
|   357       return false; |   345       return false; | 
|   358     } |   346     } | 
|   359   } |   347   } | 
|   360   return true; |   348   return true; | 
|   361 } |   349 } | 
|   362  |   350  | 
|   363 }  // namespace |   351 }  // namespace | 
|   364  |   352  | 
|   365 Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) { |   353 bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache, | 
|   366   Node* rep = GetReplacement(objs.front()->id()); |   354                                 Graph* graph, CommonOperatorBuilder* common) { | 
|   367   for (VirtualObject* obj : objs) { |   355   bool changed = false; | 
|   368     if (GetReplacement(obj->id()) != rep) { |   356   int value_input_count = static_cast<int>(cache->fields().size()); | 
|   369       return nullptr; |   357   Node* rep = GetField(i); | 
 |   358   if (!rep || !IsCreatedPhi(i)) { | 
 |   359     Node* control = NodeProperties::GetControlInput(at); | 
 |   360     cache->fields().push_back(control); | 
 |   361     Node* phi = graph->NewNode( | 
 |   362         common->Phi(MachineRepresentation::kTagged, value_input_count), | 
 |   363         value_input_count + 1, &cache->fields().front()); | 
 |   364     SetField(i, phi, true); | 
 |   365 #ifdef DEBUG | 
 |   366     if (FLAG_trace_turbo_escape) { | 
 |   367       PrintF("    Creating Phi #%d as merge of", phi->id()); | 
 |   368       for (int i = 0; i < value_input_count; i++) { | 
 |   369         PrintF(" #%d (%s)", cache->fields()[i]->id(), | 
 |   370                cache->fields()[i]->op()->mnemonic()); | 
 |   371       } | 
 |   372       PrintF("\n"); | 
 |   373     } | 
 |   374 #endif | 
 |   375     changed = true; | 
 |   376   } else { | 
 |   377     DCHECK(rep->opcode() == IrOpcode::kPhi); | 
 |   378     for (int n = 0; n < value_input_count; ++n) { | 
 |   379       Node* old = NodeProperties::GetValueInput(rep, n); | 
 |   380       if (old != cache->fields()[n]) { | 
 |   381         changed = true; | 
 |   382         NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); | 
 |   383       } | 
|   370     } |   384     } | 
|   371   } |   385   } | 
|   372   return rep; |   386   return changed; | 
 |   387 } | 
 |   388  | 
 |   389 bool VirtualObject::MergeFrom(MergeCache* cache, Node* at, Graph* graph, | 
 |   390                               CommonOperatorBuilder* common) { | 
 |   391   DCHECK(at->opcode() == IrOpcode::kEffectPhi || | 
 |   392          at->opcode() == IrOpcode::kPhi); | 
 |   393   bool changed = false; | 
 |   394   for (size_t i = 0; i < field_count(); ++i) { | 
 |   395     if (Node* field = cache->GetFields(i)) { | 
 |   396       changed = changed || GetField(i) != field; | 
 |   397       SetField(i, field); | 
 |   398       TRACE("    Field %zu agree on rep #%d\n", i, field->id()); | 
 |   399     } else { | 
 |   400       int arity = at->opcode() == IrOpcode::kEffectPhi | 
 |   401                       ? at->op()->EffectInputCount() | 
 |   402                       : at->op()->ValueInputCount(); | 
 |   403       if (cache->fields().size() == arity) { | 
 |   404         changed = MergeFields(i, at, cache, graph, common) || changed; | 
 |   405       } else { | 
 |   406         if (GetField(i) != nullptr) { | 
 |   407           TRACE("    Field %zu cleared\n", i); | 
 |   408           changed = true; | 
 |   409         } | 
 |   410         SetField(i, nullptr); | 
 |   411       } | 
 |   412     } | 
 |   413   } | 
 |   414   return changed; | 
|   373 } |   415 } | 
|   374  |   416  | 
|   375 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, |   417 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 
|   376                              CommonOperatorBuilder* common, Node* control, |   418                              CommonOperatorBuilder* common, Node* at) { | 
|   377                              int arity) { |  | 
|   378   DCHECK_GT(cache->states().size(), 0u); |   419   DCHECK_GT(cache->states().size(), 0u); | 
|   379   bool changed = false; |   420   bool changed = false; | 
|   380   for (Alias alias = 0; alias < size(); ++alias) { |   421   for (Alias alias = 0; alias < size(); ++alias) { | 
|   381     cache->objects().clear(); |   422     cache->objects().clear(); | 
|   382     VirtualObject* mergeObject = VirtualObjectFromAlias(alias); |   423     VirtualObject* mergeObject = VirtualObjectFromAlias(alias); | 
|   383     bool copy_merge_object = false; |   424     bool copy_merge_object = false; | 
|   384     size_t fields = std::numeric_limits<size_t>::max(); |   425     size_t fields = std::numeric_limits<size_t>::max(); | 
|   385     for (VirtualState* state : cache->states()) { |   426     for (VirtualState* state : cache->states()) { | 
|   386       if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { |   427       if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { | 
|   387         cache->objects().push_back(obj); |   428         cache->objects().push_back(obj); | 
|   388         if (mergeObject == obj) { |   429         if (mergeObject == obj) { | 
|   389           copy_merge_object = true; |   430           copy_merge_object = true; | 
|   390           changed = true; |  | 
|   391         } |   431         } | 
|   392         fields = std::min(obj->field_count(), fields); |   432         fields = std::min(obj->field_count(), fields); | 
|   393       } |   433       } | 
|   394     } |   434     } | 
|   395     if (cache->objects().size() == cache->states().size()) { |   435     if (cache->objects().size() == cache->states().size()) { | 
|   396       mergeObject = GetOrCreateTrackedVirtualObject( |   436       if (!mergeObject) { | 
|   397           alias, cache->objects().front()->id(), |   437         VirtualObject* obj = new (zone) | 
|   398           cache->objects().front()->IsInitialized(), fields, zone, |   438             VirtualObject(cache->objects().front()->id(), this, zone, fields, | 
|   399           copy_merge_object); |   439                           cache->objects().front()->IsInitialized()); | 
 |   440         SetVirtualObject(alias, obj); | 
 |   441         mergeObject = obj; | 
 |   442         changed = true; | 
 |   443       } else if (copy_merge_object) { | 
 |   444         VirtualObject* obj = new (zone) VirtualObject(this, *mergeObject); | 
 |   445         SetVirtualObject(alias, obj); | 
 |   446         mergeObject = obj; | 
 |   447         changed = true; | 
 |   448       } else { | 
 |   449         changed = mergeObject->ResizeFields(fields) || changed; | 
 |   450       } | 
|   400 #ifdef DEBUG |   451 #ifdef DEBUG | 
|   401       if (FLAG_trace_turbo_escape) { |   452       if (FLAG_trace_turbo_escape) { | 
|   402         PrintF("  Alias @%d, merging into %p virtual objects", alias, |   453         PrintF("  Alias @%d, merging into %p virtual objects", alias, | 
|   403                static_cast<void*>(mergeObject)); |   454                static_cast<void*>(mergeObject)); | 
|   404         for (size_t i = 0; i < cache->objects().size(); i++) { |   455         for (size_t i = 0; i < cache->objects().size(); i++) { | 
|   405           PrintF(" %p", static_cast<void*>(cache->objects()[i])); |   456           PrintF(" %p", static_cast<void*>(cache->objects()[i])); | 
|   406         } |   457         } | 
|   407         PrintF("\n"); |   458         PrintF("\n"); | 
|   408       } |   459       } | 
|   409 #endif  // DEBUG |   460 #endif  // DEBUG | 
|   410       changed = mergeObject->ResizeFields(fields) || changed; |   461       changed = mergeObject->MergeFrom(cache, at, graph, common) || changed; | 
|   411       for (size_t i = 0; i < fields; ++i) { |  | 
|   412         if (Node* field = cache->GetFields(i)) { |  | 
|   413           changed = changed || mergeObject->GetField(i) != field; |  | 
|   414           mergeObject->SetField(i, field); |  | 
|   415           TRACE("    Field %zu agree on rep #%d\n", i, field->id()); |  | 
|   416         } else { |  | 
|   417           int value_input_count = static_cast<int>(cache->fields().size()); |  | 
|   418           if (cache->fields().size() == arity) { |  | 
|   419             Node* rep = mergeObject->GetField(i); |  | 
|   420             if (!rep || !mergeObject->IsCreatedPhi(i)) { |  | 
|   421               cache->fields().push_back(control); |  | 
|   422               Node* phi = graph->NewNode( |  | 
|   423                   common->Phi(MachineRepresentation::kTagged, |  | 
|   424                               value_input_count), |  | 
|   425                   value_input_count + 1, &cache->fields().front()); |  | 
|   426               mergeObject->SetField(i, phi, true); |  | 
|   427 #ifdef DEBUG |  | 
|   428               if (FLAG_trace_turbo_escape) { |  | 
|   429                 PrintF("    Creating Phi #%d as merge of", phi->id()); |  | 
|   430                 for (int i = 0; i < value_input_count; i++) { |  | 
|   431                   PrintF(" #%d (%s)", cache->fields()[i]->id(), |  | 
|   432                          cache->fields()[i]->op()->mnemonic()); |  | 
|   433                 } |  | 
|   434                 PrintF("\n"); |  | 
|   435               } |  | 
|   436 #endif  // DEBUG |  | 
|   437               changed = true; |  | 
|   438             } else { |  | 
|   439               DCHECK(rep->opcode() == IrOpcode::kPhi); |  | 
|   440               for (int n = 0; n < value_input_count; ++n) { |  | 
|   441                 Node* old = NodeProperties::GetValueInput(rep, n); |  | 
|   442                 if (old != cache->fields()[n]) { |  | 
|   443                   changed = true; |  | 
|   444                   NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); |  | 
|   445                 } |  | 
|   446               } |  | 
|   447             } |  | 
|   448           } else { |  | 
|   449             if (mergeObject->GetField(i) != nullptr) { |  | 
|   450               TRACE("    Field %zu cleared\n", i); |  | 
|   451               changed = true; |  | 
|   452             } |  | 
|   453             mergeObject->SetField(i, nullptr); |  | 
|   454           } |  | 
|   455         } |  | 
|   456       } |  | 
|   457     } else { |   462     } else { | 
|   458       if (mergeObject) { |   463       if (mergeObject) { | 
|   459         TRACE("  Alias %d, virtual object removed\n", alias); |   464         TRACE("  Alias %d, virtual object removed\n", alias); | 
|   460         changed = true; |   465         changed = true; | 
|   461       } |   466       } | 
|   462       SetVirtualObject(alias, nullptr); |   467       SetVirtualObject(alias, nullptr); | 
|   463     } |   468     } | 
|   464   } |   469   } | 
|   465   return changed; |   470   return changed; | 
|   466 } |   471 } | 
|   467  |   472  | 
|   468 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, |   473 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, | 
|   469                                            Graph* graph, Zone* zone) |   474                                            Graph* graph, Zone* zone) | 
|   470     : stack_(zone), |   475     : stack_(zone), | 
|   471       object_analysis_(object_analysis), |   476       object_analysis_(object_analysis), | 
|   472       graph_(graph), |   477       graph_(graph), | 
|   473       zone_(zone), |   478       zone_(zone), | 
|   474       status_(graph->NodeCount(), kUnknown, zone), |   479       status_(zone), | 
|   475       next_free_alias_(0), |   480       next_free_alias_(0), | 
|   476       status_stack_(zone), |   481       status_stack_(zone), | 
|   477       aliases_(zone) {} |   482       aliases_(zone) {} | 
|   478  |   483  | 
|   479 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} |   484 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} | 
|   480  |   485  | 
|   481 bool EscapeStatusAnalysis::HasEntry(Node* node) { |   486 bool EscapeStatusAnalysis::HasEntry(Node* node) { | 
|   482   return status_[node->id()] & (kTracked | kEscaped); |   487   return status_[node->id()] & (kTracked | kEscaped); | 
|   483 } |   488 } | 
|   484  |   489  | 
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   770     replacements_.resize(graph()->NodeCount()); |   775     replacements_.resize(graph()->NodeCount()); | 
|   771     status_analysis_.ResizeStatusVector(); |   776     status_analysis_.ResizeStatusVector(); | 
|   772     RunObjectAnalysis(); |   777     RunObjectAnalysis(); | 
|   773     status_analysis_.RunStatusAnalysis(); |   778     status_analysis_.RunStatusAnalysis(); | 
|   774   } |   779   } | 
|   775 } |   780 } | 
|   776  |   781  | 
|   777 void EscapeStatusAnalysis::AssignAliases() { |   782 void EscapeStatusAnalysis::AssignAliases() { | 
|   778   size_t max_size = 1024; |   783   size_t max_size = 1024; | 
|   779   size_t min_size = 32; |   784   size_t min_size = 32; | 
|   780   size_t stack_size = std::min( |   785   size_t stack_size = | 
|   781       std::max( |   786       std::min(std::max(graph()->NodeCount() / 5, min_size), max_size); | 
|   782           std::min(graph()->NodeCount() / 5, graph()->NodeCount() / 20 + 128), |  | 
|   783           min_size), |  | 
|   784       max_size); |  | 
|   785   stack_.reserve(stack_size); |   787   stack_.reserve(stack_size); | 
|   786   ResizeStatusVector(); |   788   ResizeStatusVector(); | 
|   787   stack_.push_back(graph()->end()); |   789   stack_.push_back(graph()->end()); | 
|   788   CHECK_LT(graph()->NodeCount(), kUntrackable); |   790   CHECK_LT(graph()->NodeCount(), kUntrackable); | 
|   789   aliases_.resize(graph()->NodeCount(), kNotReachable); |   791   aliases_.resize(graph()->NodeCount(), kNotReachable); | 
|   790   aliases_[graph()->end()->id()] = kUntrackable; |   792   aliases_[graph()->end()->id()] = kUntrackable; | 
|   791   status_stack_.reserve(8); |   793   status_stack_.reserve(8); | 
|   792   TRACE("Discovering trackable nodes"); |   794   TRACE("Discovering trackable nodes"); | 
|   793   while (!stack_.empty()) { |   795   while (!stack_.empty()) { | 
|   794     Node* node = stack_.back(); |   796     Node* node = stack_.back(); | 
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   994       case IrOpcode::kStoreElement: |   996       case IrOpcode::kStoreElement: | 
|   995       case IrOpcode::kLoadElement: |   997       case IrOpcode::kLoadElement: | 
|   996       case IrOpcode::kFrameState: |   998       case IrOpcode::kFrameState: | 
|   997       case IrOpcode::kStateValues: |   999       case IrOpcode::kStateValues: | 
|   998       case IrOpcode::kReferenceEqual: |  1000       case IrOpcode::kReferenceEqual: | 
|   999       case IrOpcode::kFinishRegion: |  1001       case IrOpcode::kFinishRegion: | 
|  1000       case IrOpcode::kObjectIsSmi: |  1002       case IrOpcode::kObjectIsSmi: | 
|  1001         break; |  1003         break; | 
|  1002       default: |  1004       default: | 
|  1003         VirtualState* state = virtual_states_[node->id()]; |  1005         VirtualState* state = virtual_states_[node->id()]; | 
|  1004         if (VirtualObject* obj = ResolveVirtualObject(state, input)) { |  1006         if (VirtualObject* obj = | 
 |  1007                 GetVirtualObject(state, ResolveReplacement(input))) { | 
|  1005           if (!obj->AllFieldsClear()) { |  1008           if (!obj->AllFieldsClear()) { | 
|  1006             obj = CopyForModificationAt(obj, state, node); |  1009             obj = CopyForModificationAt(obj, state, node); | 
|  1007             obj->ClearAllFields(); |  1010             obj->ClearAllFields(); | 
|  1008             TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), |  1011             TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), | 
|  1009                   obj->id()); |  1012                   obj->id()); | 
|  1010           } |  1013           } | 
|  1011         } |  1014         } | 
|  1012         break; |  1015         break; | 
|  1013     } |  1016     } | 
|  1014   } |  1017   } | 
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1106     } |  1109     } | 
|  1107     TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), |  1110     TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), | 
|  1108           input->op()->mnemonic()); |  1111           input->op()->mnemonic()); | 
|  1109   } |  1112   } | 
|  1110   TRACE("\n"); |  1113   TRACE("\n"); | 
|  1111  |  1114  | 
|  1112   if (cache_->states().size() == 0) { |  1115   if (cache_->states().size() == 0) { | 
|  1113     return changed; |  1116     return changed; | 
|  1114   } |  1117   } | 
|  1115  |  1118  | 
|  1116   changed = mergeState->MergeFrom(cache_, zone(), graph(), common(), |  1119   changed = | 
|  1117                                   NodeProperties::GetControlInput(node), |  1120       mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; | 
|  1118                                   node->op()->EffectInputCount()) || |  | 
|  1119             changed; |  | 
|  1120  |  1121  | 
|  1121   TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); |  1122   TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); | 
|  1122  |  1123  | 
|  1123   if (changed) { |  1124   if (changed) { | 
|  1124     status_analysis_.ResizeStatusVector(); |  1125     status_analysis_.ResizeStatusVector(); | 
|  1125   } |  1126   } | 
|  1126   return changed; |  1127   return changed; | 
|  1127 } |  1128 } | 
|  1128  |  1129  | 
|  1129 void EscapeAnalysis::ProcessAllocation(Node* node) { |  1130 void EscapeAnalysis::ProcessAllocation(Node* node) { | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1235   return status_analysis_.SetEscaped(node); |  1236   return status_analysis_.SetEscaped(node); | 
|  1236 } |  1237 } | 
|  1237  |  1238  | 
|  1238 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { |  1239 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | 
|  1239   if (VirtualState* states = virtual_states_[at->id()]) { |  1240   if (VirtualState* states = virtual_states_[at->id()]) { | 
|  1240     return states->VirtualObjectFromAlias(GetAlias(id)); |  1241     return states->VirtualObjectFromAlias(GetAlias(id)); | 
|  1241   } |  1242   } | 
|  1242   return nullptr; |  1243   return nullptr; | 
|  1243 } |  1244 } | 
|  1244  |  1245  | 
|  1245 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state, |  | 
|  1246                                                     Node* node) { |  | 
|  1247   return GetVirtualObject(state, ResolveReplacement(node)); |  | 
|  1248 } |  | 
|  1249  |  | 
|  1250 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { |  1246 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { | 
|  1251   DCHECK(IsVirtual(left) && IsVirtual(right)); |  1247   DCHECK(IsVirtual(left) && IsVirtual(right)); | 
|  1252   left = ResolveReplacement(left); |  1248   left = ResolveReplacement(left); | 
|  1253   right = ResolveReplacement(right); |  1249   right = ResolveReplacement(right); | 
|  1254   if (IsEquivalentPhi(left, right)) { |  1250   if (IsEquivalentPhi(left, right)) { | 
|  1255     return true; |  1251     return true; | 
|  1256   } |  1252   } | 
|  1257   return false; |  1253   return false; | 
|  1258 } |  1254 } | 
|  1259  |  1255  | 
|  1260 int EscapeAnalysis::OffsetFromAccess(Node* node) { |  1256 int EscapeAnalysis::OffsetFromAccess(Node* node) { | 
|  1261   DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); |  1257   DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); | 
|  1262   return OpParameter<FieldAccess>(node).offset / kPointerSize; |  1258   return OpParameter<FieldAccess>(node).offset / kPointerSize; | 
|  1263 } |  1259 } | 
|  1264  |  1260  | 
|  1265 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, |  1261 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load, | 
|  1266                                         VirtualState* state) { |  1262                                         VirtualState* state) { | 
|  1267   TRACE("Load #%d from phi #%d", node->id(), from->id()); |  1263   TRACE("Load #%d from phi #%d", load->id(), from->id()); | 
|  1268  |  1264  | 
|  1269   cache_->fields().clear(); |  1265   cache_->fields().clear(); | 
|  1270   for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |  1266   for (int i = 0; i < load->op()->ValueInputCount(); ++i) { | 
|  1271     Node* input = NodeProperties::GetValueInput(node, i); |  1267     Node* input = NodeProperties::GetValueInput(load, i); | 
|  1272     cache_->fields().push_back(input); |  1268     cache_->fields().push_back(input); | 
|  1273   } |  1269   } | 
|  1274  |  1270  | 
|  1275   cache_->LoadVirtualObjectsForFieldsFrom(state, |  1271   cache_->LoadVirtualObjectsForFieldsFrom(state, | 
|  1276                                           status_analysis_.GetAliasMap()); |  1272                                           status_analysis_.GetAliasMap()); | 
|  1277   if (cache_->objects().size() == cache_->fields().size()) { |  1273   if (cache_->objects().size() == cache_->fields().size()) { | 
|  1278     cache_->GetFields(offset); |  1274     cache_->GetFields(offset); | 
|  1279     if (cache_->fields().size() == cache_->objects().size()) { |  1275     if (cache_->fields().size() == cache_->objects().size()) { | 
|  1280       Node* rep = replacement(node); |  1276       Node* rep = replacement(load); | 
|  1281       if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { |  1277       if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { | 
|  1282         int value_input_count = static_cast<int>(cache_->fields().size()); |  1278         int value_input_count = static_cast<int>(cache_->fields().size()); | 
|  1283         cache_->fields().push_back(NodeProperties::GetControlInput(from)); |  1279         cache_->fields().push_back(NodeProperties::GetControlInput(from)); | 
|  1284         Node* phi = graph()->NewNode( |  1280         Node* phi = graph()->NewNode( | 
|  1285             common()->Phi(MachineRepresentation::kTagged, value_input_count), |  1281             common()->Phi(MachineRepresentation::kTagged, value_input_count), | 
|  1286             value_input_count + 1, &cache_->fields().front()); |  1282             value_input_count + 1, &cache_->fields().front()); | 
|  1287         status_analysis_.ResizeStatusVector(); |  1283         status_analysis_.ResizeStatusVector(); | 
|  1288         SetReplacement(node, phi); |  1284         SetReplacement(load, phi); | 
|  1289         TRACE(" got phi created.\n"); |  1285         TRACE(" got phi created.\n"); | 
|  1290       } else { |  1286       } else { | 
|  1291         TRACE(" has already phi #%d.\n", rep->id()); |  1287         TRACE(" has already phi #%d.\n", rep->id()); | 
|  1292       } |  1288       } | 
|  1293     } else { |  1289     } else { | 
|  1294       TRACE(" has incomplete field info.\n"); |  1290       TRACE(" has incomplete field info.\n"); | 
|  1295     } |  1291     } | 
|  1296   } else { |  1292   } else { | 
|  1297     TRACE(" has incomplete virtual object info.\n"); |  1293     TRACE(" has incomplete virtual object info.\n"); | 
|  1298   } |  1294   } | 
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1434               obj->id()); |  1430               obj->id()); | 
|  1435       } |  1431       } | 
|  1436     } |  1432     } | 
|  1437   } |  1433   } | 
|  1438 } |  1434 } | 
|  1439  |  1435  | 
|  1440 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { |  1436 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { | 
|  1441   if ((node->opcode() == IrOpcode::kFinishRegion || |  1437   if ((node->opcode() == IrOpcode::kFinishRegion || | 
|  1442        node->opcode() == IrOpcode::kAllocate) && |  1438        node->opcode() == IrOpcode::kAllocate) && | 
|  1443       IsVirtual(node)) { |  1439       IsVirtual(node)) { | 
|  1444     if (VirtualObject* vobj = |  1440     if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()], | 
|  1445             ResolveVirtualObject(virtual_states_[effect->id()], node)) { |  1441                                                ResolveReplacement(node))) { | 
|  1446       if (Node* object_state = vobj->GetObjectState()) { |  1442       if (Node* object_state = vobj->GetObjectState()) { | 
|  1447         return object_state; |  1443         return object_state; | 
|  1448       } else { |  1444       } else { | 
|  1449         cache_->fields().clear(); |  1445         cache_->fields().clear(); | 
|  1450         for (size_t i = 0; i < vobj->field_count(); ++i) { |  1446         for (size_t i = 0; i < vobj->field_count(); ++i) { | 
|  1451           if (Node* field = vobj->GetField(i)) { |  1447           if (Node* field = vobj->GetField(i)) { | 
|  1452             cache_->fields().push_back(field); |  1448             cache_->fields().push_back(field); | 
|  1453           } |  1449           } | 
|  1454         } |  1450         } | 
|  1455         int input_count = static_cast<int>(cache_->fields().size()); |  1451         int input_count = static_cast<int>(cache_->fields().size()); | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1529         return true; |  1525         return true; | 
|  1530       } |  1526       } | 
|  1531     } |  1527     } | 
|  1532   } |  1528   } | 
|  1533   return false; |  1529   return false; | 
|  1534 } |  1530 } | 
|  1535  |  1531  | 
|  1536 }  // namespace compiler |  1532 }  // namespace compiler | 
|  1537 }  // namespace internal |  1533 }  // namespace internal | 
|  1538 }  // namespace v8 |  1534 }  // namespace v8 | 
| OLD | NEW |