Don't try to deallocate the trace recorder from inside one of its own instance methods (472049, r=brendan).
authorAndreas Gal <gal@mozilla.com>
Mon, 05 Jan 2009 16:13:53 -0800
changeset 22918 f67cbb089d003664214e7c2ae4013771d328dfa6
parent 22917 3801e3db9194c82ee945e6cb6af97612b68e27aa
child 22919 2f1228a2d07783d2d1621cb3b8291aa9018a8064
push id500
push userrsayre@mozilla.com
push dateFri, 23 Jan 2009 04:05:55 +0000
reviewersbrendan
bugs472049
milestone1.9.1b3pre
Don't try to deallocate the trace recorder from inside one of its own instance methods (472049, r=brendan).
js/src/jsinterp.cpp
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2830,17 +2830,17 @@ js_Interpret(JSContext *cx)
                   default:;
                 }
                 moreInterrupts = true;
             }
 
 #ifdef JS_TRACER
             TraceRecorder* tr = TRACE_RECORDER(cx);
             if (tr) {
-                JSMonitorRecordingStatus status = tr->monitorRecording(op);
+                JSMonitorRecordingStatus status = TraceRecorder::monitorRecording(cx, tr, op);
                 if (status == JSMRS_CONTINUE) {
                     moreInterrupts = true;
                 } else if (status == JSMRS_IMACRO) {
                     atoms = COMMON_ATOMS_START(&rt->atomState);
                     op = JSOp(*regs.pc);
                     DO_OP();    /* keep interrupting for op. */
                 } else {
                     JS_ASSERT(status == JSMRS_STOP);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -3823,77 +3823,77 @@ monitor_loop:
         return false;
       default:
         /* No, this was an unusual exit (i.e. out of memory/GC), so just resume interpretation. */
         return false;
     }
 }
 
 JS_REQUIRES_STACK JSMonitorRecordingStatus
-TraceRecorder::monitorRecording(JSOp op)
-{
-    if (lirbuf->outOMem()) {
+TraceRecorder::monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op)
+{
+    if (tr->lirbuf->outOMem()) {
         js_AbortRecording(cx, "no more LIR memory");
         js_FlushJITCache(cx);
         return JSMRS_STOP;
     }
 
     /* Process deepAbort() requests now. */
-    if (wasDeepAborted()) {
+    if (tr->wasDeepAborted()) {
         js_AbortRecording(cx, "deep abort requested");
         return JSMRS_STOP;
     }
 
-    if (walkedOutOfLoop()) {
+    if (tr->walkedOutOfLoop()) {
         if (!js_CloseLoop(cx))
             return JSMRS_STOP;
     } else {
         // Clear one-shot state used to communicate between record_JSOP_CALL and post-
         // opcode-case-guts record hook (record_FastNativeCallComplete).
-        pendingTraceableNative = NULL;
+        tr->pendingTraceableNative = NULL;
 
         // In the future, handle dslots realloc by computing an offset from dslots instead.
-        if (global_dslots != globalObj->dslots) {
+        if (tr->global_dslots != tr->globalObj->dslots) {
             js_AbortRecording(cx, "globalObj->dslots reallocated");
             return JSMRS_STOP;
         }
 
         jsbytecode* pc = cx->fp->regs->pc;
 
         /* If we hit a break, end the loop and generate an always taken loop exit guard. For other
            downward gotos (like if/else) continue recording. */
         if (*pc == JSOP_GOTO || *pc == JSOP_GOTOX) {
             jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
             if (sn && SN_TYPE(sn) == SRC_BREAK) {
                 AUDIT(breakLoopExits);
-                endLoop(JS_TRACE_MONITOR(cx).fragmento);
+                tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
                 js_DeleteRecorder(cx);
                 return JSMRS_STOP; /* done recording */
             }
         }
 
         /* An explicit return from callDepth 0 should end the loop, not abort it. */
-        if (*pc == JSOP_RETURN && callDepth == 0) {
+        if (*pc == JSOP_RETURN && tr->callDepth == 0) {
             AUDIT(returnLoopExits);
-            endLoop(JS_TRACE_MONITOR(cx).fragmento);
+            tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
             js_DeleteRecorder(cx);
             return JSMRS_STOP; /* done recording */
         }
     }
 
     /* If it's not a break or a return from a loop, continue recording and follow the trace. */
 
     /* We check for imacro-calling bytecodes inside the switch cases to resolve
        the "if" condition at the compile time. */
     bool flag;
     switch (op) {
       default: goto abort_recording;
 # define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format)               \
         case x:                                                               \
-          flag = record_##x();                                                \
+          flag = tr->record_##x();                                            \
           if (x == JSOP_ITER || x == JSOP_NEXTITER || x == JSOP_APPLY ||      \
               JSOP_IS_BINARY(x) || JSOP_IS_UNARY(x) ||                        \
               JSOP_IS_EQUALITY(x)) {                                          \
               goto imacro;                                                    \
           }                                                                   \
         break;
 # include "jsopcode.tbl"
 # undef OPDEF
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -435,17 +435,17 @@ class TraceRecorder : public avmplus::GC
 
 public:
     JS_REQUIRES_STACK
     TraceRecorder(JSContext* cx, VMSideExit*, nanojit::Fragment*, TreeInfo*,
                   unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap, 
                   VMSideExit* expectedInnerExit, nanojit::Fragment* outerToBlacklist);
     ~TraceRecorder();
 
-    JS_REQUIRES_STACK JSMonitorRecordingStatus monitorRecording(JSOp op);
+    static JS_REQUIRES_STACK JSMonitorRecordingStatus monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op);
 
     JS_REQUIRES_STACK uint8 determineSlotType(jsval* vp) const;
     JS_REQUIRES_STACK nanojit::LIns* snapshot(ExitType exitType);
     nanojit::Fragment* getFragment() const { return fragment; }
     JS_REQUIRES_STACK bool isLoopHeader(JSContext* cx) const;
     JS_REQUIRES_STACK void compile(nanojit::Fragmento* fragmento);
     JS_REQUIRES_STACK bool closeLoop(nanojit::Fragmento* fragmento, bool& demote,
                                      unsigned *demotes);