Commit 87bc38e3 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[gcmole] Fix false negatives with GC guards

GCMole mistakenly thought that GC guards such as DisallowHeapAllocation
covered the whole scope of the function they are declared in. This CL
fixes the false negatives and adds appropriate testing.

Bug: v8:10071
Change-Id: Iffb369977af90ca053a55ca8f451e037a4f460f2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497451
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70763}
parent 2361c7c6
...@@ -216,5 +216,18 @@ void TestNestedDeadVarAnalysis(Isolate* isolate) { ...@@ -216,5 +216,18 @@ void TestNestedDeadVarAnalysis(Isolate* isolate) {
raw_obj.Print(); raw_obj.Print();
} }
// Test that putting a guard in the middle of the function doesn't
// mistakenly cover the whole scope of the raw variable.
void TestGuardedDeadVarAnalysisMidFunction(Isolate* isolate) {
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
CauseGCRaw(raw_obj, isolate);
// Guarding the rest of the function from triggering a GC.
DisallowHeapAllocation no_gc;
// Should cause warning.
raw_obj.Print();
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
7736018d2ca616f7c1477102cc169ee579ee6003 7e31d257a711b1a77823633e4f19152c3e0718f4
...@@ -1067,6 +1067,8 @@ class FunctionAnalyzer { ...@@ -1067,6 +1067,8 @@ class FunctionAnalyzer {
if (callee != NULL) { if (callee != NULL) {
if (KnownToCauseGC(ctx_, callee)) { if (KnownToCauseGC(ctx_, callee)) {
out.setGC(); out.setGC();
scopes_.back().SetGCCauseLocation(
clang::FullSourceLoc(call->getExprLoc(), sm_));
} }
// Support for virtual methods that might be GC suspects. // Support for virtual methods that might be GC suspects.
...@@ -1081,6 +1083,8 @@ class FunctionAnalyzer { ...@@ -1081,6 +1083,8 @@ class FunctionAnalyzer {
if (target != NULL) { if (target != NULL) {
if (KnownToCauseGC(ctx_, target)) { if (KnownToCauseGC(ctx_, target)) {
out.setGC(); out.setGC();
scopes_.back().SetGCCauseLocation(
clang::FullSourceLoc(call->getExprLoc(), sm_));
} }
} else { } else {
// According to the documentation, {getDevirtualizedMethod} might // According to the documentation, {getDevirtualizedMethod} might
...@@ -1089,6 +1093,8 @@ class FunctionAnalyzer { ...@@ -1089,6 +1093,8 @@ class FunctionAnalyzer {
// to increase coverage. // to increase coverage.
if (SuspectedToCauseGC(ctx_, method)) { if (SuspectedToCauseGC(ctx_, method)) {
out.setGC(); out.setGC();
scopes_.back().SetGCCauseLocation(
clang::FullSourceLoc(call->getExprLoc(), sm_));
} }
} }
} }
...@@ -1244,7 +1250,7 @@ class FunctionAnalyzer { ...@@ -1244,7 +1250,7 @@ class FunctionAnalyzer {
} }
DECL_VISIT_STMT(CompoundStmt) { DECL_VISIT_STMT(CompoundStmt) {
scopes_.push_back(GCGuard(stmt, false)); scopes_.push_back(GCScope());
Environment out = env; Environment out = env;
clang::CompoundStmt::body_iterator end = stmt->body_end(); clang::CompoundStmt::body_iterator end = stmt->body_end();
for (clang::CompoundStmt::body_iterator s = stmt->body_begin(); for (clang::CompoundStmt::body_iterator s = stmt->body_begin();
...@@ -1422,7 +1428,8 @@ class FunctionAnalyzer { ...@@ -1422,7 +1428,8 @@ class FunctionAnalyzer {
out = out.Define(var->getNameAsString()); out = out.Define(var->getNameAsString());
} }
if (IsGCGuard(var->getType())) { if (IsGCGuard(var->getType())) {
scopes_.back().has_guard = true; scopes_.back().guard_location =
clang::FullSourceLoc(decl->getLocation(), sm_);
} }
return out; return out;
...@@ -1477,7 +1484,7 @@ class FunctionAnalyzer { ...@@ -1477,7 +1484,7 @@ class FunctionAnalyzer {
bool HasActiveGuard() { bool HasActiveGuard() {
for (auto s : scopes_) { for (auto s : scopes_) {
if (s.has_guard) return true; if (s.IsBeforeGCCause()) return true;
} }
return false; return false;
} }
...@@ -1503,14 +1510,26 @@ class FunctionAnalyzer { ...@@ -1503,14 +1510,26 @@ class FunctionAnalyzer {
Block* block_; Block* block_;
struct GCGuard { struct GCScope {
clang::CompoundStmt* stmt = NULL; clang::FullSourceLoc guard_location;
bool has_guard = false; clang::FullSourceLoc gccause_location;
GCGuard(clang::CompoundStmt* stmt_, bool has_guard_) // We're only interested in guards that are declared before any further GC
: stmt(stmt_), has_guard(has_guard_) {} // causing calls (see TestGuardedDeadVarAnalysisMidFunction for example).
bool IsBeforeGCCause() {
if (!guard_location.isValid()) return false;
if (!gccause_location.isValid()) return true;
return guard_location.isBeforeInTranslationUnitThan(gccause_location);
}
// After we set the first GC cause in the scope, we don't need the later
// ones.
void SetGCCauseLocation(clang::FullSourceLoc gccause_location_) {
if (gccause_location.isValid()) return;
gccause_location = gccause_location_;
}
}; };
std::vector<GCGuard> scopes_; std::vector<GCScope> scopes_;
}; };
class ProblemsFinder : public clang::ASTConsumer, class ProblemsFinder : public clang::ASTConsumer,
......
...@@ -32,4 +32,7 @@ tools/gcmole/gcmole-test.cc:193:3: warning: Possibly dead variable. ...@@ -32,4 +32,7 @@ tools/gcmole/gcmole-test.cc:193:3: warning: Possibly dead variable.
tools/gcmole/gcmole-test.cc:216:3: warning: Possibly dead variable. tools/gcmole/gcmole-test.cc:216:3: warning: Possibly dead variable.
raw_obj.Print(); raw_obj.Print();
^ ^
11 warnings generated. tools/gcmole/gcmole-test.cc:229:3: warning: Possibly dead variable.
raw_obj.Print();
^
12 warnings generated.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment