Backed out changeset d446894bc3a6
authorBill McCloskey <wmccloskey@mozilla.com>
Thu, 18 Nov 2010 18:03:41 -0800
changeset 58052 1da3a1594a1826cd3f723169053cd734d3298772
parent 58039 d446894bc3a61fb381f6d6d5e9c4ba4605fa3a16
child 58053 e8bd9ab117c586595ef6a7e6dc1665f8aa32b91d
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
milestone2.0b8pre
backs outd446894bc3a61fb381f6d6d5e9c4ba4605fa3a16
Backed out changeset d446894bc3a6
js/src/Makefile.in
js/src/assembler/assembler/MacroAssemblerARM.h
js/src/jshotloop.h
js/src/jstracer.cpp
js/src/jstracer.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -233,17 +233,16 @@ INSTALLED_HEADERS = \
 		jsscan.h \
 		jsscope.h \
 		jsscript.h \
 		jsscriptinlines.h \
 		jsstaticcheck.h \
 		jsstdint.h \
 		jsstr.h \
 		jstracer.h \
-		jshotloop.h \
 		jstypedarray.h \
 		jstypes.h \
 		jsutil.h \
 		jsvector.h \
 		jstl.h \
 		jshashtable.h \
 		jsversion.h \
 		jswrapper.h \
--- a/js/src/assembler/assembler/MacroAssemblerARM.h
+++ b/js/src/assembler/assembler/MacroAssemblerARM.h
@@ -645,23 +645,16 @@ public:
 
     Jump branchSub32(Condition cond, Address src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         sub32(src, dest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchSub32(Condition cond, Imm32 imm, Address dest)
-    {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
-        sub32(imm, dest);
-        return Jump(m_assembler.jmp(ARMCondition(cond)));
-    }
-
     Jump branchNeg32(Condition cond, RegisterID srcDest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         neg32(srcDest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
deleted file mode 100644
--- a/js/src/jshotloop.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Mozilla SpiderMonkey JaegerMonkey implementation
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2002-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef jshotloop_h___
-#define jshotloop_h___
-
-#include "jscntxt.h"
-
-namespace js {
-
-uint32
-GetHotloop(JSContext *cx);
-
-}
-
-#endif
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -6521,30 +6521,30 @@ ExecuteTree(JSContext* cx, TreeFragment*
 
     /* Restore interpreter state. */
     LeaveTree(tm, state, lr);
 
     *lrp = state.innermost;
     bool ok = !(state.builtinStatus & BUILTIN_ERROR);
     JS_ASSERT_IF(cx->throwing, !ok);
 
-    uintN iters = JS_THREAD_DATA(cx)->iterationCounter;
+    size_t iters = JS_THREAD_DATA(cx)->iterationCounter;
 
     f->execs++;
     f->iters += iters;
 
 #ifdef DEBUG
     JSStackFrame *fp = cx->fp();
     const char *prefix = "";
     if (iters == LOOP_COUNT_MAX)
         prefix = ">";
     debug_only_printf(LC_TMMinimal, "  [%.3f ms] Tree at line %u executed for %s%u iterations;"
                       " executed %u times; leave for %s at %s:%u (%s)\n",
                       double(t1-t0) / PRMJ_USEC_PER_MSEC,
-                      f->treeLineNumber, prefix, iters, f->execs,
+                      f->treeLineNumber, prefix, (uintN)iters, f->execs,
                       getExitName(lr->exitType),
                       fp->script()->filename,
                       js_FramePCToLineNumber(cx, fp),
                       js_CodeName[fp->hasImacropc() ? *fp->imacropc() : *cx->regs->pc]);
 #endif
     
 #ifdef JS_METHODJIT
     if (cx->methodJitEnabled) {
@@ -16329,39 +16329,29 @@ RecordTracePoint(JSContext* cx, uintN& i
 }
 
 LoopProfile::LoopProfile(JSStackFrame *entryfp, jsbytecode *top, jsbytecode *bottom)
     : script(entryfp->script()),
       entryfp(entryfp),
       top(top),
       bottom(bottom),
       hits(0),
-      undecided(false),
-      expensive(false),
-      unprofitable(false)
-{
-    reset();
-}
-
-void
-LoopProfile::reset()
-{
-    profiled = false;
-    traceOK = false;
-    execOK = false;
-    numAllOps = 0;
-    numSelfOps = 0;
-    numSelfOpsMult = 0;
-    branchMultiplier = 1;
-    shortLoop = false;
-    maybeShortLoop = false;
-    numInnerLoops = 0;
-    loopStackDepth = 0;
-    sp = 0;
-
+      profiled(false),
+      traceOK(false),
+      execOK(false),
+      numAllOps(0),
+      numSelfOps(0),
+      numSelfOpsMult(0),
+      branchMultiplier(1),
+      shortLoop(false),
+      maybeShortLoop(false),
+      numInnerLoops(0),
+      loopStackDepth(0),
+      sp(0)
+{
     memset(allOps, 0, sizeof(allOps));
     memset(selfOps, 0, sizeof(selfOps));
 }
 
 MonitorResult
 LoopProfile::profileLoopEdge(JSContext* cx, uintN& inlineCallCount)
 {
     if (cx->regs->pc == top) {
@@ -16447,17 +16437,17 @@ LookupOrAddProfile(JSContext *cx, TraceM
         }
     }
 
     return prof;
 }
 
 JS_REQUIRES_STACK TracePointAction
 MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist,
-                  void** traceData, uintN *traceEpoch, uint32 *loopCounter, uint32 hits)
+                  void** traceData, uintN *traceEpoch)
 {
     if (!cx->profilingEnabled)
         return RecordTracePoint(cx, inlineCallCount, blacklist, true);
 
     *blacklist = false;
 
     TraceMonitor *tm = &JS_TRACE_MONITOR(cx);
     /*
@@ -16468,18 +16458,17 @@ MonitorTracePoint(JSContext *cx, uintN& 
         return TPA_Nothing;
 
     LoopProfile *prof = LookupOrAddProfile(cx, tm, traceData, traceEpoch);
     if (!prof) {
         *blacklist = true;
         return TPA_Nothing;
     }
 
-    prof->hits += hits;
-    if (prof->hits < PROFILE_HOTLOOP)
+    if (prof->hits++ < PROFILE_HOTLOOP)
         return TPA_Nothing;
 
     AutoRetBlacklist autoRetBlacklist(cx->regs->pc, blacklist);
 
     if (prof->profiled) {
         if (prof->traceOK) {
             return RecordTracePoint(cx, inlineCallCount, blacklist, prof->execOK);
         } else {
@@ -16492,21 +16481,16 @@ MonitorTracePoint(JSContext *cx, uintN& 
 
     prof->entryfp = cx->fp();
     tm->profile = prof;
 
     if (!Interpret(cx, cx->fp(), inlineCallCount, JSINTERP_PROFILE))
         return TPA_Error;
 
     JS_ASSERT(!cx->throwing);
-
-    if (prof->undecided) {
-        *loopCounter = 2000;
-        prof->reset();
-    }
     
     return TPA_RanStuff;
 }
 
 /*
  * Returns true if pc is within the given loop. Also returns true if
  * we are in some function called by the loop.
  */
@@ -16527,40 +16511,39 @@ LoopProfile::profileOperation(JSContext*
         return ProfComplete;
     }
 
     jsbytecode *pc = cx->regs->pc;
     JSStackFrame *fp = cx->fp();
     JSScript *script = fp->script();
 
     if (!PCWithinLoop(fp, pc, *this)) {
-        debug_only_printf(LC_TMProfiler, "Profiling complete (loop exit) at line %u\n",
+        debug_only_printf(LC_TMProfiler, "Profiling complete (loop exit) at %d (line %u)\n",
+                          (int)(cx->regs->pc - script->code),
                           js_FramePCToLineNumber(cx, cx->fp()));
         tm->profile->decide(cx);
         tm->profile = NULL;
         return ProfComplete;
     }
 
     while (loopStackDepth > 0 && !PCWithinLoop(fp, pc, loopStack[loopStackDepth-1])) {
-        debug_only_printf(LC_TMProfiler, "Profiler: Exiting inner loop at line %u\n",
-                          js_FramePCToLineNumber(cx, cx->fp()));
+        debug_only_print0(LC_TMProfiler, "Profiler: Exiting inner loop\n");
         loopStackDepth--;
     }
 
     if (op == JSOP_TRACE || op == JSOP_NOTRACE) {
         if (pc != top && (loopStackDepth == 0 || pc != loopStack[loopStackDepth-1].top)) {
             if (loopStackDepth == PROFILE_MAX_INNER_LOOPS) {
                 debug_only_print0(LC_TMProfiler, "Profiling complete (maxnest)\n");
                 tm->profile->decide(cx);
                 tm->profile = NULL;
                 return ProfComplete;
             }
 
-            debug_only_printf(LC_TMProfiler, "Profiler: Entering inner loop at line %d\n",
-                              js_FramePCToLineNumber(cx, cx->fp()));
+            debug_only_print0(LC_TMProfiler, "Profiler: Entering inner loop\n");
             loopStack[loopStackDepth++] = InnerLoop(fp, pc, GetLoopBottom(cx));
         }
     }
 
     numAllOps++;
     if (loopStackDepth == 0) {
         numSelfOps++;
         numSelfOpsMult += branchMultiplier;
@@ -16591,18 +16574,16 @@ LoopProfile::profileOperation(JSContext*
 
     if (op == JSOP_NEW)
         increment(OP_NEW);
 
     if (op == JSOP_GETELEM || op == JSOP_SETELEM) {
         Value& lval = cx->regs->sp[op == JSOP_GETELEM ? -2 : -3];
         if (lval.isObject() && js_IsTypedArray(&lval.toObject()))
             increment(OP_TYPED_ARRAY);
-        else if (lval.isObject() && lval.toObject().isDenseArray() && op == JSOP_GETELEM)
-            increment(OP_ARRAY_READ);
     }
 
     if (op == JSOP_CALL) {
         increment(OP_CALL);
 
         uintN argc = GET_ARGC(cx->regs->pc);
         Value &v = cx->regs->sp[-((int)argc + 2)];
         JSObject *callee;
@@ -16722,71 +16703,79 @@ LookupLoopProfile(JSContext *cx, jsbytec
     LoopProfileMap &table = *tm->loopProfiles;
     if (LoopProfileMap::Ptr p = table.lookup(pc)) {
         JS_ASSERT(p->value->top == pc);
         return p->value;
     } else
         return NULL;
 }
 
-/* Returns true if the loop would probably take a long time to compile. */
+/*
+ * Returns true if the loop would probably take a long time to
+ * compile. Since this function recurses into nested loops, we
+ * pass a depth argument to ensure that we don't recurse too
+ * far and overflow the stack. Mostly, we're guarding against
+ * the possibility that we (incorrectly) track a loop as being
+ * nested inside itself, leading to infinite recursion.
+ */
 bool
-LoopProfile::isCompilationExpensive(JSContext *cx)
-{
+LoopProfile::isCompilationExpensive(JSContext *cx, uintN depth)
+{
+    if (depth == 0)
+        return true;
+
     /* Too many ops to compile? */
     if (numSelfOps == MAX_PROFILE_OPS)
-        expensive = true;
+        return true;
 
     /* Is the code too branchy? */
     if (numSelfOpsMult > numSelfOps*100000)
-        expensive = true;
+        return true;
 
     /* Ensure that inner loops aren't too expensive. */
     for (uintN i=0; i<numInnerLoops; i++) {
         LoopProfile *prof = LookupLoopProfile(cx, innerLoops[i].top);
-        if (prof && prof->expensive)
-            expensive = true;
-    }
-
-    return expensive;
+        if (prof && prof->isCompilationExpensive(cx, depth-1))
+            return true;
+    }
+
+    return false;
 }
 
 /*
  * This function recognizes loops that are short and that contain
  * jumps. The tracer does badly with these loops because it
  * needs to do a lot of side exits, which are somewhat
  * expensive.
  */
 bool
-LoopProfile::isCompilationUnprofitable(JSContext *cx, uintN goodOps)
-{
-    if (goodOps <= 20 && allOps[OP_FWDJUMP])
-        unprofitable = true;
+LoopProfile::isCompilationUnprofitable(JSContext *cx, uintN depth)
+{
+    if (depth == 0)
+        return true;
+
+    if (numAllOps < 15 && allOps[OP_FWDJUMP])
+        return true;
     
     /* Ensure that inner loops aren't fleeting. */
     for (uintN i=0; i<numInnerLoops; i++) {
         LoopProfile *prof = LookupLoopProfile(cx, innerLoops[i].top);
-        if (prof && prof->unprofitable)
-            unprofitable = true;
-    }
-
-    return unprofitable;
+        if (prof && prof->isCompilationUnprofitable(cx, depth-1))
+            return true;
+    }
+
+    return false;
 }
 
 /* After profiling is done, this method decides whether to trace the loop. */
 void
 LoopProfile::decide(JSContext *cx)
 {
-    bool wasUndecided = undecided;
     profiled = true;
-    undecided = false;
-
-    if (traceOK)
-        return; /* We must have enabled it from an outer loop already. */
-    
+
 #ifdef DEBUG
     uintN line = js_PCToLineNumber(cx, script, top);
 
     debug_only_printf(LC_TMProfiler, "LOOP %s:%d\n", script->filename, line);
 
     for (uintN i=0; i<numInnerLoops; i++) {
         InnerLoop &loop = innerLoops[i];
         if (LoopProfile *prof = LookupLoopProfile(cx, loop.top)) {
@@ -16797,17 +16786,16 @@ LoopProfile::decide(JSContext *cx)
     }
     debug_only_printf(LC_TMProfiler, "FEATURE float %d\n", allOps[OP_FLOAT]);
     debug_only_printf(LC_TMProfiler, "FEATURE int %d\n", allOps[OP_INT]);
     debug_only_printf(LC_TMProfiler, "FEATURE bit %d\n", allOps[OP_BIT]);
     debug_only_printf(LC_TMProfiler, "FEATURE equality %d\n", allOps[OP_EQ]);
     debug_only_printf(LC_TMProfiler, "FEATURE eval %d\n", allOps[OP_EVAL]);
     debug_only_printf(LC_TMProfiler, "FEATURE new %d\n", allOps[OP_NEW]);
     debug_only_printf(LC_TMProfiler, "FEATURE call %d\n", allOps[OP_CALL]);
-    debug_only_printf(LC_TMProfiler, "FEATURE arrayread %d\n", allOps[OP_ARRAY_READ]);
     debug_only_printf(LC_TMProfiler, "FEATURE typedarray %d\n", allOps[OP_TYPED_ARRAY]);
     debug_only_printf(LC_TMProfiler, "FEATURE fwdjump %d\n", allOps[OP_FWDJUMP]);
     debug_only_printf(LC_TMProfiler, "FEATURE recursive %d\n", allOps[OP_RECURSIVE]);
     debug_only_printf(LC_TMProfiler, "FEATURE shortLoop %d\n", shortLoop);
     debug_only_printf(LC_TMProfiler, "FEATURE maybeShortLoop %d\n", maybeShortLoop);
     debug_only_printf(LC_TMProfiler, "FEATURE numAllOps %d\n", numAllOps);
     debug_only_printf(LC_TMProfiler, "FEATURE selfOps %d\n", numSelfOps);
     debug_only_printf(LC_TMProfiler, "FEATURE selfOpsMult %g\n", numSelfOpsMult);
@@ -16821,42 +16809,37 @@ LoopProfile::decide(JSContext *cx)
     if (count(OP_RECURSIVE)) {
         debug_only_print0(LC_TMProfiler, "NOTRACE: recursive\n");
     } else if (count(OP_EVAL)) {
         debug_only_print0(LC_TMProfiler, "NOTRACE: eval\n");
     } else if (numInnerLoops > 3) {
         debug_only_print0(LC_TMProfiler, "NOTRACE: >3 inner loops\n");
     } else if (shortLoop) {
         debug_only_print0(LC_TMProfiler, "NOTRACE: short\n");
-    } else if (isCompilationExpensive(cx)) {
+    } else if (maybeShortLoop && numInnerLoops < 2) {
+        debug_only_print0(LC_TMProfiler, "NOTRACE: maybe short\n");
+    } else if (isCompilationExpensive(cx, 4)) {
         debug_only_print0(LC_TMProfiler, "NOTRACE: expensive\n");
-    } else if (maybeShortLoop && numInnerLoops < 2) {
-        if (wasUndecided) {
-            debug_only_print0(LC_TMProfiler, "NOTRACE: maybe short\n");
-        } else {
-            debug_only_print0(LC_TMProfiler, "UNDECIDED: maybe short\n");
-            undecided = true; /* Profile the loop again to see if it's still short. */
-        }
+    } else if (isCompilationUnprofitable(cx, 4)) {
+        debug_only_print0(LC_TMProfiler, "NOTRACE: unprofitable\n");
     } else {
         uintN goodOps = 0;
 
         /* The tracer handles these ops well because of type specialization. */
         goodOps += count(OP_FLOAT)*10 + count(OP_BIT)*10 + count(OP_INT)*5;
 
         /* The tracer handles these ops well because of inlining. */
         goodOps += (count(OP_CALL) + count(OP_NEW))*20;
 
         /* The tracer specialized typed array access. */
         goodOps += count(OP_TYPED_ARRAY)*10;
 
         debug_only_printf(LC_TMProfiler, "FEATURE goodOps %u\n", goodOps);
-
-        if (isCompilationUnprofitable(cx, goodOps))
-            debug_only_print0(LC_TMProfiler, "NOTRACE: unprofitable\n");
-        else if (goodOps >= numAllOps)
+        
+        if (goodOps >= numAllOps)
             traceOK = true;
     }
 
     debug_only_printf(LC_TMProfiler, "TRACE %s:%d = %d\n", script->filename, line, traceOK);
 
     if (traceOK) {
         /* Unblacklist the inner loops. */
         for (uintN i=0; i<numInnerLoops; i++) {
@@ -16873,17 +16856,17 @@ LoopProfile::decide(JSContext *cx)
                 if (IsBlacklisted(loop.top))
                     debug_only_printf(LC_TMProfiler, "Unblacklisting at %d\n",
                                       js_PCToLineNumber(cx, loop.script, loop.top));
                 Unblacklist(loop.script, loop.top);
             }
         }
     }
 
-    if (!traceOK && !undecided) {
+    if (!traceOK) {
         debug_only_printf(LC_TMProfiler, "Blacklisting at %d\n", line);
         Blacklist(top);
     }
 
     debug_only_print0(LC_TMProfiler, "\n");
 
     execOK = traceOK;
 }
@@ -16901,17 +16884,17 @@ MonitorLoopEdge(JSContext* cx, uintN& in
 
     LoopProfile *prof = LookupOrAddProfile(cx, tm, NULL, NULL);
     if (!prof)
         return MONITOR_NOT_RECORDING;
 
     if (prof->hits++ < PROFILE_HOTLOOP)
         return MONITOR_NOT_RECORDING;
 
-    if (prof->profiled || prof->undecided) {
+    if (prof->profiled) {
         if (prof->traceOK)
             return RecordLoopEdge(cx, inlineCallCount, prof->execOK);
         return MONITOR_NOT_RECORDING;
     }
 
     debug_only_printf(LC_TMProfiler, "Profiling at line %d from interpreter\n",
                       js_FramePCToLineNumber(cx, cx->fp()));
 
@@ -16924,36 +16907,24 @@ MonitorLoopEdge(JSContext* cx, uintN& in
 void
 AbortProfiling(JSContext *cx)
 {
     debug_only_print0(LC_TMProfiler, "Profiling complete (aborted)\n");
     TraceMonitor *tm = &JS_TRACE_MONITOR(cx);
     tm->profile->profiled = true;
     tm->profile->traceOK = false;
     tm->profile->execOK = false;
-    tm->profile->undecided = false;
     Blacklist(tm->profile->top);
     tm->profile = NULL;
 }
 
 #else /* JS_METHODJIT */
 
 JS_REQUIRES_STACK MonitorResult
 MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
 {
     return RecordLoopEdge(cx, inlineCallCount, true);
 }
 
 #endif /* JS_METHODJIT */
 
-uint32
-GetHotloop(JSContext *cx)
-{
-#ifdef JS_METHODJIT
-    if (cx->profilingEnabled)
-        return PROFILE_HOTLOOP;
-    else
-#endif
-        return 1;
-}
-
 } /* namespace js */
 
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -611,17 +611,17 @@ struct TreeFragment : public LinkableFra
     /* All embedded GC things are registered here so the GC can scan them. */
     Queue<Value>            gcthings;
     Queue<const js::Shape*> shapes;
     unsigned                maxNativeStackSlots;
     /* Gives the number of times we have entered this trace. */
     uintN                   execs;
     /* Gives the total number of iterations executed by the trace (up to a limit). */
     uintN                   iters;
-    
+
     inline unsigned nGlobalTypes() {
         return typeMap.length() - nStackTypes;
     }
     inline JSValueType* globalTypeMap() {
         return typeMap.data() + nStackTypes;
     }
     inline JSValueType* stackTypeMap() {
         return typeMap.data();
@@ -661,17 +661,16 @@ public:
         OP_INT, // Integer arithmetic
         OP_BIT, // Bit operations
         OP_EQ, // == and !=
         OP_EVAL, // Calls to eval()
         OP_CALL, // JSOP_CALL instructions
         OP_FWDJUMP, // Jumps with positive delta
         OP_NEW, // JSOP_NEW instructions
         OP_RECURSIVE, // Recursive calls
-        OP_ARRAY_READ, // Reads from dense arrays
         OP_TYPED_ARRAY, // Accesses to typed arrays
         OP_LIMIT
     };
 
     /* The script in which the loop header lives. */
     JSScript *script;
 
     /* The stack frame where we started profiling. Only valid while profiling! */
@@ -681,19 +680,16 @@ public:
     jsbytecode *top, *bottom;
 
     /* Number of times we have seen this loop executed; used to decide when to profile. */
     uintN hits;
 
     /* Whether we have run a complete profile of the loop. */
     bool profiled;
 
-    /* Sometimes we can't decide in one profile run whether to trace, so we set undecided. */
-    bool undecided;
-
     /* If we have profiled the loop, this saves the decision of whether to trace it. */
     bool traceOK;
 
     /*
      * Sometimes loops are not good tracing opportunities, but they are nested inside
      * loops that we want to trace. In that case, we set their traceOK flag to true,
      * but we set execOK to false. That way, the loop is traced so that it can be
      * integrated into the outer trace. But we never execute the trace on its only.
@@ -725,20 +721,16 @@ public:
     double branchMultiplier;
 
     /* Set to true if the loop is short (i.e., has fewer than 8 iterations). */
     bool shortLoop;
 
     /* Set to true if the loop may be short (has few iterations at profiling time). */
     bool maybeShortLoop;
 
-    /* These are memoized versions of isCompilationExpensive/Unprofitable. */
-    bool expensive;
-    bool unprofitable;
-
     /*
      * When we hit a nested loop while profiling, we record where it occurs
      * and how many iterations we execute it.
      */
     struct InnerLoop {
         JSStackFrame *entryfp;
         JSScript *script;
         jsbytecode *top, *bottom;
@@ -793,18 +785,16 @@ public:
         if (pos >= 0 && uintN(pos) < PROFILE_MAX_STACK)
             return stack[pos];
         else
             return StackValue(false);
     }
     
     LoopProfile(JSStackFrame *entryfp, jsbytecode *top, jsbytecode *bottom);
 
-    void reset();
-    
     enum ProfileAction {
         ProfContinue,
         ProfComplete
     };
 
     /* These two functions track the instruction mix. */
     inline void increment(OpKind kind)
     {
@@ -817,18 +807,18 @@ public:
 
     /* Called for every back edge being profiled. */
     MonitorResult profileLoopEdge(JSContext* cx, uintN& inlineCallCount);
     
     /* Called for every instruction being profiled. */
     ProfileAction profileOperation(JSContext *cx, JSOp op);
 
     /* Once a loop's profile is done, these decide whether it should be traced. */
-    bool isCompilationExpensive(JSContext *cx);
-    bool isCompilationUnprofitable(JSContext *cx, uintN goodOps);
+    bool isCompilationExpensive(JSContext *cx, uintN depth);
+    bool isCompilationUnprofitable(JSContext *cx, uintN depth);
     void decide(JSContext *cx);
 };
 
 /*
  * BUILTIN_NO_FIXUP_NEEDED indicates that after the initial LeaveTree of a deep
  * bail, the builtin call needs no further fixup when the trace exits and calls
  * LeaveTree the second time.
  */
@@ -1666,17 +1656,17 @@ MonitorLoopEdge(JSContext* cx, uintN& in
 extern JS_REQUIRES_STACK MonitorResult
 ProfileLoopEdge(JSContext* cx, uintN& inlineCallCount);
 
 extern JS_REQUIRES_STACK TracePointAction
 RecordTracePoint(JSContext*, uintN& inlineCallCount, bool* blacklist);
 
 extern JS_REQUIRES_STACK TracePointAction
 MonitorTracePoint(JSContext*, uintN& inlineCallCount, bool* blacklist,
-                  void** traceData, uintN *traceEpoch, uint32 *loopCounter, uint32 hits);
+                  void** traceData, uintN *traceEpoch);
 
 extern JS_REQUIRES_STACK TraceRecorder::AbortResult
 AbortRecording(JSContext* cx, const char* reason);
 
 extern void
 InitJIT(TraceMonitor *tm);
 
 extern void
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -52,17 +52,16 @@
 #include "assembler/assembler/LinkBuffer.h"
 #include "FrameState-inl.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 #include "InlineFrameAssembler.h"
 #include "jscompartment.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
-#include "jshotloop.h"
 
 #include "jsautooplen.h"
 
 using namespace js;
 using namespace js::mjit;
 #if defined(JS_POLYIC) || defined(JS_MONOIC)
 using namespace js::mjit::ic;
 #endif
@@ -596,18 +595,16 @@ mjit::Compiler::finishThisUp(JITScript *
             scriptTICs[i].stubEntry = stubCode.locationOf(traceICs[i].stubEntry);
             scriptTICs[i].traceData = NULL;
 #ifdef DEBUG
             scriptTICs[i].jumpTargetPC = traceICs[i].jumpTarget;
 #endif
             scriptTICs[i].hasSlowTraceHint = traceICs[i].slowTraceHint.isSet();
             if (traceICs[i].slowTraceHint.isSet())
                 scriptTICs[i].slowTraceHint = stubCode.locationOf(traceICs[i].slowTraceHint.get());
-            scriptTICs[i].loopCounterStart = GetHotloop(cx);
-            scriptTICs[i].loopCounter = scriptTICs[i].loopCounterStart;
             
             stubCode.patch(traceICs[i].addrLabel, &scriptTICs[i]);
         }
     }
 #endif /* JS_MONOIC */
 
     for (size_t i = 0; i < callPatches.length(); i++) {
         CallPatchInfo &patch = callPatches[i];
@@ -4766,39 +4763,35 @@ mjit::Compiler::jumpAndTrace(Jump j, jsb
     Label traceStart = stubcc.masm.label();
 
     stubcc.linkExitDirect(j, traceStart);
     if (slow)
         slow->linkTo(traceStart, &stubcc.masm);
 # if JS_MONOIC
     ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
     traceICs[index] = ic;
-
-    Jump nonzero = stubcc.masm.branchSub32(Assembler::NonZero, Imm32(1),
-                                           Address(Registers::ArgReg1,
-                                                   offsetof(TraceICInfo, loopCounter)));
-    stubcc.jumpInScript(nonzero, target);
 # endif
 
     /* Save and restore compiler-tracked PC, so cx->regs is right in InvokeTracer. */
     {
         jsbytecode* pc = PC;
         PC = target;
 
         OOL_STUBCALL(stubs::InvokeTracer);
 
         PC = pc;
     }
 
     Jump no = stubcc.masm.branchTestPtr(Assembler::Zero, Registers::ReturnReg,
                                         Registers::ReturnReg);
-    if (!stubcc.jumpInScript(no, target))
-        return false;
     restoreFrameRegs(stubcc.masm);
     stubcc.masm.jump(Registers::ReturnReg);
+    no.linkTo(stubcc.masm.label(), &stubcc.masm);
+    if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
+        return false;
 #endif
     return true;
 }
 
 void
 mjit::Compiler::enterBlock(JSObject *obj)
 {
     // If this is an exception entry point, then jsl_InternalThrow has set
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -968,36 +968,27 @@ RunTracer(VMFrame &f)
      */
     entryFrame->scopeChain();
     entryFrame->returnValue();
 
     bool blacklist;
     uintN inlineCallCount = 0;
     void **traceData;
     uintN *traceEpoch;
-    uint32 *loopCounter;
-    uint32 hits;
 #if JS_MONOIC
     traceData = &tic.traceData;
     traceEpoch = &tic.traceEpoch;
-    loopCounter = &tic.loopCounter;
-    *loopCounter = 1;
-    hits = tic.loopCounterStart;
 #else
     traceData = NULL;
     traceEpoch = NULL;
-    loopCounter = NULL;
-    hits = 1;
 #endif
-    tpa = MonitorTracePoint(f.cx, inlineCallCount, &blacklist, traceData, traceEpoch,
-                            loopCounter, hits);
+    tpa = MonitorTracePoint(f.cx, inlineCallCount, &blacklist, traceData, traceEpoch);
     JS_ASSERT(!TRACE_RECORDER(cx));
 
 #if JS_MONOIC
-    tic.loopCounterStart = *loopCounter;
     if (blacklist)
         DisableTraceHint(f, tic);
 #endif
 
     // Even though ExecuteTree() bypasses the interpreter, it should propagate
     // error failures correctly.
     JS_ASSERT_IF(cx->throwing, tpa == TPA_Error);
 
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -148,18 +148,16 @@ struct TraceICInfo {
     JSC::CodeLocationJump slowTraceHint;
 #ifdef DEBUG
     jsbytecode *jumpTargetPC;
 #endif
     
     /* This data is used by the tracing JIT. */
     void *traceData;
     uintN traceEpoch;
-    uint32 loopCounter;
-    uint32 loopCounterStart;
 
     bool hasSlowTraceHint : 1;
 };
 
 static const uint16 BAD_TRACEIC_INDEX = (uint16)0xffff;
 
 void JS_FASTCALL GetGlobalName(VMFrame &f, ic::MICInfo *ic);
 void JS_FASTCALL SetGlobalName(VMFrame &f, ic::MICInfo *ic);