In gcmole assume that methods exiting VM can cause GC.
authorvegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Feb 2012 11:34:50 +0000 (11:34 +0000)
committervegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Feb 2012 11:34:50 +0000 (11:34 +0000)
Detect those methods by reference to StateTag::EXTERNAL in their bodies.

R=fschneider@google.com

Review URL: https://chromiumcodereview.appspot.com/9420046

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10738 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

tools/gcmole/gcmole.cc
tools/gcmole/gcmole.lua

index 71ba24a..38ee6e0 100644 (file)
@@ -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);
   }
 
index f8d3b62..09db547 100644 (file)
@@ -106,7 +106,6 @@ function InvokeClangPluginForEachFile(filenames, cfg, func)
                                          cfg.plugin_args,
                                          cfg.triple,
                                          cfg.arch_define)
-
    for _, filename in ipairs(filenames) do
       log("-- %s", filename)
       local action = cmd_line .. " src/" .. filename .. " 2>&1"
@@ -218,7 +217,13 @@ local WHITELIST = {
    --      Callsites of such functions are safe as long as they are properly 
    --      check return value and propagate the Failure to the caller.
    --      It should be possible to extend GCMole to understand this.
-   "Heap.*AllocateFunctionPrototype"
+   "Heap.*AllocateFunctionPrototype",
+
+   -- Ignore all StateTag methods.
+   "StateTag",
+
+   -- Ignore printing of elements transition.
+   "PrintElementsTransition"
 };
 
 local function AddCause(name, cause)