• 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     eaCG->nodes[id - 1] = nullptr;
220     return true;
221 }
222 
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const223 void EACGObjectNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
224 {
225     for (auto fieldNodePair : fieldNodes) {
226         EACGFieldNode *field = fieldNodePair.second;
227         (void)field->UpdateEAStatus(eaStatus);
228     }
229 }
230 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)231 void EACGObjectNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
232                                  const IRMap *irMap)
233 {
234     if (dumped[this]) {
235         return;
236     }
237     dumped[this] = true;
238 
239     std::string name = GetName(nullptr);
240     std::string label;
241     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;
272     label = GetName(irMap) + " Reference\\n";
273     if (IsStaticRef()) {
274         label += "Static\\n";
275     }
276     std::string color;
277     GetNodeFormatInDot(label, color);
278     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
279          << "\n";
280     if (dumpPt) {
281         for (auto obj : pointsTo) {
282             fout << name << "->" << obj->GetName(nullptr) << ";"
283                  << "\n";
284         }
285         for (auto obj : pointsTo) {
286             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
287         }
288     } else {
289         for (auto outNode : out) {
290             std::string edgeStyle;
291             if (!outNode->IsObjectNode()) {
292                 edgeStyle = " [style =\"dotted\"]";
293             }
294             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";"
295                  << "\n";
296         }
297         for (auto outNode : out) {
298             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
299         }
300     }
301 }
302 
ReplaceByGlobalNode()303 bool EACGRefNode::ReplaceByGlobalNode()
304 {
305     for (EACGBaseNode *inNode : in) {
306         DEBUG_ASSERT(inNode->id > 3, "must be greater than three");  // the least valid idx is 3
307         (void)inNode->out.erase(this);
308         (void)inNode->out.insert(eaCG->GetGlobalReference());
309     }
310     in.clear();
311     for (EACGBaseNode *outNode : out) {
312         (void)outNode->in.erase(this);
313     }
314     out.clear();
315     for (EACGObjectNode *base : pointsTo) {
316         base->EraseNodeFromPointsBy(this);
317     }
318     pointsTo.clear();
319     if (meExpr != nullptr) {
320         eaCG->expr2Nodes[meExpr]->clear();
321         eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalReference());
322     }
323     DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
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;
337     label = GetName(irMap) + "\\nPointer Indirect Level : " + std::to_string(indirectLevel) + "\\n";
338     std::string color;
339     GetNodeFormatInDot(label, color);
340     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
341          << "\n";
342     for (EACGBaseNode *outNode : out) {
343         fout << name << "->" << outNode->GetName(nullptr) << " [style =\"dotted\", color = \"blue\"];"
344              << "\n";
345     }
346     for (auto outNode : out) {
347         outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
348     }
349 }
350 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)351 void EACGActualNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
352                                  const IRMap *irMap)
353 {
354     if (dumped[this]) {
355         return;
356     }
357     dumped[this] = true;
358 
359     std::string name = GetName(nullptr);
360     std::string label;
361     if (IsReturn()) {
362         label = GetName(irMap) + "\\nRet Idx : " + std::to_string(GetArgIndex()) + "\\n";
363     } else {
364         label = GetName(irMap) + "\\nArg Idx : " + std::to_string(GetArgIndex()) +
365                 " Call Site : " + std::to_string(GetCallSite()) + "\\n";
366     }
367     std::string style;
368     if (IsPhantom()) {
369         style = "dotted";
370     } else {
371         style = "bold";
372     }
373     std::string color;
374     GetNodeFormatInDot(label, color);
375     fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
376     if (dumpPt) {
377         for (auto obj : pointsTo) {
378             fout << name << "->" << obj->GetName(nullptr) << ";\n";
379         }
380         for (auto obj : pointsTo) {
381             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
382         }
383     } else {
384         for (auto outNode : out) {
385             std::string edgeStyle;
386             if (!outNode->IsObjectNode()) {
387                 edgeStyle = " [style =\"dotted\"]";
388             }
389             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
390         }
391         for (auto outNode : out) {
392             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
393         }
394     }
395 }
396 
ReplaceByGlobalNode()397 bool EACGActualNode::ReplaceByGlobalNode()
398 {
399     DEBUG_ASSERT(callSiteInfo == kInvalid, "must be invalid");
400     DEBUG_ASSERT(out.size() == 1, "the size of out must be one");
401     DEBUG_ASSERT(pointsTo.size() == 1, "the size of pointsTo must be one");
402     for (EACGBaseNode *inNode : in) {
403         inNode->out.erase(this);
404     }
405     in.clear();
406     return false;
407 }
408 
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)409 void EACGFieldNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
410                                 const IRMap *irMap)
411 {
412     if (dumped[this]) {
413         return;
414     }
415     dumped[this] = true;
416     std::string name = GetName(nullptr);
417     std::string label = GetName(irMap) + "\\nFIdx : " + std::to_string(GetFieldID()) + "\\n";
418     std::string color;
419     GetNodeFormatInDot(label, color);
420     std::string style;
421     if (IsPhantom()) {
422         style = "dotted";
423     } else {
424         style = "bold";
425     }
426     fout << name << " [shape=circle, label=\"" << label << "\", fontcolor=" << color << ", style=" << style
427          << ", margin=0];\n";
428     if (dumpPt) {
429         for (auto obj : pointsTo) {
430             fout << name << "->" << obj->GetName(nullptr) << ";\n";
431         }
432         for (auto obj : pointsTo) {
433             obj->DumpDotFile(fout, dumped, dumpPt, irMap);
434         }
435     } else {
436         for (auto outNode : out) {
437             std::string edgeStyle;
438             if (!outNode->IsObjectNode()) {
439                 edgeStyle = " [style =\"dotted\"]";
440             }
441             fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
442         }
443         for (auto outNode : out) {
444             outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
445         }
446     }
447 }
448 
ReplaceByGlobalNode()449 bool EACGFieldNode::ReplaceByGlobalNode()
450 {
451     for (EACGObjectNode *obj : pointsTo) {
452         obj->pointsBy.erase(this);
453     }
454     pointsTo.clear();
455     (void)pointsTo.insert(eaCG->GetGlobalObject());
456     for (EACGBaseNode *outNode : out) {
457         outNode->in.erase(this);
458     }
459     out.clear();
460     (void)out.insert(eaCG->GetGlobalObject());
461     bool canDelete = true;
462     std::set<EACGObjectNode *> tmp = belongsTo;
463     for (EACGObjectNode *obj : tmp) {
464         if (obj->GetEAStatus() != kGlobalEscape) {
465             canDelete = false;
466         } else {
467             belongsTo.erase(obj);
468         }
469     }
470     if (canDelete) {
471         DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
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     EACGActualNode *ret = static_cast<EACGActualNode *>(funcArgNodes[funcArgNodes.size() - 1]);
695     if (ret->IsReturn()) {
696         return ret;
697     }
698     return nullptr;
699 }
700 #ifdef DEBUG
CheckArgNodeOrder(MapleVector<EACGBaseNode * > & funcArgV)701 void EAConnectionGraph::CheckArgNodeOrder(MapleVector<EACGBaseNode *> &funcArgV)
702 {
703     uint8 preIndex = 0;
704     for (size_t i = 0; i < funcArgV.size(); ++i) {
705         DEBUG_ASSERT(funcArgV[i]->IsActualNode(), "must be ActualNode");
706         EACGActualNode *actNode = static_cast<EACGActualNode *>(funcArgV[i]);
707         if (i == funcArgV.size() - 1) {
708             if (actNode->IsReturn()) {
709                 continue;
710             } else {
711                 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
712             }
713         } else {
714             DEBUG_ASSERT(!actNode->IsReturn(), "must be return");
715             DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
716         }
717         preIndex = actNode->GetArgIndex();
718     }
719 }
720 #endif
ExprCanBeOptimized(MeExpr & expr)721 bool EAConnectionGraph::ExprCanBeOptimized(MeExpr &expr)
722 {
723     if (expr2Nodes.find(&expr) == expr2Nodes.end()) {
724         MeExpr *rhs = nullptr;
725         if (expr.GetMeOp() == kMeOpVar) {
726             DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
727             DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_dassign, "must be OP_dassign");
728             MeStmt *defStmt = static_cast<VarMeExpr *>(&expr)->GetDefStmt();
729             DassignMeStmt *dassignStmt = static_cast<DassignMeStmt *>(defStmt);
730             rhs = dassignStmt->GetRHS();
731         } else if (expr.GetMeOp() == kMeOpReg) {
732             DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
733             DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_regassign,
734                          "must be OP_regassign");
735             MeStmt *defStmt = static_cast<RegMeExpr *>(&expr)->GetDefStmt();
736             AssignMeStmt *regassignStmt = static_cast<AssignMeStmt *>(defStmt);
737             rhs = regassignStmt->GetRHS();
738         } else {
739             CHECK_FATAL(false, "impossible");
740         }
741         DEBUG_ASSERT(expr2Nodes.find(rhs) != expr2Nodes.end(), "impossible");
742         expr = *rhs;
743     }
744     MapleSet<EACGBaseNode *> &nodesTmp = *expr2Nodes[&expr];
745 
746     for (EACGBaseNode *node : nodesTmp) {
747         for (EACGObjectNode *obj : node->GetPointsToSet()) {
748             if (obj->GetEAStatus() != kNoEscape && obj->GetEAStatus() != kReturnEscape) {
749                 return false;
750             }
751         }
752     }
753     return true;
754 }
755 
GetCallSiteArgNodeVector(uint32 callSite)756 MapleVector<EACGBaseNode *> *EAConnectionGraph::GetCallSiteArgNodeVector(uint32 callSite)
757 {
758     CHECK_FATAL(callSite2Nodes.find(callSite) != callSite2Nodes.end(), "find failed");
759     ASSERT_NOT_NULL(callSite2Nodes[callSite]);
760     return callSite2Nodes[callSite];
761 }
762 
763 // if we have scc of connection graph, it will be more efficient.
PropogateEAStatus()764 void EAConnectionGraph::PropogateEAStatus()
765 {
766     bool oldStatus = CGHasUpdated();
767     do {
768         UnSetCGUpdateFlag();
769         for (EACGBaseNode *node : nodes) {
770             if (node == nullptr) {
771                 continue;
772             }
773             if (node->IsObjectNode()) {
774                 EACGObjectNode *obj = static_cast<EACGObjectNode *>(node);
775                 for (auto fieldPair : obj->GetFieldNodeMap()) {
776                     EACGBaseNode *field = fieldPair.second;
777                     (void)field->UpdateEAStatus(obj->GetEAStatus());
778                 }
779             } else {
780                 for (EACGBaseNode *pointsToNode : node->GetPointsToSet()) {
781                     (void)pointsToNode->UpdateEAStatus(node->GetEAStatus());
782                 }
783             }
784         }
785         DEBUG_ASSERT(!CGHasUpdated(), "must be Updated");
786     } while (CGHasUpdated());
787     RestoreStatus(oldStatus);
788 }
789 
GetFuncArgNodeVector() const790 const MapleVector<EACGBaseNode *> *EAConnectionGraph::GetFuncArgNodeVector() const
791 {
792     return &funcArgNodes;
793 }
794 
795 // this func is called from callee context
UpdateEACGFromCaller(const MapleVector<EACGBaseNode * > & callerCallSiteArg,const MapleVector<EACGBaseNode * > & calleeFuncArg)796 void EAConnectionGraph::UpdateEACGFromCaller(const MapleVector<EACGBaseNode *> &callerCallSiteArg,
797                                              const MapleVector<EACGBaseNode *> &calleeFuncArg)
798 {
799     DEBUG_ASSERT(abs(static_cast<int>(callerCallSiteArg.size()) - static_cast<int>(calleeFuncArg.size())) <= 1,
800                  "greater than");
801 
802     UnSetCGUpdateFlag();
803     for (uint32 i = 0; i < callerCallSiteArg.size(); ++i) {
804         EACGBaseNode *callerNode = callerCallSiteArg[i];
805         ASSERT_NOT_NULL(callerNode);
806         DEBUG_ASSERT(callerNode->IsActualNode(), "must be ActualNode");
807         if ((i == callerCallSiteArg.size() - 1) && static_cast<EACGActualNode *>(callerNode)->IsReturn()) {
808             continue;
809         }
810         bool hasGlobalEA = false;
811         for (EACGObjectNode *obj : callerNode->GetPointsToSet()) {
812             if (obj->GetEAStatus() == kGlobalEscape) {
813                 hasGlobalEA = true;
814                 break;
815             }
816         }
817         if (hasGlobalEA) {
818             EACGBaseNode *calleeNode = (calleeFuncArg)[i];
819             for (EACGObjectNode *obj : calleeNode->GetPointsToSet()) {
820                 (void)obj->UpdateEAStatus(kGlobalEscape);
821             }
822         }
823     }
824     if (CGHasUpdated()) {
825         PropogateEAStatus();
826     }
827     TrimGlobalNode();
828 }
829 
DumpDotFile(const IRMap * irMap,bool dumpPt,MapleVector<EACGBaseNode * > * dumpVec)830 void EAConnectionGraph::DumpDotFile(const IRMap *irMap, bool dumpPt, MapleVector<EACGBaseNode *> *dumpVec)
831 {
832     if (dumpVec == nullptr) {
833         dumpVec = &nodes;
834     }
835     std::filebuf fb;
836     std::string outFile = GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) + "-connectiongraph.dot";
837     fb.open(outFile, std::ios::trunc | std::ios::out);
838     CHECK_FATAL(fb.is_open(), "open file failed");
839     std::ostream cgDotFile(&fb);
840     cgDotFile << "digraph connectiongraph{\n";
841     std::map<EACGBaseNode *, bool> dumped;
842     for (auto node : nodes) {
843         dumped[node] = false;
844     }
845     for (EACGBaseNode *node : *dumpVec) {
846         if (node == nullptr) {
847             continue;
848         }
849         if (dumped[node]) {
850             continue;
851         }
852         node->DumpDotFile(cgDotFile, dumped, dumpPt, irMap);
853         dumped[node] = true;
854     }
855     cgDotFile << "}\n";
856     fb.close();
857 }
858 
CountObjEAStatus() const859 void EAConnectionGraph::CountObjEAStatus() const
860 {
861     int sum = 0;
862     int eaCount[4] = {0};  // There are 4 EAStatus.
863     for (EACGBaseNode *node : nodes) {
864         if (node == nullptr) {
865             continue;
866         }
867 
868         if (node->IsObjectNode()) {
869             EACGObjectNode *objNode = static_cast<EACGObjectNode *>(node);
870             if (!objNode->IsPhantom()) {
871                 CHECK_FATAL(objNode->locInfo != nullptr, "Impossible");
872                 MIRType *type = nullptr;
873                 const MeExpr *expr = objNode->GetMeExpr();
874                 CHECK_FATAL(expr != nullptr, "Impossible");
875                 if (expr->GetOp() == OP_gcmalloc || expr->GetOp() == OP_gcpermalloc) {
876                     TyIdx tyIdx = static_cast<const GcmallocMeExpr *>(expr)->GetTyIdx();
877                     type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
878                 } else {
879                     TyIdx tyIdx = static_cast<const OpMeExpr *>(expr)->GetTyIdx();
880                     type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
881                 }
882                 LogInfo::MapleLogger() << "[LOCATION] [" << objNode->locInfo->GetModName() << " "
883                                        << objNode->locInfo->GetFileId() << " " << objNode->locInfo->GetLineId() << " "
884                                        << EscapeName(objNode->GetEAStatus()) << " " << expr->GetExprID() << " ";
885                 type->Dump(0, false);
886                 LogInfo::MapleLogger() << "]\n";
887                 ++sum;
888                 ++eaCount[node->GetEAStatus()];
889             }
890         }
891     }
892     LogInfo::MapleLogger() << "[gcmalloc object statistics]  "
893                            << GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) << " "
894                            << "Gcmallocs: " << sum << " "
895                            << "NoEscape: " << eaCount[kNoEscape] << " "
896                            << "RetEscape: " << eaCount[kReturnEscape] << " "
897                            << "ArgEscape: " << eaCount[kArgumentEscape] << " "
898                            << "GlobalEscape: " << eaCount[kGlobalEscape] << "\n";
899 }
900 
RestoreStatus(bool old)901 void EAConnectionGraph::RestoreStatus(bool old)
902 {
903     if (old) {
904         SetCGHasUpdated();
905     } else {
906         UnSetCGUpdateFlag();
907     }
908 }
909 
910 // Update caller's ConnectionGraph using callee's summary information.
911 // If the callee's summary is not found, we just mark all the pointsTo nodes of caller's actual node to GlobalEscape.
912 // Otherwise, we do these steps:
913 //
914 // 1, update caller nodes using callee's summary, new node might be added into caller's CG in this step.
915 //
916 // 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)917 bool EAConnectionGraph::MergeCG(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> *callee)
918 {
919     TrimGlobalNode();
920     bool cgChanged = false;
921     bool oldStatus = CGHasUpdated();
922     UnSetCGUpdateFlag();
923     if (callee == nullptr) {
924         for (EACGBaseNode *actualInCaller : caller) {
925             for (EACGObjectNode *p : actualInCaller->GetPointsToSet()) {
926                 (void)p->UpdateEAStatus(EAStatus::kGlobalEscape);
927             }
928         }
929         cgChanged = CGHasUpdated();
930         if (!cgChanged) {
931             RestoreStatus(oldStatus);
932         }
933         TrimGlobalNode();
934         return cgChanged;
935     }
936     size_t callerSize = caller.size();
937     size_t calleeSize = callee->size();
938     if (callerSize > calleeSize) {
939         DEBUG_ASSERT((callerSize - calleeSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
940     } else {
941         DEBUG_ASSERT((calleeSize - callerSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
942     }
943     if (callerSize == 0 || calleeSize == 0) {
944         cgChanged = CGHasUpdated();
945         if (!cgChanged) {
946             RestoreStatus(oldStatus);
947         }
948         return cgChanged;
949     }
950     if ((callerSize != calleeSize) &&
951         (callerSize != calleeSize + 1 || static_cast<EACGActualNode *>(callee->back())->IsReturn()) &&
952         (callerSize != calleeSize - 1 || !static_cast<EACGActualNode *>(callee->back())->IsReturn())) {
953         DEBUG_ASSERT(false, "Impossible");
954     }
955 
956     callee2Caller.clear();
957     UpdateCallerNodes(caller, *callee);
958     UpdateCallerEdges();
959     UpdateCallerRetNode(caller, *callee);
960     callee2Caller.clear();
961 
962     cgChanged = CGHasUpdated();
963     if (!cgChanged) {
964         RestoreStatus(oldStatus);
965     }
966     TrimGlobalNode();
967     return cgChanged;
968 }
969 
AddMaps2Object(EACGObjectNode * caller,EACGObjectNode * callee)970 void EAConnectionGraph::AddMaps2Object(EACGObjectNode *caller, EACGObjectNode *callee)
971 {
972     if (callee2Caller.find(callee) == callee2Caller.end()) {
973         std::set<EACGObjectNode *> callerSet;
974         callee2Caller[callee] = callerSet;
975     }
976     (void)callee2Caller[callee].insert(caller);
977 }
978 
UpdateCallerRetNode(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)979 void EAConnectionGraph::UpdateCallerRetNode(MapleVector<EACGBaseNode *> &caller,
980                                             const MapleVector<EACGBaseNode *> &callee)
981 {
982     EACGActualNode *lastInCaller = static_cast<EACGActualNode *>(caller.back());
983     EACGActualNode *lastInCallee = static_cast<EACGActualNode *>(callee.back());
984     if (!lastInCaller->IsReturn()) {
985         return;
986     }
987     CHECK_FATAL(lastInCaller->GetOutSet().size() == 1, "Impossible");
988     for (EACGBaseNode *callerRetNode : lastInCaller->GetOutSet()) {
989         for (EACGObjectNode *calleeRetNode : lastInCallee->GetPointsToSet()) {
990             for (EACGObjectNode *objInCaller : callee2Caller[calleeRetNode]) {
991                 auto pointsToSet = callerRetNode->GetPointsToSet();
992                 if (pointsToSet.find(objInCaller) == pointsToSet.end()) {
993                     (void)callerRetNode->AddOutNode(*objInCaller);
994                 }
995             }
996         }
997     }
998 }
999 
1000 // Update caller node by adding some nodes which are mapped from callee.
UpdateCallerNodes(const MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)1001 void EAConnectionGraph::UpdateCallerNodes(const MapleVector<EACGBaseNode *> &caller,
1002                                           const MapleVector<EACGBaseNode *> &callee)
1003 {
1004     const size_t callerSize = caller.size();
1005     const size_t calleeSize = callee.size();
1006     const size_t actualCount = ((callerSize < calleeSize) ? callerSize : calleeSize);
1007     bool firstTime = true;
1008 
1009     for (size_t i = 0; i < actualCount; ++i) {
1010         EACGBaseNode *actualInCaller = caller.at(i);
1011         EACGBaseNode *actualInCallee = callee.at(i);
1012         UpdateNodes(*actualInCallee, *actualInCaller, firstTime);
1013     }
1014 }
1015 
1016 // Update caller edges using information from callee.
UpdateCallerEdges()1017 void EAConnectionGraph::UpdateCallerEdges()
1018 {
1019     std::set<EACGObjectNode *> set;
1020     for (auto pair : callee2Caller) {
1021         (void)set.insert(pair.first);
1022     }
1023     for (EACGObjectNode *p : set) {
1024         for (auto tempPair : p->GetFieldNodeMap()) {
1025             int32 fieldID = tempPair.first;
1026             EACGBaseNode *fieldNode = tempPair.second;
1027             for (EACGObjectNode *q : fieldNode->GetPointsToSet()) {
1028                 UpdateCallerEdgesInternal(p, fieldID, q);
1029             }
1030         }
1031     }
1032 }
1033 
1034 // Update caller edges using information of given ObjectNode from callee.
UpdateCallerEdgesInternal(EACGObjectNode * node1,int32 fieldID,EACGObjectNode * node2)1035 void EAConnectionGraph::UpdateCallerEdgesInternal(EACGObjectNode *node1, int32 fieldID, EACGObjectNode *node2)
1036 {
1037     CHECK_FATAL(callee2Caller.find(node1) != callee2Caller.end(), "find failed");
1038     CHECK_FATAL(callee2Caller.find(node2) != callee2Caller.end(), "find failed");
1039     for (EACGObjectNode *p1 : callee2Caller[node1]) {
1040         for (EACGObjectNode *q1 : callee2Caller[node2]) {
1041             EACGFieldNode *fieldNode = p1->GetFieldNodeFromIdx(fieldID);
1042             if (fieldNode == nullptr) {
1043                 CHECK_NULL_FATAL(node1);
1044                 fieldNode = node1->GetFieldNodeFromIdx(fieldID);
1045                 CHECK_FATAL(fieldNode != nullptr, "fieldNode must not be nullptr because we have handled it before!");
1046                 CHECK_FATAL(fieldNode->IsBelongTo(this), "must be belong to this");
1047                 (void)p1->AddOutNode(*fieldNode);
1048             }
1049             (void)fieldNode->AddOutNode(*q1);
1050         }
1051     }
1052 }
1053 
UpdateNodes(const EACGBaseNode & actualInCallee,EACGBaseNode & actualInCaller,bool firstTime)1054 void EAConnectionGraph::UpdateNodes(const EACGBaseNode &actualInCallee, EACGBaseNode &actualInCaller, bool firstTime)
1055 {
1056     DEBUG_ASSERT(actualInCallee.GetPointsToSet().size() > 0, "actualInCallee->GetPointsToSet().size() must gt 0!");
1057     for (EACGObjectNode *objInCallee : actualInCallee.GetPointsToSet()) {
1058         if (actualInCaller.GetPointsToSet().size() == 0) {
1059             std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1060             if (mapsTo.size() > 0) {
1061                 for (EACGObjectNode *temp : mapsTo) {
1062                     (void)actualInCaller.AddOutNode(*temp);
1063                 }
1064             } else if (objInCallee->IsBelongTo(this)) {
1065                 DEBUG_ASSERT(false, "must be belong to this");
1066             } else {
1067                 EACGObjectNode *phantom = CreateObjectNode(nullptr, actualInCaller.GetEAStatus(), true, TyIdx(0));
1068                 (void)actualInCaller.AddOutNode(*phantom);
1069                 AddMaps2Object(phantom, objInCallee);
1070                 UpdateCallerWithCallee(*phantom, *objInCallee, firstTime);
1071             }
1072         } else {
1073             for (EACGObjectNode *objInCaller : actualInCaller.GetPointsToSet()) {
1074                 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1075                 if (mapsTo.find(objInCaller) == mapsTo.end()) {
1076                     AddMaps2Object(objInCaller, objInCallee);
1077                     UpdateCallerWithCallee(*objInCaller, *objInCallee, firstTime);
1078                 }
1079             }
1080         }
1081     }
1082 }
1083 
1084 // The escape state of the nodes in MapsTo(which is the object node in caller) is marked
1085 // GlobalEscape if the escape state of object node in callee is GlobalEscape.
1086 // Otherwise, the escape state of the caller nodes is not affected.
UpdateCallerWithCallee(EACGObjectNode & objInCaller,const EACGObjectNode & objInCallee,bool firstTime)1087 void EAConnectionGraph::UpdateCallerWithCallee(EACGObjectNode &objInCaller, const EACGObjectNode &objInCallee,
1088                                                bool firstTime)
1089 {
1090     if (objInCallee.GetEAStatus() == EAStatus::kGlobalEscape) {
1091         (void)objInCaller.UpdateEAStatus(EAStatus::kGlobalEscape);
1092     }
1093 
1094     // At this moment, a node in caller is mapped to the corresponding node in callee,
1095     // we need make sure that all the field nodes also exist in caller. If not,
1096     // we create both the field node and the phantom object node it should point to for the caller.
1097     for (auto tempPair : objInCallee.GetFieldNodeMap()) {
1098         EACGFieldNode *fieldInCaller = objInCaller.GetFieldNodeFromIdx(tempPair.first);
1099         EACGFieldNode *fieldInCallee = tempPair.second;
1100         if (fieldInCaller == nullptr && fieldInCallee->IsBelongTo(this)) {
1101             (void)objInCaller.AddOutNode(*fieldInCallee);
1102         }
1103         fieldInCaller = GetOrCreateFieldNodeFromIdx(objInCaller, tempPair.first);
1104         UpdateNodes(*fieldInCallee, *fieldInCaller, firstTime);
1105     }
1106 }
1107 
GetOrCreateFieldNodeFromIdx(EACGObjectNode & obj,int32 fieldID)1108 EACGFieldNode *EAConnectionGraph::GetOrCreateFieldNodeFromIdx(EACGObjectNode &obj, int32 fieldID)
1109 {
1110     EACGFieldNode *ret = obj.GetFieldNodeFromIdx(fieldID);
1111     if (ret == nullptr) {
1112         // this node is always phantom
1113         ret = CreateFieldNode(nullptr, obj.GetEAStatus(), fieldID, &obj, true);
1114     }
1115     return ret;
1116 }
1117 }  // namespace maple
1118