changeset 19686:fa75218e3942

Fix nested Timer and MemUse tracking logic
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Tue, 03 Mar 2015 10:32:17 -0800
parents 787e9bd5966e
children 9d2ff2e8360d
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugCloseable.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMemUseTracker.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/AccumulatedDebugValue.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/CloseableCounterImpl.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 20 files changed, 227 insertions(+), 198 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Mar 03 10:32:17 2015 -0800
@@ -38,7 +38,6 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.framemap.*;
@@ -245,7 +244,7 @@
      */
     public static SchedulePhase emitFrontEnd(Providers providers, TargetDescription target, StructuredGraph graph, Map<ResolvedJavaMethod, StructuredGraph> cache,
                     PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites) {
-        try (Scope s = Debug.scope("FrontEnd"); TimerCloseable a = FrontEnd.start()) {
+        try (Scope s = Debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start()) {
             if (speculationLog != null) {
                 speculationLog.collectFailedSpeculations();
             }
@@ -281,7 +280,7 @@
 
     public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Backend backend,
                     TargetDescription target, T compilationResult, CompilationResultBuilderFactory factory, SchedulePhase schedule, RegisterConfig registerConfig, LIRSuites lirSuites) {
-        try (Scope s = Debug.scope("BackEnd"); TimerCloseable a = BackEnd.start()) {
+        try (Scope s = Debug.scope("BackEnd"); DebugCloseable a = BackEnd.start()) {
             // Repeatedly run the LIR code generation pass to improve statistical profiling results.
             for (int i = 0; i < EmitLIRRepeatCount.getValue(); i++) {
                 SchedulePhase dummySchedule = new SchedulePhase();
@@ -318,7 +317,7 @@
 
     public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc,
                     RegisterConfig registerConfig, LIRSuites lirSuites) {
-        try (Scope ds = Debug.scope("EmitLIR"); TimerCloseable a = EmitLIR.start()) {
+        try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) {
             List<Block> blocks = schedule.getCFG().getBlocks();
             Block startBlock = schedule.getCFG().getStartBlock();
             assert startBlock != null;
@@ -378,7 +377,7 @@
 
     public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Set<ResolvedJavaMethod> inlinedMethods, LIRGenerationResult lirGenRes,
                     CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
-        try (TimerCloseable a = EmitCode.start()) {
+        try (DebugCloseable a = EmitCode.start()) {
             FrameMap frameMap = lirGenRes.getFrameMap();
             CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
             backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
--- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java	Tue Mar 03 10:32:17 2015 -0800
@@ -29,7 +29,6 @@
 import org.junit.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 
 public class DebugTimerTest {
 
@@ -63,9 +62,9 @@
             long spinA;
             long spinB;
 
-            try (TimerCloseable a1 = timerA.start()) {
+            try (DebugCloseable a1 = timerA.start()) {
                 spinA = spin(50);
-                try (TimerCloseable b1 = timerB.start()) {
+                try (DebugCloseable b1 = timerB.start()) {
                     spinB = spin(50);
                 }
             }
@@ -83,15 +82,15 @@
         DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, null, null, System.out);
         try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
             DebugTimer timerC = Debug.timer("TimerC");
-            try (TimerCloseable c1 = timerC.start()) {
+            try (DebugCloseable c1 = timerC.start()) {
                 spin(50);
-                try (TimerCloseable c2 = timerC.start()) {
+                try (DebugCloseable c2 = timerC.start()) {
                     spin(50);
-                    try (TimerCloseable c3 = timerC.start()) {
+                    try (DebugCloseable c3 = timerC.start()) {
                         spin(50);
-                        try (TimerCloseable c4 = timerC.start()) {
+                        try (DebugCloseable c4 = timerC.start()) {
                             spin(50);
-                            try (TimerCloseable c5 = timerC.start()) {
+                            try (DebugCloseable c5 = timerC.start()) {
                                 spin(50);
                             }
                         }
@@ -115,13 +114,13 @@
             long spinD1;
             long spinE;
 
-            try (TimerCloseable d1 = timerD.start()) {
+            try (DebugCloseable d1 = timerD.start()) {
                 spinD1 = spin(50);
-                try (TimerCloseable e1 = timerE.start()) {
+                try (DebugCloseable e1 = timerE.start()) {
                     spinE = spin(50);
-                    try (TimerCloseable d2 = timerD.start()) {
+                    try (DebugCloseable d2 = timerD.start()) {
                         spin(50);
-                        try (TimerCloseable d3 = timerD.start()) {
+                        try (DebugCloseable d3 = timerD.start()) {
                             spin(50);
                         }
                     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Mar 03 10:32:17 2015 -0800
@@ -1131,8 +1131,8 @@
 
     private static final DebugMemUseTracker VOID_MEM_USE_TRACKER = new DebugMemUseTracker() {
 
-        public Closeable start() {
-            return MemUseTrackerImpl.VOID_CLOSEABLE;
+        public DebugCloseable start() {
+            return DebugCloseable.VOID_CLOSEABLE;
         }
 
         public long getCurrentValue() {
@@ -1319,8 +1319,8 @@
 
     private static final DebugTimer VOID_TIMER = new DebugTimer() {
 
-        public TimerCloseable start() {
-            return TimerImpl.VOID_CLOSEABLE;
+        public DebugCloseable start() {
+            return DebugCloseable.VOID_CLOSEABLE;
         }
 
         public void setConditional(boolean flag) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugCloseable.java	Tue Mar 03 10:32:17 2015 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.debug;
+
+/**
+ * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and
+ * adds the elapsed time since {@code start()} to the total for the timer.
+ */
+public interface DebugCloseable extends AutoCloseable {
+
+    DebugCloseable VOID_CLOSEABLE = new DebugCloseable() {
+
+        @Override
+        public void close() {
+        }
+    };
+
+    void close();
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMemUseTracker.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMemUseTracker.java	Tue Mar 03 10:32:17 2015 -0800
@@ -36,10 +36,6 @@
  */
 public interface DebugMemUseTracker {
 
-    public interface Closeable extends AutoCloseable {
-        void close();
-    }
-
     /**
      * Creates a point from which memory usage will be recorded if memory use tracking is
      * {@linkplain Debug#isMemUseTrackingEnabled() enabled}.
@@ -47,7 +43,7 @@
      * @return an object that must be closed once the activity has completed to add the memory used
      *         since this call to the total for this tracker
      */
-    Closeable start();
+    DebugCloseable start();
 
     /**
      * Gets the current value of this tracker.
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Tue Mar 03 10:32:17 2015 -0800
@@ -24,8 +24,6 @@
 
 import java.util.concurrent.*;
 
-import com.oracle.graal.debug.internal.*;
-
 /**
  * A timer for some activity of interest. A timer should be deployed using the try-with-resources
  * pattern:
@@ -45,7 +43,7 @@
      * @return an object that must be closed once the activity has completed to add the elapsed time
      *         since this call to the total for this timer
      */
-    TimerCloseable start();
+    DebugCloseable start();
 
     /**
      * Sets a flag determining if this timer is only enabled if timing is
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/AccumulatedDebugValue.java	Tue Mar 03 10:32:17 2015 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.debug.internal;
+
+public abstract class AccumulatedDebugValue extends DebugValue {
+    protected final DebugValue flat;
+
+    public AccumulatedDebugValue(String name, boolean conditional, DebugValue flat) {
+        super(name + "_Accm", conditional);
+        this.flat = flat;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/CloseableCounterImpl.java	Tue Mar 03 10:32:17 2015 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.debug.internal;
+
+import com.oracle.graal.debug.*;
+
+/**
+ * A helper class for DebugValues that can nest and need to split out accumulated and flat values
+ * for some kind of counter-like measurement.
+ */
+abstract class CloseableCounterImpl implements DebugCloseable {
+
+    protected final CloseableCounterImpl parent;
+    protected final AccumulatedDebugValue counter;
+    protected final long start;
+    protected long nestedAmountToSubtract;
+
+    CloseableCounterImpl(CloseableCounterImpl parent, AccumulatedDebugValue counter) {
+        this.parent = parent;
+        this.start = getCounterValue();
+        this.counter = counter;
+    }
+
+    @Override
+    public void close() {
+        long end = getCounterValue();
+        long difference = end - start;
+        if (parent != null) {
+            if (!counter.getName().equals(parent.counter.getName())) {
+                parent.nestedAmountToSubtract += difference;
+
+                // Look for our counter in an outer scope and fix up
+                // the adjustment to the flat count
+                CloseableCounterImpl ancestor = parent.parent;
+                while (ancestor != null) {
+                    if (ancestor.counter.getName().equals(counter.getName())) {
+                        ancestor.nestedAmountToSubtract -= difference;
+                        break;
+                    }
+                    ancestor = ancestor.parent;
+                }
+            }
+        }
+        long flatAmount = difference - nestedAmountToSubtract;
+        counter.addToCurrentValue(difference);
+        counter.flat.addToCurrentValue(flatAmount);
+    }
+
+    abstract long getCounterValue();
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java	Tue Mar 03 10:32:17 2015 -0800
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.debug.internal;
 
+import static com.oracle.graal.debug.DebugCloseable.*;
 import static java.lang.Thread.*;
 
 import java.lang.management.*;
@@ -29,7 +30,7 @@
 import com.oracle.graal.debug.*;
 import com.sun.management.ThreadMXBean;
 
-public final class MemUseTrackerImpl extends DebugValue implements DebugMemUseTracker {
+public final class MemUseTrackerImpl extends AccumulatedDebugValue implements DebugMemUseTracker {
 
     private static final ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
 
@@ -42,35 +43,25 @@
         return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead;
     }
 
-    public static final Closeable VOID_CLOSEABLE = new Closeable() {
-
-        @Override
-        public void close() {
-        }
-    };
-
     /**
      * Records the most recent active tracker.
      */
-    private static final ThreadLocal<CloseableImpl> currentTracker = new ThreadLocal<>();
-
-    private final DebugValue flat;
+    private static final ThreadLocal<CloseableCounterImpl> currentTracker = new ThreadLocal<>();
 
     public MemUseTrackerImpl(String name) {
-        super(name + "_Accm", true);
-        this.flat = new DebugValue(name + "_Flat", true) {
+        super(name, false, new DebugValue(name + "_Flat", true) {
 
             @Override
             public String toString(long value) {
                 return valueToString(value);
             }
-        };
+        });
     }
 
     @Override
-    public Closeable start() {
+    public DebugCloseable start() {
         if (!isConditional() || Debug.isMemUseTrackingEnabled()) {
-            CloseableImpl result = new CloseableImpl();
+            MemUseCloseableCounterImpl result = new MemUseCloseableCounterImpl(this);
             currentTracker.set(result);
             return result;
         } else {
@@ -87,27 +78,21 @@
         return valueToString(value);
     }
 
-    private final class CloseableImpl implements Closeable {
+    private static final class MemUseCloseableCounterImpl extends CloseableCounterImpl implements DebugCloseable {
 
-        private final CloseableImpl parent;
-        private final long start;
-        private long nestedAmountToSubtract;
+        private MemUseCloseableCounterImpl(AccumulatedDebugValue counter) {
+            super(currentTracker.get(), counter);
+        }
 
-        private CloseableImpl() {
-            this.parent = currentTracker.get();
-            this.start = getCurrentThreadAllocatedBytes();
+        @Override
+        long getCounterValue() {
+            return getCurrentThreadAllocatedBytes();
         }
 
         @Override
         public void close() {
-            long end = getCurrentThreadAllocatedBytes();
-            long allocated = end - start;
-            if (parent != null) {
-                parent.nestedAmountToSubtract += allocated;
-            }
+            super.close();
             currentTracker.set(parent);
-            MemUseTrackerImpl.this.addToCurrentValue(allocated);
-            flat.addToCurrentValue(allocated - nestedAmountToSubtract);
         }
     }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Tue Mar 03 16:10:35 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.debug.internal;
-
-import com.oracle.graal.debug.*;
-
-/**
- * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and
- * adds the elapsed time since {@code start()} to the total for the timer.
- */
-public interface TimerCloseable extends AutoCloseable {
-
-    void close();
-}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Tue Mar 03 10:32:17 2015 -0800
@@ -22,35 +22,27 @@
  */
 package com.oracle.graal.debug.internal;
 
+import static com.oracle.graal.debug.DebugCloseable.*;
+
 import java.lang.management.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.debug.*;
 
-public final class TimerImpl extends DebugValue implements DebugTimer {
+public final class TimerImpl extends AccumulatedDebugValue implements DebugTimer {
 
     private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
 
-    public static final TimerCloseable VOID_CLOSEABLE = new TimerCloseable() {
-
-        @Override
-        public void close() {
-        }
-    };
-
     /**
      * Records the most recent active timer.
      */
-    private static final ThreadLocal<AbstractTimer> currentTimer = new ThreadLocal<>();
-
-    private final FlatTimer flat;
+    private static final ThreadLocal<CloseableCounterImpl> currentTimer = new ThreadLocal<>();
 
     static class FlatTimer extends DebugValue implements DebugTimer {
-        private final TimerImpl accm;
+        private TimerImpl accm;
 
-        public FlatTimer(TimerImpl accm, String name) {
-            super(name + "_Flat", accm.isConditional());
-            this.accm = accm;
+        public FlatTimer(String name, boolean conditional) {
+            super(name + "_Flat", conditional);
         }
 
         @Override
@@ -62,31 +54,24 @@
             return accm.getTimeUnit();
         }
 
-        public TimerCloseable start() {
+        public DebugCloseable start() {
             return accm.start();
         }
     }
 
     public TimerImpl(String name, boolean conditional) {
-        super(name + "_Accm", conditional);
-        this.flat = new FlatTimer(this, name);
+        super(name, conditional, new FlatTimer(name, conditional));
+        ((FlatTimer) flat).accm = this;
     }
 
     @Override
-    public TimerCloseable start() {
+    public DebugCloseable start() {
         if (!isConditional() || Debug.isTimeEnabled()) {
-            long startTime;
-            if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
-                startTime = threadMXBean.getCurrentThreadCpuTime();
-            } else {
-                startTime = System.nanoTime();
-            }
-
             AbstractTimer result;
             if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
-                result = new CpuTimeTimer(this, startTime);
+                result = new CpuTimeTimer(this);
             } else {
-                result = new SystemNanosTimer(this, startTime);
+                result = new SystemNanosTimer(this);
             }
             currentTimer.set(result);
             return result;
@@ -100,7 +85,7 @@
     }
 
     public DebugTimer getFlat() {
-        return flat;
+        return (FlatTimer) flat;
     }
 
     @Override
@@ -112,68 +97,39 @@
         return TimeUnit.NANOSECONDS;
     }
 
-    private abstract static class AbstractTimer implements TimerCloseable {
+    private abstract static class AbstractTimer extends CloseableCounterImpl implements DebugCloseable {
 
-        private final AbstractTimer parent;
-        private final TimerImpl timer;
-        private final long startTime;
-        private long nestedTimeToSubtract;
-
-        private AbstractTimer(TimerImpl timer, long startTime) {
-            this.parent = currentTimer.get();
-            this.timer = timer;
-            this.startTime = startTime;
+        private AbstractTimer(AccumulatedDebugValue counter) {
+            super(currentTimer.get(), counter);
         }
 
         @Override
         public void close() {
-            long endTime = currentTime();
-            long timeSpan = endTime - startTime;
-            if (parent != null) {
-                if (timer != parent.timer) {
-                    parent.nestedTimeToSubtract += timeSpan;
-
-                    // Look for our timer in an outer timing scope and fix up
-                    // the adjustment to the flat time
-                    AbstractTimer ancestor = parent.parent;
-                    while (ancestor != null) {
-                        if (ancestor.timer == timer) {
-                            ancestor.nestedTimeToSubtract -= timeSpan;
-                            break;
-                        }
-                        ancestor = ancestor.parent;
-                    }
-                }
-            }
+            super.close();
             currentTimer.set(parent);
-            long flatTime = timeSpan - nestedTimeToSubtract;
-            timer.addToCurrentValue(timeSpan);
-            timer.flat.addToCurrentValue(flatTime);
         }
-
-        protected abstract long currentTime();
     }
 
     private final class SystemNanosTimer extends AbstractTimer {
 
-        public SystemNanosTimer(TimerImpl timer, long startTime) {
-            super(timer, startTime);
+        public SystemNanosTimer(TimerImpl timer) {
+            super(timer);
         }
 
         @Override
-        protected long currentTime() {
+        protected long getCounterValue() {
             return System.nanoTime();
         }
     }
 
     private final class CpuTimeTimer extends AbstractTimer {
 
-        public CpuTimeTimer(TimerImpl timer, long startTime) {
-            super(timer, startTime);
+        public CpuTimeTimer(TimerImpl timer) {
+            super(timer);
         }
 
         @Override
-        protected long currentTime() {
+        protected long getCounterValue() {
             return threadMXBean.getCurrentThreadCpuTime();
         }
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Mar 03 10:32:17 2015 -0800
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.options.*;
@@ -887,7 +886,7 @@
 
     @SuppressWarnings("all")
     public Map<Node, Node> addDuplicates(Iterable<? extends Node> newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) {
-        try (TimerCloseable s = DuplicateGraph.start()) {
+        try (DebugCloseable s = DuplicateGraph.start()) {
             return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements);
         }
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Mar 03 10:32:17 2015 -0800
@@ -34,7 +34,6 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.Edges.Type;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Node.Input;
@@ -64,7 +63,7 @@
     private static final DebugTimer Init_IterableIds = Debug.timer("NodeClass.Init.IterableIds");
 
     private static <T extends Annotation> T getAnnotationTimed(AnnotatedElement e, Class<T> annotationClass) {
-        try (TimerCloseable s = Init_AnnotationParsing.start()) {
+        try (DebugCloseable s = Init_AnnotationParsing.start()) {
             return e.getAnnotation(annotationClass);
         }
     }
@@ -147,15 +146,15 @@
         this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz);
 
         NodeFieldsScanner fs = new NodeFieldsScanner(calcOffset, superNodeClass);
-        try (TimerCloseable t = Init_FieldScanning.start()) {
+        try (DebugCloseable t = Init_FieldScanning.start()) {
             fs.scan(clazz, clazz.getSuperclass(), false);
         }
 
-        try (TimerCloseable t1 = Init_Edges.start()) {
+        try (DebugCloseable t1 = Init_Edges.start()) {
             successors = new SuccessorEdges(fs.directSuccessors, fs.successors);
             inputs = new InputEdges(fs.directInputs, fs.inputs);
         }
-        try (TimerCloseable t1 = Init_Data.start()) {
+        try (DebugCloseable t1 = Init_Data.start()) {
             data = new Fields(fs.data);
         }
 
@@ -168,7 +167,7 @@
         assert info != null : "Missing NodeInfo annotation on " + clazz;
         this.nameTemplate = info.nameTemplate();
 
-        try (TimerCloseable t1 = Init_AllowedUsages.start()) {
+        try (DebugCloseable t1 = Init_AllowedUsages.start()) {
             allowedUsageTypes = superNodeClass == null ? EnumSet.noneOf(InputType.class) : superNodeClass.allowedUsageTypes.clone();
             allowedUsageTypes.addAll(Arrays.asList(info.allowedUsageTypes()));
         }
@@ -178,7 +177,7 @@
             this.iterableId = presetIterableId;
         } else if (IterableNodeType.class.isAssignableFrom(clazz)) {
             ITERABLE_NODE_TYPES.increment();
-            try (TimerCloseable t1 = Init_IterableIds.start()) {
+            try (DebugCloseable t1 = Init_IterableIds.start()) {
                 this.iterableId = nextIterableId.getAndIncrement();
 
                 NodeClass<?> snc = superNodeClass;
@@ -335,7 +334,7 @@
             Input inputAnnotation = getAnnotationTimed(field, Node.Input.class);
             OptionalInput optionalInputAnnotation = getAnnotationTimed(field, Node.OptionalInput.class);
             Successor successorAnnotation = getAnnotationTimed(field, Successor.class);
-            try (TimerCloseable s = Init_FieldScanningInner.start()) {
+            try (DebugCloseable s = Init_FieldScanningInner.start()) {
                 Class<?> type = field.getType();
                 int modifiers = field.getModifiers();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Tue Mar 03 10:32:17 2015 -0800
@@ -172,7 +172,7 @@
         EventProvider eventProvider = Graal.getRequiredCapability(EventProvider.class);
         CompilationEvent compilationEvent = eventProvider.newCompilationEvent();
 
-        try (TimerCloseable a = CompilationTime.start()) {
+        try (DebugCloseable a = CompilationTime.start()) {
             // If there is already compiled code for this method on our level we simply return.
             // Graal compiles are always at the highest compile level, even in non-tiered mode so we
             // only need to check for that value.
@@ -259,7 +259,7 @@
                 }
             }
 
-            try (TimerCloseable b = CodeInstallationTime.start()) {
+            try (DebugCloseable b = CodeInstallationTime.start()) {
                 installedCode = (HotSpotInstalledCode) installMethod(result);
                 if (!isOSR) {
                     ProfilingInfo profile = method.getProfilingInfo();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Tue Mar 03 10:32:17 2015 -0800
@@ -29,8 +29,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.DebugMemUseTracker.Closeable;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.options.*;
@@ -87,7 +85,7 @@
 
     public final <B extends AbstractBlockBase<B>> void apply(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, C context, boolean dumpLIR) {
         try (Scope s = Debug.scope(getName(), this)) {
-            try (TimerCloseable a = timer.start(); Closeable c = memUseTracker.start()) {
+            try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) {
                 run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context);
                 if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) {
                     Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "After phase %s", getName());
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java	Tue Mar 03 10:32:17 2015 -0800
@@ -23,7 +23,7 @@
 package com.oracle.graal.lir.stackslotalloc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.lir.phases.LIRPhase.Options.LIROptimization;
+import static com.oracle.graal.lir.phases.LIRPhase.Options.*;
 
 import java.util.*;
 import java.util.function.*;
@@ -33,7 +33,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
@@ -75,7 +74,7 @@
     }
 
     public void allocateStackSlots(FrameMapBuilderTool builder, LIRGenerationResult res) {
-        try (TimerCloseable t = MainTimer.start()) {
+        try (DebugCloseable t = MainTimer.start()) {
             new Allocator(res.getLIR(), builder).allocate();
         }
     }
@@ -100,7 +99,7 @@
             // insert by to
             this.active = new PriorityQueue<>((a, b) -> a.to() - b.to());
 
-            try (TimerCloseable t = NumInstTimer.start()) {
+            try (DebugCloseable t = NumInstTimer.start()) {
                 // step 1: number instructions
                 this.maxOpId = numberInstructions(lir, sortedBlocks);
             }
@@ -112,12 +111,12 @@
             long currentFrameSize = Debug.isMeterEnabled() ? frameMapBuilder.getFrameMap().currentFrameSize() : 0;
             Set<LIRInstruction> usePos;
             // step 2: build intervals
-            try (Scope s = Debug.scope("StackSlotAllocationBuildIntervals"); Indent indent = Debug.logAndIndent("BuildIntervals"); TimerCloseable t = BuildIntervalsTimer.start()) {
+            try (Scope s = Debug.scope("StackSlotAllocationBuildIntervals"); Indent indent = Debug.logAndIndent("BuildIntervals"); DebugCloseable t = BuildIntervalsTimer.start()) {
                 usePos = buildIntervals();
             }
             // step 3: verify intervals
             if (Debug.isEnabled()) {
-                try (TimerCloseable t = VerifyIntervalsTimer.start()) {
+                try (DebugCloseable t = VerifyIntervalsTimer.start()) {
                     verifyIntervals();
                 }
             }
@@ -125,7 +124,7 @@
                 dumpIntervals("Before stack slot allocation");
             }
             // step 4: allocate stack slots
-            try (TimerCloseable t = AllocateSlotsTimer.start()) {
+            try (DebugCloseable t = AllocateSlotsTimer.start()) {
                 allocateStackSlots();
             }
             if (Debug.isDumpEnabled()) {
@@ -133,7 +132,7 @@
             }
 
             // step 5: assign stack slots
-            try (TimerCloseable t = AssignSlotsTimer.start()) {
+            try (DebugCloseable t = AssignSlotsTimer.start()) {
                 assignStackSlots(usePos);
             }
             Debug.dump(lir, "After StackSlot assignment");
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java	Tue Mar 03 10:32:17 2015 -0800
@@ -26,8 +26,6 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.DebugMemUseTracker.Closeable;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
@@ -96,7 +94,7 @@
     }
 
     public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
-        try (TimerCloseable a = timer.start(); Scope s = Debug.scope(getClass(), this); Closeable c = memUseTracker.start()) {
+        try (DebugCloseable a = timer.start(); Scope s = Debug.scope(getClass(), this); DebugCloseable c = memUseTracker.start()) {
             if (dumpGraph && Debug.isDumpEnabled(BEFORE_PHASE_DUMP_LEVEL)) {
                 Debug.dump(BEFORE_PHASE_DUMP_LEVEL, graph, "Before phase %s", getName());
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Tue Mar 03 10:32:17 2015 -0800
@@ -41,7 +41,6 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
@@ -262,7 +261,7 @@
 
         StructuredGraph graph = UseSnippetGraphCache ? graphs.get(method) : null;
         if (graph == null) {
-            try (TimerCloseable a = SnippetPreparationTime.start()) {
+            try (DebugCloseable a = SnippetPreparationTime.start()) {
                 FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal
                                 : FrameStateProcessing.CollapseFrameForSingleSideEffect;
                 StructuredGraph newGraph = makeGraph(method, recursiveEntry, inliningPolicy(method), frameStateProcessing);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Mar 03 10:32:17 2015 -0800
@@ -43,7 +43,6 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node;
@@ -520,7 +519,7 @@
             SnippetTemplate template = UseSnippetTemplateCache ? templates.get(args.cacheKey) : null;
             if (template == null) {
                 SnippetTemplates.increment();
-                try (TimerCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.scope("SnippetSpecialization", args.info.method)) {
+                try (DebugCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.scope("SnippetSpecialization", args.info.method)) {
                     template = new SnippetTemplate(providers, snippetReflection, args);
                     if (UseSnippetTemplateCache) {
                         templates.put(args.cacheKey, template);
@@ -1099,7 +1098,7 @@
      */
     public Map<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args) {
         assert assertSnippetKills(replacee);
-        try (TimerCloseable a = args.info.instantiationTimer.start(); TimerCloseable b = instantiationTimer.start()) {
+        try (DebugCloseable a = args.info.instantiationTimer.start(); DebugCloseable b = instantiationTimer.start()) {
             args.info.instantiationCounter.increment();
             instantiationCounter.increment();
             // Inline the snippet nodes, replacing parameters with the given args in the process
@@ -1246,7 +1245,7 @@
      */
     public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
         assert assertSnippetKills(replacee);
-        try (TimerCloseable a = args.info.instantiationTimer.start()) {
+        try (DebugCloseable a = args.info.instantiationTimer.start()) {
             args.info.instantiationCounter.increment();
             instantiationCounter.increment();
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Mar 03 16:10:35 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Tue Mar 03 10:32:17 2015 -0800
@@ -36,8 +36,6 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.debug.DebugMemUseTracker.Closeable;
-import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.phases.*;
@@ -131,7 +129,7 @@
         try {
             PhaseSuite<HighTierContext> graphBuilderSuite = createGraphBuilderSuite();
 
-            try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) {
+            try (DebugCloseable a = PartialEvaluationTime.start(); DebugCloseable c = PartialEvaluationMemUse.start()) {
                 graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES);
             }
 
@@ -157,7 +155,7 @@
         }
 
         CompilationResult result = null;
-        try (TimerCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache()); Closeable c = CompilationMemUse.start()) {
+        try (DebugCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache()); DebugCloseable c = CompilationMemUse.start()) {
             CodeCacheProvider codeCache = providers.getCodeCache();
             CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
             CompilationResult compilationResult = new CompilationResult(name);
@@ -190,7 +188,7 @@
         result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()]));
 
         InstalledCode installedCode;
-        try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start(); Closeable c = CodeInstallationMemUse.start()) {
+        try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); DebugCloseable a = CodeInstallationTime.start(); DebugCloseable c = CodeInstallationMemUse.start()) {
             installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog, predefinedInstalledCode);
         } catch (Throwable e) {
             throw Debug.handle(e);