From 120d50c6d9b0236ac281994ab912915537f15c4e Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Thu, 18 Nov 2010 18:03:41 -0800 Subject: [PATCH] Backed out changeset d446894bc3a6 --- js/src/Makefile.in | 1 - .../assembler/assembler/MacroAssemblerARM.h | 7 - js/src/jshotloop.h | 51 ------- js/src/jstracer.cpp | 139 +++++++----------- js/src/jstracer.h | 18 +-- js/src/methodjit/Compiler.cpp | 13 +- js/src/methodjit/InvokeHelpers.cpp | 11 +- js/src/methodjit/MonoIC.h | 2 - 8 files changed, 63 insertions(+), 179 deletions(-) delete mode 100644 js/src/jshotloop.h diff --git a/js/src/Makefile.in b/js/src/Makefile.in index e8f5a49ba2b..674d5ffeae8 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -238,7 +238,6 @@ INSTALLED_HEADERS = \ jsstdint.h \ jsstr.h \ jstracer.h \ - jshotloop.h \ jstypedarray.h \ jstypes.h \ jsutil.h \ diff --git a/js/src/assembler/assembler/MacroAssemblerARM.h b/js/src/assembler/assembler/MacroAssemblerARM.h index bfa30828088..15aca15c81b 100644 --- a/js/src/assembler/assembler/MacroAssemblerARM.h +++ b/js/src/assembler/assembler/MacroAssemblerARM.h @@ -650,13 +650,6 @@ public: 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)); diff --git a/js/src/jshotloop.h b/js/src/jshotloop.h deleted file mode 100644 index 64d86f9c41f..00000000000 --- 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 diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 8956f9fdd32..dacb5e772c6 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -6526,7 +6526,7 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, 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; @@ -6539,7 +6539,7 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, 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), @@ -16334,29 +16334,19 @@ LoopProfile::LoopProfile(JSStackFrame *entryfp, jsbytecode *top, jsbytecode *bot top(top), bottom(bottom), hits(0), - undecided(false), - expensive(false), - unprofitable(false) + profiled(false), + traceOK(false), + execOK(false), + numAllOps(0), + numSelfOps(0), + numSelfOpsMult(0), + branchMultiplier(1), + shortLoop(false), + maybeShortLoop(false), + numInnerLoops(0), + loopStackDepth(0), + sp(0) { - 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; - memset(allOps, 0, sizeof(allOps)); memset(selfOps, 0, sizeof(selfOps)); } @@ -16452,7 +16442,7 @@ LookupOrAddProfile(JSContext *cx, TraceMonitor *tm, void** traceData, uintN *tra 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); @@ -16473,8 +16463,7 @@ MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist, 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); @@ -16497,11 +16486,6 @@ MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist, return TPA_Error; JS_ASSERT(!cx->throwing); - - if (prof->undecided) { - *loopCounter = 2000; - prof->reset(); - } return TPA_RanStuff; } @@ -16532,7 +16516,8 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op) 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; @@ -16540,8 +16525,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op) } 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--; } @@ -16554,8 +16538,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op) 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)); } } @@ -16596,8 +16579,6 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op) 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) { @@ -16727,26 +16708,36 @@ LookupLoopProfile(JSContext *cx, jsbytecode *pc) 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; iexpensive) - expensive = true; + if (prof && prof->isCompilationExpensive(cx, depth-1)) + return true; } - return expensive; + return false; } /* @@ -16756,32 +16747,30 @@ LoopProfile::isCompilationExpensive(JSContext *cx) * expensive. */ bool -LoopProfile::isCompilationUnprofitable(JSContext *cx, uintN goodOps) +LoopProfile::isCompilationUnprofitable(JSContext *cx, uintN depth) { - if (goodOps <= 20 && allOps[OP_FWDJUMP]) - unprofitable = true; + if (depth == 0) + return true; + + if (numAllOps < 15 && allOps[OP_FWDJUMP]) + return true; /* Ensure that inner loops aren't fleeting. */ for (uintN i=0; iunprofitable) - unprofitable = true; + if (prof && prof->isCompilationUnprofitable(cx, depth-1)) + return true; } - return unprofitable; + 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); @@ -16802,7 +16791,6 @@ LoopProfile::decide(JSContext *cx) 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]); @@ -16826,15 +16814,12 @@ LoopProfile::decide(JSContext *cx) 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)) { - 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. */ - } + debug_only_print0(LC_TMProfiler, "NOTRACE: maybe short\n"); + } else if (isCompilationExpensive(cx, 4)) { + debug_only_print0(LC_TMProfiler, "NOTRACE: expensive\n"); + } else if (isCompilationUnprofitable(cx, 4)) { + debug_only_print0(LC_TMProfiler, "NOTRACE: unprofitable\n"); } else { uintN goodOps = 0; @@ -16848,10 +16833,8 @@ LoopProfile::decide(JSContext *cx) 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; } @@ -16878,7 +16861,7 @@ LoopProfile::decide(JSContext *cx) } } - if (!traceOK && !undecided) { + if (!traceOK) { debug_only_printf(LC_TMProfiler, "Blacklisting at %d\n", line); Blacklist(top); } @@ -16906,7 +16889,7 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) 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; @@ -16929,7 +16912,6 @@ AbortProfiling(JSContext *cx) tm->profile->profiled = true; tm->profile->traceOK = false; tm->profile->execOK = false; - tm->profile->undecided = false; Blacklist(tm->profile->top); tm->profile = NULL; } @@ -16944,16 +16926,5 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) #endif /* JS_METHODJIT */ -uint32 -GetHotloop(JSContext *cx) -{ -#ifdef JS_METHODJIT - if (cx->profilingEnabled) - return PROFILE_HOTLOOP; - else -#endif - return 1; -} - } /* namespace js */ diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 1e12d881e82..2f2819d7b0d 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -616,7 +616,7 @@ struct TreeFragment : public LinkableFragment 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; } @@ -666,7 +666,6 @@ public: 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 }; @@ -686,9 +685,6 @@ public: /* 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; @@ -730,10 +726,6 @@ public: /* 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. @@ -798,8 +790,6 @@ public: LoopProfile(JSStackFrame *entryfp, jsbytecode *top, jsbytecode *bottom); - void reset(); - enum ProfileAction { ProfContinue, ProfComplete @@ -822,8 +812,8 @@ public: 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); }; @@ -1671,7 +1661,7 @@ 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); diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 63882908e60..b074daeb960 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -57,7 +57,6 @@ #include "jscompartment.h" #include "jsobjinlines.h" #include "jsopcodeinlines.h" -#include "jshotloop.h" #include "jsautooplen.h" @@ -601,8 +600,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp) 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]); } @@ -4771,11 +4768,6 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) # 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. */ @@ -4790,10 +4782,11 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) 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; } diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index dc8c4206365..9f28a2e8dfa 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -973,26 +973,17 @@ RunTracer(VMFrame &f) 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 diff --git a/js/src/methodjit/MonoIC.h b/js/src/methodjit/MonoIC.h index 44e4ed210bb..6500625da9d 100644 --- a/js/src/methodjit/MonoIC.h +++ b/js/src/methodjit/MonoIC.h @@ -153,8 +153,6 @@ struct TraceICInfo { /* This data is used by the tracing JIT. */ void *traceData; uintN traceEpoch; - uint32 loopCounter; - uint32 loopCounterStart; bool hasSlowTraceHint : 1; };