Index: tools/gcmole/gcmole.cc |
diff --git a/tools/gcmole/gcmole.cc b/tools/gcmole/gcmole.cc |
index 71ba24a33bf739526d79048cb35dd88ca64e1d9b..38ee6e07ef72209ee9159d517d529d15633cf265 100644 |
--- a/tools/gcmole/gcmole.cc |
+++ b/tools/gcmole/gcmole.cc |
@@ -69,6 +69,21 @@ static bool InV8Namespace(const clang::NamedDecl* decl) { |
} |
+static std::string EXTERNAL("EXTERNAL"); |
+static std::string STATE_TAG("enum v8::internal::StateTag"); |
+ |
+static bool IsExternalVMState(const clang::ValueDecl* var) { |
+ const clang::EnumConstantDecl* enum_constant = |
+ dyn_cast<clang::EnumConstantDecl>(var); |
+ if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) { |
+ clang::QualType type = enum_constant->getType(); |
+ return (type.getAsString() == STATE_TAG); |
+ } |
+ |
+ return false; |
+} |
+ |
+ |
struct Resolver { |
explicit Resolver(clang::ASTContext& ctx) |
: ctx_(ctx), decl_ctx_(ctx.getTranslationUnitDecl()) { |
@@ -121,6 +136,13 @@ class CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> { |
return true; |
} |
+ virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) { |
+ // If function mentions EXTERNAL VMState add artificial garbage collection |
+ // mark. |
+ if (IsExternalVMState(expr->getDecl())) AddCallee("CollectGarbage"); |
+ return true; |
+ } |
+ |
void AnalyzeFunction(const clang::FunctionDecl* f) { |
MangledName name; |
if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) { |
@@ -278,6 +300,10 @@ class ExprEffect { |
return reinterpret_cast<Environment*>(effect_ & ~kAllEffects); |
} |
+ static ExprEffect GC() { |
+ return ExprEffect(kCausesGC, NULL); |
+ } |
+ |
private: |
ExprEffect(int effect, Environment* env) |
: effect_((effect & kAllEffects) | |
@@ -790,6 +816,9 @@ class FunctionAnalyzer { |
ExprEffect Use(const clang::Expr* parent, |
const clang::ValueDecl* var, |
const Environment& env) { |
+ if (IsExternalVMState(var)) { |
+ return ExprEffect::GC(); |
+ } |
return Use(parent, var->getType(), var->getNameAsString(), env); |
} |