Add SpeedTracerLogger instrumentation to DevMode

Review at http://gwt-code-reviews.appspot.com/704802

Review by: zundel@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8480 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java
index 1e037fa..744e939 100644
--- a/dev/core/src/com/google/gwt/dev/Compiler.java
+++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -171,9 +171,7 @@
     ModuleDef[] modules = new ModuleDef[options.getModuleNames().size()];
     int i = 0;
     for (String moduleName : options.getModuleNames()) {
-      SpeedTracerLogger.start(CompilerEventType.MODULE_DEF, "phase", "loadFromClassPath", "moduleName", moduleName);
       modules[i++] = ModuleDefLoader.loadFromClassPath(logger, moduleName, true);
-      SpeedTracerLogger.end(CompilerEventType.MODULE_DEF);
     }
     return run(logger, modules);
   }
diff --git a/dev/core/src/com/google/gwt/dev/DevMode.java b/dev/core/src/com/google/gwt/dev/DevMode.java
index 5dda46e..ae085c4 100644
--- a/dev/core/src/com/google/gwt/dev/DevMode.java
+++ b/dev/core/src/com/google/gwt/dev/DevMode.java
@@ -34,6 +34,8 @@
 import com.google.gwt.dev.util.arg.ArgHandlerModuleName;
 import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
 import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 import com.google.gwt.util.tools.ArgHandlerString;
 import com.google.gwt.util.tools.Utility;
 
@@ -362,23 +364,26 @@
 
     TreeLogger branch = getTopLogger().branch(TreeLogger.TRACE,
         "Loading modules");
-    for (String moduleName : options.getModuleNames()) {
-      TreeLogger moduleBranch = branch.branch(TreeLogger.TRACE, moduleName);
-      try {
-        ModuleDef module = loadModule(moduleBranch, moduleName, false);
-        // Create a hard reference to the module to avoid gc-ing it until we
-        // actually load the module from the browser.
-        startupModules.put(module.getName(), module);
-        if (!options.isNoServer()) {
-          validateServletTags(moduleBranch, servletValidator, module, webXml);
-        }
-        TreeLogger loadLogger = moduleBranch.branch(TreeLogger.DEBUG,
-            "Bootstrap link for command-line module '" + moduleName + "'");
-        link(loadLogger, module);
-      } catch (UnableToCompleteException e) {
-        // Already logged.
-        return false;
+    SpeedTracerLogger.start(DevModeEventType.SLOW_STARTUP);
+    try {
+      for (String moduleName : options.getModuleNames()) {
+        TreeLogger moduleBranch = branch.branch(TreeLogger.TRACE, moduleName);
+          ModuleDef module = loadModule(moduleBranch, moduleName, false);
+          // Create a hard reference to the module to avoid gc-ing it until we
+          // actually load the module from the browser.
+          startupModules.put(module.getName(), module);
+          if (!options.isNoServer()) {
+            validateServletTags(moduleBranch, servletValidator, module, webXml);
+          }
+          TreeLogger loadLogger = moduleBranch.branch(TreeLogger.DEBUG,
+              "Bootstrap link for command-line module '" + moduleName + "'");
+          link(loadLogger, module);
       }
+    } catch (UnableToCompleteException e) {
+      // Already logged.
+      return false;
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.SLOW_STARTUP);
     }
     return true;
   }
@@ -393,6 +398,7 @@
       return -1;
     }
 
+    SpeedTracerLogger.start(DevModeEventType.JETTY_STARTUP);
     boolean clearCallback = true;
     try {
       ui.setCallback(RestartServerEvent.getType(), this);
@@ -435,6 +441,7 @@
       System.err.println("Unable to start embedded HTTP server");
       e.printStackTrace();
     } finally {
+      SpeedTracerLogger.end(DevModeEventType.JETTY_STARTUP);
       if (clearCallback) {
         // Clear the callback if we failed to start the server
         ui.setCallback(RestartServerEvent.getType(), null);
diff --git a/dev/core/src/com/google/gwt/dev/DevModeBase.java b/dev/core/src/com/google/gwt/dev/DevModeBase.java
index 379c936..91d1514 100644
--- a/dev/core/src/com/google/gwt/dev/DevModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/DevModeBase.java
@@ -42,6 +42,8 @@
 import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
 import com.google.gwt.dev.util.arg.OptionGenDir;
 import com.google.gwt.dev.util.arg.OptionLogLevel;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
 import com.google.gwt.util.tools.ArgHandlerFlag;
 import com.google.gwt.util.tools.ArgHandlerString;
 
@@ -87,6 +89,7 @@
 
     public ModuleSpaceHost createModuleSpaceHost(ModuleHandle module,
         String moduleName) throws UnableToCompleteException {
+      SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_HOST_CREATE);
       // TODO(jat): add support for closing an active module
       TreeLogger logger = module.getLogger();
       try {
@@ -101,6 +104,8 @@
         logger.log(TreeLogger.ERROR, "Exception initializing module", e);
         module.unload();
         throw e;
+      } finally {
+        SpeedTracerLogger.end(DevModeEventType.MODULE_SPACE_HOST_CREATE);
       }
     }
   }
@@ -1025,6 +1030,7 @@
       throw new IllegalStateException("Startup code has already been run");
     }
 
+    SpeedTracerLogger.start(DevModeEventType.STARTUP);
     // See if there was a UI specified by command-line args
     ui = createUI();
 
@@ -1035,6 +1041,7 @@
        * TODO (amitmanjhi): Adding this redundant logging to narrow down a
        * failure. Remove soon.
        */
+      SpeedTracerLogger.end(DevModeEventType.STARTUP);
       getTopLogger().log(TreeLogger.ERROR, "shell failed in doStartup method");
       return false;
     }
@@ -1073,11 +1080,13 @@
        * TODO (amitmanjhi): Adding this redundant logging to narrow down a
        * failure. Remove soon.
        */
+      SpeedTracerLogger.end(DevModeEventType.STARTUP);
       getTopLogger().log(TreeLogger.ERROR,
           "shell failed in doSlowStartup method");
       return false;
     }
 
+    SpeedTracerLogger.end(DevModeEventType.STARTUP);
     return true;
   }
 
@@ -1104,6 +1113,8 @@
   private DevModeUI createUI() {
     DevModeUI newUI = null;
 
+    SpeedTracerLogger.start(DevModeEventType.CREATE_UI);
+
     if (headlessMode) {
       newUI = new HeadlessUI(options);
     } else {
@@ -1128,6 +1139,7 @@
       baseLogLevelForUI = TreeLogger.Type.INFO;
     }
 
+    SpeedTracerLogger.end(DevModeEventType.CREATE_UI);
     return newUI;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java
index 72862ae..1ee4a40 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java
@@ -18,6 +18,8 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 import com.google.gwt.dev.util.xml.ReflectiveParser;
 import com.google.gwt.util.tools.Utility;
 
@@ -127,18 +129,24 @@
    */
   public static ModuleDef loadFromClassPath(TreeLogger logger,
       String moduleName, boolean refresh) throws UnableToCompleteException {
-    // Look up the module's physical name; if null, we are either encountering
-    // the module for the first time, or else the name is already physical
-    String physicalName = moduleEffectiveNameToPhysicalName.get(moduleName);
-    if (physicalName != null) {
-      moduleName = physicalName;
+    SpeedTracerLogger.start(
+        CompilerEventType.MODULE_DEF, "phase", "loadFromClassPath", "moduleName", moduleName);
+    try {
+      // Look up the module's physical name; if null, we are either encountering
+      // the module for the first time, or else the name is already physical
+      String physicalName = moduleEffectiveNameToPhysicalName.get(moduleName);
+      if (physicalName != null) {
+        moduleName = physicalName;
+      }
+      ModuleDef moduleDef = tryGetLoadedModule(logger, moduleName, refresh);
+      if (moduleDef != null) {
+        return moduleDef;
+      }
+      ModuleDefLoader loader = new ModuleDefLoader();
+      return loader.doLoadModule(logger, moduleName);
+    } finally {
+      SpeedTracerLogger.end(CompilerEventType.MODULE_DEF);
     }
-    ModuleDef moduleDef = tryGetLoadedModule(logger, moduleName, refresh);
-    if (moduleDef != null) {
-      return moduleDef;
-    }
-    ModuleDefLoader loader = new ModuleDefLoader();
-    return loader.doLoadModule(logger, moduleName);
   }
 
   private static ModuleDef tryGetLoadedModule(TreeLogger logger,
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
index 082c0e2..47fdf30 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
@@ -18,6 +18,8 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.javac.CompilationStateBuilder.CompileMoreLater;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -81,11 +83,17 @@
 
   public void addGeneratedCompilationUnits(TreeLogger logger,
       Collection<GeneratedUnit> generatedUnits) {
-    logger = logger.branch(TreeLogger.DEBUG, "Adding '" + generatedUnits.size()
-        + "' new generated units");
-    Collection<CompilationUnit> newUnits = compileMoreLater.addGeneratedTypes(
-        logger, generatedUnits);
-    assimilateUnits(logger, newUnits);
+    SpeedTracerLogger.start(DevModeEventType.GENERATED_UNITS_ADD);
+
+    try {
+      logger = logger.branch(TreeLogger.DEBUG, "Adding '"
+          + generatedUnits.size() + "' new generated units");
+      Collection<CompilationUnit> newUnits = compileMoreLater.addGeneratedTypes(
+          logger, generatedUnits);
+      assimilateUnits(logger, newUnits);
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.GENERATED_UNITS_ADD);
+    }
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
index 17fef15..36a653d 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
@@ -22,6 +22,8 @@
 import com.google.gwt.dev.javac.JdtCompiler.UnitProcessor;
 import com.google.gwt.dev.js.ast.JsProgram;
 import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import org.apache.commons.collections.map.AbstractReferenceMap;
 import org.apache.commons.collections.map.ReferenceIdentityMap;
@@ -54,7 +56,6 @@
 
       public void process(CompilationUnitBuilder builder,
           CompilationUnitDeclaration cud, List<CompiledClass> compiledClasses) {
-
         Map<AbstractMethodDeclaration, JsniMethod> jsniMethods = JsniCollector.collectJsniMethods(
             cud, builder.getSource(), jsProgram);
 
@@ -133,7 +134,12 @@
     
     public Collection<CompilationUnit> addGeneratedTypes(TreeLogger logger,
         Collection<GeneratedUnit> generatedUnits) {
-      return doBuildGeneratedTypes(logger, generatedUnits, this);
+      SpeedTracerLogger.start(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+      try {
+        return doBuildGeneratedTypes(logger, generatedUnits, this);
+      } finally {
+        SpeedTracerLogger.end(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+      }
     }
 
     void addValidUnit(CompilationUnit unit) {
@@ -188,12 +194,22 @@
 
   public static CompilationState buildFrom(TreeLogger logger,
       Set<Resource> resources) {
-    return instance.doBuildFrom(logger, resources, null);
+     SpeedTracerLogger.start(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+     try {
+       return instance.doBuildFrom(logger, resources, null);
+     } finally {
+       SpeedTracerLogger.end(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+     }
   }
 
   public static CompilationState buildFrom(TreeLogger logger,
       Set<Resource> resources, AdditionalTypeProviderDelegate delegate) {
-    return instance.doBuildFrom(logger, resources, delegate);
+    SpeedTracerLogger.start(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+    try {
+      return instance.doBuildFrom(logger, resources, delegate);
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+    }
   }
 
   public static CompilationStateBuilder get() {
@@ -267,46 +283,52 @@
    */
   public synchronized CompilationState doBuildFrom(TreeLogger logger,
       Set<Resource> resources, AdditionalTypeProviderDelegate compilerDelegate) {
-    Map<String, CompilationUnit> resultUnits = new HashMap<String, CompilationUnit>();
+    SpeedTracerLogger.start(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+    
+    try {
+      Map<String, CompilationUnit> resultUnits = new HashMap<String, CompilationUnit>();
 
-    // For each incoming Java source file...
-    for (Resource resource : resources) {
-      // Try to get an existing unit from the cache.
-      String location = resource.getLocation();
-      ResourceTag tag = resourceContentCache.get(location);
-      if (tag != null && tag.getLastModified() == resource.getLastModified()) {
-        ContentId contentId = tag.getContentId();
-        CompilationUnit existingUnit = unitCache.get(contentId);
-        if (existingUnit != null && existingUnit.isCompiled()) {
-          resultUnits.put(existingUnit.getTypeName(), existingUnit);
+      // For each incoming Java source file...
+      for (Resource resource : resources) {
+        // Try to get an existing unit from the cache.
+        String location = resource.getLocation();
+        ResourceTag tag = resourceContentCache.get(location);
+        if (tag != null && tag.getLastModified() == resource.getLastModified()) {
+          ContentId contentId = tag.getContentId();
+          CompilationUnit existingUnit = unitCache.get(contentId);
+          if (existingUnit != null && existingUnit.isCompiled()) {
+            resultUnits.put(existingUnit.getTypeName(), existingUnit);
+          }
         }
       }
-    }
 
-    // Winnow the reusable set of units down to those still valid.
-    CompilationUnitInvalidator.retainValidUnits(TreeLogger.NULL,
-        resultUnits.values());
+      // Winnow the reusable set of units down to those still valid.
+      CompilationUnitInvalidator.retainValidUnits(TreeLogger.NULL,
+                                                  resultUnits.values());
 
-    // Compile everything else.
-    CompileMoreLater compileMoreLater = new CompileMoreLater(compilerDelegate);
-    List<CompilationUnitBuilder> builders = new ArrayList<CompilationUnitBuilder>();
-    for (Resource resource : resources) {
-      String typeName = Shared.toTypeName(resource.getPath());
-      CompilationUnit validUnit = resultUnits.get(typeName);
-      if (validUnit != null) {
-        compileMoreLater.addValidUnit(validUnit);
-        // Report any existing errors as if the unit were recompiled.
-        CompilationUnitInvalidator.reportErrors(logger, validUnit);
-      } else {
-        builders.add(new ResourceCompilationUnitBuilder(typeName, resource));
+      // Compile everything else.
+      CompileMoreLater compileMoreLater = new CompileMoreLater(compilerDelegate);
+      List<CompilationUnitBuilder> builders = new ArrayList<CompilationUnitBuilder>();
+      for (Resource resource : resources) {
+        String typeName = Shared.toTypeName(resource.getPath());
+        CompilationUnit validUnit = resultUnits.get(typeName);
+        if (validUnit != null) {
+          compileMoreLater.addValidUnit(validUnit);
+          // Report any existing errors as if the unit were recompiled.
+          CompilationUnitInvalidator.reportErrors(logger, validUnit);
+        } else {
+          builders.add(new ResourceCompilationUnitBuilder(typeName, resource));
+        }
       }
-    }
-    compileMoreLater.compile(logger, builders, resultUnits);
+      compileMoreLater.compile(logger, builders, resultUnits);
 
-    // Invalidate units with invalid refs.
-    invalidateUnitsWithInvalidRefs(logger, resultUnits,
-        Collections.<ContentId> emptySet());
-    return new CompilationState(logger, resultUnits.values(), compileMoreLater);
+      // Invalidate units with invalid refs.
+      invalidateUnitsWithInvalidRefs(logger, resultUnits,
+                                     Collections.<ContentId> emptySet());
+      return new CompilationState(logger, resultUnits.values(), compileMoreLater);
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.COMPILATION_STATE_BUILDER_PROCESS);
+    }
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
index 933fd10..c89ca5b 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
@@ -317,11 +317,17 @@
    */
   public static List<CompilationUnit> compile(
       Collection<CompilationUnitBuilder> builders) {
-    DefaultUnitProcessor processor = new DefaultUnitProcessor();
-    JdtCompiler compiler = new JdtCompiler(processor);
-    processor.setCompiler(compiler);
-    compiler.doCompile(builders);
-    return processor.getResults();
+    SpeedTracerLogger.start(CompilerEventType.JDT_COMPILER);
+
+    try {
+      DefaultUnitProcessor processor = new DefaultUnitProcessor();
+      JdtCompiler compiler = new JdtCompiler(processor);
+      processor.setCompiler(compiler);
+      compiler.doCompile(builders);
+      return processor.getResults();
+    } finally {
+      SpeedTracerLogger.end(CompilerEventType.JDT_COMPILER);
+    }
   }
 
   public static CompilerOptions getCompilerOptions() {
diff --git a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
index c3f6d1b..2111c51 100644
--- a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
@@ -56,6 +56,7 @@
 import com.google.gwt.dev.util.Name;
 import com.google.gwt.dev.util.Name.InternalName;
 import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
 import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.io.PrintWriter;
@@ -546,6 +547,8 @@
    * creating JRealClassType/JGenericType objects.
    */
   private CollectClassData processClass(CompiledClass compiledClass) {
+    SpeedTracerLogger.start(DevModeEventType.VISIT_CLASS_FILE);
+    
     byte[] classBytes = compiledClass.getBytes();
     ClassReader reader = new ClassReader(classBytes);
     CollectClassData mcv = new CollectClassData();
@@ -554,6 +557,8 @@
       cv = new TraceClassVisitor(cv, new PrintWriter(System.out));
     }
     reader.accept(cv, 0);
+    
+    SpeedTracerLogger.end(DevModeEventType.VISIT_CLASS_FILE);    
     return mcv;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
index 2281eae..a42cd89 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
@@ -19,6 +19,8 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.dev.util.Name;
 import com.google.gwt.dev.util.Name.BinaryName;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -313,6 +315,8 @@
    * Runs the module's user startup code.
    */
   public final void onLoad(TreeLogger logger) throws UnableToCompleteException {
+    SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_LOAD);
+
     // Tell the host we're ready for business.
     //
     host.onModuleReady(this);
@@ -369,7 +373,13 @@
             onModuleLoad.setAccessible(true);
             invokeNativeVoid("fireOnModuleLoadStart", null,
                 new Class[] {String.class}, new Object[] {entryPointTypeName});
-            onModuleLoad.invoke(module);
+
+            SpeedTracerLogger.start(DevModeEventType.ON_MODULE_LOAD);
+            try {
+              onModuleLoad.invoke(module);
+            } finally {
+              SpeedTracerLogger.end(DevModeEventType.ON_MODULE_LOAD);
+            }
           }
         } finally {
           Method exit = implClass.getDeclaredMethod("exit", boolean.class);
@@ -400,6 +410,8 @@
       }
       logger.log(TreeLogger.ERROR, unableToLoadMessage, caught);
       throw new UnableToCompleteException();
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.MODULE_SPACE_LOAD);
     }
   }
 
@@ -410,6 +422,8 @@
     Throwable caught = null;
     String msg = null;
     String resultName = null;
+
+    SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_REBIND_AND_CREATE);
     try {
       // Rebind operates on source-level names.
       //
@@ -439,6 +453,8 @@
       caught = e;
     } catch (InvocationTargetException e) {
       caught = e.getTargetException();
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.MODULE_SPACE_REBIND_AND_CREATE);
     }
 
     // Always log here because sometimes this method gets called from static
@@ -577,20 +593,25 @@
    */
   private Class<?> loadClassFromSourceName(String sourceName)
       throws ClassNotFoundException {
-    String toTry = sourceName;
-    while (true) {
-      try {
-        return Class.forName(toTry, true, getIsolatedClassLoader());
-      } catch (ClassNotFoundException e) {
-        // Assume that the last '.' should be '$' and try again.
-        //
-        int i = toTry.lastIndexOf('.');
-        if (i == -1) {
-          throw e;
-        }
+    SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_CLASS_LOAD);
+    try {
+      String toTry = sourceName;
+      while (true) {
+        try {
+          return Class.forName(toTry, true, getIsolatedClassLoader());
+        } catch (ClassNotFoundException e) {
+          // Assume that the last '.' should be '$' and try again.
+          //
+          int i = toTry.lastIndexOf('.');
+          if (i == -1) {
+            throw e;
+          }
 
-        toTry = toTry.substring(0, i) + "$" + toTry.substring(i + 1);
+          toTry = toTry.substring(0, i) + "$" + toTry.substring(i + 1);
+        }
       }
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.MODULE_SPACE_CLASS_LOAD);
     }
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
index 6e877e4..0e81845 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpaceOOPHM.java
@@ -18,6 +18,8 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.javac.JsniMethod;
 import com.google.gwt.dev.shell.JsValue.DispatchObject;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.util.List;
 import java.util.Set;
@@ -102,6 +104,8 @@
       Object[] args) throws Throwable {
     TreeLogger branch = host.getLogger().branch(TreeLogger.SPAM,
         "Invoke native method " + name, null);
+    SpeedTracerLogger.start(DevModeEventType.JAVA_TO_JS_CALL);
+
     CompilingClassLoader isolatedClassLoader = getIsolatedClassLoader();
     JsValueOOPHM jsthis = new JsValueOOPHM();
     Class<?> jthisType = (jthis == null) ? Object.class : jthis.getClass();
@@ -120,11 +124,13 @@
       channel.invokeJavascript(isolatedClassLoader, jsthis, name, argv,
           returnVal);
       branch.log(TreeLogger.SPAM, "  returned " + returnVal);
+      return returnVal;
     } catch (Throwable t) {
       branch.log(TreeLogger.SPAM, "exception thrown", t);
       throw t;
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.JAVA_TO_JS_CALL);
     }
-    return returnVal;
   }
 
   @Override
diff --git a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
index 243185c..0ce8bc8 100644
--- a/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
+++ b/dev/core/src/com/google/gwt/dev/shell/OophmSessionHandler.java
@@ -21,7 +21,8 @@
 import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
 import com.google.gwt.dev.shell.JsValue.DispatchMethod;
 import com.google.gwt.dev.shell.JsValue.DispatchObject;
-import com.google.gwt.dev.util.PerfLogger;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.lang.reflect.Member;
 import java.util.Collections;
@@ -61,8 +62,8 @@
   }
 
   @Override
-  public ExceptionOrReturnValue getProperty(BrowserChannelServer channel, int refId,
-      int dispId) {
+  public ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
+      int refId, int dispId) {
     ModuleSpace moduleSpace = moduleMap.get(channel);
     ModuleHandle moduleHandle = moduleHandleMap.get(channel);
     assert moduleSpace != null && moduleHandle != null;
@@ -95,8 +96,9 @@
    * Invoke a method on a server object in from client code.
    */
   @Override
-  public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisVal,
-      int methodDispatchId, Value[] args) {
+  public ExceptionOrReturnValue invoke(BrowserChannelServer channel,
+      Value thisVal, int methodDispatchId, Value[] args) {
+    SpeedTracerLogger.start(DevModeEventType.JS_TO_JAVA_CALL);
     ServerObjectsTable localObjects = channel.getJavaObjectsExposedInBrowser();
     ModuleSpace moduleSpace = moduleMap.get(channel);
     ModuleHandle moduleHandle = moduleHandleMap.get(channel);
@@ -158,6 +160,7 @@
           t.getClass(), t);
     }
     Value retVal = channel.convertFromJsValue(localObjects, jsRetVal);
+    SpeedTracerLogger.end(DevModeEventType.JS_TO_JAVA_CALL);
     return new ExceptionOrReturnValue(exception, retVal);
   }
 
@@ -165,7 +168,7 @@
   public synchronized TreeLogger loadModule(BrowserChannelServer channel,
       String moduleName, String userAgent, String url, String tabKey,
       String sessionKey, byte[] userAgentIcon) {
-    PerfLogger.start("OophmSessionHandler.loadModule " + moduleName);
+    SpeedTracerLogger.start(DevModeEventType.MODULE_INIT);
     ModuleHandle moduleHandle = host.createModuleLogger(moduleName, userAgent,
         url, tabKey, sessionKey, channel, userAgentIcon);
     TreeLogger logger = moduleHandle.getLogger();
@@ -173,11 +176,9 @@
     ModuleSpace moduleSpace = null;
     try {
       // Attach a new ModuleSpace to make it programmable.
-      ModuleSpaceHost msh = host.createModuleSpaceHost(moduleHandle,
-          moduleName);
+      ModuleSpaceHost msh = host.createModuleSpaceHost(moduleHandle, moduleName);
       moduleSpace = new ModuleSpaceOOPHM(msh, moduleName, channel);
       moduleMap.put(channel, moduleSpace);
-      PerfLogger.start("ModuleSpace.onLoad");
       moduleSpace.onLoad(logger);
       moduleHandle.getLogger().log(TreeLogger.INFO,
           "Module " + moduleName + " has been loaded");
@@ -186,26 +187,26 @@
       // that can go wrong trying to load a module, including Error-derived
       // things like NoClassDefFoundError.
       // 
-      moduleHandle.getLogger().log(TreeLogger.ERROR, "Failed to load module '"
-          + moduleName + "' from user agent '" + userAgent + "' at "
-          + channel.getRemoteEndpoint(), e);
+      moduleHandle.getLogger().log(
+          TreeLogger.ERROR,
+          "Failed to load module '" + moduleName + "' from user agent '"
+              + userAgent + "' at " + channel.getRemoteEndpoint(), e);
       if (moduleSpace != null) {
-        moduleSpace.dispose();        
+        moduleSpace.dispose();
       }
       moduleHandle.unload();
       moduleMap.remove(channel);
       moduleHandleMap.remove(channel);
       return null;
     } finally {
-      PerfLogger.end();
-      PerfLogger.end();
+      SpeedTracerLogger.end(DevModeEventType.MODULE_INIT);
     }
     return moduleHandle.getLogger();
   }
 
   @Override
-  public ExceptionOrReturnValue setProperty(BrowserChannelServer channel, int refId,
-      int dispId, Value newValue) {
+  public ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
+      int refId, int dispId, Value newValue) {
     ModuleSpace moduleSpace = moduleMap.get(channel);
     ModuleHandle moduleHandle = moduleHandleMap.get(channel);
     assert moduleSpace != null && moduleHandle != null;
diff --git a/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java b/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
index 313903e..c748f75 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ShellModuleSpaceHost.java
@@ -22,6 +22,8 @@
 import com.google.gwt.dev.cfg.Rules;
 import com.google.gwt.dev.javac.CompilationState;
 import com.google.gwt.dev.javac.StandardGeneratorContext;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.io.File;
 
@@ -82,31 +84,36 @@
       throws UnableToCompleteException {
     this.space = readySpace;
 
-    // Establish an environment for JavaScript property providers to run.
-    //
-    ModuleSpacePropertyOracle propOracle = new ModuleSpacePropertyOracle(
-        module.getProperties(), module.getActiveLinkerNames(), readySpace);
+    SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_HOST_READY);
+    try {
+      // Establish an environment for JavaScript property providers to run.
+      //
+      ModuleSpacePropertyOracle propOracle = new ModuleSpacePropertyOracle(
+          module.getProperties(), module.getActiveLinkerNames(), readySpace);
 
-    // Set up the rebind oracle for the module.
-    // It has to wait until now because we need to inject javascript.
-    //
-    Rules rules = module.getRules();
-    StandardGeneratorContext genCtx = new StandardGeneratorContext(
-        compilationState, module, genDir, new ArtifactSet());
-    rebindOracle = new StandardRebindOracle(propOracle, rules, genCtx);
+      // Set up the rebind oracle for the module.
+      // It has to wait until now because we need to inject javascript.
+      //
+      Rules rules = module.getRules();
+      StandardGeneratorContext genCtx = new StandardGeneratorContext(
+          compilationState, module, genDir, new ArtifactSet());
+      rebindOracle = new StandardRebindOracle(propOracle, rules, genCtx);
 
-    // Create a completely isolated class loader which owns all classes
-    // associated with a particular module. This effectively builds a
-    // separate 'domain' for each running module, so that they all behave as
-    // though they are running separately. This allows the shell to run
-    // multiple modules, both in succession and simultaneously, without getting
-    // confused.
-    //
-    // Note that the compiling class loader has no parent. This keeps it from
-    // accidentally 'escaping' its domain and loading classes from the system
-    // class loader (the one that loaded the shell itself).
-    //
-    classLoader = new CompilingClassLoader(logger, compilationState, readySpace);
+      // Create a completely isolated class loader which owns all classes
+      // associated with a particular module. This effectively builds a
+      // separate 'domain' for each running module, so that they all behave as
+      // though they are running separately. This allows the shell to run
+      // multiple modules, both in succession and simultaneously, without getting
+      // confused.
+      //
+      // Note that the compiling class loader has no parent. This keeps it from
+      // accidentally 'escaping' its domain and loading classes from the system
+      // class loader (the one that loaded the shell itself).
+      //
+      classLoader = new CompilingClassLoader(logger, compilationState, readySpace);
+    } finally {
+      SpeedTracerLogger.end(DevModeEventType.MODULE_SPACE_HOST_READY);
+    }
   }
 
   public String rebind(TreeLogger logger, String sourceTypeName)
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
index 3a3d22f..f42e126 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardRebindOracle.java
@@ -24,6 +24,8 @@
 import com.google.gwt.dev.javac.StandardGeneratorContext;
 import com.google.gwt.dev.jdt.RebindOracle;
 import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -49,20 +51,24 @@
 
     public String rebind(TreeLogger logger, String typeName,
         ArtifactAcceptor artifactAcceptor) throws UnableToCompleteException {
-
-      genCtx.setPropertyOracle(propOracle);
-      String result = tryRebind(logger, typeName);
-      if (artifactAcceptor != null) {
-        // Go ahead and call finish() to accept new artifacts.
-        ArtifactSet newlyGeneratedArtifacts = genCtx.finish(logger);
-        if (!newlyGeneratedArtifacts.isEmpty()) {
-          artifactAcceptor.accept(logger, newlyGeneratedArtifacts);
+      SpeedTracerLogger.start(DevModeEventType.REBIND);
+      try {
+        genCtx.setPropertyOracle(propOracle);
+        String result = tryRebind(logger, typeName);
+        if (artifactAcceptor != null) {
+          // Go ahead and call finish() to accept new artifacts.
+          ArtifactSet newlyGeneratedArtifacts = genCtx.finish(logger);
+          if (!newlyGeneratedArtifacts.isEmpty()) {
+            artifactAcceptor.accept(logger, newlyGeneratedArtifacts);
+          }
         }
+        if (result == null) {
+          result = typeName;
+        }
+        return result;
+      } finally {
+        SpeedTracerLogger.end(DevModeEventType.REBIND);
       }
-      if (result == null) {
-        result = typeName;
-      }
-      return result;
     }
 
     private String tryRebind(TreeLogger logger, String typeName)
diff --git a/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java b/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
index 3ac466a..9b7e61c 100644
--- a/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
+++ b/dev/core/src/com/google/gwt/dev/shell/rewrite/HostedModeClassRewriter.java
@@ -22,6 +22,8 @@
 import com.google.gwt.dev.asm.Opcodes;
 import com.google.gwt.dev.asm.commons.Method;
 import com.google.gwt.dev.shell.JsValueGlue;
+import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -217,6 +219,7 @@
    */
   public byte[] rewrite(TypeOracle typeOracle, String className,
       byte[] classBytes, Map<String, String> anonymousClassMap) {
+    SpeedTracerLogger.start(DevModeEventType.CLASS_BYTES_REWRITE);
     String desc = toDescriptor(className);
     assert (!jsoIntfDescs.contains(desc));
 
@@ -244,6 +247,7 @@
     }
 
     new ClassReader(classBytes).accept(v, 0);
+    SpeedTracerLogger.end(DevModeEventType.CLASS_BYTES_REWRITE);
     return writer.toByteArray();
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/util/log/speedtracer/DevModeEventType.java b/dev/core/src/com/google/gwt/dev/util/log/speedtracer/DevModeEventType.java
index f6a14f6..81f04eb 100644
--- a/dev/core/src/com/google/gwt/dev/util/log/speedtracer/DevModeEventType.java
+++ b/dev/core/src/com/google/gwt/dev/util/log/speedtracer/DevModeEventType.java
@@ -22,26 +22,25 @@
  * {@link com.google.gwt.dev.DevMode}
  */
 public enum DevModeEventType implements EventType {
-  CLASS_BYTES_REWRITE("Class bytes rewrite", "DarkBlue"), // foil Eclipse
+  CLASS_BYTES_REWRITE("Class bytes rewrite", "DarkBlue"), //
   COMPILATION_STATE_BUILDER_PROCESS("CompilationStateBuilder process",
-      "CornflowerBlue"), //
+      "Teal"), //
   CREATE_UI("Create UI", "BlueViolet"), //
-  GENERATED_UNITS_ADD("Generated units add", "FireBrick"), //
-  GENERATOR_RUN("Generator run", "Red"), //
-  JAVA_TO_JS_CALL("Java to JS call", "LightSteelBlue"), //
-  JDT_COMPILE("JDT compile", "Blue"), //
-  JETTY_STARTUP("Jetty startup", "Chartreuse"), //
-  JS_TO_JAVA_CALL("JS to Java call", "LightSlateGray"), //
-  MODULE_DEF_LOAD("ModuleDef load", "Yellow"), //
-  MODULE_DEF_NORMALIZE("ModuleDef normalize", "GoldenRod"), //
-  MODULE_DEF_REFRESH("ModuleDef refresh", "GoldenRod"), //
-  MODULE_INIT("Module init", "LightGoldenRodYellow"), //
+  GENERATED_UNITS_ADD("Generated units add", "Brown"), //
+  GENERATOR_RUN("Generator run", "Tomato"), //
+  JAVA_TO_JS_CALL("Java to JS call", "LightSkyBlue"), //
+  JETTY_STARTUP("Jetty startup", "Orchid"), //
+  JS_TO_JAVA_CALL("JS to Java call", "OrangeRed"), //
+  MODULE_DEF_LOAD("ModuleDef load", "Peru"), //
+  MODULE_DEF_NORMALIZE("ModuleDef normalize", "DarkKhaki"), //
+  MODULE_DEF_REFRESH("ModuleDef refresh", "DarkKhaki"), //
+  MODULE_INIT("Module init", "Khaki"), //
   MODULE_SPACE_CLASS_LOAD("ModuleSpace class load", "Ivory"), //
-  MODULE_SPACE_HOST_CREATE("ModuleSpaceHost create", "Yellow"), //
-  MODULE_SPACE_HOST_READY("ModuleSpaceHost ready", "Moccasin"), //
+  MODULE_SPACE_HOST_CREATE("ModuleSpaceHost create", "Peachpuff"), //
+  MODULE_SPACE_HOST_READY("ModuleSpaceHost ready", "Linen"), //
   MODULE_SPACE_LOAD("ModuleSpace load", "LemonChiffon"), //
   MODULE_SPACE_REBIND_AND_CREATE("ModuleSpace rebindAndCreate", "Crimson"), //
-  ON_MODULE_LOAD("onModuleLoad", "LawnGreen"), //
+  ON_MODULE_LOAD("onModuleLoad", "LightGreen"), //
   REBIND("Rebind", "Tomato"), //
   REBOUND_TYPE_CREATE("Rebound type create", "Crimson"), //
   RESOURCE_ORACLE_REFRESH("ResourceOracle refresh", "Orange"), //