Backed out changeset 8ea3083a9787
authorDavid Anderson <danderson@mozilla.com>
Fri, 15 Oct 2010 15:29:57 -0700
changeset 56033 5b332db148d38831eb4afcb9950d6b44fc35dfea
parent 56025 8ea3083a97877ac69342206d0e7218633cc17cf5
child 56034 4545f5987736ebd43aad26ec5e26b261dcb4a7bd
push id16371
push userrsayre@mozilla.com
push dateMon, 18 Oct 2010 17:04:27 +0000
treeherdermozilla-central@eae6bdacf6d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b8pre
backs out8ea3083a97877ac69342206d0e7218633cc17cf5
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 8ea3083a9787
js/src/jscntxt.h
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsemit.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsopcode.tbl
js/src/jspropertycache.cpp
js/src/jstracer.cpp
js/src/jsxdrapi.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
js/src/trace-test/tests/jaeger/bug563000/trap-force-return-1.js
js/src/trace-test/tests/jaeger/bug563000/trap-parent-from-trap.js
js/src/trace-test/tests/jaeger/bug563000/trap-self-from-trap.js
js/src/trace-test/tests/jaeger/deepBailAfterRunTracer.js
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -2003,17 +2003,17 @@ struct JSContext
 
     bool hasfp() {
         JS_ASSERT_IF(regs, regs->fp);
         return !!regs;
     }
 
   public:
     friend class js::StackSpace;
-    friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, JSInterpMode);
+    friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, uintN);
 
     void resetCompartment();
 
     /* 'regs' must only be changed by calling this function. */
     void setCurrentRegs(JSFrameRegs *regs) {
         JS_ASSERT_IF(regs, regs->fp);
         this->regs = regs;
         if (!regs)
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -230,16 +230,22 @@ JS_SetTrap(JSContext *cx, JSScript *scri
         return JS_FALSE;
 
     if (script == JSScript::emptyScript()) {
         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
                                      NULL, JSMSG_READ_ONLY, "empty script");
         return JS_FALSE;
     }
 
+    if (JSOp(*pc) == JSOP_BEGIN) {
+        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
+                                     NULL, JSMSG_READ_ONLY, "trap invalid on BEGIN opcode");
+        return JS_FALSE;
+    }
+
     JS_ASSERT((JSOp) *pc != JSOP_TRAP);
     junk = NULL;
     rt = cx->runtime;
     DBG_LOCK(rt);
     trap = FindTrap(rt, script, pc);
     if (trap) {
         JS_ASSERT(trap->script == script && trap->pc == pc);
         JS_ASSERT(*pc == JSOP_TRAP);
@@ -1011,16 +1017,23 @@ JS_PCToLineNumber(JSContext *cx, JSScrip
 
 JS_PUBLIC_API(jsbytecode *)
 JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
 {
     return js_LineNumberToPC(script, lineno);
 }
 
 JS_PUBLIC_API(jsbytecode *)
+JS_FirstValidPC(JSContext *cx, JSScript *script)
+{
+    jsbytecode *pc = script->code;
+    return *pc == JSOP_BEGIN ? pc + JSOP_BEGIN_LENGTH : pc;
+}
+
+JS_PUBLIC_API(jsbytecode *)
 JS_EndPC(JSContext *cx, JSScript *script)
 {
     return script->code + script->length;
 }
 
 JS_PUBLIC_API(uintN)
 JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
 {
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -155,16 +155,19 @@ js_WrapWatchedSetter(JSContext *cx, jsid
 
 extern JS_PUBLIC_API(uintN)
 JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
 
 extern JS_PUBLIC_API(jsbytecode *)
 JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
 
 extern JS_PUBLIC_API(jsbytecode *)
+JS_FirstValidPC(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(jsbytecode *)
 JS_EndPC(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(uintN)
 JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);
 
 extern JS_PUBLIC_API(JSBool)
 JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun);
 
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -3711,20 +3711,25 @@ out:
 bad:
     ok = JS_FALSE;
     goto out;
 }
 
 JSBool
 js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body)
 {
+    CG_SWITCH_TO_PROLOG(cg);
+    JS_ASSERT(CG_NEXT(cg) == CG_BASE(cg));
+    if (js_Emit1(cx, cg, JSOP_BEGIN) < 0)
+        return false;
+    CG_SWITCH_TO_MAIN(cg);
+
     if (cg->flags & TCF_FUN_IS_GENERATOR) {
-        /* JSOP_GENERATOR must be the first instruction. */
+        /* JSOP_GENERATOR must be the first real instruction. */
         CG_SWITCH_TO_PROLOG(cg);
-        JS_ASSERT(CG_NEXT(cg) == CG_BASE(cg));
         if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0)
             return false;
         CG_SWITCH_TO_MAIN(cg);
     }
 
     if (cg->needsEagerArguments()) {
         CG_SWITCH_TO_PROLOG(cg);
         if (js_Emit1(cx, cg, JSOP_ARGUMENTS) < 0 || js_Emit1(cx, cg, JSOP_POP) < 0)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -77,16 +77,17 @@
 #include "jsvector.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Logging.h"
 
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
+#include "jsprobes.h"
 #include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsstrinlines.h"
 #include "jsopcodeinlines.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
@@ -728,22 +729,37 @@ Invoke(JSContext *cx, const CallArgs &ar
             JSObject *thisp = thisv.toObject().thisObject(cx);
             if (!thisp)
                  return false;
             JS_ASSERT(IsSaneThisObject(*thisp));
             thisv.setObject(*thisp);
         }
     }
 
+    JSInterpreterHook hook = cx->debugHooks->callHook;
+    void *hookData = NULL;
+    if (JS_UNLIKELY(hook != NULL))
+        hookData = hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData);
+
     /* Run function until JSOP_STOP, JSOP_RETURN or error. */
     JSBool ok;
     {
         AutoPreserveEnumerators preserve(cx);
+        Probes::enterJSFun(cx, fun);
         ok = RunScript(cx, script, fp);
-    }
+        Probes::exitJSFun(cx, fun);
+    }
+
+    if (JS_UNLIKELY(hookData != NULL)) {
+        hook = cx->debugHooks->callHook;
+        if (hook)
+            hook(cx, fp, JS_FALSE, &ok, hookData);
+    }
+
+    PutActivationObjects(cx, fp);
 
     args.rval() = fp->returnValue();
     JS_ASSERT_IF(ok && (flags & JSINVOKE_CONSTRUCT), !args.rval().isPrimitive());
 
     return ok;
 }
 
 bool
@@ -2140,38 +2156,21 @@ IteratorNext(JSContext *cx, JSObject *it
             *rval = *ni->currentValue();
             ni->incValueCursor();
             return true;
         }
     }
     return js_IteratorNext(cx, iterobj, rval);
 }
 
-static inline bool
-ScriptPrologue(JSContext *cx, JSStackFrame *fp)
-{
-    if (fp->isConstructing()) {
-        JSObject *obj = js_CreateThisForFunction(cx, &fp->callee());
-        if (!obj)
-            return false;
-        fp->functionThis().setObject(*obj);
-    }
-    JSInterpreterHook hook = cx->debugHooks->callHook;
-    if (JS_UNLIKELY(hook != NULL))
-        fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
-
-    Probes::enterJSFun(cx, fp->maybeFun());
-
-    return true;
-}
 
 namespace js {
 
 JS_REQUIRES_STACK JS_NEVER_INLINE bool
-Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInterpMode interpMode)
+Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, uintN interpFlags)
 {
 #ifdef MOZ_TRACEVIS
     TraceVisStateObj tvso(cx, S_INTERP);
 #endif
     JSAutoResolveFlags rf(cx, JSRESOLVE_INFER);
 
 # ifdef DEBUG
     /*
@@ -2392,17 +2391,17 @@ Interpret(JSContext *cx, JSStackFrame *e
 #if defined(JS_TRACER) && defined(JS_METHODJIT)
 # define LEAVE_ON_SAFE_POINT()                                                \
     do {                                                                      \
         JS_ASSERT_IF(leaveOnSafePoint, !TRACE_RECORDER(cx));                  \
         if (leaveOnSafePoint && !regs.fp->hasImacropc() &&                    \
             script->maybeNativeCodeForPC(regs.fp->isConstructing(), regs.pc)) { \
             JS_ASSERT(!TRACE_RECORDER(cx));                                   \
             interpReturnOK = true;                                            \
-            goto leave_on_safe_point;                                         \
+            goto stop_recording;                                              \
         }                                                                     \
     } while (0)
 #else
 # define LEAVE_ON_SAFE_POINT() /* nop */
 #endif
 
 #define BRANCH(n)                                                             \
     JS_BEGIN_MACRO                                                            \
@@ -2428,47 +2427,35 @@ Interpret(JSContext *cx, JSStackFrame *e
     JS_BEGIN_MACRO                                                            \
         if (cx->debugHooks->interruptHook)                                    \
             ENABLE_INTERRUPTS();                                              \
     JS_END_MACRO
 
     /* Check for too deep of a native thread stack. */
     JS_CHECK_RECURSION(cx, return JS_FALSE);
 
-    JSFrameRegs regs = *cx->regs;
+    MUST_FLOW_THROUGH("exit");
+    ++cx->interpLevel;
 
     /* Repoint cx->regs to a local variable for faster access. */
-    struct InterpExitGuard {
-        JSContext *cx;
-        const JSFrameRegs &regs;
-        JSFrameRegs *prevContextRegs;
-        InterpExitGuard(JSContext *cx, JSFrameRegs &regs)
-          : cx(cx), regs(regs), prevContextRegs(cx->regs) {
-            cx->setCurrentRegs(&regs);
-            ++cx->interpLevel;
-        }
-        ~InterpExitGuard() {
-            --cx->interpLevel;
-            JS_ASSERT(cx->regs == &regs);
-            *prevContextRegs = regs;
-            cx->setCurrentRegs(prevContextRegs);
-        }
-    } interpGuard(cx, regs);
+    JSFrameRegs *const prevContextRegs = cx->regs;
+    JSFrameRegs regs = *cx->regs;
+    cx->setCurrentRegs(&regs);
 
     /* Copy in hot values that change infrequently. */
     JSRuntime *const rt = cx->runtime;
     JSScript *script = regs.fp->script();
     Value *argv = regs.fp->maybeFormalArgs();
     CHECK_INTERRUPT_HANDLER();
 
     JS_ASSERT(!script->isEmpty());
     JS_ASSERT(script->length > 1);
 
 #if defined(JS_TRACER) && defined(JS_METHODJIT)
-    bool leaveOnSafePoint = (interpMode == JSINTERP_SAFEPOINT);
+    bool leaveOnSafePoint = !!(interpFlags & JSINTERP_SAFEPOINT);
 # define CLEAR_LEAVE_ON_TRACE_POINT() ((void) (leaveOnSafePoint = false))
 #else
 # define CLEAR_LEAVE_ON_TRACE_POINT() ((void) 0)
 #endif
 
     if (!entryFrame)
         entryFrame = regs.fp;
 
@@ -2478,17 +2465,17 @@ Interpret(JSContext *cx, JSStackFrame *e
      * the atom map to turn frequently executed LOAD_ATOM into simple array
      * access. For less frequent object and regexp loads we have to recover
      * the segment from atoms pointer first.
      */
     JSAtom **atoms = script->atomMap.vector;
 
 #if JS_HAS_GENERATORS
     if (JS_UNLIKELY(regs.fp->isGeneratorFrame())) {
-        JS_ASSERT(interpGuard.prevContextRegs == &cx->generatorFor(regs.fp)->regs);
+        JS_ASSERT(prevContextRegs == &cx->generatorFor(regs.fp)->regs);
         JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
         JS_ASSERT((size_t) (regs.sp - regs.fp->base()) <= StackDepth(script));
 
         /*
          * To support generator_throw and to catch ignored exceptions,
          * fail if cx->throwing is set.
          */
         if (cx->throwing)
@@ -2497,36 +2484,27 @@ Interpret(JSContext *cx, JSStackFrame *e
 #endif
 
 #ifdef JS_TRACER
     /*
      * The method JIT may have already initiated a recording, in which case
      * there should already be a valid recorder. Otherwise...
      * we cannot reenter the interpreter while recording.
      */
-    if (interpMode == JSINTERP_RECORD) {
+    if (interpFlags & JSINTERP_RECORD) {
         JS_ASSERT(TRACE_RECORDER(cx));
         ENABLE_INTERRUPTS();
     } else if (TRACE_RECORDER(cx)) {
         AbortRecording(cx, "attempt to reenter interpreter while recording");
     }
 
     if (regs.fp->hasImacropc())
         atoms = COMMON_ATOMS_START(&rt->atomState);
 #endif
 
-    /* Don't call the script prologue if executing between Method and Trace JIT. */
-    if (interpMode == JSINTERP_NORMAL) {
-        JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), regs.pc == script->code);
-        if (!ScriptPrologue(cx, regs.fp))
-            goto error;
-    }
-
-    CHECK_INTERRUPT_HANDLER();
-
     /* State communicated between non-local jumps: */
     JSBool interpReturnOK;
     JSAtom *atomNotDefined;
 
     /*
      * It is important that "op" be initialized before calling DO_OP because
      * it is possible for "op" to be specially assigned during the normal
      * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
@@ -2602,18 +2580,17 @@ Interpret(JSContext *cx, JSStackFrame *e
             moreInterrupts = true;
         }
 
 #ifdef JS_TRACER
         if (TraceRecorder* tr = TRACE_RECORDER(cx)) {
             AbortableRecordingStatus status = tr->monitorRecording(op);
             JS_ASSERT_IF(cx->throwing, status == ARECORD_ERROR);
 
-            if (interpMode != JSINTERP_NORMAL) {
-                JS_ASSERT(interpMode == JSINTERP_RECORD || JSINTERP_SAFEPOINT);
+            if (interpFlags & (JSINTERP_RECORD | JSINTERP_SAFEPOINT)) {
                 switch (status) {
                   case ARECORD_IMACRO_ABORTED:
                   case ARECORD_ABORTED:
                   case ARECORD_COMPLETED:
                   case ARECORD_STOP:
 #ifdef JS_METHODJIT
                     leaveOnSafePoint = true;
                     LEAVE_ON_SAFE_POINT();
@@ -2778,21 +2755,37 @@ BEGIN_CASE(JSOP_STOP)
     }
 #endif
 
     interpReturnOK = true;
     if (entryFrame != regs.fp)
   inline_return:
     {
         JS_ASSERT(!js_IsActiveWithOrBlock(cx, &regs.fp->scopeChain(), 0));
-        interpReturnOK = ScriptEpilogue(cx, regs.fp, interpReturnOK);
-        CHECK_INTERRUPT_HANDLER();
-
-        /* The JIT inlines ScriptEpilogue. */
-  jit_return:
+        if (JS_UNLIKELY(regs.fp->hasHookData())) {
+            if (JSInterpreterHook hook = cx->debugHooks->callHook) {
+                hook(cx, regs.fp, JS_FALSE, &interpReturnOK, regs.fp->hookData());
+                CHECK_INTERRUPT_HANDLER();
+            }
+        }
+
+        PutActivationObjects(cx, regs.fp);
+
+        Probes::exitJSFun(cx, regs.fp->maybeFun());
+
+        /*
+         * If inline-constructing, replace primitive rval with the new object
+         * passed in via |this|, and instrument this constructor invocation.
+         */
+        if (regs.fp->isConstructing()) {
+            if (regs.fp->returnValue().isPrimitive())
+                regs.fp->setReturnValue(ObjectValue(regs.fp->constructorThis()));
+            JS_RUNTIME_METER(cx->runtime, constructs);
+        }
+
         Value *newsp = regs.fp->actualArgs() - 1;
         newsp[-1] = regs.fp->returnValue();
         cx->stack().popInlineFrame(cx, regs.fp->prev(), newsp);
 
         /* Sync interpreter registers. */
         script = regs.fp->script();
         argv = regs.fp->maybeFormalArgs();
         atoms = FrameAtomBase(cx, regs.fp);
@@ -2805,16 +2798,28 @@ BEGIN_CASE(JSOP_STOP)
                       == JSOP_CALL_LENGTH);
             TRACE_0(LeaveFrame);
             len = JSOP_CALL_LENGTH;
             DO_NEXT_OP(len);
         }
         goto error;
     } else {
         JS_ASSERT(regs.sp == regs.fp->base());
+        if (regs.fp->isConstructing() && regs.fp->returnValue().isPrimitive())
+            regs.fp->setReturnValue(ObjectValue(regs.fp->constructorThis()));
+
+#if defined(JS_TRACER) && defined(JS_METHODJIT)
+        /* Hack: re-push rval so either JIT will read it properly. */
+        regs.fp->setBailedAtReturn();
+        if (TRACE_RECORDER(cx)) {
+            AbortRecording(cx, "recording out of Interpret");
+            interpReturnOK = true;
+            goto stop_recording;
+        }
+#endif
     }
     interpReturnOK = true;
     goto exit;
 }
 
 BEGIN_CASE(JSOP_DEFAULT)
     regs.sp--;
     /* FALL THROUGH */
@@ -4559,16 +4564,51 @@ BEGIN_CASE(JSOP_ENUMELEM)
     FETCH_ELEMENT_ID(obj, -1, id);
     Value rval = regs.sp[-3];
     if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
         goto error;
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
+BEGIN_CASE(JSOP_BEGIN)
+{
+    if (regs.fp->isConstructing()) {
+        JSObject *obj2 = js_CreateThisForFunction(cx, &regs.fp->callee());
+        if (!obj2)
+            goto error;
+        regs.fp->functionThis().setObject(*obj2);
+    }
+
+    /* Call the debugger hook if present. */
+    if (JSInterpreterHook hook = cx->debugHooks->callHook) {
+        regs.fp->setHookData(hook(cx, regs.fp, JS_TRUE, 0,
+                                  cx->debugHooks->callHookData));
+        CHECK_INTERRUPT_HANDLER();
+    }
+
+    JS_RUNTIME_METER(rt, inlineCalls);
+
+    Probes::enterJSFun(cx, regs.fp->fun());
+
+#ifdef JS_METHODJIT
+    /* Try to ensure methods are method JIT'd.  */
+    mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, regs.fp);
+    if (status == mjit::Compile_Error)
+        goto error;
+    if (!TRACE_RECORDER(cx) && status == mjit::Compile_Okay) {
+        if (!mjit::JaegerShot(cx))
+            goto error;
+        interpReturnOK = true;
+        goto inline_return;
+    }
+#endif
+}
+END_CASE(JSOP_BEGIN)
+
 {
     JSFunction *newfun;
     JSObject *callee;
     uint32 flags;
     uintN argc;
     Value *vp;
 
 BEGIN_CASE(JSOP_NEW)
@@ -4658,41 +4698,22 @@ BEGIN_CASE(JSOP_APPLY)
             argv = regs.fp->formalArgsEnd() - newfun->nargs;
             atoms = script->atomMap.vector;
 
             /* Now that the new frame is rooted, maybe create a call object. */
             if (newfun->isHeavyweight() && !js_GetCallObject(cx, regs.fp))
                 goto error;
 
             inlineCallCount++;
-            JS_RUNTIME_METER(rt, inlineCalls);
 
             TRACE_0(EnterFrame);
 
-            CHECK_INTERRUPT_HANDLER();
-
-#ifdef JS_METHODJIT
-            /* Try to ensure methods are method JIT'd.  */
-            mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, regs.fp);
-            if (status == mjit::Compile_Error)
-                goto error;
-            if (!TRACE_RECORDER(cx) && status == mjit::Compile_Okay) {
-                interpReturnOK = mjit::JaegerShot(cx);
-                CHECK_INTERRUPT_HANDLER();
-                goto jit_return;
-            }
-#endif
-
-            if (!ScriptPrologue(cx, regs.fp))
-                goto error;
-
-            CHECK_INTERRUPT_HANDLER();
-
             /* Load first op and dispatch it (safe since JSOP_STOP). */
             op = (JSOp) *regs.pc;
+            JS_ASSERT(op == JSOP_BEGIN);
             DO_OP();
         }
 
         Probes::enterJSFun(cx, newfun);
         JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
         Probes::exitJSFun(cx, newfun);
         regs.sp = vp + 1;
         if (!ok)
@@ -6907,57 +6928,58 @@ END_CASE(JSOP_ARRAYPUSH)
 #ifdef DEBUG
     cx->tracePrevPc = NULL;
 #endif
 
     if (entryFrame != regs.fp)
         goto inline_return;
 
   exit:
-    interpReturnOK = ScriptEpilogue(cx, regs.fp, interpReturnOK);
-    regs.fp->setFinishedInInterpreter();
-
     /*
      * At this point we are inevitably leaving an interpreted function or a
      * top-level script, and returning to one of:
      * (a) an "out of line" call made through js_Invoke;
      * (b) a js_Execute activation;
      * (c) a generator (SendToGenerator, jsiter.c).
      *
      * We must not be in an inline frame. The check above ensures that for the
      * error case and for a normal return, the code jumps directly to parent's
      * frame pc.
      */
     JS_ASSERT(entryFrame == regs.fp);
+    JS_ASSERT(cx->regs == &regs);
+    *prevContextRegs = regs;
+    cx->setCurrentRegs(prevContextRegs);
 
 #ifdef JS_TRACER
-    JS_ASSERT_IF(interpReturnOK && interpMode == JSINTERP_RECORD, !TRACE_RECORDER(cx));
+    JS_ASSERT_IF(interpReturnOK && (interpFlags & JSINTERP_RECORD), !TRACE_RECORDER(cx));
     if (TRACE_RECORDER(cx))
         AbortRecording(cx, "recording out of Interpret");
 #endif
 
     JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), !js_IsActiveWithOrBlock(cx, &regs.fp->scopeChain(), 0));
 
+    --cx->interpLevel;
+
     return interpReturnOK;
 
   atom_not_defined:
     {
         const char *printable;
 
         printable = js_AtomToPrintableString(cx, atomNotDefined);
         if (printable)
             js_ReportIsNotDefined(cx, printable);
         goto error;
     }
 
-    /*
-     * This path is used when it's guaranteed the method can be finished
-     * inside the JIT.
-     */
 #if defined(JS_TRACER) && defined(JS_METHODJIT)
-  leave_on_safe_point:
+  stop_recording:
 #endif
+    JS_ASSERT(cx->regs == &regs);
+    *prevContextRegs = regs;
+    cx->setCurrentRegs(prevContextRegs);
     return interpReturnOK;
 }
 
 } /* namespace js */
 
 #endif /* !defined jsinvoke_cpp___ */
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -54,21 +54,20 @@ struct JSFrameRegs
 {
     STATIC_SKIP_INFERENCE
     js::Value       *sp;                  /* stack pointer */
     jsbytecode      *pc;                  /* program counter */
     JSStackFrame    *fp;                  /* active frame */
 };
 
 /* Flags to toggle js::Interpret() execution. */
-enum JSInterpMode
+enum JSInterpFlags
 {
-    JSINTERP_NORMAL            =     0, /* Interpreter is running normally. */
-    JSINTERP_RECORD            =     1, /* interpreter has been started to record/run traces */
-    JSINTERP_SAFEPOINT         =     2  /* interpreter should leave on a method JIT safe point */
+    JSINTERP_RECORD            =     0x1, /* interpreter has been started to record/run traces */
+    JSINTERP_SAFEPOINT         =     0x2  /* interpreter should leave on a method JIT safe point */
 };
 
 /* Flags used in JSStackFrame::flags_ */
 enum JSFrameFlags
 {
     /* Primary frame type */
     JSFRAME_GLOBAL             =     0x1, /* frame pushed for a global script */
     JSFRAME_FUNCTION           =     0x2, /* frame pushed for a scripted call */
@@ -79,17 +78,17 @@ enum JSFrameFlags
     JSFRAME_DEBUGGER           =    0x10, /* frame pushed by JS_EvaluateInStackFrame */
     JSFRAME_GENERATOR          =    0x20, /* frame is associated with a generator */
     JSFRAME_FLOATING_GENERATOR =    0x40, /* frame is is in generator obj, not on stack */
     JSFRAME_CONSTRUCTING       =    0x80, /* frame is for a constructor invocation */
 
     /* Temporary frame states */
     JSFRAME_ASSIGNING          =   0x100, /* not-JOF_ASSIGNING op is assigning */
     JSFRAME_YIELDING           =   0x200, /* js::Interpret dispatched JSOP_YIELD */
-    JSFRAME_FINISHED_IN_INTERPRETER = 0x400, /* set if frame finished in Interpret() */
+    JSFRAME_BAILED_AT_RETURN   =   0x400, /* bailed at JSOP_RETURN */
 
     /* Concerning function arguments */
     JSFRAME_OVERRIDE_ARGS      =  0x1000, /* overridden arguments local variable */
     JSFRAME_OVERFLOW_ARGS      =  0x2000, /* numActualArgs > numFormalArgs */
     JSFRAME_UNDERFLOW_ARGS     =  0x4000, /* numActualArgs < numFormalArgs */
 
     /* Lazy frame initialization */
     JSFRAME_HAS_IMACRO_PC      =   0x8000, /* frame has imacpc value available */
@@ -676,22 +675,22 @@ struct JSStackFrame
     void setYielding() {
         flags_ |= JSFRAME_YIELDING;
     }
 
     void clearYielding() {
         flags_ &= ~JSFRAME_YIELDING;
     }
 
-    void setFinishedInInterpreter() {
-        flags_ |= JSFRAME_FINISHED_IN_INTERPRETER;
+    bool isBailedAtReturn() const {
+        return flags_ & JSFRAME_BAILED_AT_RETURN;
     }
 
-    bool finishedInInterpreter() const {
-        return !!(flags_ & JSFRAME_FINISHED_IN_INTERPRETER);
+    void setBailedAtReturn() {
+        flags_ |= JSFRAME_BAILED_AT_RETURN;
     }
 
     /*
      * Variables object accessors
      *
      * A stack frame's 'varobj' refers to the 'variables object' (ES3 term)
      * associated with the Execution Context's VariableEnvironment (ES5 10.3).
      *
@@ -978,17 +977,17 @@ extern JS_FORCES_STACK bool
 Execute(JSContext *cx, JSObject *chain, JSScript *script,
         JSStackFrame *prev, uintN flags, Value *result);
 
 /*
  * Execute the caller-initialized frame for a user-defined script or function
  * pointed to by cx->fp until completion or error.
  */
 extern JS_REQUIRES_STACK JS_NEVER_INLINE bool
-Interpret(JSContext *cx, JSStackFrame *stopFp, uintN inlineCallCount = 0, JSInterpMode mode = JSINTERP_NORMAL);
+Interpret(JSContext *cx, JSStackFrame *stopFp, uintN inlineCallCount = 0, uintN interpFlags = 0);
 
 extern JS_REQUIRES_STACK bool
 RunScript(JSContext *cx, JSScript *script, JSStackFrame *fp);
 
 #define JSPROP_INITIALIZER 0x100   /* NB: Not a valid property attribute. */
 
 extern bool
 CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -1,10 +1,9 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=4 sw=4 et tw=99:
  *
  * ***** 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/
@@ -107,17 +106,17 @@ JSStackFrame::resetInvokeCallFrame()
                            JSFRAME_UNDERFLOW_ARGS |
                            JSFRAME_HAS_CALL_OBJ |
                            JSFRAME_HAS_ARGS_OBJ |
                            JSFRAME_OVERRIDE_ARGS |
                            JSFRAME_HAS_PREVPC |
                            JSFRAME_HAS_RVAL |
                            JSFRAME_HAS_SCOPECHAIN |
                            JSFRAME_HAS_ANNOTATION |
-                           JSFRAME_FINISHED_IN_INTERPRETER)));
+                           JSFRAME_BAILED_AT_RETURN)));
     flags_ &= JSFRAME_FUNCTION |
               JSFRAME_OVERFLOW_ARGS |
               JSFRAME_HAS_PREVPC |
               JSFRAME_UNDERFLOW_ARGS;
 
     JS_ASSERT_IF(!hasCallObj(), scopeChain_ == calleeValue().toObject().getParent());
     JS_ASSERT_IF(hasCallObj(), scopeChain_ == callObj().getParent());
     if (hasCallObj())
@@ -258,21 +257,16 @@ JSStackFrame::stealFrameAndSlots(js::Val
      * Repoint Call, Arguments, Block and With objects to the new live frame.
      * Call and Arguments are done directly because we have pointers to them.
      * Block and With objects are done indirectly through 'liveFrame'. See
      * js_LiveFrameToFloating comment in jsiter.h.
      */
     if (hasCallObj()) {
         callObj().setPrivate(this);
         otherfp->flags_ &= ~JSFRAME_HAS_CALL_OBJ;
-        if (js_IsNamedLambda(fun())) {
-            JSObject *env = callObj().getParent();
-            JS_ASSERT(env->getClass() == &js_DeclEnvClass);
-            env->setPrivate(this);
-        }
     }
     if (hasArgsObj()) {
         argsObj().setPrivate(this);
         otherfp->flags_ &= ~JSFRAME_HAS_ARGS_OBJ;
     }
 }
 
 inline js::Value &
@@ -674,40 +668,11 @@ ValuePropertyBearer(JSContext *cx, const
     }
 
     JSObject *pobj;
     if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
         return NULL;
     return pobj;
 }
 
-static inline bool
-ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
-{
-    Probes::exitJSFun(cx, fp->maybeFun());
-    JSInterpreterHook hook = cx->debugHooks->callHook;
-    if (hook && fp->hasHookData())
-        hook(cx, fp, JS_FALSE, &ok, fp->hookData());
-
-    /*
-     * An eval frame's parent owns its activation objects. A yielding frame's
-     * activation objects are transferred to the floating frame, stored in the
-     * generator.
-     */
-    if (fp->isFunctionFrame() && !fp->isEvalFrame() && !fp->isYielding())
-        PutActivationObjects(cx, fp);
-
-    /*
-     * If inline-constructing, replace primitive rval with the new object
-     * passed in via |this|, and instrument this constructor invocation.
-     */
-    if (fp->isConstructing()) {
-        if (fp->returnValue().isPrimitive())
-            fp->setReturnValue(ObjectValue(fp->constructorThis()));
-        JS_RUNTIME_METER(cx->runtime, constructs);
-    }
-
-    return ok;
-}
-
 }
 
 #endif /* jsinterpinlines_h__ */
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1267,17 +1267,17 @@ SendToGenerator(JSContext *cx, JSGenerat
                             JS_GetFunctionId(gen->floatingFrame()->fun()));
         return JS_FALSE;
     }
 
     /* Check for OOM errors here, where we can fail easily. */
     if (!cx->ensureGeneratorStackSpace())
         return JS_FALSE;
 
-    JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
+    JS_ASSERT(gen->state ==  JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
     switch (op) {
       case JSGENOP_NEXT:
       case JSGENOP_SEND:
         if (gen->state == JSGEN_OPEN) {
             /*
              * Store the argument to send as the result of the yield
              * expression.
              */
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -618,9 +618,11 @@ OPDEF(JSOP_FORGLOBAL,     246,"forglobal
  * They are emitted directly after instructions, such as DEFFUN, that need fast access to
  * the blockChain. The special NULLBLOCKCHAIN is needed because the JOF_OBJECT
  * does not permit NULL object references, since it stores an index into a table of
  * objects.
  */
 OPDEF(JSOP_BLOCKCHAIN,    247,"blockchain",    NULL,  3,  0,  0,  0, JOF_OBJECT)
 OPDEF(JSOP_NULLBLOCKCHAIN,248,"nullblockchain",NULL,  1,  0,  0,  0, JOF_BYTE)
 
-/* When changing bytecodes, don't forget to update JSXDR_BYTECODE_VERSION. */
+OPDEF(JSOP_BEGIN,         249,"begin",         NULL,  1,  0,  0,  0,  JOF_BYTE|JOF_TMPSLOT)
+
+/* When adding bytecodes, don't forget to update JSXDR_BYTECODE_VERSION. */
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -303,17 +303,17 @@ PropertyCache::fill(JSContext *cx, JSObj
 static inline JSAtom *
 GetAtomFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op, const JSCodeSpec &cs)
 {
     if (op == JSOP_LENGTH)
         return cx->runtime->atomState.lengthAtom;
 
     // The method JIT's implementation of instanceof contains an internal lookup
     // of the prototype property.
-    if (op == JSOP_INSTANCEOF)
+    if (op == JSOP_INSTANCEOF || op == JSOP_BEGIN)
         return cx->runtime->atomState.classPrototypeAtom;
 
     ptrdiff_t pcoff = (JOF_TYPE(cs.format) == JOF_SLOTATOM) ? SLOTNO_LEN : 0;
     JSAtom *atom;
     GET_ATOM_FROM_BYTECODE(cx->fp()->script(), pc, pcoff, atom);
     return atom;
 }
 
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -10448,23 +10448,16 @@ TraceRecorder::record_EnterFrame()
     }
 
     /* Try inlining one level in case this recursion doesn't go too deep. */
     if (fp->script() == fp->prev()->script() &&
         fp->prev()->prev() && fp->prev()->prev()->script() == fp->script()) {
         RETURN_STOP_A("recursion started inlining");
     }
 
-    if (fp->isConstructing()) {
-        LIns* args[] = { callee_ins, INS_CONSTPTR(&js_ObjectClass), cx_ins };
-        LIns* tv_ins = lir->insCall(&js_CreateThisFromTrace_ci, args);
-        guard(false, lir->insEqP_0(tv_ins), OOM_EXIT);
-        set(&fp->thisValue(), tv_ins);
-    }
-
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_LeaveFrame()
 {
     debug_only_stmt(JSStackFrame *fp = cx->fp();)
 
@@ -11158,16 +11151,30 @@ TraceRecorder::emitNativePropertyOp(cons
     // lost!  Therefore this can only be used for setters of shared properties.
     // In that case we ignore the result value anyway.
     LIns* status_ins = lir->insLoad(LIR_ldi, lirbuf->state,
                                     (int) offsetof(TracerState, builtinStatus), ACCSET_OTHER);
     propagateFailureToBuiltinStatus(ok_ins, status_ins);
     guard(true, lir->insEqI_0(status_ins), STATUS_EXIT);
 }
 
+JS_REQUIRES_STACK AbortableRecordingStatus
+TraceRecorder::record_JSOP_BEGIN()
+{
+    JSStackFrame* fp = cx->fp();
+    if (fp->isConstructing()) {
+        LIns* callee_ins = get(&cx->fp()->calleeValue());
+        LIns* args[] = { callee_ins, INS_CONSTPTR(&js_ObjectClass), cx_ins };
+        LIns* tv_ins = lir->insCall(&js_CreateThisFromTrace_ci, args);
+        guard(false, lir->insEqP_0(tv_ins), OOM_EXIT);
+        set(&fp->thisValue(), tv_ins);
+    }
+    return ARECORD_CONTINUE;
+}
+
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[], bool rooted)
 {
     if (JSTN_ERRTYPE(sn) == FAIL_STATUS) {
         // This needs to capture the pre-call state of the stack. So do not set
         // pendingSpecializedNative before taking this snapshot.
         JS_ASSERT(!pendingSpecializedNative);
 
--- a/js/src/jsxdrapi.h
+++ b/js/src/jsxdrapi.h
@@ -200,17 +200,17 @@ JS_XDRFindClassById(JSXDRState *xdr, uin
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number should be XDR'ed once near the front of any file or
  * larger storage unit containing XDR'ed bytecode and other data, and checked
  * before deserialization of bytecode.  If the saved version does not match
  * the current version, abort deserialization and invalidate the file.
  */
-#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 74)
+#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 73)
 
 /*
  * Library-private functions.
  */
 extern JSBool
 js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
 
 JS_END_EXTERN_C
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -302,22 +302,16 @@ mjit::Compiler::generatePrologue()
                                               FrameFlagsAddress(), Imm32(JSFRAME_HAS_SCOPECHAIN));
             masm.loadPayload(Address(JSFrameReg, JSStackFrame::offsetOfCallee(fun)), t0);
             masm.loadPtr(Address(t0, offsetof(JSObject, parent)), t0);
             masm.storePtr(t0, Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()));
             hasScope.linkTo(masm.label(), &masm);
         }
     }
 
-    if (isConstructing)
-        constructThis();
-
-    if (debugMode)
-        stubCall(stubs::EnterScript);
-
     return Compile_Okay;
 }
 
 CompileStatus
 mjit::Compiler::generateEpilogue()
 {
     return Compile_Okay;
 }
@@ -1344,26 +1338,26 @@ mjit::Compiler::generateMethod()
             PC += JSOP_LOCALINC_LENGTH;
             if (popped)
                 PC += JSOP_POP_LENGTH;
             break;
           }
           END_CASE(JSOP_LOCALDEC)
 
           BEGIN_CASE(JSOP_BINDNAME)
-            jsop_bindname(fullAtomIndex(PC), true);
+            jsop_bindname(fullAtomIndex(PC));
           END_CASE(JSOP_BINDNAME)
 
           BEGIN_CASE(JSOP_SETPROP)
-            jsop_setprop(script->getAtom(fullAtomIndex(PC)), true);
+            jsop_setprop(script->getAtom(fullAtomIndex(PC)));
           END_CASE(JSOP_SETPROP)
 
           BEGIN_CASE(JSOP_SETNAME)
           BEGIN_CASE(JSOP_SETMETHOD)
-            jsop_setprop(script->getAtom(fullAtomIndex(PC)), true);
+            jsop_setprop(script->getAtom(fullAtomIndex(PC)));
           END_CASE(JSOP_SETNAME)
 
           BEGIN_CASE(JSOP_THROW)
             prepareStubCall(Uses(1));
             stubCall(stubs::Throw);
             frame.pop();
           END_CASE(JSOP_THROW)
 
@@ -1703,16 +1697,21 @@ mjit::Compiler::generateMethod()
           BEGIN_CASE(JSOP_DECGLOBAL)
           BEGIN_CASE(JSOP_GLOBALINC)
           BEGIN_CASE(JSOP_GLOBALDEC)
             /* Advances PC automatically. */
             jsop_globalinc(op, GET_SLOTNO(PC));
             break;
           END_CASE(JSOP_GLOBALINC)
 
+          BEGIN_CASE(JSOP_BEGIN)
+            if (isConstructing)
+                constructThis();
+          END_CASE(JSOP_BEGIN)
+
           default:
            /* Sorry, this opcode isn't implemented yet. */
 #ifdef JS_METHODJIT_SPEW
             JaegerSpew(JSpew_Abort, "opcode %s not handled yet (%s line %d)\n", OpcodeNames[op],
                        script->filename, js_PCToLineNumber(cx, script, PC));
 #endif
             return Compile_Abort;
         }
@@ -1926,21 +1925,16 @@ mjit::Compiler::emitReturnValue(Assemble
 void
 mjit::Compiler::emitReturn(FrameEntry *fe)
 {
     JS_ASSERT_IF(!fun, JSOp(*PC) == JSOP_STOP);
 
     /* Only the top of the stack can be returned. */
     JS_ASSERT_IF(fe, fe == frame.peek(-1));
 
-    if (debugMode) {
-        prepareStubCall(Uses(0));
-        stubCall(stubs::LeaveScript);
-    }
-
     /*
      * If there's a function object, deal with the fact that it can escape.
      * Note that after we've placed the call object, all tracked state can
      * be thrown away. This will happen anyway because the next live opcode
      * (if any) must have an incoming edge.
      *
      * However, it's an optimization to throw it away early - the tracker
      * won't be spilled on further exits or join points.
@@ -2363,38 +2357,30 @@ mjit::Compiler::emitStubCmpOp(BoolStub s
                                     : Assembler::NonZero;
         Jump j = masm.branchTest32(cond, Registers::ReturnReg,
                                    Registers::ReturnReg);
         jumpAndTrace(j, target);
     }
 }
 
 void
-mjit::Compiler::jsop_setprop_slow(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_setprop_slow(JSAtom *atom)
 {
     prepareStubCall(Uses(2));
     masm.move(ImmPtr(atom), Registers::ArgReg1);
-    if (usePropCache)
-        stubCall(STRICT_VARIANT(stubs::SetName));
-    else
-        stubCall(STRICT_VARIANT(stubs::SetPropNoCache));
+    stubCall(STRICT_VARIANT(stubs::SetName));
     JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
     frame.shimmy(1);
 }
 
 void
-mjit::Compiler::jsop_getprop_slow(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_getprop_slow()
 {
     prepareStubCall(Uses(1));
-    if (usePropCache) {
-        stubCall(stubs::GetProp);
-    } else {
-        masm.move(ImmPtr(atom), Registers::ArgReg1);
-        stubCall(stubs::GetPropNoCache);
-    }
+    stubCall(stubs::GetProp);
     frame.pop();
     frame.pushSynced();
 }
 
 bool
 mjit::Compiler::jsop_callprop_slow(JSAtom *atom)
 {
     prepareStubCall(Uses(1));
@@ -2449,41 +2435,41 @@ mjit::Compiler::passMICAddress(MICGenInf
 #if defined JS_POLYIC
 void
 mjit::Compiler::passPICAddress(PICGenInfo &pic)
 {
     pic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 
 void
-mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
+mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
 {
     FrameEntry *top = frame.peek(-1);
 
     /* If the incoming type will never PIC, take slow path. */
     if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
         JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom,
                      top->getKnownType() != JSVAL_TYPE_STRING);
-        jsop_getprop_slow(atom, usePropCache);
+        jsop_getprop_slow();
         return;
     }
 
     /*
      * These two must be loaded first. The objReg because the string path
      * wants to read it, and the shapeReg because it could cause a spill that
      * the string path wouldn't sink back.
      */
     RegisterID objReg = Registers::ReturnReg;
     RegisterID shapeReg = Registers::ReturnReg;
     if (atom == cx->runtime->atomState.lengthAtom) {
         objReg = frame.copyDataIntoReg(top);
         shapeReg = frame.allocReg();
     }
 
-    PICGenInfo pic(ic::PICInfo::GET, usePropCache);
+    PICGenInfo pic(ic::PICInfo::GET);
 
     /* Guard that the type is an object. */
     Jump typeCheck;
     if (doTypeCheck && !top->isTypeKnown()) {
         RegisterID reg = frame.tempRegForType(top);
         pic.typeReg = reg;
 
         /* Start the hot path where it's easy to patch it. */
@@ -2580,17 +2566,17 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
     pics.append(pic);
 }
 
 #ifdef JS_POLYIC
 void
 mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
                                  RegisterID idReg, RegisterID shapeReg)
 {
-    PICGenInfo pic(ic::PICInfo::GETELEM, true);
+    PICGenInfo pic(ic::PICInfo::GETELEM);
 
     pic.objRemat = frame.dataRematInfo(obj);
     pic.idRemat = frame.dataRematInfo(id);
     pic.shapeReg = shapeReg;
     pic.hasTypeCheck = false;
 
     pic.fastPathStart = masm.label();
 
@@ -2693,17 +2679,17 @@ mjit::Compiler::jsop_callprop_generic(JS
     /*
      * These two must be loaded first. The objReg because the string path
      * wants to read it, and the shapeReg because it could cause a spill that
      * the string path wouldn't sink back.
      */
     RegisterID objReg = frame.copyDataIntoReg(top);
     RegisterID shapeReg = frame.allocReg();
 
-    PICGenInfo pic(ic::PICInfo::CALL, true);
+    PICGenInfo pic(ic::PICInfo::CALL);
 
     /* Guard that the type is an object. */
     pic.typeReg = frame.copyTypeIntoReg(top);
 
     /* Start the hot path where it's easy to patch it. */
     pic.fastPathStart = masm.label();
 
     /*
@@ -2861,17 +2847,17 @@ mjit::Compiler::jsop_callprop_str(JSAtom
     return true;
 }
 
 bool
 mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
 {
     FrameEntry *top = frame.peek(-1);
 
-    PICGenInfo pic(ic::PICInfo::CALL, true);
+    PICGenInfo pic(ic::PICInfo::CALL);
 
     JS_ASSERT(top->isTypeKnown());
     JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT);
 
     pic.fastPathStart = masm.label();
     pic.hasTypeCheck = false;
     pic.typeReg = Registers::ReturnReg;
 
@@ -2978,50 +2964,58 @@ mjit::Compiler::jsop_callprop(JSAtom *at
     }
 
     if (top->isTypeKnown())
         return jsop_callprop_obj(atom);
     return jsop_callprop_generic(atom);
 }
 
 void
-mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_setprop(JSAtom *atom)
 {
     FrameEntry *lhs = frame.peek(-2);
     FrameEntry *rhs = frame.peek(-1);
 
     /* If the incoming type will never PIC, take slow path. */
     if (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_OBJECT) {
-        jsop_setprop_slow(atom, usePropCache);
+        jsop_setprop_slow(atom);
         return;
     }
 
     JSOp op = JSOp(*PC);
 
-    PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET, usePropCache);
+    PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET);
     pic.atom = atom;
 
     /* Guard that the type is an object. */
     Jump typeCheck;
     if (!lhs->isTypeKnown()) {
         RegisterID reg = frame.tempRegForType(lhs);
         pic.typeReg = reg;
 
         /* Start the hot path where it's easy to patch it. */
         pic.fastPathStart = masm.label();
         Jump j = masm.testObject(Assembler::NotEqual, reg);
 
         pic.typeCheck = stubcc.linkExit(j, Uses(2));
         stubcc.leave();
 
+        /*
+         * This gets called from PROPINC/PROPDEC which aren't compatible with
+         * the normal SETNAME property cache logic.
+         */
+        JSOp op = JSOp(*PC);
         stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
-        if (usePropCache)
+        if (op == JSOP_SETNAME || op == JSOP_SETPROP || op == JSOP_SETGNAME || op ==
+            JSOP_SETMETHOD) {
             stubcc.call(STRICT_VARIANT(stubs::SetName));
-        else
+        } else {
             stubcc.call(STRICT_VARIANT(stubs::SetPropNoCache));
+        }
+
         typeCheck = stubcc.masm.jump();
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
         pic.hasTypeCheck = false;
         pic.typeReg = Registers::ReturnReg;
     }
 
@@ -3114,17 +3108,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
 #endif
 
     pics.append(pic);
 }
 
 void
 mjit::Compiler::jsop_name(JSAtom *atom)
 {
-    PICGenInfo pic(ic::PICInfo::NAME, true);
+    PICGenInfo pic(ic::PICInfo::NAME);
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.allocReg();
     pic.typeReg = Registers::ReturnReg;
     pic.atom = atom;
     pic.hasTypeCheck = false;
     pic.fastPathStart = masm.label();
 
@@ -3146,17 +3140,17 @@ mjit::Compiler::jsop_name(JSAtom *atom)
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 }
 
 void
 mjit::Compiler::jsop_xname(JSAtom *atom)
 {
-    PICGenInfo pic(ic::PICInfo::XNAME, true);
+    PICGenInfo pic(ic::PICInfo::XNAME);
 
     FrameEntry *fe = frame.peek(-1);
     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
         jsop_getprop(atom);
         return;
     }
 
     if (!fe->isTypeKnown()) {
@@ -3188,19 +3182,19 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
     JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgJumpOffset) == SCOPENAME_JUMP_OFFSET);
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 }
 
 void
-mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache)
+mjit::Compiler::jsop_bindname(uint32 index)
 {
-    PICGenInfo pic(ic::PICInfo::BIND, usePropCache);
+    PICGenInfo pic(ic::PICInfo::BIND);
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.allocReg();
     pic.typeReg = Registers::ReturnReg;
     pic.atom = script->getAtom(index);
     pic.hasTypeCheck = false;
     pic.fastPathStart = masm.label();
 
@@ -3251,52 +3245,47 @@ mjit::Compiler::jsop_name(JSAtom *atom)
 
 void
 mjit::Compiler::jsop_xname(JSAtom *atom)
 {
     jsop_getprop(atom);
 }
 
 void
-mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck, bool usePropCache)
+mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck)
 {
-    jsop_getprop_slow(atom, usePropCache);
+    jsop_getprop_slow();
 }
 
 bool
 mjit::Compiler::jsop_callprop(JSAtom *atom)
 {
     return jsop_callprop_slow(atom);
 }
 
 void
-mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_setprop(JSAtom *atom)
 {
-    jsop_setprop_slow(atom, usePropCache);
+    jsop_setprop_slow(atom);
 }
 
 void
-mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache)
+mjit::Compiler::jsop_bindname(uint32 index)
 {
     RegisterID reg = frame.allocReg();
     Address scopeChain(JSFrameReg, JSStackFrame::offsetOfScopeChain());
     masm.loadPtr(scopeChain, reg);
 
     Address address(reg, offsetof(JSObject, parent));
 
     Jump j = masm.branchPtr(Assembler::NotEqual, masm.payloadOf(address), ImmPtr(0));
 
     stubcc.linkExit(j, Uses(0));
     stubcc.leave();
-    if (usePropCache) {
-        stubcc.call(stubs::BindName);
-    } else {
-        masm.move(ImmPtr(script->getAtom(index)), Registers::ArgReg1);
-        stubcc.call(stubs::BindNameNoCache);
-    }
+    stubcc.call(stubs::BindName);
 
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     stubcc.rejoin(Changes(1));
 }
 #endif
 
 void
@@ -3429,29 +3418,29 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
 
         frame.push(Int32Value(amt));
         // V 1
 
         /* Use sub since it calls ValueToNumber instead of string concat. */
         jsop_binary(JSOP_SUB, stubs::Sub);
         // N+1
 
-        jsop_bindname(index, false);
+        jsop_bindname(index);
         // V+1 OBJ
 
         frame.dup2();
         // V+1 OBJ V+1 OBJ
 
         frame.shift(-3);
         // OBJ OBJ V+1
 
         frame.shift(-1);
         // OBJ V+1
 
-        jsop_setprop(atom, false);
+        jsop_setprop(atom);
         // V+1
 
         if (pop)
             frame.pop();
     } else {
         /* The pre-value is observed, making this more tricky. */
 
         jsop_name(atom);
@@ -3464,29 +3453,29 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
         // N N
 
         frame.push(Int32Value(-amt));
         // N N 1
 
         jsop_binary(JSOP_ADD, stubs::Add);
         // N N+1
 
-        jsop_bindname(index, false);
+        jsop_bindname(index);
         // N N+1 OBJ
 
         frame.dup2();
         // N N+1 OBJ N+1 OBJ
 
         frame.shift(-3);
         // N OBJ OBJ N+1
 
         frame.shift(-1);
         // N OBJ N+1
 
-        jsop_setprop(atom, false);
+        jsop_setprop(atom);
         // N N+1
 
         frame.pop();
         // N
     }
 
     if (pop)
         PC += JSOP_POP_LENGTH;
@@ -3522,17 +3511,17 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
 
             frame.push(Int32Value(amt));
             // OBJ V 1
 
             /* Use sub since it calls ValueToNumber instead of string concat. */
             jsop_binary(JSOP_SUB, stubs::Sub);
             // OBJ V+1
 
-            jsop_setprop(atom, false);
+            jsop_setprop(atom);
             // V+1
 
             if (pop)
                 frame.pop();
         } else {
             /* The pre-value is observed, making this more tricky. */
 
             frame.dup();
@@ -3554,17 +3543,17 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
             // OBJ N N+1
 
             frame.dupAt(-3);
             // OBJ N N+1 OBJ
 
             frame.dupAt(-2);
             // OBJ N N+1 OBJ N+1
 
-            jsop_setprop(atom, false);
+            jsop_setprop(atom);
             // OBJ N N+1 N+1
 
             frame.popn(2);
             // OBJ N
 
             frame.shimmy(1);
             // N
         }
@@ -4359,17 +4348,17 @@ mjit::Compiler::constructThis()
 
     // Load the callee.
     Address callee(JSFrameReg, JSStackFrame::offsetOfCallee(fun));
     RegisterID calleeReg = frame.allocReg();
     masm.loadPayload(callee, calleeReg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, calleeReg);
 
     // Get callee.prototype.
-    jsop_getprop(cx->runtime->atomState.classPrototypeAtom, false, false);
+    jsop_getprop(cx->runtime->atomState.classPrototypeAtom);
 
     // Reach into the proto Value and grab a register for its data.
     FrameEntry *protoFe = frame.peek(-1);
     RegisterID protoReg = frame.ownRegForData(protoFe);
 
     // Now, get the type. If it's not an object, set protoReg to NULL.
     Jump isNotObject = frame.testObject(Assembler::NotEqual, protoFe);
     stubcc.linkExitDirect(isNotObject, stubcc.masm.label());
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -134,18 +134,17 @@ class Compiler : public BaseCompiler
         Label joinPoint;
         DataLabelPtr fastNcodePatch;
         DataLabelPtr slowNcodePatch;
         bool hasSlowNcode;
     };
 
 #if defined JS_POLYIC
     struct PICGenInfo {
-        PICGenInfo(ic::PICInfo::Kind kind, bool usePropCache)
-          : kind(kind), usePropCache(usePropCache)
+        PICGenInfo(ic::PICInfo::Kind kind) : kind(kind)
         { }
         ic::PICInfo::Kind kind;
         Label fastPathStart;
         Label storeBack;
         Label typeCheck;
         Label slowPathStart;
         DataLabelPtr addrLabel;
         RegisterID shapeReg;
@@ -153,35 +152,33 @@ class Compiler : public BaseCompiler
         RegisterID idReg;
         RegisterID typeReg;
         Label shapeGuard;
         JSAtom *atom;
         StateRemat objRemat;
         StateRemat idRemat;
         Call callReturn;
         bool hasTypeCheck;
-        bool usePropCache;
         ValueRemat vr;
 # if defined JS_CPU_X64
         ic::PICLabels labels;
 # endif
 
-        void copySimpleMembersTo(ic::PICInfo &ic) const {
-            ic.kind = kind;
-            ic.shapeReg = shapeReg;
-            ic.objReg = objReg;
-            ic.atom = atom;
-            ic.usePropCache = usePropCache;
+        void copySimpleMembersTo(ic::PICInfo &pi) const {
+            pi.kind = kind;
+            pi.shapeReg = shapeReg;
+            pi.objReg = objReg;
+            pi.atom = atom;
             if (kind == ic::PICInfo::SET) {
-                ic.u.vr = vr;
+                pi.u.vr = vr;
             } else if (kind != ic::PICInfo::NAME) {
-                ic.u.get.idReg = idReg;
-                ic.u.get.typeReg = typeReg;
-                ic.u.get.hasTypeCheck = hasTypeCheck;
-                ic.u.get.objRemat = objRemat.offset;
+                pi.u.get.idReg = idReg;
+                pi.u.get.typeReg = typeReg;
+                pi.u.get.hasTypeCheck = hasTypeCheck;
+                pi.u.get.objRemat = objRemat.offset;
             }
         }
 
     };
 #endif
 
     struct Defs {
         Defs(uint32 ndefs)
@@ -273,20 +270,20 @@ class Compiler : public BaseCompiler
 #endif
 #ifdef JS_MONOIC
     void passMICAddress(MICGenInfo &mic);
 #endif
     void constructThis();
 
     /* Opcode handlers. */
     void jumpAndTrace(Jump j, jsbytecode *target, Jump *slowOne = NULL, Jump *slowTwo = NULL);
-    void jsop_bindname(uint32 index, bool usePropCache);
+    void jsop_bindname(uint32 index);
     void jsop_setglobal(uint32 index);
     void jsop_getglobal(uint32 index);
-    void jsop_getprop_slow(JSAtom *atom, bool usePropCache = true);
+    void jsop_getprop_slow();
     void jsop_getarg(uint32 index);
     void jsop_this();
     void emitReturn(FrameEntry *fe);
     void emitFinalReturn(Assembler &masm);
     void loadReturnValue(Assembler *masm, FrameEntry *fe);
     void emitReturnValue(Assembler *masm, FrameEntry *fe);
     void dispatchCall(VoidPtrStubUInt32 stub, uint32 argc);
     void interruptCheckHelper();
@@ -300,20 +297,20 @@ class Compiler : public BaseCompiler
     void jsop_getgname(uint32 index);
     void jsop_getgname_slow(uint32 index);
     void jsop_setgname(uint32 index);
     void jsop_setgname_slow(uint32 index);
     void jsop_bindgname();
     void jsop_setelem_slow();
     void jsop_getelem_slow();
     void jsop_unbrand();
-    void jsop_getprop(JSAtom *atom, bool typeCheck = true, bool usePropCache = true);
+    void jsop_getprop(JSAtom *atom, bool typeCheck = true);
     void jsop_length();
-    void jsop_setprop(JSAtom *atom, bool usePropCache = true);
-    void jsop_setprop_slow(JSAtom *atom, bool usePropCache = true);
+    void jsop_setprop(JSAtom *atom);
+    void jsop_setprop_slow(JSAtom *atom);
     bool jsop_callprop_slow(JSAtom *atom);
     bool jsop_callprop(JSAtom *atom);
     bool jsop_callprop_obj(JSAtom *atom);
     bool jsop_callprop_str(JSAtom *atom);
     bool jsop_callprop_generic(JSAtom *atom);
     void jsop_instanceof();
     void jsop_name(JSAtom *atom);
     void jsop_xname(JSAtom *atom);
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -68,16 +68,19 @@
 #include "StubCalls-inl.h"
 
 #include "jsautooplen.h"
 
 using namespace js;
 using namespace js::mjit;
 using namespace JSC;
 
+static bool
+InlineReturn(VMFrame &f, JSBool ok, JSBool popFrame = JS_TRUE);
+
 static jsbytecode *
 FindExceptionHandler(JSContext *cx)
 {
     JSStackFrame *fp = cx->fp();
     JSScript *script = fp->script();
 
 top:
     if (cx->throwing && script->trynotesOffset) {
@@ -169,29 +172,56 @@ top:
 /*
  * Clean up a frame and return.  popFrame indicates whether to additionally pop
  * the frame and store the return value on the caller's stack.  The frame will
  * normally be popped by the caller on return from a call into JIT code,
  * so must be popped here when that caller code will not execute.  This can be
  * either because of a call into an un-JITable script, or because the call is
  * throwing an exception.
  */
-static void
-InlineReturn(VMFrame &f)
+static bool
+InlineReturn(VMFrame &f, JSBool ok, JSBool popFrame)
 {
     JSContext *cx = f.cx;
     JSStackFrame *fp = f.regs.fp;
 
     JS_ASSERT(f.fp() != f.entryFp);
 
     JS_ASSERT(!js_IsActiveWithOrBlock(cx, &fp->scopeChain(), 0));
 
-    Value *newsp = fp->actualArgs() - 1;
-    newsp[-1] = fp->returnValue();
-    cx->stack().popInlineFrame(cx, fp->prev(), newsp);
+    // Marker for debug support.
+    if (JS_UNLIKELY(fp->hasHookData())) {
+        JSInterpreterHook hook;
+        JSBool status;
+
+        hook = cx->debugHooks->callHook;
+        if (hook) {
+            /*
+             * Do not pass &ok directly as exposing the address inhibits
+             * optimizations and uninitialised warnings.
+             */
+            status = ok;
+            hook(cx, fp, JS_FALSE, &status, fp->hookData());
+            ok = (status == JS_TRUE);
+            // CHECK_INTERRUPT_HANDLER();
+        }
+    }
+
+    PutActivationObjects(cx, fp);
+
+    if (fp->isConstructing() && fp->returnValue().isPrimitive())
+        fp->setReturnValue(fp->thisValue());
+
+    if (popFrame) {
+        Value *newsp = fp->actualArgs() - 1;
+        newsp[-1] = fp->returnValue();
+        cx->stack().popInlineFrame(cx, fp->prev(), newsp);
+    }
+
+    return ok;
 }
 
 void JS_FASTCALL
 stubs::SlowCall(VMFrame &f, uint32 argc)
 {
     Value *vp = f.regs.sp - (argc + 2);
 
     if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0))
@@ -337,28 +367,29 @@ stubs::CompileFunction(VMFrame &f, uint3
         THROWV(NULL);
 
     CompileStatus status = CanMethodJIT(cx, script, fp);
     if (status == Compile_Okay)
         return script->getJIT(callingNew)->invokeEntry;
 
     /* Function did not compile... interpret it. */
     JSBool ok = Interpret(cx, fp);
-    InlineReturn(f);
+    InlineReturn(f, ok);
 
     if (!ok)
         THROWV(NULL);
 
     return NULL;
 }
 
 static inline bool
 UncachedInlineCall(VMFrame &f, uint32 flags, void **pret, uint32 argc)
 {
     JSContext *cx = f.cx;
+    JSStackFrame *fp = f.fp();
     Value *vp = f.regs.sp - (argc + 2);
     JSObject &callee = vp->toObject();
     JSFunction *newfun = callee.getFunctionPrivate();
     JSScript *newscript = newfun->script();
 
     /* Get pointer to new frame/slots, prepare arguments. */
     StackSpace &stack = cx->stack();
     JSStackFrame *newfp = stack.getInlineFrameWithinLimit(cx, f.regs.sp, argc,
@@ -376,34 +407,40 @@ UncachedInlineCall(VMFrame &f, uint32 fl
     /* Officially push the frame. */
     stack.pushInlineFrame(cx, newscript, newfp, &f.regs);
     JS_ASSERT(newfp == f.regs.fp);
 
     /* Scope with a call object parented by callee's parent. */
     if (newfun->isHeavyweight() && !js_GetCallObject(cx, newfp))
         return false;
 
+    /* Marker for debug support. */
+    if (JSInterpreterHook hook = cx->debugHooks->callHook) {
+        newfp->setHookData(hook(cx, fp, JS_TRUE, 0,
+                                cx->debugHooks->callHookData));
+    }
+
     /* Try to compile if not already compiled. */
     if (newscript->getJITStatus(newfp->isConstructing()) == JITScript_None) {
         if (mjit::TryCompile(cx, newfp) == Compile_Error) {
             /* A runtime exception was thrown, get out. */
-            InlineReturn(f);
+            InlineReturn(f, JS_FALSE);
             return false;
         }
     }
 
     /* If newscript was successfully compiled, run it. */
     if (JITScript *jit = newscript->getJIT(newfp->isConstructing())) {
         *pret = jit->invokeEntry;
         return true;
     }
 
     /* Otherwise, run newscript in the interpreter. */
     bool ok = !!Interpret(cx, cx->fp());
-    InlineReturn(f);
+    InlineReturn(f, JS_TRUE);
 
     *pret = NULL;
     return ok;
 }
 
 void * JS_FASTCALL
 stubs::UncachedNew(VMFrame &f, uint32 argc)
 {
@@ -532,28 +569,21 @@ js_InternalThrow(VMFrame &f)
             break;
 
         // If on the 'topmost' frame (where topmost means the first frame
         // called into through js_Interpret). In this case, we still unwind,
         // but we shouldn't return from a JS function, because we're not in a
         // JS function.
         bool lastFrame = (f.entryFp == f.fp());
         js_UnwindScope(cx, 0, cx->throwing);
-
-        // For consistency with Interpret(), always run the script epilogue.
-        // This simplifies interactions with RunTracer(), since it can assume
-        // no matter how a function exited (error or not), that the epilogue
-        // does not need to be run.
-        ScriptEpilogue(f.cx, f.fp(), false);
-
         if (lastFrame)
             break;
 
         JS_ASSERT(f.regs.sp == cx->regs->sp);
-        InlineReturn(f);
+        InlineReturn(f, JS_FALSE);
     }
 
     JS_ASSERT(f.regs.sp == cx->regs->sp);
 
     if (!pc)
         return NULL;
 
     JSStackFrame *fp = cx->fp();
@@ -576,73 +606,46 @@ stubs::CreateThis(VMFrame &f, JSObject *
     JSStackFrame *fp = f.fp();
     JSObject *callee = &fp->callee();
     JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
     if (!obj)
         THROW();
     fp->formalArgs()[-1].setObject(*obj);
 }
 
-void JS_FASTCALL
-stubs::EnterScript(VMFrame &f)
+static inline void
+AdvanceReturnPC(JSContext *cx)
 {
-    JSStackFrame *fp = f.fp();
-    JSContext *cx = f.cx;
-    JSInterpreterHook hook = cx->debugHooks->callHook;
-    if (JS_UNLIKELY(hook != NULL))
-        fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
-
-    Probes::enterJSFun(cx, fp->maybeFun());
-}
-
-void JS_FASTCALL
-stubs::LeaveScript(VMFrame &f)
-{
-    JSStackFrame *fp = f.fp();
-    JSContext *cx = f.cx;
-    Probes::exitJSFun(cx, fp->maybeFun());
-    JSInterpreterHook hook = cx->debugHooks->callHook;
-
-    if (hook && fp->hasHookData()) {
-        JSBool ok = JS_TRUE;
-        hook(cx, fp, JS_FALSE, &ok, fp->hookData());
-        if (!ok)
-            THROW();
-    }
+    /* Simulate an inline_return by advancing the pc. */
+    JS_ASSERT(*cx->regs->pc == JSOP_CALL ||
+              *cx->regs->pc == JSOP_NEW ||
+              *cx->regs->pc == JSOP_EVAL ||
+              *cx->regs->pc == JSOP_APPLY);
+    cx->regs->pc += JSOP_CALL_LENGTH;
 }
 
 #ifdef JS_TRACER
 
-/*
- * Called when an error is in progress and the topmost frame could not handle
- * it. This will unwind to a given frame, or find and align to an exception
- * handler in the process.
- */
 static inline bool
-HandleErrorInExcessFrame(VMFrame &f, JSStackFrame *stopFp, bool searchedTopmostFrame = true)
+HandleErrorInExcessFrames(VMFrame &f, JSStackFrame *stopFp)
 {
     JSContext *cx = f.cx;
 
     /*
      * Callers of this called either Interpret() or JaegerShot(), which would
      * have searched for exception handlers already. If we see stopFp, just
      * return false. Otherwise, pop the frame, since it's guaranteed useless.
-     *
-     * Note that this also guarantees ScriptEpilogue() has been called.
      */
     JSStackFrame *fp = cx->fp();
-    if (searchedTopmostFrame) {
-        if (fp == stopFp)
-            return false;
+    if (fp == stopFp)
+        return false;
 
-        InlineReturn(f);
-    }
+    bool returnOK = InlineReturn(f, false);
 
     /* Remove the bottom frame. */
-    bool returnOK = false;
     for (;;) {
         fp = cx->fp();
 
         /* Clear imacros. */
         if (fp->hasImacropc()) {
             cx->regs->pc = fp->imacropc();
             fp->clearImacropc();
         }
@@ -659,203 +662,100 @@ HandleErrorInExcessFrame(VMFrame &f, JSS
         }
 
         /* Don't unwind if this was the entry frame. */
         if (fp == stopFp)
             break;
 
         /* Unwind and return. */
         returnOK &= bool(js_UnwindScope(cx, 0, returnOK || cx->throwing));
-        returnOK = ScriptEpilogue(cx, fp, returnOK);
-        InlineReturn(f);
+        returnOK = InlineReturn(f, returnOK);
     }
 
     JS_ASSERT(&f.regs == cx->regs);
     JS_ASSERT_IF(!returnOK, cx->fp() == stopFp);
 
     return returnOK;
 }
 
-/* Returns whether the current PC has method JIT'd code. */
 static inline void *
 AtSafePoint(JSContext *cx)
 {
     JSStackFrame *fp = cx->fp();
     if (fp->hasImacropc())
         return false;
 
     JSScript *script = fp->script();
     return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc);
 }
 
-/*
- * Interprets until either a safe point is reached that has method JIT'd
- * code, or the current frame tries to return.
- */
 static inline JSBool
 PartialInterpret(VMFrame &f)
 {
     JSContext *cx = f.cx;
     JSStackFrame *fp = cx->fp();
 
 #ifdef DEBUG
     JSScript *script = fp->script();
-    JS_ASSERT(!fp->finishedInInterpreter());
     JS_ASSERT(fp->hasImacropc() ||
               !script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc));
 #endif
 
     JSBool ok = JS_TRUE;
     ok = Interpret(cx, fp, 0, JSINTERP_SAFEPOINT);
 
     return ok;
 }
 
 JS_STATIC_ASSERT(JSOP_NOP == 0);
 
-/* Returns whether the current PC would return, popping the frame. */
 static inline JSOp
 FrameIsFinished(JSContext *cx)
 {
     JSOp op = JSOp(*cx->regs->pc);
     return (op == JSOP_RETURN ||
             op == JSOP_RETRVAL ||
             op == JSOP_STOP)
         ? op
         : JSOP_NOP;
 }
 
-
-/* Simulate an inline_return by advancing the pc. */
-static inline void
-AdvanceReturnPC(JSContext *cx)
-{
-    JS_ASSERT(*cx->regs->pc == JSOP_CALL ||
-              *cx->regs->pc == JSOP_NEW ||
-              *cx->regs->pc == JSOP_EVAL ||
-              *cx->regs->pc == JSOP_APPLY);
-    cx->regs->pc += JSOP_CALL_LENGTH;
-}
-
-
-/*
- * Given a frame that is about to return, make sure its return value and
- * activation objects are fixed up. Then, pop the frame and advance the
- * current PC. Note that while we could enter the JIT at this point, the
- * logic would still be necessary for the interpreter, so it's easier
- * (and faster) to finish frames in C++ even if at a safe point here.
- */
-static bool
-HandleFinishedFrame(VMFrame &f, JSStackFrame *entryFrame)
-{
-    JSContext *cx = f.cx;
-
-    JS_ASSERT(FrameIsFinished(cx));
-
-    /*
-     * This is the most difficult and complicated piece of the tracer
-     * integration, and historically has been very buggy. The problem is that
-     * although this frame has to be popped (see RemoveExcessFrames), it may
-     * be at a JSOP_RETURN opcode, and it might not have ever been executed.
-     * That is, fp->rval may not be set to the top of the stack, and if it
-     * has, the stack has already been decremented. Note that fp->rval is not
-     * the only problem: the epilogue may never have been executed.
-     *
-     * Here are the edge cases and whether the frame has been exited cleanly:
-     *  1. No: A trace exited directly before a RETURN op, and the
-     *         interpreter never ran.
-     *  2. Yes: The interpreter exited cleanly.
-     *  3. No: The interpreter exited on a safe point. LEAVE_ON_SAFE_POINT
-     *         is not used in between JSOP_RETURN and advancing the PC,
-     *         therefore, it cannot have been run if at a safe point.
-     *  4. No: Somewhere in the RunTracer call tree, we removed a frame,
-     *         and we returned to a JSOP_RETURN opcode. Note carefully
-     *         that in this situation, FrameIsFinished() returns true!
-     *  5. Yes: The function exited in the method JIT. However, in this
-     *         case, we'll never enter HandleFinishedFrame(): we always
-     *         immediately pop JIT'd frames.
-     *
-     * Since the only scenario where this fixup is NOT needed is a normal exit
-     * from the interpreter, we can cleanly check for this scenario by checking
-     * a bit it sets in the frame.
-     */
-    bool returnOK = true;
-    if (!cx->fp()->finishedInInterpreter()) {
-        if (JSOp(*cx->regs->pc) == JSOP_RETURN)
-            cx->fp()->setReturnValue(f.regs.sp[-1]);
-
-        returnOK = ScriptEpilogue(cx, cx->fp(), true);
-    }
-
-    JS_ASSERT_IF(cx->fp()->isFunctionFrame() &&
-                 !cx->fp()->isEvalFrame(),
-                 !cx->fp()->hasCallObj());
-
-    if (cx->fp() != entryFrame) {
-        InlineReturn(f);
-        AdvanceReturnPC(cx);
-    }
-
-    return returnOK;
-}
-
-/*
- * Given a frame newer than the entry frame, try to finish it. If it's at a
- * return position, pop the frame. If it's at a safe point, execute it in
- * Jaeger code. Otherwise, try to interpret until a safe point.
- *
- * While this function is guaranteed to make progress, it may not actually
- * finish or pop the current frame. It can either:
- *   1) Finalize a finished frame, or
- *   2) Finish and finalize the frame in the Method JIT, or
- *   3) Interpret, which can:
- *     a) Propagate an error, or
- *     b) Finish the frame, but not finalize it, or
- *     c) Abruptly leave at any point in the frame, or in a newer frame
- *        pushed by a call, that has method JIT'd code.
- */
-static bool
-EvaluateExcessFrame(VMFrame &f, JSStackFrame *entryFrame)
-{
-    JSContext *cx = f.cx;
-    JSStackFrame *fp = cx->fp();
-
-    /*
-     * A "finished" frame is when the interpreter rested on a STOP,
-     * RETURN, RETRVAL, etc. We check for finished frames BEFORE looking
-     * for a safe point. If the frame was finished, we could have already
-     * called ScriptEpilogue(), and entering the JIT could call it twice.
-     */
-    if (!fp->hasImacropc() && FrameIsFinished(cx))
-        return HandleFinishedFrame(f, entryFrame);
-
-    if (void *ncode = AtSafePoint(cx)) {
-        if (!JaegerShotAtSafePoint(cx, ncode))
-            return false;
-        InlineReturn(f);
-        AdvanceReturnPC(cx);
-        return true;
-    }
-
-    return PartialInterpret(f);
-}
-
-/*
- * Evaluate frames newer than the entry frame until all are gone. This will
- * always leave f.regs.fp == entryFrame.
- */
 static bool
 FinishExcessFrames(VMFrame &f, JSStackFrame *entryFrame)
 {
     JSContext *cx = f.cx;
+    while (cx->fp() != entryFrame || entryFrame->hasImacropc()) {
+        if (void *ncode = AtSafePoint(cx)) {
+            if (!JaegerShotAtSafePoint(cx, ncode)) {
+                if (!HandleErrorInExcessFrames(f, entryFrame))
+                    return false;
 
-    while (cx->fp() != entryFrame || entryFrame->hasImacropc()) {
-        if (!EvaluateExcessFrame(f, entryFrame)) {
-            if (!HandleErrorInExcessFrame(f, entryFrame))
-                return false;
+                /* Could be anywhere - restart outer loop. */
+                continue;
+            }
+            InlineReturn(f, JS_TRUE);
+            AdvanceReturnPC(cx);
+        } else {
+            if (!PartialInterpret(f)) {
+                if (!HandleErrorInExcessFrames(f, entryFrame))
+                    return false;
+            } else if (cx->fp() != entryFrame) {
+                /*
+                 * Partial interpret could have dropped us anywhere. Deduce the
+                 * edge case: at a RETURN, needing to pop a frame.
+                 */
+                JS_ASSERT(!cx->fp()->hasImacropc());
+                if (FrameIsFinished(cx)) {
+                    JSOp op = JSOp(*cx->regs->pc);
+                    if (op == JSOP_RETURN && !cx->fp()->isBailedAtReturn())
+                        cx->fp()->setReturnValue(f.regs.sp[-1]);
+                    InlineReturn(f, JS_TRUE);
+                    AdvanceReturnPC(cx);
+                }
+            }
         }
     }
 
     return true;
 }
 
 #if JS_MONOIC
 static void
@@ -920,28 +820,28 @@ RunTracer(VMFrame &f)
     tpa = MonitorTracePoint(f.cx, inlineCallCount, blacklist);
     JS_ASSERT(!TRACE_RECORDER(cx));
 
 #if JS_MONOIC
     if (blacklist)
         DisableTraceHint(f, mic);
 #endif
 
-    // Even though ExecuteTree() bypasses the interpreter, it should propagate
-    // error failures correctly.
-    JS_ASSERT_IF(cx->throwing, tpa == TPA_Error);
+    if ((tpa == TPA_RanStuff || tpa == TPA_Recorded) && cx->throwing)
+        tpa = TPA_Error;
 
+	/* Sync up the VMFrame's view of cx->fp(). */
 	f.fp() = cx->fp();
-    JS_ASSERT(f.fp() == cx->fp());
+
     switch (tpa) {
       case TPA_Nothing:
         return NULL;
 
       case TPA_Error:
-        if (!HandleErrorInExcessFrame(f, entryFrame, f.fp()->finishedInInterpreter()))
+        if (!HandleErrorInExcessFrames(f, entryFrame))
             THROWV(NULL);
         JS_ASSERT(!cx->fp()->hasImacropc());
         break;
 
       case TPA_RanStuff:
       case TPA_Recorded:
         break;
     }
@@ -969,36 +869,42 @@ RunTracer(VMFrame &f)
      */
 
   restart:
     /* Step 1. Finish frames created after the entry frame. */
     if (!FinishExcessFrames(f, entryFrame))
         THROWV(NULL);
 
     /* IMacros are guaranteed to have been removed by now. */
-    JS_ASSERT(f.fp() == entryFrame);
     JS_ASSERT(!entryFrame->hasImacropc());
 
-    /* Step 2. If entryFrame is done, use a special path to return to EnterMethodJIT(). */
-    if (FrameIsFinished(cx)) {
-        if (!HandleFinishedFrame(f, entryFrame))
-            THROWV(NULL);
+    /* Step 2. If entryFrame is at a safe point, just leave. */
+    if (void *ncode = AtSafePoint(cx))
+        return ncode;
+
+    /* Step 3. If entryFrame is at a RETURN, then leave slightly differently. */
+    if (JSOp op = FrameIsFinished(cx)) {
+        /* We're not guaranteed that the RETURN was run. */
+        if (op == JSOP_RETURN && !entryFrame->isBailedAtReturn())
+            entryFrame->setReturnValue(f.regs.sp[-1]);
+
+        /* Cleanup activation objects on the frame unless it's owned by an Invoke. */
+        if (f.fp() != f.entryFp) {
+            if (!InlineReturn(f, JS_TRUE, JS_FALSE))
+                THROWV(NULL);
+        }
 
         void *retPtr = JS_FUNC_TO_DATA_PTR(void *, InjectJaegerReturn);
         *f.returnAddressLocation() = retPtr;
         return NULL;
     }
 
-    /* Step 3. If entryFrame is at a safe point, just leave. */
-    if (void *ncode = AtSafePoint(cx))
-        return ncode;
-
     /* Step 4. Do a partial interp, then restart the whole process. */
     if (!PartialInterpret(f)) {
-        if (!HandleErrorInExcessFrame(f, entryFrame))
+        if (!HandleErrorInExcessFrames(f, entryFrame))
             THROWV(NULL);
     }
 
     goto restart;
 }
 
 #endif /* JS_TRACER */
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -685,20 +685,20 @@ class SetPropCompiler : public PICStubCo
         } 
 
         return generateStub(obj->shape(), shape, false, !obj->hasSlotsArray());
     }
 };
 
 class GetPropCompiler : public PICStubCompiler
 {
-    JSObject    *obj;
-    JSAtom      *atom;
-    VoidStubPIC stub;
-    int         lastStubSecondShapeGuard;
+    JSObject *obj;
+    JSAtom *atom;
+    void   *stub;
+    int lastStubSecondShapeGuard;
 
     static int32 inlineShapeOffset(ic::PICInfo &pic) {
 #if defined JS_NUNBOX32
         return GETPROP_INLINE_SHAPE_OFFSET;
 #elif defined JS_PUNBOX64
         return pic.labels.getprop.inlineShapeOffset;
 #endif
     }
@@ -728,21 +728,26 @@ class GetPropCompiler : public PICStubCo
     }
 
     inline int32 dslotsLoad() {
         return dslotsLoad(pic);
     }
 
   public:
     GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
+                    VoidStub stub)
+      : PICStubCompiler("getprop", f, script, pic), obj(obj), atom(atom),
+        stub(JS_FUNC_TO_DATA_PTR(void *, stub)),
+        lastStubSecondShapeGuard(pic.secondShapeGuard)
+    { }
+
+    GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
                     VoidStubPIC stub)
-      : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic),
-        obj(obj),
-        atom(atom),
-        stub(stub),
+      : PICStubCompiler("callprop", f, script, pic), obj(obj), atom(atom),
+        stub(JS_FUNC_TO_DATA_PTR(void *, stub)),
         lastStubSecondShapeGuard(pic.secondShapeGuard)
     { }
 
     static void reset(ic::PICInfo &pic)
     {
         RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH);
         repatcher.repatchLEAToLoadPtr(pic.storeBack.instructionAtOffset(dslotsLoad(pic)));
         repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(
@@ -2002,54 +2007,36 @@ class BindNameCompiler : public PICStubC
 
         if (!generateStub(obj))
             return NULL;
 
         return obj;
     }
 };
 
-static void JS_FASTCALL
-DisabledLengthIC(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::Length(f);
-}
-
-static void JS_FASTCALL
-DisabledGetPropIC(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::GetProp(f);
-}
-
-static void JS_FASTCALL
-DisabledGetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::GetPropNoCache(f, pic->atom);
-}
-
 void JS_FASTCALL
 ic::GetProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
     JSAtom *atom = pic->atom;
     if (atom == f.cx->runtime->atomState.lengthAtom) {
         if (f.regs.sp[-1].isString()) {
-            GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledLengthIC);
+            GetPropCompiler cc(f, script, NULL, *pic, NULL, stubs::Length);
             if (!cc.generateStringLengthStub()) {
                 cc.disable("error");
                 THROW();
             }
             JSString *str = f.regs.sp[-1].toString();
             f.regs.sp[-1].setInt32(str->length());
             return;
         } else if (!f.regs.sp[-1].isPrimitive()) {
             JSObject *obj = &f.regs.sp[-1].toObject();
             if (obj->isArray() || (obj->isArguments() && !obj->isArgsLengthOverridden())) {
-                GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledLengthIC);
+                GetPropCompiler cc(f, script, obj, *pic, NULL, stubs::Length);
                 if (obj->isArray()) {
                     if (!cc.generateArrayLengthStub()) {
                         cc.disable("error");
                         THROW();
                     }
                     f.regs.sp[-1].setNumber(obj->getArrayLength());
                 } else if (obj->isArguments()) {
                     if (!cc.generateArgsLengthStub()) {
@@ -2064,20 +2051,17 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
         atom = f.cx->runtime->atomState.lengthAtom;
     }
 
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-1]);
     if (!obj)
         THROW();
 
     if (pic->shouldGenerate()) {
-        VoidStubPIC stub = pic->usePropCache
-                           ? DisabledGetPropIC
-                           : DisabledGetPropICNoCache;
-        GetPropCompiler cc(f, script, obj, *pic, atom, stub);
+        GetPropCompiler cc(f, script, obj, *pic, atom, stubs::GetProp);
         if (!cc.update()) {
             cc.disable("error");
             THROW();
         }
     }
 
     Value v;
     if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v))
@@ -2111,26 +2095,26 @@ ic::GetElem(VMFrame &f, ic::PICInfo *pic
     Value v;
     if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v))
         THROW();
     f.regs.sp[-2] = v;
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
-DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic)
+SetPropDumb(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::SetName<strict>(f, pic->atom);
+    stubs::SetPropNoCache<strict>(f, pic->atom);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
-DisabledSetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
+SetPropSlow(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::SetPropNoCache<strict>(f, pic->atom);
+    stubs::SetName<strict>(f, pic->atom);
 }
 
 void JS_FASTCALL
 ic::SetProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
     if (!obj)
         THROW();
@@ -2142,32 +2126,45 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic
     // Important: We update the PIC before looking up the property so that the
     // PIC is updated only if the property already exists. The PIC doesn't try
     // to optimize adding new properties; that is for the slow case.
     //
     // Also note, we can't use SetName for PROPINC PICs because the property
     // cache can't handle a GET and SET from the same scripted PC.
     //
 
-    VoidStubPIC stub = pic->usePropCache
-                       ? STRICT_VARIANT(DisabledSetPropIC)
-                       : STRICT_VARIANT(DisabledSetPropICNoCache);
+    VoidStubPIC stub;
+    switch (JSOp(*f.regs.pc)) {
+      case JSOP_PROPINC:
+      case JSOP_PROPDEC:
+      case JSOP_INCPROP:
+      case JSOP_DECPROP:
+      case JSOP_NAMEINC:
+      case JSOP_NAMEDEC:
+      case JSOP_INCNAME:
+      case JSOP_DECNAME:
+        stub = STRICT_VARIANT(SetPropDumb);
+        break;
+      default:
+        stub = STRICT_VARIANT(SetPropSlow);
+        break;
+    }
 
     SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub);
     if (!cc.update()) {
         cc.disable("error");
         THROW();
     }
     
     Value rval = f.regs.sp[-1];
     stub(f, pic);
 }
 
 static void JS_FASTCALL
-DisabledCallPropIC(VMFrame &f, ic::PICInfo *pic)
+CallPropSlow(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::CallProp(f, pic->atom);
 }
 
 void JS_FASTCALL
 ic::CallProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSContext *cx = f.cx;
@@ -2252,17 +2249,17 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pi
                                       &rval)) {
                 THROW();
             }
             regs.sp[-1] = lval;
             regs.sp[-2] = rval;
         }
     }
 
-    GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, DisabledCallPropIC);
+    GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, CallPropSlow);
     if (usePIC) {
         if (lval.isObject()) {
             if (!cc.update()) {
                 cc.disable("error");
                 THROW();
             }
         } else if (lval.isString()) {
             if (!cc.generateStringCallStub()) {
@@ -2281,36 +2278,36 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pi
         regs.sp[-2].setString(ATOM_TO_STRING(pic->atom));
         if (!js_OnUnknownMethod(cx, regs.sp - 2))
             THROW();
     }
 #endif
 }
 
 static void JS_FASTCALL
-DisabledNameIC(VMFrame &f, ic::PICInfo *pic)
+SlowName(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::Name(f);
 }
 
 static void JS_FASTCALL
-DisabledXNameIC(VMFrame &f, ic::PICInfo *pic)
+SlowXName(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::GetProp(f);
 }
 
 void JS_FASTCALL
 ic::XName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
     /* GETXPROP is guaranteed to have an object. */
     JSObject *obj = &f.regs.sp[-1].toObject();
 
-    ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, DisabledXNameIC);
+    ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, SlowXName);
 
     if (!cc.updateForXName()) {
         cc.disable("error");
         THROW();
     }
 
     Value rval;
     if (!cc.retrieve(&rval))
@@ -2318,50 +2315,41 @@ ic::XName(VMFrame &f, ic::PICInfo *pic)
     f.regs.sp[-1] = rval;
 }
 
 void JS_FASTCALL
 ic::Name(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledNameIC);
+    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, SlowName);
 
     if (!cc.updateForName()) {
         cc.disable("error");
         THROW();
     }
 
     Value rval;
     if (!cc.retrieve(&rval))
         THROW();
     f.regs.sp[0] = rval;
 }
 
 static void JS_FASTCALL
-DisabledBindNameIC(VMFrame &f, ic::PICInfo *pic)
+SlowBindName(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::BindName(f);
 }
 
-static void JS_FASTCALL
-DisabledBindNameICNoCache(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::BindNameNoCache(f, pic->atom);
-}
-
 void JS_FASTCALL
 ic::BindName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    VoidStubPIC stub = pic->usePropCache
-                       ? DisabledBindNameIC
-                       : DisabledBindNameICNoCache;
-    BindNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, stub);
+    BindNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, SlowBindName);
 
     JSObject *obj = cc.update();
     if (!obj) {
         cc.disable("error");
         THROW();
     }
 
     f.regs.sp[0].setObject(*obj);
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -231,19 +231,16 @@ struct PICInfo {
     int secondShapeGuard : 11;
 
     Kind kind : 3;
 
     // True if register R holds the base object shape along exits from the
     // last stub.
     bool shapeRegHasBaseShape : 1;
 
-    // True if can use the property cache.
-    bool usePropCache : 1;
-
     // State flags.
     bool hit : 1;                   // this PIC has been executed
     bool inlinePathPatched : 1;     // inline path has been patched
 
     RegisterID shapeReg : 5;        // also the out type reg
     RegisterID objReg   : 5;        // also the out data reg
 
     // Number of stubs generated.
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -94,25 +94,16 @@ stubs::BindName(VMFrame &f)
         obj = js_FindIdentifierBase(cx, &f.fp()->scopeChain(), id);
         if (!obj)
             THROW();
     }
     f.regs.sp++;
     f.regs.sp[-1].setObject(*obj);
 }
 
-void JS_FASTCALL
-stubs::BindNameNoCache(VMFrame &f, JSAtom *atom)
-{
-    JSObject *obj = js_FindIdentifierBase(f.cx, &f.fp()->scopeChain(), ATOM_TO_JSID(atom));
-    if (!obj)
-        THROW();
-    f.regs.sp[0].setObject(*obj);
-}
-
 JSObject * JS_FASTCALL
 stubs::BindGlobalName(VMFrame &f)
 {
     return f.fp()->scopeChain().getGlobal();
 }
 
 template<JSBool strict>
 void JS_FASTCALL
@@ -2073,30 +2064,16 @@ InlineGetProp(VMFrame &f)
 void JS_FASTCALL
 stubs::GetProp(VMFrame &f)
 {
     if (!InlineGetProp(f))
         THROW();
 }
 
 void JS_FASTCALL
-stubs::GetPropNoCache(VMFrame &f, JSAtom *atom)
-{
-    JSContext *cx = f.cx;
-
-    Value *vp = &f.regs.sp[-1];
-    JSObject *obj = ValueToObject(cx, vp);
-    if (!obj)
-        THROW();
-
-    if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp))
-        THROW();
-}
-
-void JS_FASTCALL
 stubs::CallProp(VMFrame &f, JSAtom *origAtom)
 {
     JSContext *cx = f.cx;
     JSFrameRegs &regs = f.regs;
 
     Value lval;
     lval = regs.sp[-1];
 
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -60,18 +60,16 @@ void JS_FASTCALL InitMethod(VMFrame &f, 
 
 void JS_FASTCALL HitStackQuota(VMFrame &f);
 void * JS_FASTCALL FixupArity(VMFrame &f, uint32 argc);
 void * JS_FASTCALL CompileFunction(VMFrame &f, uint32 argc);
 void JS_FASTCALL SlowNew(VMFrame &f, uint32 argc);
 void JS_FASTCALL SlowCall(VMFrame &f, uint32 argc);
 void * JS_FASTCALL UncachedNew(VMFrame &f, uint32 argc);
 void * JS_FASTCALL UncachedCall(VMFrame &f, uint32 argc);
-void JS_FASTCALL EnterScript(VMFrame &f);
-void JS_FASTCALL LeaveScript(VMFrame &f);
 
 /*
  * Result struct for UncachedXHelper.
  *
  * These functions can have one of two results:
  *
  *   (1) The function was executed in the interpreter. Then all fields
  *       are NULL.
@@ -109,25 +107,23 @@ void * JS_FASTCALL InvokeTracer(VMFrame 
 #else
 void * JS_FASTCALL InvokeTracer(VMFrame &f);
 #endif
 
 void * JS_FASTCALL LookupSwitch(VMFrame &f, jsbytecode *pc);
 void * JS_FASTCALL TableSwitch(VMFrame &f, jsbytecode *origPc);
 
 void JS_FASTCALL BindName(VMFrame &f);
-void JS_FASTCALL BindNameNoCache(VMFrame &f, JSAtom *atom);
 JSObject * JS_FASTCALL BindGlobalName(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetName(VMFrame &f, JSAtom *atom);
 template<JSBool strict> void JS_FASTCALL SetPropNoCache(VMFrame &f, JSAtom *atom);
 template<JSBool strict> void JS_FASTCALL SetGlobalName(VMFrame &f, JSAtom *atom);
 template<JSBool strict> void JS_FASTCALL SetGlobalNameDumb(VMFrame &f, JSAtom *atom);
 void JS_FASTCALL Name(VMFrame &f);
 void JS_FASTCALL GetProp(VMFrame &f);
-void JS_FASTCALL GetPropNoCache(VMFrame &f, JSAtom *atom);
 void JS_FASTCALL GetElem(VMFrame &f);
 void JS_FASTCALL CallElem(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetElem(VMFrame &f);
 void JS_FASTCALL Length(VMFrame &f);
 void JS_FASTCALL CallName(VMFrame &f);
 void JS_FASTCALL GetUpvar(VMFrame &f, uint32 index);
 void JS_FASTCALL GetGlobalName(VMFrame &f);
 
--- a/js/src/trace-test/tests/jaeger/bug563000/trap-force-return-1.js
+++ b/js/src/trace-test/tests/jaeger/bug563000/trap-force-return-1.js
@@ -1,7 +1,7 @@
 setDebug(true);
 function main() {
   return "failure";
 }
 /* JSOP_RETURN in main. */
-trap(main, 3, "'success'");
+trap(main, 4, "'success'");
 assertEq(main(), "success");
--- a/js/src/trace-test/tests/jaeger/bug563000/trap-parent-from-trap.js
+++ b/js/src/trace-test/tests/jaeger/bug563000/trap-parent-from-trap.js
@@ -5,17 +5,17 @@ function child() {
   x = "failure1";
   /* JSOP_STOP in parent. */
   trap(parent, 10, "success()");
 }
 
 function parent() {
   x = "failure2";
 }
-/* First op in parent. */
-trap(parent, 0, "child()");
+/* First op in parent: because of JSOP_BEGIN, it is op 1. */
+trap(parent, 1, "child()");
 
 function success() {
   x = "success";
 }
 
 parent();
 assertEq(x, "success");
--- a/js/src/trace-test/tests/jaeger/bug563000/trap-self-from-trap.js
+++ b/js/src/trace-test/tests/jaeger/bug563000/trap-self-from-trap.js
@@ -1,23 +1,23 @@
 setDebug(true);
 x = "notset";
 
 function doNothing() { }
 
 function myparent(nested) {
   if (nested) {
     /* JSOP_CALL to doNothing in myparent with nested = true. */
-    trap(myparent, 24, "success()");
+    trap(myparent, 25, "success()");
     doNothing();
   } else {
     doNothing();
   }
 }
 /* JSOP_CALL to doNothing in myparent with nested = false. */
-trap(myparent, 35, "myparent(true)");
+trap(myparent, 36, "myparent(true)");
 
 function success() {
   x = "success";
 }
 
 myparent(false);
 assertEq(x, "success");
deleted file mode 100644
--- a/js/src/trace-test/tests/jaeger/deepBailAfterRunTracer.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var o = { };
-for (var i = 0; i <= 50; i++)
-    o[i] = i;
-
-Object.defineProperty(o, "51", { get: assertEq });
-
-var threw = 0;
-function g(o, i) {
-    try {
-        assertEq(o[i], i);
-    } catch (e) {
-        threw++;
-    }
-}
-
-function f() {
-    for (var i = 0; i <= 51; i++)
-      g(o, i);
-}
-
-f();
-f();
-f();
-assertEq(threw, 3);
-