Make JsInliner avoid inlining pinned methods.

At the Java AST level some methods might be pinned (e.g. the ones
appearing in Impl.getNameOf()) and those should not be inlined
by the JsInliner.

Change-Id: I74ccf8cdc078b07109e029d77b84fff89a9cacae
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index a8cd0aa..af202f4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -359,14 +359,14 @@
   /**
    * Returns true if the inliner should try to inline {@code method}.
    */
-  public boolean allowInliningOf(JMethod method) {
+  public boolean isInliningAllowed(JMethod method) {
     return !pinnedMethods.contains(method);
   }
 
   /**
    * Returns true if {@link MakeCallsStatic} should try to statify {@code method}.
    */
-  public boolean allowStatificationOf(JMethod method) {
+  public boolean isDevitualizationAllowed(JMethod method) {
     return !pinnedMethods.contains(method);
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index af6aa40..a9da6fe 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1261,6 +1261,10 @@
 
       JsFunction jsFunc = pop(); // body
 
+      if (!program.isInliningAllowed(x)) {
+        jsProgram.disallowInlining(jsFunc);
+      }
+
       // Collect the resulting function to be considered by the JsInliner.
       if (methodsForJsInlining.contains(x)) {
         functionsForJsInlining.add(jsFunc);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 83dac4a..d9b2d2b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -256,7 +256,7 @@
         return false;
       }
 
-      if (!program.allowStatificationOf(method)) {
+      if (!program.isDevitualizationAllowed(method)) {
         // Method has been specifically excluded from statification.
         return false;
       }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
index b3ccbc8..f1b327f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
@@ -123,7 +123,7 @@
         return false;
       }
 
-      if (!program.allowInliningOf(method)) {
+      if (!program.isInliningAllowed(method)) {
         return false;
       }
 
diff --git a/dev/core/src/com/google/gwt/dev/js/JsInliner.java b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
index 97c06a6..53763bb 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsInliner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
@@ -868,9 +868,12 @@
      */
     private JsFunction programFunction;
 
+    private JsProgram program;
+
     public InliningVisitor(JsProgram program, Set<JsNode> whitelist) {
-      invocationCountingVisitor.accept(program);
+      this.program = program;
       this.whitelist = whitelist;
+      invocationCountingVisitor.accept(program);
     }
 
     /**
@@ -998,6 +1001,10 @@
         return;
       }
 
+      if (!program.isInliningAllowed(invokedFunction)) {
+        return;
+      }
+
       /*
        * Don't inline huge functions into huge multi-expressions. Some JS
        * engines will blow up.
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
index 5a8398b..0765451 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
@@ -17,6 +17,7 @@
 import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.SourceOrigin;
+import com.google.gwt.thirdparty.guava.common.collect.Sets;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -38,6 +39,8 @@
 
   private final Set<JsFunction> indexedFunctionSet = new HashSet<JsFunction>();
 
+  private final Set<JsFunction> preventInliningOf = Sets.newHashSet();
+
   private final JsScope objectScope;
 
   private final JsScope topScope;
@@ -143,6 +146,14 @@
     this.indexedFunctionSet.addAll(indexedFunctions.values());
   }
 
+  public void disallowInlining(JsFunction function) {
+    preventInliningOf.add(function);
+  }
+
+  public boolean isInliningAllowed(JsFunction function) {
+    return !preventInliningOf.contains(function);
+  }
+
   @Override
   public void traverse(JsVisitor v, JsContext ctx) {
     if (v.visit(this, ctx)) {
diff --git a/user/src/com/google/gwt/core/client/impl/Impl.java b/user/src/com/google/gwt/core/client/impl/Impl.java
index d1bab4c..f8358f8 100644
--- a/user/src/com/google/gwt/core/client/impl/Impl.java
+++ b/user/src/com/google/gwt/core/client/impl/Impl.java
@@ -158,9 +158,9 @@
   }-*/;
 
   /**
-   * Returns the obfuscated name of members in the compiled output. This is a
-   * thin wrapper around JNameOf AST nodes and is therefore meaningless to
-   * implement in Development Mode.
+   * Returns the obfuscated name of members in the compiled output. This is a thin wrapper around
+   * JNameOf AST nodes and is therefore meaningless to implement in Development Mode.
+   * If the requested member is a method, the method will not be devirtualized, inlined or prunned.
    *
    * @param jsniIdent a string literal specifying a type, field, or method. Raw
    *          type names may also be used to obtain the name of the type's seed
diff --git a/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java b/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java
index 3973fcb..306973d 100644
--- a/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java
+++ b/user/test/com/google/gwt/core/client/impl/StackTraceCreatorTest.java
@@ -151,20 +151,14 @@
   }
 
   private static void throwException1(boolean throwNative) throws Throwable {
-    if (Math.abs(Math.random()) < 0) { return; } // Dummy code to prevent inlining
-
     throwException2(throwNative);
   }
 
   private static void throwException2(boolean throwNative) throws Throwable {
-    if (Math.abs(Math.random()) < 0) { return; } // Dummy code to prevent inlining
-
     throwException3(throwNative);
   }
 
   private static void throwException3(boolean throwNative) throws Throwable {
-    if (Math.abs(Math.random()) < 0) { return; } // Dummy code to prevent inlining
-
     if (throwNative) {
       throwNative(true /* really throw exception */);
     } else {