Merge.
authorAndreas Gal <gal@mozilla.com>
Sat, 05 Jul 2008 19:18:14 -0700
changeset 17443 f4c96a566c4c826d41a6249d784b90e465c66cff
parent 17442 138fc2d7f4fe744306e5244549030edfb3d9469c (diff)
parent 17441 1a4d440c60e4d2dbc9fd3c6c50ab7c9dc6e0b0b7 (current diff)
child 17444 355d79be4adfe120ebcb0ee2f61ee463106f10e5
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a1pre
Merge.
js/src/jstracer.cpp
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -321,16 +321,19 @@ js_NewContext(JSRuntime *rt, size_t stac
         JS_UNLOCK_GC(rt);
     }
 
     cxCallback = rt->cxCallback;
     if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
         js_DestroyContext(cx, JSDCM_NEW_FAILED);
         return NULL;
     }
+    
+    js_InitJIT(cx);
+    
     return cx;
 }
 
 void
 js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
 {
     JSRuntime *rt;
     JSContextCallback cxCallback;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2692,19 +2692,17 @@ js_Interpret(JSContext *cx)
     JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)
 
 #define LOAD_FUNCTION(PCOFF)                                                  \
     JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
 
 #define MONITOR_BRANCH()                                                      \
     JS_BEGIN_MACRO                                                            \
         JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);                           \
-        if (TRACING_ENABLED(cx) &&                                            \
-                (((tm->freq++ & TRACE_TRIGGER_MASK) == 0) ||                  \
-                        (tm->recorder != NULL)))                              \
+        if (TRACING_ENABLED(cx))                                              \
             ENABLE_TRACER(js_LoopEdge(cx));                                   \
     JS_END_MACRO
 
     /*
      * Prepare to call a user-supplied branch handler, and abort the script
      * if it returns false.
      */
 #define CHECK_BRANCH()                                                        \
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -215,17 +215,17 @@ TraceRecorder::~TraceRecorder()
 #endif
     delete cse_filter;
     delete expr_filter;
     delete lir_buf_writer;
 }
 
 /* Determine the current call depth (starting with the entry frame.) */
 unsigned
-TraceRecorder::calldepth() const
+TraceRecorder::getCallDepth() const
 {
     JSStackFrame* fp = cx->fp;
     unsigned depth = 0;
     while (fp != entryFrame) {
         ++depth;
         fp = fp->down;
     }
     return depth;
@@ -510,17 +510,17 @@ TraceRecorder::snapshot()
     LIns* data = lir_buf_writer->skip(sizeof(VMSideExitInfo) + slots * sizeof(char));
     VMSideExitInfo* si = (VMSideExitInfo*)data->payload();
     buildTypeMap(entryFrame, cx->fp, *cx->fp->regs, si->typeMap);
     /* setup side exit structure */
     memset(&exit, 0, sizeof(exit));
 #ifdef DEBUG
     exit.from = fragment;
 #endif
-    exit.calldepth = calldepth();
+    exit.calldepth = getCallDepth();
     exit.sp_adj = (cx->fp->regs->sp - entryRegs.sp) * sizeof(double);
     exit.ip_adj = cx->fp->regs->pc - entryRegs.pc;
     exit.vmprivate = si;
     return &exit;
 }
 
 void
 TraceRecorder::guard(bool expected, LIns* cond)
@@ -540,63 +540,64 @@ TraceRecorder::closeLoop(Fragmento* frag
         return;
     }
     fragment->lastIns = lir->ins0(LIR_loop);
     ((VMFragmentInfo*)fragment->vmprivate)->maxNativeFrameSlots = maxNativeFrameSlots;
     compile(fragmento->assm(), fragment);
 }
 
 bool
-TraceRecorder::loopEdge(JSContext* cx)
+TraceRecorder::loopEdge()
 {
     if (cx->fp->regs->pc == entryRegs.pc) {
         closeLoop(JS_TRACE_MONITOR(cx).fragmento);
         return false; /* done recording */
     }
     return false; /* abort recording */
 }
 
 void
+TraceRecorder::stop()
+{
+    fragment->blacklist();
+}
+
+void
 js_DeleteRecorder(JSContext* cx)
 {
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
     delete tm->recorder;
     tm->recorder = NULL;
 }
 
+#define HOTLOOP 10
+
 bool
 js_LoopEdge(JSContext* cx)
 {
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
 
     /* is the recorder currently active? */
     if (tm->recorder) {
-        if (tm->recorder->loopEdge(cx))
+        if (tm->recorder->loopEdge())
             return true; /* keep recording */
         js_DeleteRecorder(cx);
         return false; /* done recording */
     }
 
-    if (!tm->fragmento) {
-        Fragmento* fragmento = new (&gc) Fragmento(core);
-#ifdef DEBUG
-        fragmento->labels = new (&gc) LabelMap(core, NULL);
-#endif
-        fragmento->assm()->setCallTable(builtins);
-        tm->fragmento = fragmento;
-    }
-
     InterpState state;
     state.ip = (FOpcodep)cx->fp->regs->pc;
 
     Fragment* f = tm->fragmento->getLoop(state);
-
     if (!f->code()) {
-        tm->recorder = new (&gc) TraceRecorder(cx, tm->fragmento, f);
-        return true; /* start recording */
+        if (!f->isBlacklisted() && ++f->hits() > HOTLOOP) {
+            tm->recorder = new (&gc) TraceRecorder(cx, tm->fragmento, f);
+             return true; /* start recording */
+        }
+        return false;
     }
 
     /* execute previously recorded race */
     VMFragmentInfo* fi = (VMFragmentInfo*)f->vmprivate;
     double native[fi->maxNativeFrameSlots+1];
 #ifdef DEBUG
     *(uint64*)&native[fi->maxNativeFrameSlots] = 0xdeadbeefdeadbeefLL;
 #endif
@@ -629,19 +630,34 @@ js_LoopEdge(JSContext* cx)
 }
 
 void
 js_AbortRecording(JSContext* cx, const char* reason)
 {
 #ifdef DEBUG
     printf("Abort recording: %s.\n", reason);
 #endif
+    JS_TRACE_MONITOR(cx).recorder->stop();
     js_DeleteRecorder(cx);
 }
 
+extern void
+js_InitJIT(JSContext* cx)
+{
+    JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+    if (!tm->fragmento) {
+        Fragmento* fragmento = new (&gc) Fragmento(core);
+#ifdef DEBUG
+        fragmento->labels = new (&gc) LabelMap(core, NULL);
+#endif
+        fragmento->assm()->setCallTable(builtins);
+        tm->fragmento = fragmento;
+    }
+}
+
 jsval&
 TraceRecorder::argval(unsigned n) const
 {
     JS_ASSERT((n >= 0) && (n <= cx->fp->argc));
     return cx->fp->argv[n];
 }
 
 jsval&
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -120,17 +120,17 @@ class TraceRecorder {
     bool onFrame(void* p) const;
     unsigned nativeFrameSlots(JSStackFrame* fp, JSFrameRegs& regs) const;
     size_t   nativeFrameOffset(void* p) const;
     void import(jsval*, char *prefix = NULL, int index = 0);
     void trackNativeFrameUse(unsigned slots);
     
     nanojit::SideExit* snapshot();
 
-    unsigned calldepth() const;
+    unsigned getCallDepth() const;
 
     void set(void* p, nanojit::LIns* l);
     nanojit::LIns* get(void* p);
     
     void guard(bool expected, nanojit::LIns* cond);
     
     void closeLoop(nanojit::Fragmento* fragmento);
     
@@ -172,17 +172,18 @@ class TraceRecorder {
     bool guardThatObjectIsDenseArray(JSObject* obj, 
             nanojit::LIns* obj_ins, nanojit::LIns*& dslots_ins);
     bool guardDenseArrayIndexWithinBounds(JSObject* obj, jsint idx, 
             nanojit::LIns* obj_ins, nanojit::LIns*& dslots_ins, nanojit::LIns* idx_ins);
 public:
     TraceRecorder(JSContext* cx, nanojit::Fragmento*, nanojit::Fragment*);
     ~TraceRecorder();
 
-    bool loopEdge(JSContext* cx);
+    bool loopEdge();
+    void stop();
     
     bool JSOP_INTERRUPT();
     bool JSOP_PUSH();
     bool JSOP_POPV();
     bool JSOP_ENTERWITH();
     bool JSOP_LEAVEWITH();
     bool JSOP_RETURN();
     bool JSOP_GOTO();
@@ -424,23 +425,24 @@ FASTCALL jsint builtin_UnboxInt32(JSCont
  * For this we use a loop table. Adjacent slots in the loop table, one for each
  * loop header in a given script, are requested using lock-free synchronization
  * from the runtime-wide loop table slot space, when the script is compiled.
  *
  * The loop table also doubles as trace tree pointer table once a loop achieves
  * a certain number of iterations and we recorded a tree for that loop.
  */
 struct JSTraceMonitor {
-    int                     freq;
     nanojit::Fragmento*     fragmento;
     TraceRecorder*          recorder;
 };
 
 #define TRACING_ENABLED(cx)       JS_HAS_OPTION(cx, JSOPTION_JIT)
-#define TRACE_TRIGGER_MASK 0x3f
 
 extern bool
 js_LoopEdge(JSContext* cx);
 
 extern void
 js_AbortRecording(JSContext* cx, const char* reason);
 
+extern void
+js_InitJIT(JSContext* cx);
+
 #endif /* jstracer_h___ */
--- a/js/src/trace.js
+++ b/js/src/trace.js
@@ -1,11 +1,12 @@
 f = function() {
 	var q = 1;
-	for (var i = 0; i < 500000; ++i)
+	for (var j = 0; j < 500; ++j)
+	for (var i = 0; i < 5000; ++i)
 		++q;
 	print("q=" + q + " i=" + i);
 }
 
 var before = Date.now();
 f();
 var after = Date.now();
 print(after - before);