SOYC work to pass the caller's class into calls to SourceInfo.makeChild() and J(s)Program.createSourceInfoSynthetic().

Patch by: bobv
Review by: kprobst, spoon


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3772 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
index 6d16a2e..fbc9675 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardLinkerContext.java
@@ -338,7 +338,8 @@
     funcName.setObfuscatable(false);
 
     try {
-      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic("Linker-derived JS");
+      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(
+          StandardLinkerContext.class, "Linker-derived JS");
       parser.setSourceInfo(sourceInfo);
       parser.parseInto(topScope, jsProgram.getGlobalBlock(), r, 1);
     } catch (IOException e) {
diff --git a/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java b/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
index 50411c5..ddb7c7b 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
@@ -53,8 +53,9 @@
       JsProgram jsPgm = new JsProgram();
       JsParser jsParser = new JsParser();
       StringReader r = new StringReader(jsniSrc);
-      jsParser.setSourceInfo(jsPgm.createSourceInfoSynthetic("Default property provider for "
-          + getProperty().getName()));
+      jsParser.setSourceInfo(jsPgm.createSourceInfoSynthetic(
+          DefaultPropertyProvider.class, "Default property provider for "
+              + getProperty().getName()));
       List<JsStatement> stmts = jsParser.parse(jsPgm.getScope(), r, 1);
       JsFunction fn = (JsFunction) ((JsExprStmt) stmts.get(0)).getExpression();
       return fn.getBody();
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
index 81effa0..2477a25 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
@@ -1006,7 +1006,8 @@
     List<JsStatement> stmts;
     try {
       // TODO Provide more context here
-      jsParser.setSourceInfo(jsPgm.createSourceInfoSynthetic("Module.xml"));
+      jsParser.setSourceInfo(jsPgm.createSourceInfoSynthetic(
+          ModuleDefSchema.class, "Module.xml"));
       stmts = jsParser.parse(jsPgm.getScope(), r, startLineNumber);
     } catch (IOException e) {
       logger.log(TreeLogger.ERROR, "Error reading script source", e);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 2c57e5c..edf1d27 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -129,7 +129,7 @@
     }
 
     SourceInfo sourceInfo = reboundEntryType.getSourceInfo().makeChild(
-        "Rebound entry point");
+        JavaToJavaScriptCompiler.class, "Rebound entry point");
     JExpression qualifier = null;
     if (!entryMethod.isStatic()) {
       qualifier = JGwtCreate.createInstantiationExpression(program, sourceInfo,
@@ -152,9 +152,10 @@
       RebindPermutationOracle rpo, String[] mainClassNames, JProgram program)
       throws UnableToCompleteException {
     JMethod bootStrapMethod = program.createMethod(
-        program.createSourceInfoSynthetic("Bootstrap method"),
-        "init".toCharArray(), program.getIndexedType("EntryMethodHolder"),
-        program.getTypeVoid(), false, true, true, false, false);
+        program.createSourceInfoSynthetic(JavaToJavaScriptCompiler.class,
+            "Bootstrap method"), "init".toCharArray(),
+        program.getIndexedType("EntryMethodHolder"), program.getTypeVoid(),
+        false, true, true, false, false);
     bootStrapMethod.freezeParamTypes();
 
     JMethodBody body = (JMethodBody) bootStrapMethod.getBody();
@@ -247,7 +248,8 @@
    */
   private static JStatement makeStatsCalls(JProgram program,
       String mainClassName) {
-    SourceInfo sourceInfo = program.createSourceInfoSynthetic("onModuleStart() stats call");
+    SourceInfo sourceInfo = program.createSourceInfoSynthetic(
+        JavaToJavaScriptCompiler.class, "onModuleStart() stats call");
     JMethod isStatsAvailableMethod = program.getIndexedMethod("Stats.isStatsAvailable");
     JMethod onModuleStartMethod = program.getIndexedMethod("Stats.onModuleStart");
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java b/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
index cd5c570..c8d9e9b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/SourceInfo.java
@@ -106,7 +106,7 @@
   private final EnumMap<Axis, Correlation> correlations = new EnumMap<Axis, Correlation>(
       Axis.class);
   /**
-   * This flag controls the behavior of {@link #makeChild(String)}.
+   * This flag controls the behavior of {@link #makeChild}.
    */
   private final boolean createDescendants;
   private final int endPos;
@@ -364,10 +364,12 @@
     }
 
     Set<Correlation> allCorrelations = getAllCorrelations();
+    Set<Correlation> primaryCorrelations = getPrimaryCorrelations();
     if (!allCorrelations.isEmpty()) {
       toReturn.append("\nCorrelations:\n");
       for (Correlation c : allCorrelations) {
-        toReturn.append("  " + c + "\n");
+        toReturn.append((primaryCorrelations.contains(c) ? " *" : "  ") + c
+            + "\n");
       }
     }
 
@@ -416,8 +418,8 @@
    * Create a derived SourceInfo object. If SourceInfo collection is disabled,
    * this method will return the current object.
    */
-  public SourceInfo makeChild(String description) {
-    return makeChild(description, EMPTY_SOURCEINFO_ARRAY);
+  public SourceInfo makeChild(Class<?> caller, String description) {
+    return makeChild(caller, description, EMPTY_SOURCEINFO_ARRAY);
   }
 
   /**
@@ -425,15 +427,14 @@
    * nodes were merged to create a new node. The derived node will inherit its
    * location from the SourceInfo object on which the method is invoked.
    */
-  public SourceInfo makeChild(String description,
+  public SourceInfo makeChild(Class<?> caller, String description,
       SourceInfo... additionalAncestors) {
     if (!createDescendants) {
       return this;
     }
 
-    // TODO : Force the caller to be passed in
-    return new SourceInfo(this, description, "Unrecorded caller",
-        additionalAncestors);
+    String callerName = caller == null ? "Unrecorded caller" : caller.getName();
+    return new SourceInfo(this, description, callerName, additionalAncestors);
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
index 78688e6..0ac6def 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
@@ -35,8 +35,8 @@
    * These are only supposed to be constructed by JProgram.
    */
   JArrayType(JProgram program, JType leafType, int dims) {
-    super(program, leafType.getSourceInfo().makeChild("Array type"), calcName(
-        leafType, dims), false, false);
+    super(program, leafType.getSourceInfo().makeChild(JArrayType.class,
+        "Array type"), calcName(leafType, dims), false, false);
     this.leafType = leafType;
     this.dims = dims;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
index 761bd2e..7126366 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
@@ -38,12 +38,16 @@
     } else {
       this.program = program;
     }
-    
+
     if (info != null) {
       this.info = info;
     } else {
-      // This indicates a deficiency in the compiler
-      this.info = SourceInfo.UNKNOWN.makeChild("Unknown "
+      /*
+       * This indicates a deficiency in the compiler. We use getClass() instead
+       * of the usual class literal to figure out what kind of thing was being
+       * constructed.
+       */
+      this.info = SourceInfo.UNKNOWN.makeChild(getClass(), "Unknown "
           + getClass().getSimpleName());
     }
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
index efa30c3..903897c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
@@ -28,8 +28,8 @@
    */
   JPrimitiveType(JProgram program, String name, String signatureName,
       String wrapperTypeName, JLiteral defaultValue) {
-    super(program, program.createSourceInfoSynthetic(name + " primitive type"),
-        name, defaultValue);
+    super(program, program.createSourceInfoSynthetic(JPrimitiveType.class, name
+        + " primitive type"), name, defaultValue);
     this.signatureName = signatureName;
     this.wrapperTypeName = wrapperTypeName;
   }
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 20c5f13..d8d528c 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
@@ -186,25 +186,25 @@
   private List<JsonObject> jsonTypeTable;
 
   private final JAbsentArrayDimension literalAbsentArrayDim = new JAbsentArrayDimension(
-      this, createSourceInfoSynthetic("Absent array dimension"));
+      this, createSourceInfoSynthetic(JProgram.class, "Absent array dimension"));
 
   private final JBooleanLiteral literalFalse = new JBooleanLiteral(this,
-      createSourceInfoSynthetic("false literal"), false);
+      createSourceInfoSynthetic(JProgram.class, "false literal"), false);
 
   private final JIntLiteral literalIntNegOne = new JIntLiteral(this,
-      createSourceInfoSynthetic("-1 literal"), -1);
+      createSourceInfoSynthetic(JProgram.class, "-1 literal"), -1);
 
   private final JIntLiteral literalIntOne = new JIntLiteral(this,
-      createSourceInfoSynthetic("1 literal"), 1);
+      createSourceInfoSynthetic(JProgram.class, "1 literal"), 1);
 
   private final JIntLiteral literalIntZero = new JIntLiteral(this,
-      createSourceInfoSynthetic("0 literal"), 0);
+      createSourceInfoSynthetic(JProgram.class, "0 literal"), 0);
 
   private final JNullLiteral literalNull = new JNullLiteral(this,
-      createSourceInfoSynthetic("null literal"));
+      createSourceInfoSynthetic(JProgram.class, "null literal"));
 
   private final JBooleanLiteral literalTrue = new JBooleanLiteral(this,
-      createSourceInfoSynthetic("true literal"), true);
+      createSourceInfoSynthetic(JProgram.class, "true literal"), true);
 
   private JField nullField;
 
@@ -251,7 +251,7 @@
   private final Map<String, JReferenceType> typeNameMap = new HashMap<String, JReferenceType>();
 
   private final JNullType typeNull = new JNullType(this,
-      createSourceInfoSynthetic("null type"));
+      createSourceInfoSynthetic(JProgram.class, "null type"));
 
   private final JPrimitiveType typeShort = new JPrimitiveType(this, "short",
       "S", "java.lang.Short", literalIntZero);
@@ -266,7 +266,8 @@
       "java.lang.Void", null);
 
   public JProgram() {
-    super(null, SourceInfoJava.INTRINSIC.makeChild("Top-level program"));
+    super(null, SourceInfoJava.INTRINSIC.makeChild(JProgram.class,
+        "Top-level program"));
   }
 
   public void addEntryMethod(JMethod entryPoint) {
@@ -466,9 +467,9 @@
    * Create a SourceInfo object when the source is created by the compiler
    * itself.
    */
-  public SourceInfo createSourceInfoSynthetic(String description) {
-    // TODO : Force the caller to be passed in
-    return createSourceInfo(0, "Synthetic").makeChild(description);
+  public SourceInfo createSourceInfoSynthetic(Class<?> caller,
+      String description) {
+    return createSourceInfo(0, caller.getName()).makeChild(caller, description);
   }
 
   public JReferenceType generalizeTypes(
@@ -549,7 +550,8 @@
 
   public JCharLiteral getLiteralChar(char c) {
     // could be interned
-    return new JCharLiteral(this, createSourceInfoSynthetic(c + " literal"), c);
+    return new JCharLiteral(this, createSourceInfoSynthetic(JProgram.class, c
+        + " literal"), c);
   }
 
   /**
@@ -587,9 +589,8 @@
           0).getBody();
       clinitBody.getStatements().add(decl);
 
-      classLiteral = new JClassLiteral(this,
-          createSourceInfoSynthetic("class literal for " + type.getName()),
-          type, field);
+      classLiteral = new JClassLiteral(this, createSourceInfoSynthetic(
+          JProgram.class, "class literal for " + type.getName()), type, field);
       classLiterals.put(type, classLiteral);
     } else {
       // Make sure the field hasn't been pruned.
@@ -609,18 +610,20 @@
    */
   public JClassSeed getLiteralClassSeed(JClassType type) {
     // could be interned
-    return new JClassSeed(this, createSourceInfoSynthetic("class seed"), type);
+    return new JClassSeed(this, createSourceInfoSynthetic(JProgram.class,
+        "class seed"), type);
   }
 
   public JDoubleLiteral getLiteralDouble(double d) {
     // could be interned
-    return new JDoubleLiteral(this, createSourceInfoSynthetic(d + " literal"),
-        d);
+    return new JDoubleLiteral(this, createSourceInfoSynthetic(JProgram.class, d
+        + " literal"), d);
   }
 
   public JFloatLiteral getLiteralFloat(float f) {
     // could be interned
-    return new JFloatLiteral(this, createSourceInfoSynthetic(f + " literal"), f);
+    return new JFloatLiteral(this, createSourceInfoSynthetic(JProgram.class, f
+        + " literal"), f);
   }
 
   public JIntLiteral getLiteralInt(int i) {
@@ -633,13 +636,14 @@
         return literalIntOne;
       default:
         // could be interned
-        return new JIntLiteral(this, createSourceInfoSynthetic(i + " literal"),
-            i);
+        return new JIntLiteral(this, createSourceInfoSynthetic(JProgram.class,
+            i + " literal"), i);
     }
   }
 
   public JLongLiteral getLiteralLong(long l) {
-    return new JLongLiteral(this, createSourceInfoSynthetic(l + " literal"), l);
+    return new JLongLiteral(this, createSourceInfoSynthetic(JProgram.class, l
+        + " literal"), l);
   }
 
   public JNullLiteral getLiteralNull() {
@@ -658,16 +662,17 @@
 
   public JField getNullField() {
     if (nullField == null) {
-      nullField = new JField(this, createSourceInfoSynthetic("Null field"),
-          "nullField", null, typeNull, false, Disposition.FINAL);
+      nullField = new JField(this, createSourceInfoSynthetic(JProgram.class,
+          "Null field"), "nullField", null, typeNull, false, Disposition.FINAL);
     }
     return nullField;
   }
 
   public JMethod getNullMethod() {
     if (nullMethod == null) {
-      nullMethod = new JMethod(this, createSourceInfoSynthetic("Null method"),
-          "nullMethod", null, typeNull, false, false, true, true);
+      nullMethod = new JMethod(this, createSourceInfoSynthetic(JProgram.class,
+          "Null method"), "nullMethod", null, typeNull, false, false, true,
+          true);
     }
     return nullMethod;
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index 86d1727..baddacc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -138,7 +138,8 @@
     private void processDims(JNewArray x, Context ctx, JArrayType arrayType,
         int dims) {
       // override the type of the called method with the array's type
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("Creating dimensions");
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          ArrayVisitor.class, "Creating dimensions");
       JMethodCall call = new JMethodCall(program, sourceInfo, null, initDims,
           arrayType);
       JsonArray classLitList = new JsonArray(program, sourceInfo);
@@ -174,9 +175,10 @@
     private void processInitializers(JNewArray x, Context ctx,
         JArrayType arrayType) {
       // override the type of the called method with the array's type
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("Array initializer");
-      JMethodCall call = new JMethodCall(program, sourceInfo, null,
-          initValues, arrayType);
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          ArrayVisitor.class, "Array initializer");
+      JMethodCall call = new JMethodCall(program, sourceInfo, null, initValues,
+          arrayType);
       JLiteral classLit = x.getClassLiteral();
       JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
       JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index fd333b0..7771dfe 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -361,7 +361,7 @@
         JReferenceType enclosingType) {
       JType type = (JType) typeMap.get(binding.type);
       SourceInfo info = enclosingType.getSourceInfo().makeChild(
-          "Field " + String.valueOf(binding.name));
+          BuildDeclMapVisitor.class, "Field " + String.valueOf(binding.name));
       JField field = program.createField(info, binding.name, enclosingType,
           type, false, Disposition.FINAL);
       info.addCorrelation(Correlation.by(field));
@@ -386,8 +386,9 @@
         String argName, JMethod enclosingMethod) {
       JType type = (JType) typeMap.get(arg.type);
       JParameter param = program.createParameter(
-          enclosingMethod.getSourceInfo().makeChild("Parameter " + argName),
-          argName.toCharArray(), type, true, false, enclosingMethod);
+          enclosingMethod.getSourceInfo().makeChild(BuildTypeMap.class,
+              "Parameter " + argName), argName.toCharArray(), type, true,
+          false, enclosingMethod);
       return param;
     }
 
@@ -408,17 +409,18 @@
 
       // Define the method
       JMethod synthetic = program.createMethod(type.getSourceInfo().makeChild(
-          "Synthetic constructor"), "new".toCharArray(), type, type, false,
-          true, true, false, false);
+          BuildDeclMapVisitor.class, "Synthetic constructor"),
+          "new".toCharArray(), type, type, false, true, true, false, false);
 
       // new Foo() : Create the instance
       JNewInstance newInstance = new JNewInstance(program,
-          type.getSourceInfo().makeChild("new instance"), type);
+          type.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+              "new instance"), type);
 
       // (new Foo()).Foo() : Invoke the constructor method on the instance
       JMethodCall call = new JMethodCall(program,
-          type.getSourceInfo().makeChild("constructor invocation"),
-          newInstance, constructor);
+          type.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+              "constructor invocation"), newInstance, constructor);
       List<JExpression> args = call.getArgs();
 
       /*
@@ -429,8 +431,9 @@
       JParameter enclosingInstance = null;
       if (!staticClass) {
         enclosingInstance = program.createParameter(
-            synthetic.getSourceInfo().makeChild("outer instance"),
-            "this$outer".toCharArray(), enclosingType, false, false, synthetic);
+            synthetic.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+                "outer instance"), "this$outer".toCharArray(), enclosingType,
+            false, false, synthetic);
       }
 
       /*
@@ -445,16 +448,17 @@
          */
         if (enclosingInstance != null && !i.hasNext()) {
           args.add(new JParameterRef(program,
-              synthetic.getSourceInfo().makeChild("enclosing instance"),
-              enclosingInstance));
+              synthetic.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+                  "enclosing instance"), enclosingInstance));
         } else {
           JParameter syntheticParam = program.createParameter(
-              synthetic.getSourceInfo().makeChild("Argument " + param.getName()),
+              synthetic.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+                  "Argument " + param.getName()),
               param.getName().toCharArray(), param.getType(), true, false,
               synthetic);
           args.add(new JParameterRef(program,
-              syntheticParam.getSourceInfo().makeChild("reference"),
-              syntheticParam));
+              syntheticParam.getSourceInfo().makeChild(
+                  BuildDeclMapVisitor.class, "reference"), syntheticParam));
         }
       }
 
@@ -463,7 +467,8 @@
 
       // return (new Foo()).Foo() : The only statement in the function
       JReturnStatement ret = new JReturnStatement(program,
-          synthetic.getSourceInfo().makeChild("Return statement"), call);
+          synthetic.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+              "Return statement"), call);
 
       // Add the return statement to the method body
       JMethodBody body = (JMethodBody) synthetic.getBody();
@@ -578,9 +583,9 @@
             && type != program.getTypeJavaLangObject()
             && type != program.getIndexedType("Array")) {
           JMethod getClassMethod = program.createMethod(
-              type.getSourceInfo().makeChild("Synthetic getClass()"),
-              "getClass".toCharArray(), type, program.getTypeJavaLangClass(),
-              false, false, false, false, false);
+              type.getSourceInfo().makeChild(BuildDeclMapVisitor.class,
+                  "Synthetic getClass()"), "getClass".toCharArray(), type,
+              program.getTypeJavaLangClass(), false, false, false, false, false);
           assert (type.methods.get(2) == getClassMethod);
           getClassMethod.freezeParamTypes();
         }
@@ -655,8 +660,9 @@
             assert newMethod.getName().equals("valueOf");
             assert typeMap.get(parameters[0]) == program.getTypeJavaLangString();
             program.createParameter(newMethod.getSourceInfo().makeChild(
-                "name parameter"), "name".toCharArray(),
-                program.getTypeJavaLangString(), true, false, newMethod);
+                BuildDeclMapVisitor.class, "name parameter"),
+                "name".toCharArray(), program.getTypeJavaLangString(), true,
+                false, newMethod);
           } else {
             assert false;
           }
@@ -908,15 +914,17 @@
          * more like output JavaScript. Clinit is always in slot 0, init (if it
          * exists) is always in slot 1.
          */
-        JMethod clinit = program.createMethod(
-            info.makeChild("Class initializer"), "$clinit".toCharArray(),
-            newType, program.getTypeVoid(), false, true, true, true, false);
+        JMethod clinit = program.createMethod(info.makeChild(
+            BuildTypeMapVisitor.class, "Class initializer"),
+            "$clinit".toCharArray(), newType, program.getTypeVoid(), false,
+            true, true, true, false);
         clinit.freezeParamTypes();
 
         if (newType instanceof JClassType) {
-          JMethod init = program.createMethod(
-              info.makeChild("Instance initializer"), "$init".toCharArray(),
-              newType, program.getTypeVoid(), false, false, true, true, false);
+          JMethod init = program.createMethod(info.makeChild(
+              BuildTypeMapVisitor.class, "Instance initializer"),
+              "$init".toCharArray(), newType, program.getTypeVoid(), false,
+              false, true, true, false);
           init.freezeParamTypes();
         }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index 8514ba0..b1f061c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -104,7 +104,8 @@
       // the 0th entry is the "always false" entry
       classes.add(null);
       jsonObjects.add(new JsonObject(program,
-          program.createSourceInfoSynthetic("always-false typeinfo entry")));
+          program.createSourceInfoSynthetic(AssignTypeIdsVisitor.class,
+              "always-false typeinfo entry")));
 
       /*
        * Do String first to reserve typeIds 1 and 2 for Object and String,
@@ -258,7 +259,8 @@
       }
 
       // Create a sparse lookup object.
-      SourceInfo sourceInfo = program.createSourceInfoSynthetic("typeinfo lookup");
+      SourceInfo sourceInfo = program.createSourceInfoSynthetic(
+          AssignTypeIdsVisitor.class, "typeinfo lookup");
       JsonObject jsonObject = new JsonObject(program, sourceInfo);
       // Start at 1; 0 is Object and always true.
       for (int i = 1; i < nextQueryId; ++i) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index ef50130..81370c1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -666,8 +666,9 @@
       if (lhs instanceof JValueLiteral && rhs instanceof JValueLiteral) {
         Object lhsObj = ((JValueLiteral) lhs).getValueObj();
         Object rhsObj = ((JValueLiteral) rhs).getValueObj();
-        ctx.replaceMe(program.getLiteralString(lhs.getSourceInfo().makeChild(
-            "String concatenation", rhs.getSourceInfo()),
+        ctx.replaceMe(program.getLiteralString(
+            lhs.getSourceInfo().makeChild(DeadCodeVisitor.class,
+                "String concatenation", rhs.getSourceInfo()),
             String.valueOf(lhsObj) + String.valueOf(rhsObj)));
       }
     }
@@ -1628,7 +1629,7 @@
         Object result = actual.invoke(instance, paramValues);
         if (result instanceof String) {
           ctx.replaceMe(program.getLiteralString(x.getSourceInfo().makeChild(
-              "Optimized String call"), (String) result));
+              DeadCodeVisitor.class, "Optimized String call"), (String) result));
         } else if (result instanceof Boolean) {
           ctx.replaceMe(program.getLiteralBoolean(((Boolean) result).booleanValue()));
         } else if (result instanceof Character) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 674df57..d3cbdfb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -533,7 +533,8 @@
 
     JStringLiteral processConstant(StringConstant x) {
       return program.getLiteralString(currentMethod.getSourceInfo().makeChild(
-          "String literal"), x.stringValue().toCharArray());
+          JavaASTGenerationVisitor.class, "String literal"),
+          x.stringValue().toCharArray());
     }
 
     /**
@@ -1958,7 +1959,7 @@
 
     private JField createEnumValueMap(JEnumType type) {
       SourceInfo sourceInfo = type.getSourceInfo().makeChild(
-          "enum value lookup map");
+          JavaASTGenerationVisitor.class, "enum value lookup map");
       JsonObject map = new JsonObject(program, sourceInfo);
       for (JEnumField field : type.enumList) {
         // JSON maps require leading underscores to prevent collisions.
@@ -2093,7 +2094,8 @@
                 "FieldRef referencing field in a different type.");
           }
         }
-        return new JFieldRef(program, info.makeChild("Reference",
+        return new JFieldRef(program, info.makeChild(
+            JavaASTGenerationVisitor.class, "Reference",
             variable.getSourceInfo()), instance, field, currentClass);
       }
       throw new InternalCompilerException("Unknown JVariable subclass.");
@@ -2508,7 +2510,7 @@
     private void writeEnumValueOfMethod(JEnumType type, JField mapField) {
       // return Enum.valueOf(map, name);
       SourceInfo sourceInfo = mapField.getSourceInfo().makeChild(
-          "enum accessor method");
+          JavaASTGenerationVisitor.class, "enum accessor method");
       JFieldRef mapRef = new JFieldRef(program, sourceInfo, null, mapField,
           type);
       JVariableRef nameRef = createVariableRef(sourceInfo,
@@ -2524,7 +2526,7 @@
     private void writeEnumValuesMethod(JEnumType type) {
       // return new E[]{A,B,C};
       SourceInfo sourceInfo = type.getSourceInfo().makeChild(
-          "enum values method");
+          JavaASTGenerationVisitor.class, "enum values method");
       List<JExpression> initializers = new ArrayList<JExpression>();
       for (JEnumField field : type.enumList) {
         JFieldRef fieldRef = new JFieldRef(program, sourceInfo, null, field,
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 bbdbfb3..f80d5d3 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
@@ -318,7 +318,7 @@
       } else {
         // create a new peer JsFunction
         SourceInfo sourceInfo = x.getSourceInfo().makeChild(
-            "Translated JS function");
+            CreateNamesAndScopesVisitor.class, "Translated JS function");
         jsFunction = new JsFunction(sourceInfo, topScope, globalName, true);
         methodBodyMap.put(x.getBody(), jsFunction);
       }
@@ -1309,7 +1309,8 @@
        * }
        * </pre>
        */
-      SourceInfo sourceInfo = program.createSourceInfoSynthetic("gwtOnLoad");
+      SourceInfo sourceInfo = program.createSourceInfoSynthetic(
+          GenerateJavaScriptAST.class, "gwtOnLoad");
       JsName gwtOnLoadName = topScope.declareName("gwtOnLoad");
       gwtOnLoadName.setObfuscatable(false);
       JsFunction gwtOnLoad = new JsFunction(sourceInfo, topScope,
@@ -1363,7 +1364,8 @@
         JsName jsName = entry.getValue();
         JsExpression longObjectAlloc = longObjects.get(jsName);
         JsVar var = new JsVar(vars.getSourceInfo().makeChild(
-            "Long literal " + entry.getKey()), jsName);
+            GenerateJavaScriptVisitor.class, "Long literal " + entry.getKey()),
+            jsName);
         var.setInitExpr(longObjectAlloc);
         vars.add(var);
       }
@@ -1371,7 +1373,8 @@
 
     private void generateNullFunc(List<JsStatement> globalStatements) {
       // handle null method
-      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic("Null function");
+      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(
+          GenerateJavaScriptAST.class, "Null function");
       JsFunction nullFunc = new JsFunction(sourceInfo, topScope,
           nullMethodName, true);
       sourceInfo.addCorrelation(Correlation.by(nullFunc));
@@ -1382,7 +1385,7 @@
     private void generateSeedFuncAndPrototype(JClassType x,
         List<JsStatement> globalStmts) {
       SourceInfo sourceInfo = x.getSourceInfo().makeChild(
-          "Seed and function prototype");
+          GenerateJavaScriptVisitor.class, "Seed and function prototype");
       if (x != program.getTypeJavaLangString()) {
         JsName seedFuncName = names.get(x);
 
@@ -1436,7 +1439,8 @@
         List<JsStatement> globalStmts) {
       JMethod toStringMeth = program.getIndexedMethod("Object.toString");
       if (x.methods.contains(toStringMeth)) {
-        SourceInfo sourceInfo = x.getSourceInfo().makeChild("_.toString");
+        SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+            GenerateJavaScriptVisitor.class, "_.toString");
         // _.toString = function(){return this.java_lang_Object_toString();}
 
         // lhs
@@ -1473,7 +1477,7 @@
           return;
         }
         SourceInfo sourceInfo = x.getSourceInfo().makeChild(
-            "Type id assignment");
+            GenerateJavaScriptVisitor.class, "Type id assignment");
         JsNameRef fieldRef = typeIdName.makeRef(sourceInfo);
         fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
         JsNumberLiteral typeIdLit = jsProgram.getNumberLiteral(typeId);
@@ -1489,7 +1493,8 @@
         // Was pruned; this compilation must have no JSO instanceof tests.
         return;
       }
-      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic("Type marker");
+      SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(
+          GenerateJavaScriptAST.class, "Type marker");
       JsNameRef fieldRef = typeMarkerName.makeRef(sourceInfo);
       fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
       JsExpression asg = createAssignment(fieldRef,
@@ -1499,7 +1504,8 @@
 
     private JsExpression generateTypeTable() {
       JsArrayLiteral arrayLit = new JsArrayLiteral(
-          jsProgram.createSourceInfoSynthetic("Type table"));
+          jsProgram.createSourceInfoSynthetic(GenerateJavaScriptAST.class,
+              "Type table"));
       for (int i = 0; i < program.getJsonTypeTable().size(); ++i) {
         JsonObject jsonObject = program.getJsonTypeTable().get(i);
         accept(jsonObject);
@@ -1512,7 +1518,7 @@
       for (int i = 0; i < x.methods.size(); ++i) {
         JMethod method = x.methods.get(i);
         SourceInfo sourceInfo = method.getSourceInfo().makeChild(
-            "vtable assignment");
+            GenerateJavaScriptVisitor.class, "vtable assignment");
         if (!method.isStatic() && !method.isAbstract()) {
           JsNameRef lhs = polymorphicNames.get(method).makeRef(sourceInfo);
           lhs.setQualifier(globalTemp.makeRef(sourceInfo));
@@ -1528,7 +1534,7 @@
       clinitFunc.setImpliedExecute(superClinit);
       List<JsStatement> statements = clinitFunc.getBody().getStatements();
       SourceInfo sourceInfo = clinitFunc.getSourceInfo().makeChild(
-          "clinit reassignment");
+          GenerateJavaScriptVisitor.class, "clinit reassignment");
       // self-assign to the null method immediately (to prevent reentrancy)
       JsExpression asg = createAssignment(clinitFunc.getName().makeRef(
           sourceInfo), nullMethodName.makeRef(sourceInfo));
@@ -1547,7 +1553,8 @@
       }
 
       JMethod clinitMethod = enclosingType.methods.get(0);
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("clinit invocation");
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          GenerateJavaScriptVisitor.class, "clinit invocation");
       JsInvocation jsInvocation = new JsInvocation(sourceInfo);
       jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
       return jsInvocation;
@@ -1570,7 +1577,8 @@
       }
 
       JMethod clinitMethod = enclosingType.methods.get(0);
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("clinit call");
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          GenerateJavaScriptVisitor.class, "clinit call");
       JsInvocation jsInvocation = new JsInvocation(sourceInfo);
       jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
       return jsInvocation;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
index 13ce278..c2e737e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
@@ -130,9 +130,9 @@
 
     // Create the new method.
     String name = objectMethod.getName() + "__devirtual$";
-    JMethod newMethod = program.createMethod(
-        sourceInfo.makeChild("Devirtualized method"), name.toCharArray(), jsoType,
-        objectMethod.getType(), false, true, true, false, false);
+    JMethod newMethod = program.createMethod(sourceInfo.makeChild(
+        JsoDevirtualizer.class, "Devirtualized method"), name.toCharArray(),
+        jsoType, objectMethod.getType(), false, true, true, false, false);
 
     // Setup parameters.
     JParameter thisParam = program.createParameter(sourceInfo,
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 5cb6caa..fed1cd4 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
@@ -84,7 +84,7 @@
       @Override
       public void endVisit(JsThisRef x, JsContext<JsExpression> ctx) {
         ctx.replaceMe(thisParam.makeRef(x.getSourceInfo().makeChild(
-            "Devirtualized instance")));
+            RewriteJsniMethodBody.class, "Devirtualized instance")));
       }
 
       @Override
@@ -114,16 +114,16 @@
       public void endVisit(JParameterRef x, Context ctx) {
         JParameter param = varMap.get(x.getTarget());
         JParameterRef paramRef = new JParameterRef(x.getProgram(),
-            x.getSourceInfo().makeChild("Reference to devirtualized parameter"),
-            param);
+            x.getSourceInfo().makeChild(RewriteMethodBody.class,
+                "Reference to devirtualized parameter"), param);
         ctx.replaceMe(paramRef);
       }
 
       @Override
       public void endVisit(JThisRef x, Context ctx) {
         JParameterRef paramRef = new JParameterRef(x.getProgram(),
-            x.getSourceInfo().makeChild("Reference to devirtualized instance"),
-            thisParam);
+            x.getSourceInfo().makeChild(RewriteMethodBody.class,
+                "Reference to devirtualized instance"), thisParam);
         ctx.replaceMe(paramRef);
       }
     }
@@ -145,14 +145,14 @@
        * its enclosing class.
        */
       JProgram program = x.getProgram();
-      JMethod newMethod = new JMethod(program,
-          sourceInfo.makeChild("Devirtualized function"), newName, enclosingType,
-          returnType, false, true, true, x.isPrivate());
+      JMethod newMethod = new JMethod(program, sourceInfo.makeChild(
+          CreateStaticImplsVisitor.class, "Devirtualized function"), newName,
+          enclosingType, returnType, false, true, true, x.isPrivate());
 
       // Setup parameters; map from the old params to the new params
-      JParameter thisParam = program.createParameter(
-          sourceInfo.makeChild("Instance parameter"), "this$static".toCharArray(),
-          enclosingType, true, true, newMethod);
+      JParameter thisParam = program.createParameter(sourceInfo.makeChild(
+          CreateStaticImplsVisitor.class, "Instance parameter"),
+          "this$static".toCharArray(), enclosingType, true, true, newMethod);
       Map<JParameter, JParameter> varMap = new IdentityHashMap<JParameter, JParameter>();
       for (int i = 0; i < x.params.size(); ++i) {
         JParameter oldVar = x.params.get(i);
@@ -173,7 +173,8 @@
       newMethod.setBody(movedBody);
 
       // Create a new body for the instance method that delegates to the static
-      SourceInfo delegateCallSourceInfo = sourceInfo.makeChild("Degelgating to devirtualized method");
+      SourceInfo delegateCallSourceInfo = sourceInfo.makeChild(
+          CreateStaticImplsVisitor.class, "Degelgating to devirtualized method");
       JMethodBody newBody = new JMethodBody(program, delegateCallSourceInfo);
       x.setBody(newBody);
       JMethodCall newCall = new JMethodCall(program, delegateCallSourceInfo,
@@ -204,8 +205,10 @@
         // TODO: Do we really need to do that in BuildTypeMap?
         JsFunction jsFunc = ((JsniMethodBody) movedBody).getFunc();
         JsName paramName = jsFunc.getScope().declareName("this$static");
-        jsFunc.getParameters().add(0,
-            new JsParameter(sourceInfo.makeChild("Static accessor"), paramName));
+        jsFunc.getParameters().add(
+            0,
+            new JsParameter(sourceInfo.makeChild(
+                CreateStaticImplsVisitor.class, "Static accessor"), paramName));
         RewriteJsniMethodBody rewriter = new RewriteJsniMethodBody(paramName);
         // Accept the body to avoid the recursion blocker.
         rewriter.accept(jsFunc.getBody());
@@ -293,8 +296,8 @@
   static JMethodCall makeStaticCall(JMethodCall x, JMethod newMethod) {
     // Update the call site
     JMethodCall newCall = new JMethodCall(x.getProgram(),
-        x.getSourceInfo().makeChild("Devirtualized function call"), null,
-        newMethod);
+        x.getSourceInfo().makeChild(MakeCallsStatic.class,
+            "Devirtualized function call"), null, newMethod);
 
     // The qualifier becomes the first arg
     newCall.getArgs().add(x.getInstance());
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index 4ffa405..a8262fb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -276,7 +276,8 @@
       JMethod method = x.getTarget();
       for (JParameter param : method.params) {
         addAssignment(param, new JParameterRef(program,
-            program.createSourceInfoSynthetic("Fake assignment"), param));
+            program.createSourceInfoSynthetic(RecordVisitor.class,
+                "Fake assignment"), param));
       }
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/js/JsIEBlockSizeVisitor.java b/dev/core/src/com/google/gwt/dev/js/JsIEBlockSizeVisitor.java
index 6b602a5..8927798 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsIEBlockSizeVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsIEBlockSizeVisitor.java
@@ -78,7 +78,8 @@
      * necessary to prevent any given block from exceeding the maximum size.
      */
     private void restructure(List<JsStatement> statements) {
-      SourceInfo sourceInfo = program.createSourceInfoSynthetic("Restructured to reduce block size");
+      SourceInfo sourceInfo = program.createSourceInfoSynthetic(
+          JsIEBlockSizeVisitor.class, "Restructured to reduce block size");
       // This outer loop will collapse the newly-created block into super-blocks
       while (statements.size() > MAX_BLOCK_SIZE) {
         ListIterator<JsStatement> i = statements.listIterator();
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 a53ed05..bb6a184 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsInliner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
@@ -72,7 +72,7 @@
 /**
  * Perform inlining optimizations on the JavaScript AST.
  * 
- * TODO(bobv): remove anything that's duplicating work with {@link JsStaticEval};
+ * TODO(bobv): remove anything that's duplicating work with {@link JsStaticEval}
  * migrate other stuff to that class perhaps.
  */
 public class JsInliner {
@@ -190,8 +190,9 @@
        * Create a new comma expression with the original LHS and the LHS of the
        * nested comma expression.
        */
-      JsBinaryOperation newOp = new JsBinaryOperation(x.getSourceInfo().makeChild(
-          "Simplifying comma expression"), JsBinaryOperator.COMMA);
+      JsBinaryOperation newOp = new JsBinaryOperation(
+          x.getSourceInfo().makeChild(CommaNormalizer.class,
+              "Simplifying comma expression"), JsBinaryOperator.COMMA);
       newOp.setArg1(x.getArg1());
       newOp.setArg2(toUpdate.getArg1());
 
@@ -595,9 +596,9 @@
      * parameters to ensure that an exception does not prevent their evaluation.
      * 
      * In the case of a nested invocation, such as
-     * <code>F(r1, r2, G(r3, r4), f1);</code> the evaluation order is
-     * guaranteed to be maintained, provided that no required parameters occur
-     * after the nested invocation.
+     * <code>F(r1, r2, G(r3, r4), f1);</code> the evaluation order is guaranteed
+     * to be maintained, provided that no required parameters occur after the
+     * nested invocation.
      */
     @Override
     public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
@@ -763,7 +764,7 @@
            * statements.
            */
           JsBlock b = new JsBlock(x.getSourceInfo().makeChild(
-              "Block required for control function"));
+              InliningVisitor.class, "Block required for control function"));
           b.getStatements().addAll(statements);
           ctx.replaceMe(b);
           return;
@@ -797,7 +798,8 @@
       assert !statements.isEmpty();
 
       // Find or create the JsVars as the first statement
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("Synthetic locals");
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          InliningVisitor.class, "Synthetic locals");
       JsVars vars;
       if (statements.get(0) instanceof JsVars) {
         vars = (JsVars) statements.get(0);
@@ -897,7 +899,8 @@
        * ensures that this logic will function correctly in the case of a single
        * expression.
        */
-      SourceInfo sourceInfo = x.getSourceInfo().makeChild("Inlined invocation");
+      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
+          InliningVisitor.class, "Inlined invocation");
       ListIterator<JsExpression> i = hoisted.listIterator(hoisted.size());
       JsExpression op = i.previous();
       while (i.hasPrevious()) {
@@ -1013,7 +1016,7 @@
     }
 
     /**
-     * Like accept(), but remove counts for all invocations in <code>expr</code>.
+     * Like accept(), but remove counts for all invocations in expr.
      */
     public void removeCountsFor(JsExpression expr) {
       assert (!removingCounts);
@@ -1073,7 +1076,8 @@
       }
 
       JsExpression replacement = tryGetReplacementExpression(
-          x.getSourceInfo().makeChild("Inlined expression"), x.getName());
+          x.getSourceInfo().makeChild(NameRefReplacerVisitor.class,
+              "Inlined expression"), x.getName());
 
       if (replacement != null) {
         ctx.replaceMe(replacement);
@@ -1095,8 +1099,8 @@
 
     /**
      * Determine the replacement expression to use in place of a reference to a
-     * given name. Returns <code>null</code> if no replacement has been set
-     * for the name.
+     * given name. Returns <code>null</code> if no replacement has been set for
+     * the name.
      */
     private JsExpression tryGetReplacementExpression(SourceInfo sourceInfo,
         JsName name) {
@@ -1520,7 +1524,7 @@
         JsExpression init = var.getInitExpr();
         if (init != null) {
           SourceInfo sourceInfo = var.getSourceInfo().makeChild(
-              "Hoisted initializer into inline site");
+              JsInliner.class, "Hoisted initializer into inline site");
           JsBinaryOperation assignment = new JsBinaryOperation(sourceInfo,
               JsBinaryOperator.ASG);
           assignment.setArg1(var.getName().makeRef(sourceInfo));
@@ -1616,7 +1620,6 @@
      * are disjoint. This prevents inlining of the following:
      * 
      * static int i; public void add(int a) { i += a; }; add(i++);
-     * 
      */
     if (hasCommonIdents(arguments, toInline, parameterIdents)) {
       return false;
diff --git a/dev/core/src/com/google/gwt/dev/js/JsParser.java b/dev/core/src/com/google/gwt/dev/js/JsParser.java
index 8228842..3ddf964 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsParser.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsParser.java
@@ -242,7 +242,7 @@
 
       case TokenStream.STRING:
         return program.getStringLiteral(sourceInfoStack.peek().makeChild(
-            "JS String literal"), node.getString());
+            JsParser.class, "JS String literal"), node.getString());
 
       case TokenStream.NUMBER:
         return mapNumber(node);
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index 653f8db..f7f33e7 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -145,7 +145,8 @@
         itr.add(x.makeStmt());
         itr.next();
         ctx.replaceMe(x.getName().makeRef(
-            x.getSourceInfo().makeChild("Shuffled evaluation order")));
+            x.getSourceInfo().makeChild(EvalFunctionsAtTopScope.class,
+                "Shuffled evaluation order")));
       }
 
       // Dive into the function itself.
@@ -189,11 +190,11 @@
     @Override
     public void endVisit(JsVars x, JsContext<JsStatement> ctx) {
       JsVars strippedVars = new JsVars(x.getSourceInfo().makeChild(
-          "Simplified execution"));
+          MustExecVisitor.class, "Simplified execution"));
       boolean mustReplace = false;
       for (JsVar var : x) {
         JsVar strippedVar = new JsVar(var.getSourceInfo().makeChild(
-            "Simplified execution"), var.getName());
+            MustExecVisitor.class, "Simplified execution"), var.getName());
         strippedVars.add(strippedVar);
         if (var.getInitExpr() != null) {
           mustReplace = true;
@@ -303,14 +304,16 @@
         if (condEval.isBooleanTrue()) {
           // e.g. (true() ? then : else) -> true() && then
           JsBinaryOperation binOp = new JsBinaryOperation(
-              x.getSourceInfo().makeChild("Simplified always-true condition"),
-              JsBinaryOperator.AND, condExpr, thenExpr);
+              x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+                  "Simplified always-true condition"), JsBinaryOperator.AND,
+              condExpr, thenExpr);
           ctx.replaceMe(accept(binOp));
         } else if (condEval.isBooleanFalse()) {
           // e.g. (false() ? then : else) -> false() || else
           JsBinaryOperation binOp = new JsBinaryOperation(
-              x.getSourceInfo().makeChild("Simplified always-false condition"),
-              JsBinaryOperator.OR, condExpr, elseExpr);
+              x.getSourceInfo().makeChild(StaticEvalVisitor.class,
+                  "Simplified always-false condition"), JsBinaryOperator.OR,
+              condExpr, elseExpr);
           ctx.replaceMe(accept(binOp));
         }
       }
@@ -334,7 +337,7 @@
           visitor.accept(x.getBody());
           if (!visitor.hasBreakContinueStatements()) {
             JsBlock block = new JsBlock(x.getSourceInfo().makeChild(
-                "Simplified always-false condition"));
+                StaticEvalVisitor.class, "Simplified always-false condition"));
             block.getStatements().add(x.getBody());
             block.getStatements().add(expr.makeStmt());
             ctx.replaceMe(accept(block));
@@ -368,7 +371,7 @@
         // If false, replace with initializers and condition.
         if (cond.isBooleanFalse()) {
           JsBlock block = new JsBlock(x.getSourceInfo().makeChild(
-              "Simplified always-false condition"));
+              StaticEvalVisitor.class, "Simplified always-false condition"));
           if (x.getInitExpr() != null) {
             block.getStatements().add(x.getInitExpr().makeStmt());
           }
@@ -403,12 +406,12 @@
         if (cond.isBooleanTrue()) {
           onlyStmtToExecute = thenStmt;
           removed = elseStmt;
-          sourceInfo = x.getSourceInfo().makeChild(
+          sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
               "Simplified always-true condition");
         } else if (cond.isBooleanFalse()) {
           onlyStmtToExecute = elseStmt;
           removed = thenStmt;
-          sourceInfo = x.getSourceInfo().makeChild(
+          sourceInfo = x.getSourceInfo().makeChild(StaticEvalVisitor.class,
               "Simplified always-false condition");
         } else {
           return;
@@ -466,7 +469,7 @@
         // If false, replace with condition.
         if (cond.isBooleanFalse()) {
           JsBlock block = new JsBlock(x.getSourceInfo().makeChild(
-              "Simplified always-false condition"));
+              StaticEvalVisitor.class, "Simplified always-false condition"));
           block.getStatements().add(expr.makeStmt());
           JsStatement decls = ensureDeclarations(x.getBody());
           if (decls != null) {
@@ -540,7 +543,7 @@
         return stmts.get(0);
       } else {
         JsBlock jsBlock = new JsBlock(stmt.getSourceInfo().makeChild(
-            "Ensuring declarations"));
+            StaticEvalVisitor.class, "Ensuring declarations"));
         jsBlock.getStatements().addAll(stmts);
         return jsBlock;
       }
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java b/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
index 5c3895f..9bbbc72 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStringInterner.java
@@ -133,7 +133,7 @@
       }
 
       ctx.replaceMe(name.makeRef(x.getSourceInfo().makeChild(
-          "Interned reference")));
+          JsStringInterner.class, "Interned reference")));
 
       return false;
     }
@@ -164,9 +164,10 @@
 
     if (v.toCreate.size() > 0) {
       // Create the pool of variable names.
-      JsVars vars = new JsVars(
-          program.createSourceInfoSynthetic("Interned string pool"));
-      SourceInfo sourceInfo = program.createSourceInfoSynthetic("Interned string assignment");
+      JsVars vars = new JsVars(program.createSourceInfoSynthetic(
+          JsStringInterner.class, "Interned string pool"));
+      SourceInfo sourceInfo = program.createSourceInfoSynthetic(
+          JsStringInterner.class, "Interned string assignment");
       for (Map.Entry<JsStringLiteral, JsName> entry : v.toCreate.entrySet()) {
         JsVar var = new JsVar(sourceInfo, entry.getValue());
         var.setInitExpr(entry.getKey());
diff --git a/dev/core/src/com/google/gwt/dev/js/SourceInfoHistogram.java b/dev/core/src/com/google/gwt/dev/js/SourceInfoHistogram.java
index 1329035..8f262c9 100644
--- a/dev/core/src/com/google/gwt/dev/js/SourceInfoHistogram.java
+++ b/dev/core/src/com/google/gwt/dev/js/SourceInfoHistogram.java
@@ -619,7 +619,7 @@
         + ".node {display:inline; z-index: 0;}" + ".story {display: none;}"
         + "div.node:hover > .story {"
         + "  display:block; float:right; clear: right; background: inherit; "
-        + "  position: relative; border-left: 8px solid white; z-index: 1;}"
+        + "  position: relative; border-left: 8px solid white; z-index: 1; max-width:50%;}"
         + "</style>");
     out.println("</head><body>");
 
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
index aa49818..1792dbe 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
@@ -29,7 +29,7 @@
   private JsExpression qualifier;
 
   public JsNameRef(SourceInfo sourceInfo, JsName name) {
-    super(sourceInfo.makeChild("Reference"));
+    super(sourceInfo.makeChild(JsNameRef.class, "Reference"));
     this.name = name;
     maybeUpdateSourceInfo();
   }
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 511587b..68e4988 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
@@ -26,18 +26,18 @@
 public final class JsProgram extends JsNode<JsProgram> {
 
   private final JsStatement debuggerStmt = new JsDebugger(
-      createSourceInfoSynthetic("debugger statement"));
+      createSourceInfoSynthetic(JsProgram.class, "debugger statement"));
 
-  private final JsEmpty emptyStmt = new JsEmpty(
-      createSourceInfoSynthetic("Empty statement"));
+  private final JsEmpty emptyStmt = new JsEmpty(createSourceInfoSynthetic(
+      JsProgram.class, "Empty statement"));
 
   private final JsBooleanLiteral falseLiteral = new JsBooleanLiteral(
-      createSourceInfoSynthetic("false literal"), false);
+      createSourceInfoSynthetic(JsProgram.class, "false literal"), false);
 
   private final JsGlobalBlock globalBlock;
 
   private final JsNullLiteral nullLiteral = new JsNullLiteral(
-      createSourceInfoSynthetic("null literal"));
+      createSourceInfoSynthetic(JsProgram.class, "null literal"));
 
   private final Map<Double, JsNumberLiteral> numberLiteralMap = new HashMap<Double, JsNumberLiteral>();
 
@@ -50,7 +50,7 @@
   private final JsScope topScope;
 
   private final JsBooleanLiteral trueLiteral = new JsBooleanLiteral(
-      createSourceInfoSynthetic("true literal"), true);
+      createSourceInfoSynthetic(JsProgram.class, "true literal"), true);
 
   private boolean enableSourceInfoDescendants;
 
@@ -58,9 +58,11 @@
    * Constructs a JavaScript program object.
    */
   public JsProgram() {
-    super(SourceInfoJs.INTRINSIC.makeChild("JavaScript program"));
+    super(SourceInfoJs.INTRINSIC.makeChild(JsProgram.class,
+        "JavaScript program"));
     rootScope = new JsRootScope(this);
-    globalBlock = new JsGlobalBlock(createSourceInfoSynthetic("global block"));
+    globalBlock = new JsGlobalBlock(createSourceInfoSynthetic(JsProgram.class,
+        "global block"));
     topScope = new JsScope(rootScope, "Global");
     objectScope = new JsScope(rootScope, "Object");
   }
@@ -70,9 +72,9 @@
         enableSourceInfoDescendants);
   }
 
-  public SourceInfo createSourceInfoSynthetic(String description) {
-    // TODO : Force the caller to be passed in
-    return createSourceInfo(0, "Synthetic").makeChild(description);
+  public SourceInfo createSourceInfoSynthetic(Class<?> caller,
+      String description) {
+    return createSourceInfo(0, caller.getName()).makeChild(caller, description);
   }
 
   public JsBooleanLiteral getBooleanLiteral(boolean truth) {
@@ -114,8 +116,8 @@
   public JsNumberLiteral getNumberLiteral(double value) {
     JsNumberLiteral lit = numberLiteralMap.get(value);
     if (lit == null) {
-      lit = new JsNumberLiteral(createSourceInfoSynthetic("Number literal "
-          + value), value);
+      lit = new JsNumberLiteral(createSourceInfoSynthetic(JsProgram.class,
+          "Number literal " + value), value);
       numberLiteralMap.put(value, lit);
     }
     return lit;
@@ -159,7 +161,7 @@
 
   public JsNameRef getUndefinedLiteral() {
     return rootScope.findExistingName("undefined").makeRef(
-        createSourceInfoSynthetic("undefined reference"));
+        createSourceInfoSynthetic(JsProgram.class, "undefined reference"));
   }
 
   /**