• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ea_connection_graph.h"
17 
18 namespace maple {
19 constexpr maple::uint32 kInvalid = 0xffffffff;
CheckAllConnectionInNodes()20 void EACGBaseNode::CheckAllConnectionInNodes()
21 {
22 #ifdef DEBUG
23     for (EACGBaseNode *inNode : in) {
24         ASSERT_NOT_NULL(eaCG->nodes[inNode->id - 1]);
25         DEBUG_ASSERT(eaCG->nodes[inNode->id - 1] == inNode, "must be inNode");
26     }
27     for (EACGBaseNode *outNode : out) {
28         ASSERT_NOT_NULL(eaCG->nodes[outNode->id - 1]);
29         DEBUG_ASSERT(eaCG->nodes[outNode->id - 1] == outNode, "must be outNode");
30     }
31     for (EACGObjectNode *obj : pointsTo) {
32         ASSERT_NOT_NULL(eaCG->nodes[obj->id - 1]);
33         DEBUG_ASSERT(eaCG->nodes[obj->id - 1] == obj, "must be obj");
34     }
35     if (IsFieldNode()) {
36         for (EACGObjectNode *obj : static_cast<EACGFieldNode *>(this)->GetBelongsToObj()) {
37             ASSERT_NOT_NULL(eaCG->nodes[obj->id - 1]);
38             DEBUG_ASSERT(eaCG->nodes[obj->id - 1] == obj, "must be obj");
39         }
40     }
41 #endif
42 }
43 
AddOutNode(EACGBaseNode & newOut)44 bool EACGBaseNode::AddOutNode(EACGBaseNode &newOut)
45 {
46     if (out.find(&newOut) != out.end()) {
47         return false;
48     }
49     bool newIsLocal = newOut.UpdateEAStatus(eaStatus);
50     if (eaStatus == kGlobalEscape && pointsTo.size() > 0) {
51         if (newIsLocal) {
52             eaCG->SetCGUpdateFlag();
53         }
54         return newIsLocal;
55     }
56     (void)out.insert(&newOut);
57     (void)newOut.in.insert(this);
58     DEBUG_ASSERT(newOut.pointsTo.size() != 0, "must be greater than zero");
59     bool hasChanged = UpdatePointsTo(newOut.pointsTo);
60     eaCG->SetCGUpdateFlag();
61     return hasChanged;
62 }
63 
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const64 void EACGBaseNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
65 {
66     for (EACGBaseNode *outNode : out) {
67         (void)outNode->UpdateEAStatus(eaStatus);
68     }
69 }
70 
GetName(const IRMap * irMap) const71 std::string EACGBaseNode::GetName(const IRMap *irMap) const
72 {
73     std::string name;
74     if (irMap == nullptr || meExpr == nullptr) {
75         name += std::to_string(id);
76     } else {
77         name += std::to_string(id);
78         name += "\\n";
79         if (meExpr->GetMeOp() == kMeOpVar) {
80             VarMeExpr *varMeExpr = static_cast<VarMeExpr *>(meExpr);
81             const MIRSymbol *sym = varMeExpr->GetOst()->GetMIRSymbol();
82             name += ((sym->GetStIdx().IsGlobal() ? "$" : "%") + sym->GetName() + "\\nmx" +
83                      std::to_string(meExpr->GetExprID()) + " (field)" + std::to_string(varMeExpr->GetFieldID()));
84         } else if (meExpr->GetMeOp() == kMeOpIvar) {
85             IvarMeExpr *ivarMeExpr = static_cast<IvarMeExpr *>(meExpr);
86             MeExpr *base = ivarMeExpr->GetBase();
87             VarMeExpr *varMeExpr = nullptr;
88             if (base->GetMeOp() == kMeOpVar) {
89                 varMeExpr = static_cast<VarMeExpr *>(base);
90             } else {
91                 name += std::to_string(id);
92                 return name;
93             }
94             const MIRSymbol *sym = varMeExpr->GetOst()->GetMIRSymbol();
95             name += (std::string("base :") + (sym->GetStIdx().IsGlobal() ? "$" : "%") + sym->GetName() + "\\nmx" +
96                      std::to_string(meExpr->GetExprID()) + " (field)" + std::to_string(ivarMeExpr->GetFieldID()));
97         } else if (meExpr->GetOp() == OP_gcmalloc || meExpr->GetOp() == OP_gcmallocjarray) {
98             name += "mx" + std::to_string(meExpr->GetExprID());
99         }
100     }
101     return name;
102 }
103 
UpdatePointsTo(const std::set<EACGObjectNode * > & cPointsTo)104 bool EACGBaseNode::UpdatePointsTo(const std::set<EACGObjectNode *> &cPointsTo)
105 {
106     size_t oldPtSize = pointsTo.size();
107     pointsTo.insert(cPointsTo.begin(), cPointsTo.end());
108     if (oldPtSize == pointsTo.size()) {
109         return false;
110     }
111     for (EACGObjectNode *pt : pointsTo) {
112         pt->Insert2PointsBy(this);
113     }
114     for (EACGBaseNode *pred : in) {
115         (void)pred->UpdatePointsTo(pointsTo);
116     }
117     return true;
118 }
119 
GetNodeFormatInDot(std::string & label,std::string & color) const120 void EACGBaseNode::GetNodeFormatInDot(std::string &label, std::string &color) const
121 {
122     switch (GetEAStatus()) {
123         case kNoEscape:
124             label += "NoEscape";
125             color = "darkgreen";
126             break;
127         case kArgumentEscape:
128             label += "ArgEscape";
129             color = "brown";
130             break;
131         case kReturnEscape:
132             label += "RetEscape";
133             color = "orange";
134             break;
135         case kGlobalEscape:
136             label += "GlobalEscape";
137             color = "red";
138             break;
139     }
140 }
141 
CanIgnoreRC() const142 bool EACGBaseNode::CanIgnoreRC() const
143 {
144     for (auto obj : pointsTo) {
145         if (!obj->GetIgnorRC()) {
146             return false;
147         }
148     }
149     return true;
150 }
151 
CheckAllConnectionInNodes()152 void EACGObjectNode::CheckAllConnectionInNodes()
153 {
154 #ifdef DEBUG
155     for (EACGBaseNode *inNode : in) {
156         ASSERT_NOT_NULL(eaCG->nodes[inNode->id - 1]);
157         DEBUG_ASSERT(eaCG->nodes[inNode->id - 1] == inNode, "must be inNode");
158     }
159     for (EACGBaseNode *outNode : out) {
160         ASSERT_NOT_NULL(eaCG->nodes[outNode->id - 1]);
161         DEBUG_ASSERT(eaCG->nodes[outNode->id - 1] == outNode, "must be outNode");
162     }
163     for (EACGBaseNode *pBy : pointsBy) {
164         ASSERT_NOT_NULL(eaCG->nodes[pBy->id - 1]);
165         DEBUG_ASSERT(eaCG->nodes[pBy->id - 1] == pBy, "must be pBy");
166     }
167     for (auto fieldPair : fieldNodes) {
168         EACGFieldNode *field = fieldPair.second;
169         DEBUG_ASSERT(field->fieldID == fieldPair.first, "must be fieldPair.first");
170         ASSERT_NOT_NULL(eaCG->nodes[field->id - 1]);
171         DEBUG_ASSERT(eaCG->nodes[field->id - 1] == field, "must be filed");
172     }
173 #endif
174 }
175 
IsPointedByFieldNode() const176 bool EACGObjectNode::IsPointedByFieldNode() const
177 {
178     for (EACGBaseNode *pBy : pointsBy) {
179         if (pBy->IsFieldNode()) {
180             return true;
181         }
182     }
183     return false;
184 }
185 
AddOutNode(EACGBaseNode & newOut)186 bool EACGObjectNode::AddOutNode(EACGBaseNode &newOut)
187 {
188     DEBUG_ASSERT(newOut.IsFieldNode(), "must be fieldNode");
189     EACGFieldNode *field = static_cast<EACGFieldNode *>(&newOut);
190     fieldNodes[field->GetFieldID()] = field;
191     (void)newOut.UpdateEAStatus(eaStatus);
192     field->AddBelongTo(this);
193     return true;
194 }
195 
ReplaceByGlobalNode()196 bool EACGObjectNode::ReplaceByGlobalNode()
197 {
198     DEBUG_ASSERT(out.size() == 0, "must be zero");
199     for (EACGBaseNode *node : pointsBy) {
200         node->pointsTo.erase(this);
201         (void)node->pointsTo.insert(eaCG->GetGlobalObject());
202     }
203     pointsBy.clear();
204     for (EACGBaseNode *inNode : in) {
205         (void)inNode->out.erase(this);
206         (void)inNode->out.insert(eaCG->GetGlobalObject());
207     }
208     in.clear();
209     for (auto fieldPair : fieldNodes) {
210         EACGFieldNode *field = fieldPair.second;
211         field->belongsTo.erase(this);
212     }
213     fieldNodes.clear();
214     if (meExpr != nullptr) {
215         eaCG->expr2Nodes[meExpr]->clear();
216         eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalObject());
217     }
218     DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be");
219     CHECK_FATAL(id > 0, "must not be zero");
220     eaCG->nodes[id - 1] = nullptr;
221     return true;
222 }
223 
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const224 void EACGObjectNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
225 {
226     for (auto fieldNodePair : fieldNodes) {
227         EACGFieldNode *field = fieldNodePair.second;
228         (void)field->UpdateEAStatus(eaStatus);
229     }
230 }
231 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)232 void EACGObjectNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
233                                  const IRMap *irMap)
234 {
235     if (dumped[this]) {
236         return;
237     }
238     dumped[this] = true;
239 
240     std::string name = GetName(nullptr);
241     std::string label = GetName(irMap) + " Object\\n";
242     std::string color;
243     GetNodeFormatInDot(label, color);
244     std::string style;
245     if (IsPhantom()) {
246         style = "dotted";
247     } else {
248         style = "bold";
249     }
250     fout << name << " [shape=box, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
251     for (auto fieldPair : fieldNodes) {
252         EACGBaseNode *field = fieldPair.second;
253         fout << name << "->" << field->GetName(nullptr) << ";"
254              << "\n";
255     }
256     for (auto fieldPair : fieldNodes) {
257         EACGBaseNode *field = fieldPair.second;
258         field->DumpDotFile(fout, dumped, dumpPt, irMap);
259     }
260 }
261 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)262 void EACGRefNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
263                               const IRMap *irMap)
264 {
265     if (dumped[this]) {
266         return;
267     }
268     dumped[this] = true;
269 
270     std::string name = GetName(nullptr);
271     std::string label = GetName(irMap) + " Reference\\n";
272     if (IsStaticRef()) {
273         label += "Static\\n";
274     }
275     std::string color;
276     GetNodeFormatInDot(label, color);
277     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
278          << "\n";
279     if (dumpPt) {
280         for (auto obj : pointsTo) {
281             fout << name << "->" << obj->GetName(nullptr) << ";"
282                  << "\n";
283         }
284         for (auto obj : pointsTo) {
285             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
286         }
287     } else {
288         for (auto outNode : out) {
289             std::string edgeStyle;
290             if (!outNode->IsObjectNode()) {
291                 edgeStyle = " [style =\"dotted\"]";
292             }
293             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";"
294                  << "\n";
295         }
296         for (auto outNode : out) {
297             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
298         }
299     }
300 }
301 
ReplaceByGlobalNode()302 bool EACGRefNode::ReplaceByGlobalNode()
303 {
304     for (EACGBaseNode *inNode : in) {
305         DEBUG_ASSERT(inNode->id > 3, "must be greater than three");  // the least valid idx is 3
306         (void)inNode->out.erase(this);
307         (void)inNode->out.insert(eaCG->GetGlobalReference());
308     }
309     in.clear();
310     for (EACGBaseNode *outNode : out) {
311         (void)outNode->in.erase(this);
312     }
313     out.clear();
314     for (EACGObjectNode *base : pointsTo) {
315         base->EraseNodeFromPointsBy(this);
316     }
317     pointsTo.clear();
318     if (meExpr != nullptr) {
319         eaCG->expr2Nodes[meExpr]->clear();
320         eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalReference());
321     }
322     DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
323     CHECK_FATAL(id > 0, "must not be zero");
324     eaCG->nodes[id - 1] = nullptr;
325     return true;
326 }
327 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)328 void EACGPointerNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
329                                   const IRMap *irMap)
330 {
331     if (dumped[this]) {
332         return;
333     }
334     dumped[this] = true;
335     std::string name = GetName(nullptr);
336     std::string label = GetName(irMap) + "\\nPointer Indirect Level : " + std::to_string(indirectLevel) + "\\n";
337     std::string color;
338     GetNodeFormatInDot(label, color);
339     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
340          << "\n";
341     for (EACGBaseNode *outNode : out) {
342         fout << name << "->" << outNode->GetName(nullptr) << " [style =\"dotted\", color = \"blue\"];"
343              << "\n";
344     }
345     for (auto outNode : out) {
346         outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
347     }
348 }
349 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)350 void EACGActualNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
351                                  const IRMap *irMap)
352 {
353     if (dumped[this]) {
354         return;
355     }
356     dumped[this] = true;
357 
358     std::string name = GetName(nullptr);
359     std::string label;
360     if (IsReturn()) {
361         label = GetName(irMap) + "\\nRet Idx : " + std::to_string(GetArgIndex()) + "\\n";
362     } else {
363         label = GetName(irMap) + "\\nArg Idx : " + std::to_string(GetArgIndex()) +
364                 " Call Site : " + std::to_string(GetCallSite()) + "\\n";
365     }
366     std::string style;
367     if (IsPhantom()) {
368         style = "dotted";
369     } else {
370         style = "bold";
371     }
372     std::string color;
373     GetNodeFormatInDot(label, color);
374     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
375     if (dumpPt) {
376         for (auto obj : pointsTo) {
377             fout << name << "->" << obj->GetName(nullptr) << ";\n";
378         }
379         for (auto obj : pointsTo) {
380             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
381         }
382     } else {
383         for (auto outNode : out) {
384             std::string edgeStyle;
385             if (!outNode->IsObjectNode()) {
386                 edgeStyle = " [style =\"dotted\"]";
387             }
388             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
389         }
390         for (auto outNode : out) {
391             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
392         }
393     }
394 }
395 
ReplaceByGlobalNode()396 bool EACGActualNode::ReplaceByGlobalNode()
397 {
398     DEBUG_ASSERT(callSiteInfo == kInvalid, "must be invalid");
399     DEBUG_ASSERT(out.size() == 1, "the size of out must be one");
400     DEBUG_ASSERT(pointsTo.size() == 1, "the size of pointsTo must be one");
401     for (EACGBaseNode *inNode : in) {
402         inNode->out.erase(this);
403     }
404     in.clear();
405     return false;
406 }
407 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)408 void EACGFieldNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
409                                 const IRMap *irMap)
410 {
411     if (dumped[this]) {
412         return;
413     }
414     dumped[this] = true;
415     std::string name = GetName(nullptr);
416     std::string label = GetName(irMap) + "\\nFIdx : " + std::to_string(GetFieldID()) + "\\n";
417     std::string color;
418     GetNodeFormatInDot(label, color);
419     std::string style;
420     if (IsPhantom()) {
421         style = "dotted";
422     } else {
423         style = "bold";
424     }
425     fout << name << " [shape=circle, label=\"" << label << "\", fontcolor=" << color << ", style=" << style
426          << ", margin=0];\n";
427     if (dumpPt) {
428         for (auto obj : pointsTo) {
429             fout << name << "->" << obj->GetName(nullptr) << ";\n";
430         }
431         for (auto obj : pointsTo) {
432             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
433         }
434     } else {
435         for (auto outNode : out) {
436             std::string edgeStyle;
437             if (!outNode->IsObjectNode()) {
438                 edgeStyle = " [style =\"dotted\"]";
439             }
440             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
441         }
442         for (auto outNode : out) {
443             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
444         }
445     }
446 }
447 
ReplaceByGlobalNode()448 bool EACGFieldNode::ReplaceByGlobalNode()
449 {
450     for (EACGObjectNode *obj : pointsTo) {
451         obj->pointsBy.erase(this);
452     }
453     pointsTo.clear();
454     (void)pointsTo.insert(eaCG->GetGlobalObject());
455     for (EACGBaseNode *outNode : out) {
456         outNode->in.erase(this);
457     }
458     out.clear();
459     (void)out.insert(eaCG->GetGlobalObject());
460     bool canDelete = true;
461     std::set<EACGObjectNode *> tmp = belongsTo;
462     for (EACGObjectNode *obj : tmp) {
463         if (obj->GetEAStatus() != kGlobalEscape) {
464             canDelete = false;
465         } else {
466             belongsTo.erase(obj);
467         }
468     }
469     if (canDelete) {
470         DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
471         CHECK_FATAL(id > 0, "must not be zero");
472         eaCG->nodes[id - 1] = nullptr;
473         for (EACGBaseNode *inNode : in) {
474             DEBUG_ASSERT(!inNode->IsObjectNode(), "must be ObjectNode");
475             inNode->out.erase(this);
476             (void)inNode->out.insert(eaCG->globalField);
477         }
478         for (auto exprPair : eaCG->expr2Nodes) {
479             size_t eraseSize = exprPair.second->erase(this);
480             if (eraseSize != 0 && exprPair.first->GetMeOp() != kMeOpIvar && exprPair.first->GetMeOp() != kMeOpOp) {
481                 DEBUG_ASSERT(false, "must be kMeOpIvar or kMeOpOp");
482             }
483             if (exprPair.second->size() == 0) {
484                 exprPair.second->insert(eaCG->globalField);
485             }
486         }
487         in.clear();
488         return true;
489     }
490     return false;
491 }
492 
DeleteEACG() const493 void EAConnectionGraph::DeleteEACG() const
494 {
495     for (EACGBaseNode *node : nodes) {
496         if (node == nullptr) {
497             continue;
498         }
499         delete node;
500         node = nullptr;
501     }
502 }
503 
TrimGlobalNode() const504 void EAConnectionGraph::TrimGlobalNode() const
505 {
506     for (EACGBaseNode *node : nodes) {
507         if (node == nullptr) {
508             continue;
509         }
510         constexpr int leastIdx = 3;
511         if (node->id <= leastIdx) {
512             continue;
513         }
514         bool canDelete = false;
515         if (node->GetEAStatus() == kGlobalEscape) {
516             canDelete = node->ReplaceByGlobalNode();
517         }
518 #ifdef DEBUG
519         node->CheckAllConnectionInNodes();
520 #endif
521         if (canDelete) {
522             delete node;
523             node = nullptr;
524         }
525     }
526 }
527 
InitGlobalNode()528 void EAConnectionGraph::InitGlobalNode()
529 {
530     globalObj = CreateObjectNode(nullptr, kNoEscape, true, TyIdx(0));
531     globalRef = CreateReferenceNode(nullptr, kNoEscape, true);
532     (void)globalRef->AddOutNode(*globalObj);
533     (void)globalRef->AddOutNode(*globalRef);
534     globalField = CreateFieldNode(nullptr, kNoEscape, -1, globalObj, true);  // -1 expresses global
535     (void)globalField->AddOutNode(*globalObj);
536     (void)globalField->AddOutNode(*globalRef);
537     (void)globalField->AddOutNode(*globalField);
538     (void)globalRef->AddOutNode(*globalField);
539     globalObj->eaStatus = kGlobalEscape;
540     globalField->eaStatus = kGlobalEscape;
541     globalRef->eaStatus = kGlobalEscape;
542 }
543 
CreateObjectNode(MeExpr * expr,EAStatus initialEas,bool isPh,TyIdx tyIdx)544 EACGObjectNode *EAConnectionGraph::CreateObjectNode(MeExpr *expr, EAStatus initialEas, bool isPh, TyIdx tyIdx)
545 {
546     EACGObjectNode *newObjNode =
547         new (std::nothrow) EACGObjectNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isPh);
548     ASSERT_NOT_NULL(newObjNode);
549     nodes.push_back(newObjNode);
550     if (expr != nullptr) {
551         if (expr2Nodes.find(expr) == expr2Nodes.end()) {
552             expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
553             expr2Nodes[expr]->insert(newObjNode);
554         } else {
555             DEBUG_ASSERT(false, "must find expr");
556         }
557     }
558     return newObjNode;
559 }
560 
CreatePointerNode(MeExpr * expr,EAStatus initialEas,int inderictL)561 EACGPointerNode *EAConnectionGraph::CreatePointerNode(MeExpr *expr, EAStatus initialEas, int inderictL)
562 {
563     EACGPointerNode *newPointerNode =
564         new (std::nothrow) EACGPointerNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, inderictL);
565     ASSERT_NOT_NULL(newPointerNode);
566     nodes.push_back(newPointerNode);
567     if (expr != nullptr) {
568         if (expr2Nodes.find(expr) == expr2Nodes.end()) {
569             expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
570             expr2Nodes[expr]->insert(newPointerNode);
571         } else {
572             DEBUG_ASSERT(false, "must find expr");
573         }
574     }
575     return newPointerNode;
576 }
577 
CreateReferenceNode(MeExpr * expr,EAStatus initialEas,bool isStatic)578 EACGRefNode *EAConnectionGraph::CreateReferenceNode(MeExpr *expr, EAStatus initialEas, bool isStatic)
579 {
580     EACGRefNode *newRefNode =
581         new (std::nothrow) EACGRefNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isStatic);
582     ASSERT_NOT_NULL(newRefNode);
583     nodes.push_back(newRefNode);
584     if (expr != nullptr) {
585         if (expr2Nodes.find(expr) == expr2Nodes.end()) {
586             expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
587             expr2Nodes[expr]->insert(newRefNode);
588         } else {
589             DEBUG_ASSERT(false, "must find expr");
590         }
591         if (expr->GetMeOp() != kMeOpVar && expr->GetMeOp() != kMeOpAddrof && expr->GetMeOp() != kMeOpReg &&
592             expr->GetMeOp() != kMeOpOp) {
593             DEBUG_ASSERT(false, "must be kMeOpVar, kMeOpAddrof, kMeOpReg or kMeOpOp");
594         }
595     }
596     return newRefNode;
597 }
598 
TouchCallSite(uint32 callSiteInfo)599 void EAConnectionGraph::TouchCallSite(uint32 callSiteInfo)
600 {
601     CHECK_FATAL(callSite2Nodes.find(callSiteInfo) != callSite2Nodes.end(), "find failed");
602     if (callSite2Nodes[callSiteInfo] == nullptr) {
603         MapleVector<EACGBaseNode *> *tmp = alloc->GetMemPool()->New<MapleVector<EACGBaseNode *>>(alloc->Adapter());
604         callSite2Nodes[callSiteInfo] = tmp;
605     }
606 }
607 
CreateActualNode(EAStatus initialEas,bool isReurtn,bool isPh,uint8 argIdx,uint32 callSiteInfo)608 EACGActualNode *EAConnectionGraph::CreateActualNode(EAStatus initialEas, bool isReurtn, bool isPh, uint8 argIdx,
609                                                     uint32 callSiteInfo)
610 {
611     MeExpr *expr = nullptr;
612     DEBUG_ASSERT(isPh, "must be ph");
613     DEBUG_ASSERT(callSiteInfo != 0, "must not be zero");
614     EACGActualNode *newActNode = new (std::nothrow) EACGActualNode(
615         mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isReurtn, isPh, argIdx, callSiteInfo);
616     ASSERT_NOT_NULL(newActNode);
617     nodes.push_back(newActNode);
618     if (expr != nullptr) {
619         if (expr2Nodes.find(expr) == expr2Nodes.end()) {
620             expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
621             expr2Nodes[expr]->insert(newActNode);
622         } else {
623             DEBUG_ASSERT(false, "must find expr");
624         }
625     }
626     if (callSiteInfo != kInvalid) {
627         DEBUG_ASSERT(callSite2Nodes[callSiteInfo] != nullptr, "must touched before");
628         callSite2Nodes[callSiteInfo]->push_back(newActNode);
629 #ifdef DEBUG
630         CheckArgNodeOrder(*callSite2Nodes[callSiteInfo]);
631 #endif
632     } else {
633         funcArgNodes.push_back(newActNode);
634     }
635     return newActNode;
636 }
637 
CreateFieldNode(MeExpr * expr,EAStatus initialEas,FieldID fId,EACGObjectNode * belongTo,bool isPh)638 EACGFieldNode *EAConnectionGraph::CreateFieldNode(MeExpr *expr, EAStatus initialEas, FieldID fId,
639                                                   EACGObjectNode *belongTo, bool isPh)
640 {
641     EACGFieldNode *newFieldNode = new (std::nothrow)
642         EACGFieldNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, fId, belongTo, isPh);
643     ASSERT_NOT_NULL(newFieldNode);
644     nodes.push_back(newFieldNode);
645     if (expr != nullptr) {
646         if (expr2Nodes.find(expr) == expr2Nodes.end()) {
647             expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
648             expr2Nodes[expr]->insert(newFieldNode);
649         } else {
650             expr2Nodes[expr]->insert(newFieldNode);
651         }
652         if (expr->GetMeOp() != kMeOpIvar && expr->GetMeOp() != kMeOpOp) {
653             DEBUG_ASSERT(false, "must be kMeOpIvar or kMeOpOp");
654         }
655     }
656     return newFieldNode;
657 }
658 
GetCGNodeFromExpr(MeExpr * me)659 EACGBaseNode *EAConnectionGraph::GetCGNodeFromExpr(MeExpr *me)
660 {
661     if (expr2Nodes.find(me) == expr2Nodes.end()) {
662         return nullptr;
663     }
664     return *(expr2Nodes[me]->begin());
665 }
666 
UpdateExprOfNode(EACGBaseNode & node,MeExpr * me)667 void EAConnectionGraph::UpdateExprOfNode(EACGBaseNode &node, MeExpr *me)
668 {
669     if (expr2Nodes.find(me) == expr2Nodes.end()) {
670         expr2Nodes[me] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
671         expr2Nodes[me]->insert(&node);
672     } else {
673         if (node.IsFieldNode()) {
674             expr2Nodes[me]->insert(&node);
675         } else {
676             if (expr2Nodes[me]->find(&node) == expr2Nodes[me]->end()) {
677                 CHECK_FATAL(false, "must be filed node");
678             }
679         }
680     }
681     node.SetMeExpr(*me);
682 }
683 
UpdateExprOfGlobalRef(MeExpr * me)684 void EAConnectionGraph::UpdateExprOfGlobalRef(MeExpr *me)
685 {
686     UpdateExprOfNode(*globalRef, me);
687 }
688 
GetReturnNode() const689 EACGActualNode *EAConnectionGraph::GetReturnNode() const
690 {
691     if (funcArgNodes.size() == 0) {
692         return nullptr;
693     }
694     CHECK_FATAL(funcArgNodes.size() > 0, "must not be zero");
695     EACGActualNode *ret = static_cast<EACGActualNode *>(funcArgNodes[funcArgNodes.size() - 1]);
696     if (ret->IsReturn()) {
697         return ret;
698     }
699     return nullptr;
700 }
701 #ifdef DEBUG
CheckArgNodeOrder(MapleVector<EACGBaseNode * > & funcArgV)702 void EAConnectionGraph::CheckArgNodeOrder(MapleVector<EACGBaseNode *> &funcArgV)
703 {
704     uint8 preIndex = 0;
705     for (size_t i = 0; i < funcArgV.size(); ++i) {
706         DEBUG_ASSERT(funcArgV[i]->IsActualNode(), "must be ActualNode");
707         EACGActualNode *actNode = static_cast<EACGActualNode *>(funcArgV[i]);
708         if (i == funcArgV.size() - 1) {
709             if (actNode->IsReturn()) {
710                 continue;
711             } else {
712                 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
713             }
714         } else {
715             DEBUG_ASSERT(!actNode->IsReturn(), "must be return");
716             DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
717         }
718         preIndex = actNode->GetArgIndex();
719     }
720 }
721 #endif
ExprCanBeOptimized(MeExpr & expr)722 bool EAConnectionGraph::ExprCanBeOptimized(MeExpr &expr)
723 {
724     if (expr2Nodes.find(&expr) == expr2Nodes.end()) {
725         MeExpr *rhs = nullptr;
726         if (expr.GetMeOp() == kMeOpVar) {
727             DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
728             DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_dassign, "must be OP_dassign");
729             MeStmt *defStmt = static_cast<VarMeExpr *>(&expr)->GetDefStmt();
730             DassignMeStmt *dassignStmt = static_cast<DassignMeStmt *>(defStmt);
731             rhs = dassignStmt->GetRHS();
732         } else if (expr.GetMeOp() == kMeOpReg) {
733             DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
734             DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_regassign,
735                          "must be OP_regassign");
736             MeStmt *defStmt = static_cast<RegMeExpr *>(&expr)->GetDefStmt();
737             AssignMeStmt *regassignStmt = static_cast<AssignMeStmt *>(defStmt);
738             rhs = regassignStmt->GetRHS();
739         } else {
740             CHECK_FATAL(false, "impossible");
741         }
742         DEBUG_ASSERT(expr2Nodes.find(rhs) != expr2Nodes.end(), "impossible");
743         expr = *rhs;
744     }
745     MapleSet<EACGBaseNode *> &nodesTmp = *expr2Nodes[&expr];
746 
747     for (EACGBaseNode *node : nodesTmp) {
748         for (EACGObjectNode *obj : node->GetPointsToSet()) {
749             if (obj->GetEAStatus() != kNoEscape && obj->GetEAStatus() != kReturnEscape) {
750                 return false;
751             }
752         }
753     }
754     return true;
755 }
756 
GetCallSiteArgNodeVector(uint32 callSite)757 MapleVector<EACGBaseNode *> *EAConnectionGraph::GetCallSiteArgNodeVector(uint32 callSite)
758 {
759     CHECK_FATAL(callSite2Nodes.find(callSite) != callSite2Nodes.end(), "find failed");
760     ASSERT_NOT_NULL(callSite2Nodes[callSite]);
761     return callSite2Nodes[callSite];
762 }
763 
764 // if we have scc of connection graph, it will be more efficient.
PropogateEAStatus()765 void EAConnectionGraph::PropogateEAStatus()
766 {
767     bool oldStatus = CGHasUpdated();
768     do {
769         UnSetCGUpdateFlag();
770         for (EACGBaseNode *node : nodes) {
771             if (node == nullptr) {
772                 continue;
773             }
774             if (node->IsObjectNode()) {
775                 EACGObjectNode *obj = static_cast<EACGObjectNode *>(node);
776                 for (auto fieldPair : obj->GetFieldNodeMap()) {
777                     EACGBaseNode *field = fieldPair.second;
778                     (void)field->UpdateEAStatus(obj->GetEAStatus());
779                 }
780             } else {
781                 for (EACGBaseNode *pointsToNode : node->GetPointsToSet()) {
782                     (void)pointsToNode->UpdateEAStatus(node->GetEAStatus());
783                 }
784             }
785         }
786         DEBUG_ASSERT(!CGHasUpdated(), "must be Updated");
787     } while (CGHasUpdated());
788     RestoreStatus(oldStatus);
789 }
790 
GetFuncArgNodeVector() const791 const MapleVector<EACGBaseNode *> *EAConnectionGraph::GetFuncArgNodeVector() const
792 {
793     return &funcArgNodes;
794 }
795 
796 // this func is called from callee context
UpdateEACGFromCaller(const MapleVector<EACGBaseNode * > & callerCallSiteArg,const MapleVector<EACGBaseNode * > & calleeFuncArg)797 void EAConnectionGraph::UpdateEACGFromCaller(const MapleVector<EACGBaseNode *> &callerCallSiteArg,
798                                              const MapleVector<EACGBaseNode *> &calleeFuncArg)
799 {
800     DEBUG_ASSERT(abs(static_cast<int>(callerCallSiteArg.size()) - static_cast<int>(calleeFuncArg.size())) <= 1,
801                  "greater than");
802 
803     UnSetCGUpdateFlag();
804     for (uint32 i = 0; i < callerCallSiteArg.size(); ++i) {
805         EACGBaseNode *callerNode = callerCallSiteArg[i];
806         ASSERT_NOT_NULL(callerNode);
807         DEBUG_ASSERT(callerNode->IsActualNode(), "must be ActualNode");
808         CHECK_FATAL(callerCallSiteArg.size() - 1, "must not be zero");
809         if ((i == callerCallSiteArg.size() - 1) && static_cast<EACGActualNode *>(callerNode)->IsReturn()) {
810             continue;
811         }
812         bool hasGlobalEA = false;
813         for (EACGObjectNode *obj : callerNode->GetPointsToSet()) {
814             if (obj->GetEAStatus() == kGlobalEscape) {
815                 hasGlobalEA = true;
816                 break;
817             }
818         }
819         if (hasGlobalEA) {
820             EACGBaseNode *calleeNode = (calleeFuncArg)[i];
821             for (EACGObjectNode *obj : calleeNode->GetPointsToSet()) {
822                 (void)obj->UpdateEAStatus(kGlobalEscape);
823             }
824         }
825     }
826     if (CGHasUpdated()) {
827         PropogateEAStatus();
828     }
829     TrimGlobalNode();
830 }
831 
DumpDotFile(const IRMap * irMap,bool dumpPt,MapleVector<EACGBaseNode * > * dumpVec)832 void EAConnectionGraph::DumpDotFile(const IRMap *irMap, bool dumpPt, MapleVector<EACGBaseNode *> *dumpVec)
833 {
834     if (dumpVec == nullptr) {
835         dumpVec = &nodes;
836     }
837     std::filebuf fb;
838     std::string outFile = GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) + "-connectiongraph.dot";
839     fb.open(outFile, std::ios::trunc | std::ios::out);
840     CHECK_FATAL(fb.is_open(), "open file failed");
841     std::ostream cgDotFile(&fb);
842     cgDotFile << "digraph connectiongraph{\n";
843     std::map<EACGBaseNode *, bool> dumped;
844     for (auto node : nodes) {
845         dumped[node] = false;
846     }
847     for (EACGBaseNode *node : *dumpVec) {
848         if (node == nullptr) {
849             continue;
850         }
851         if (dumped[node]) {
852             continue;
853         }
854         node->DumpDotFile(cgDotFile, dumped, dumpPt, irMap);
855         dumped[node] = true;
856     }
857     cgDotFile << "}\n";
858     fb.close();
859 }
860 
CountObjEAStatus() const861 void EAConnectionGraph::CountObjEAStatus() const
862 {
863     int sum = 0;
864     int eaCount[4] = {0};  // There are 4 EAStatus.
865     for (EACGBaseNode *node : nodes) {
866         if (node == nullptr) {
867             continue;
868         }
869 
870         if (node->IsObjectNode()) {
871             EACGObjectNode *objNode = static_cast<EACGObjectNode *>(node);
872             if (!objNode->IsPhantom()) {
873                 CHECK_FATAL(objNode->locInfo != nullptr, "Impossible");
874                 MIRType *type = nullptr;
875                 const MeExpr *expr = objNode->GetMeExpr();
876                 CHECK_FATAL(expr != nullptr, "Impossible");
877                 if (expr->GetOp() == OP_gcmalloc || expr->GetOp() == OP_gcpermalloc) {
878                     TyIdx tyIdx = static_cast<const GcmallocMeExpr *>(expr)->GetTyIdx();
879                     type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
880                 } else {
881                     TyIdx tyIdx = static_cast<const OpMeExpr *>(expr)->GetTyIdx();
882                     type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
883                 }
884                 LogInfo::MapleLogger() << "[LOCATION] [" << objNode->locInfo->GetModName() << " "
885                                        << objNode->locInfo->GetFileId() << " " << objNode->locInfo->GetLineId() << " "
886                                        << EscapeName(objNode->GetEAStatus()) << " " << expr->GetExprID() << " ";
887                 type->Dump(0, false);
888                 LogInfo::MapleLogger() << "]\n";
889                 ++sum;
890                 ++eaCount[node->GetEAStatus()];
891             }
892         }
893     }
894     LogInfo::MapleLogger() << "[gcmalloc object statistics]  "
895                            << GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) << " "
896                            << "Gcmallocs: " << sum << " "
897                            << "NoEscape: " << eaCount[kNoEscape] << " "
898                            << "RetEscape: " << eaCount[kReturnEscape] << " "
899                            << "ArgEscape: " << eaCount[kArgumentEscape] << " "
900                            << "GlobalEscape: " << eaCount[kGlobalEscape] << "\n";
901 }
902 
RestoreStatus(bool old)903 void EAConnectionGraph::RestoreStatus(bool old)
904 {
905     if (old) {
906         SetCGHasUpdated();
907     } else {
908         UnSetCGUpdateFlag();
909     }
910 }
911 
912 // Update caller's ConnectionGraph using callee's summary information.
913 // If the callee's summary is not found, we just mark all the pointsTo nodes of caller's actual node to GlobalEscape.
914 // Otherwise, we do these steps:
915 //
916 // 1, update caller nodes using callee's summary, new node might be added into caller's CG in this step.
917 //
918 // 2, update caller edges using callee's summary, new points-to edge might be added into caller's CG in this step.
MergeCG(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > * callee)919 bool EAConnectionGraph::MergeCG(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> *callee)
920 {
921     TrimGlobalNode();
922     bool cgChanged = false;
923     bool oldStatus = CGHasUpdated();
924     UnSetCGUpdateFlag();
925     if (callee == nullptr) {
926         for (EACGBaseNode *actualInCaller : caller) {
927             for (EACGObjectNode *p : actualInCaller->GetPointsToSet()) {
928                 (void)p->UpdateEAStatus(EAStatus::kGlobalEscape);
929             }
930         }
931         cgChanged = CGHasUpdated();
932         if (!cgChanged) {
933             RestoreStatus(oldStatus);
934         }
935         TrimGlobalNode();
936         return cgChanged;
937     }
938     size_t callerSize = caller.size();
939     size_t calleeSize = callee->size();
940     if (callerSize > calleeSize) {
941         DEBUG_ASSERT((callerSize - calleeSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
942     } else {
943         DEBUG_ASSERT((calleeSize - callerSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
944     }
945     if (callerSize == 0 || calleeSize == 0) {
946         cgChanged = CGHasUpdated();
947         if (!cgChanged) {
948             RestoreStatus(oldStatus);
949         }
950         return cgChanged;
951     }
952     if ((callerSize != calleeSize) &&
953         (callerSize != calleeSize + 1 || static_cast<EACGActualNode *>(callee->back())->IsReturn()) &&
954         (callerSize != calleeSize - 1 || !static_cast<EACGActualNode *>(callee->back())->IsReturn())) {
955         DEBUG_ASSERT(false, "Impossible");
956     }
957 
958     callee2Caller.clear();
959     UpdateCallerNodes(caller, *callee);
960     UpdateCallerEdges();
961     UpdateCallerRetNode(caller, *callee);
962     callee2Caller.clear();
963 
964     cgChanged = CGHasUpdated();
965     if (!cgChanged) {
966         RestoreStatus(oldStatus);
967     }
968     TrimGlobalNode();
969     return cgChanged;
970 }
971 
AddMaps2Object(EACGObjectNode * caller,EACGObjectNode * callee)972 void EAConnectionGraph::AddMaps2Object(EACGObjectNode *caller, EACGObjectNode *callee)
973 {
974     if (callee2Caller.find(callee) == callee2Caller.end()) {
975         std::set<EACGObjectNode *> callerSet;
976         callee2Caller[callee] = callerSet;
977     }
978     (void)callee2Caller[callee].insert(caller);
979 }
980 
UpdateCallerRetNode(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)981 void EAConnectionGraph::UpdateCallerRetNode(MapleVector<EACGBaseNode *> &caller,
982                                             const MapleVector<EACGBaseNode *> &callee)
983 {
984     EACGActualNode *lastInCaller = static_cast<EACGActualNode *>(caller.back());
985     EACGActualNode *lastInCallee = static_cast<EACGActualNode *>(callee.back());
986     if (!lastInCaller->IsReturn()) {
987         return;
988     }
989     CHECK_FATAL(lastInCaller->GetOutSet().size() == 1, "Impossible");
990     for (EACGBaseNode *callerRetNode : lastInCaller->GetOutSet()) {
991         for (EACGObjectNode *calleeRetNode : lastInCallee->GetPointsToSet()) {
992             for (EACGObjectNode *objInCaller : callee2Caller[calleeRetNode]) {
993                 auto pointsToSet = callerRetNode->GetPointsToSet();
994                 if (pointsToSet.find(objInCaller) == pointsToSet.end()) {
995                     (void)callerRetNode->AddOutNode(*objInCaller);
996                 }
997             }
998         }
999     }
1000 }
1001 
1002 // Update caller node by adding some nodes which are mapped from callee.
UpdateCallerNodes(const MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)1003 void EAConnectionGraph::UpdateCallerNodes(const MapleVector<EACGBaseNode *> &caller,
1004                                           const MapleVector<EACGBaseNode *> &callee)
1005 {
1006     const size_t callerSize = caller.size();
1007     const size_t calleeSize = callee.size();
1008     const size_t actualCount = ((callerSize < calleeSize) ? callerSize : calleeSize);
1009     bool firstTime = true;
1010 
1011     for (size_t i = 0; i < actualCount; ++i) {
1012         EACGBaseNode *actualInCaller = caller.at(i);
1013         EACGBaseNode *actualInCallee = callee.at(i);
1014         UpdateNodes(*actualInCallee, *actualInCaller, firstTime);
1015     }
1016 }
1017 
1018 // Update caller edges using information from callee.
UpdateCallerEdges()1019 void EAConnectionGraph::UpdateCallerEdges()
1020 {
1021     std::set<EACGObjectNode *> set;
1022     for (auto pair : callee2Caller) {
1023         (void)set.insert(pair.first);
1024     }
1025     for (EACGObjectNode *p : set) {
1026         for (auto tempPair : p->GetFieldNodeMap()) {
1027             int32 fieldID = tempPair.first;
1028             EACGBaseNode *fieldNode = tempPair.second;
1029             for (EACGObjectNode *q : fieldNode->GetPointsToSet()) {
1030                 UpdateCallerEdgesInternal(p, fieldID, q);
1031             }
1032         }
1033     }
1034 }
1035 
1036 // Update caller edges using information of given ObjectNode from callee.
UpdateCallerEdgesInternal(EACGObjectNode * node1,int32 fieldID,EACGObjectNode * node2)1037 void EAConnectionGraph::UpdateCallerEdgesInternal(EACGObjectNode *node1, int32 fieldID, EACGObjectNode *node2)
1038 {
1039     CHECK_FATAL(callee2Caller.find(node1) != callee2Caller.end(), "find failed");
1040     CHECK_FATAL(callee2Caller.find(node2) != callee2Caller.end(), "find failed");
1041     for (EACGObjectNode *p1 : callee2Caller[node1]) {
1042         for (EACGObjectNode *q1 : callee2Caller[node2]) {
1043             EACGFieldNode *fieldNode = p1->GetFieldNodeFromIdx(fieldID);
1044             if (fieldNode == nullptr) {
1045                 CHECK_NULL_FATAL(node1);
1046                 fieldNode = node1->GetFieldNodeFromIdx(fieldID);
1047                 CHECK_FATAL(fieldNode != nullptr, "fieldNode must not be nullptr because we have handled it before!");
1048                 CHECK_FATAL(fieldNode->IsBelongTo(this), "must be belong to this");
1049                 (void)p1->AddOutNode(*fieldNode);
1050             }
1051             (void)fieldNode->AddOutNode(*q1);
1052         }
1053     }
1054 }
1055 
UpdateNodes(const EACGBaseNode & actualInCallee,EACGBaseNode & actualInCaller,bool firstTime)1056 void EAConnectionGraph::UpdateNodes(const EACGBaseNode &actualInCallee, EACGBaseNode &actualInCaller, bool firstTime)
1057 {
1058     DEBUG_ASSERT(actualInCallee.GetPointsToSet().size() > 0, "actualInCallee->GetPointsToSet().size() must gt 0!");
1059     for (EACGObjectNode *objInCallee : actualInCallee.GetPointsToSet()) {
1060         if (actualInCaller.GetPointsToSet().size() == 0) {
1061             std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1062             if (mapsTo.size() > 0) {
1063                 for (EACGObjectNode *temp : mapsTo) {
1064                     (void)actualInCaller.AddOutNode(*temp);
1065                 }
1066             } else if (objInCallee->IsBelongTo(this)) {
1067                 DEBUG_ASSERT(false, "must be belong to this");
1068             } else {
1069                 EACGObjectNode *phantom = CreateObjectNode(nullptr, actualInCaller.GetEAStatus(), true, TyIdx(0));
1070                 ASSERT_NOT_NULL(phantom);
1071                 (void)actualInCaller.AddOutNode(*phantom);
1072                 AddMaps2Object(phantom, objInCallee);
1073                 UpdateCallerWithCallee(*phantom, *objInCallee, firstTime);
1074             }
1075         } else {
1076             for (EACGObjectNode *objInCaller : actualInCaller.GetPointsToSet()) {
1077                 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1078                 if (mapsTo.find(objInCaller) == mapsTo.end()) {
1079                     AddMaps2Object(objInCaller, objInCallee);
1080                     UpdateCallerWithCallee(*objInCaller, *objInCallee, firstTime);
1081                 }
1082             }
1083         }
1084     }
1085 }
1086 
1087 // The escape state of the nodes in MapsTo(which is the object node in caller) is marked
1088 // GlobalEscape if the escape state of object node in callee is GlobalEscape.
1089 // Otherwise, the escape state of the caller nodes is not affected.
UpdateCallerWithCallee(EACGObjectNode & objInCaller,const EACGObjectNode & objInCallee,bool firstTime)1090 void EAConnectionGraph::UpdateCallerWithCallee(EACGObjectNode &objInCaller, const EACGObjectNode &objInCallee,
1091                                                bool firstTime)
1092 {
1093     if (objInCallee.GetEAStatus() == EAStatus::kGlobalEscape) {
1094         (void)objInCaller.UpdateEAStatus(EAStatus::kGlobalEscape);
1095     }
1096 
1097     // At this moment, a node in caller is mapped to the corresponding node in callee,
1098     // we need make sure that all the field nodes also exist in caller. If not,
1099     // we create both the field node and the phantom object node it should point to for the caller.
1100     for (auto tempPair : objInCallee.GetFieldNodeMap()) {
1101         EACGFieldNode *fieldInCaller = objInCaller.GetFieldNodeFromIdx(tempPair.first);
1102         EACGFieldNode *fieldInCallee = tempPair.second;
1103         if (fieldInCaller == nullptr && fieldInCallee->IsBelongTo(this)) {
1104             (void)objInCaller.AddOutNode(*fieldInCallee);
1105         }
1106         fieldInCaller = GetOrCreateFieldNodeFromIdx(objInCaller, tempPair.first);
1107         UpdateNodes(*fieldInCallee, *fieldInCaller, firstTime);
1108     }
1109 }
1110 
GetOrCreateFieldNodeFromIdx(EACGObjectNode & obj,int32 fieldID)1111 EACGFieldNode *EAConnectionGraph::GetOrCreateFieldNodeFromIdx(EACGObjectNode &obj, int32 fieldID)
1112 {
1113     EACGFieldNode *ret = obj.GetFieldNodeFromIdx(fieldID);
1114     if (ret == nullptr) {
1115         // this node is always phantom
1116         ret = CreateFieldNode(nullptr, obj.GetEAStatus(), fieldID, &obj, true);
1117     }
1118     return ret;
1119 }
1120 }  // namespace maple
1121