Backout 54cd89b0f1fa (bug 712714 backout). Talos will probably report fake regressions for this patch, do not back out for this reason.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 09 Jan 2012 06:29:50 -0800
changeset 84036 7ab4f1ebc7cc60fd22cf6def3819798417918bb6
parent 84035 b6c60a28454d68d2bab7899c164ca8205dc8e5ed
child 84037 8abe69741c4f362079a083f77c83d6a4a4a389ef
push id21819
push userbmo@edmorley.co.uk
push dateMon, 09 Jan 2012 20:36:23 +0000
treeherdermozilla-central@c713003d3226 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs712714
milestone12.0a1
backs out54cd89b0f1fa936a6c763f31f34d8b5b6ff4bb2c
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
Backout 54cd89b0f1fa (bug 712714 backout). Talos will probably report fake regressions for this patch, do not back out for this reason.
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/Parser.cpp
js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js
js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js
js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
js/src/jsanalyze.cpp
js/src/jsanalyze.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcode.tbl
js/src/jsprvtd.h
js/src/jsxdrapi.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/MonoIC.h
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
js/src/methodjit/StubCalls-inl.h
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2712,16 +2712,40 @@ CheckSideEffects(JSContext *cx, Bytecode
       case PN_NULLARY:
         if (pn->isKind(PNK_DEBUGGER))
             *answer = JS_TRUE;
         break;
     }
     return ok;
 }
 
+bool
+BytecodeEmitter::needsImplicitThis()
+{
+    if (!compileAndGo())
+        return true;
+    if (!inFunction()) {
+        JSObject *scope = scopeChain();
+        while (scope) {
+            if (scope->isWith())
+                return true;
+            scope = scope->enclosingScope();
+        }
+    }
+    for (const FunctionBox *funbox = this->funbox; funbox; funbox = funbox->parent) {
+        if (funbox->tcflags & TCF_IN_WITH)
+            return true;
+    }
+    for (StmtInfo *stmt = topStmt; stmt; stmt = stmt->down) {
+        if (stmt->type == STMT_WITH)
+            return true;
+    }
+    return false;
+}
+
 static JSBool
 EmitNameOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSBool callContext)
 {
     JSOp op;
 
     if (!BindNameToSlot(cx, bce, pn))
         return JS_FALSE;
     op = pn->getOp();
@@ -2747,28 +2771,36 @@ EmitNameOp(JSContext *cx, BytecodeEmitte
             JS_ASSERT(op == JSOP_ARGUMENTS || op == JSOP_CALLEE);
             break;
         }
     }
 
     if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) {
         if (Emit1(cx, bce, op) < 0)
             return JS_FALSE;
-        /* Need to provide |this| value for call */
-        if (callContext && Emit1(cx, bce, JSOP_UNDEFINED) < 0)
-            return JS_FALSE;
     } else {
         if (!pn->pn_cookie.isFree()) {
             EMIT_UINT16_IMM_OP(op, pn->pn_cookie.asInteger());
         } else {
             if (!EmitAtomOp(cx, pn, op, bce))
                 return JS_FALSE;
         }
     }
 
+    /* Need to provide |this| value for call */
+    if (callContext) {
+        if (op == JSOP_CALLNAME && bce->needsImplicitThis()) {
+            if (!EmitAtomOp(cx, pn, JSOP_IMPLICITTHIS, bce))
+                return false;
+        } else {
+            if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
+                return false;
+        }
+    }
+
     return JS_TRUE;
 }
 
 #if JS_HAS_XML_SUPPORT
 static bool
 EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     JS_ASSERT(!bce->inStrictMode());
@@ -2780,43 +2812,58 @@ EmitXMLName(JSContext *cx, ParseNode *pn
     uintN oldflags = bce->flags;
     bce->flags &= ~TCF_IN_FOR_INIT;
     if (!EmitTree(cx, bce, pn2))
         return false;
     bce->flags |= oldflags & TCF_IN_FOR_INIT;
     if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
         return false;
 
-    return Emit1(cx, bce, op) >= 0;
+    if (Emit1(cx, bce, op) < 0)
+        return false;
+
+    return true;
 }
 #endif
 
 static inline bool
 EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op)
 {
     if (Emit1(cx, bce, op) < 0)
         return false;
     CheckTypeSet(cx, bce, op);
+    if (op == JSOP_CALLELEM)
+        return Emit1(cx, bce, JSOP_SWAP) >= 0;
     return true;
 }
 
 static bool
 EmitSpecialPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     /*
      * Special case for obj.__proto__ to deoptimize away from fast paths in the
      * interpreter and trace recorder, which skip dense array instances by
      * going up to Array.prototype before looking up the property name.
      */
     jsatomid index;
     if (!bce->makeAtomIndex(pn->pn_atom, &index))
         return false;
     if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
         return false;
-    return EmitElemOpBase(cx, bce, op);
+
+    if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
+        return false;
+
+    if (!EmitElemOpBase(cx, bce, op))
+        return false;
+
+    if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_SWAP) < 0)
+        return false;
+
+    return true;
 }
 
 static bool
 EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
            JSBool callContext, JSOp *psuffix = NULL)
 {
     ParseNode *pn2, *pndot, *pnup, *pndown;
     ptrdiff_t top;
@@ -2886,20 +2933,29 @@ EmitPropOp(JSContext *cx, ParseNode *pn,
             pndot->pn_expr = pndown;
             pndown = pndot;
         } while ((pndot = pnup) != NULL);
     } else {
         if (!EmitTree(cx, bce, pn2))
             return false;
     }
 
+    if (op == JSOP_CALLPROP && Emit1(cx, bce, JSOP_DUP) < 0)
+        return false;
+
     if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
         return false;
 
-    return EmitAtomOp(cx, pn, op, bce, psuffix);
+    if (!EmitAtomOp(cx, pn, op, bce, psuffix))
+        return false;
+
+    if (op == JSOP_CALLPROP && Emit1(cx, bce, JSOP_SWAP) < 0)
+        return false;
+
+    return true;
 }
 
 static bool
 EmitPropIncDec(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     JSOp suffix = JSOP_NOP;
     if (!EmitPropOp(cx, pn, op, bce, false, &suffix))
         return false;
@@ -3053,16 +3109,19 @@ EmitElemOp(JSContext *cx, ParseNode *pn,
     if (op == JSOP_GETELEM && left->isKind(PNK_NAME) && right->isKind(PNK_NUMBER)) {
         if (!BindNameToSlot(cx, bce, left))
             return false;
     }
 
     if (!EmitTree(cx, bce, left))
         return false;
 
+    if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
+        return false;
+
     /* The right side of the descendant operator is implicitly quoted. */
     JS_ASSERT(op != JSOP_DESCENDANTS || !right->isKind(PNK_STRING) ||
               right->isOp(JSOP_QNAMEPART));
     if (!EmitTree(cx, bce, right))
         return false;
     if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0)
         return false;
     return EmitElemOpBase(cx, bce, op);
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -740,16 +740,18 @@ struct BytecodeEmitter : public TreeCont
         for (StmtInfo *stmt = topStmt; stmt; stmt = stmt->down) {
             if (STMT_IS_LOOP(stmt))
                 return false;
         }
         flags |= TCF_HAS_SINGLETONS;
         return true;
     }
 
+    bool needsImplicitThis();
+
     TokenStream *tokenStream() { return &parser->tokenStream; }
 
     jsbytecode *base() const { return current->base; }
     jsbytecode *limit() const { return current->limit; }
     jsbytecode *next() const { return current->next; }
     jsbytecode *code(ptrdiff_t offset) const { return base() + offset; }
     ptrdiff_t offset() const { return next() - base(); }
     jsbytecode *prologBase() const { return prolog.base; }
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -237,16 +237,24 @@ Parser::newFunctionBox(JSObject *obj, Pa
             funbox->inLoop = true;
             break;
         }
     }
     funbox->level = tc->staticLevel;
     funbox->tcflags = (TCF_IN_FUNCTION | (tc->flags & (TCF_COMPILE_N_GO | TCF_STRICT_MODE_CODE)));
     if (tc->innermostWith)
         funbox->tcflags |= TCF_IN_WITH;
+    if (!tc->inFunction()) {
+        JSObject *scope = tc->scopeChain();
+        while (scope) {
+            if (scope->isWith())
+                funbox->tcflags |= TCF_IN_WITH;
+            scope = scope->enclosingScope();
+        }
+    }
     return funbox;
 }
 
 void
 Parser::trace(JSTracer *trc)
 {
     ObjectBox *objbox = traceListHead;
     while (objbox) {
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js
@@ -1,10 +1,10 @@
 // |jit-test| mjitalways;debug
 setDebug(true);
 
 function nop(){}
 function caller(code, obj) {
   eval(code); // Make the compiler give up on binding analysis.
   return x;
 }
-trap(caller, 12, "var x = 'success'; nop()");
+trap(caller, 13, "var x = 'success'; nop()");
 assertEq(caller("var y = 'ignominy'", this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
@@ -2,10 +2,10 @@
 setDebug(true);
 
 function nop(){}
 function caller(obj) {
   assertJit();
   var x = "failure";
   return x;
 }
-trap(caller, 14, "x = 'success'; nop()");
+trap(caller, 15, "x = 'success'; nop()");
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js
@@ -1,16 +1,16 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 
 function myparent(nested) {
   if (nested) {
     /* noop call in myparent */
-    trap(myparent, 49, "success()");
+    trap(myparent, 48, "success()");
   } else {
     myparent(true);
     x = "failure";
     noop();
   }
 }
 function noop() { }
 function success() { x = "success"; }
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
@@ -2,23 +2,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, 26, "success()");
     doNothing();
   } else {
     doNothing();
   }
 }
 /* JSOP_CALL to doNothing in myparent with nested = false. */
-trap(myparent, 34, "myparent(true)");
+trap(myparent, 37, "myparent(true)");
 
 function success() {
   x = "success";
 }
 
 myparent(false);
 assertEq(x, "success");
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -1387,24 +1387,16 @@ ScriptAnalysis::analyzeSSA(JSContext *cx
                  * Propagate the current value of the local to the pushed value,
                  * and remember it with an extended use on the opcode.
                  */
                 stack[stackDepth - 1] = code->poppedValues[0] = values[slot];
             }
             break;
           }
 
-          case JSOP_CALLARG:
-          case JSOP_CALLLOCAL: {
-            uint32_t slot = GetBytecodeSlot(script, pc);
-            if (trackSlot(slot))
-                stack[stackDepth - 2] = code->poppedValues[0] = values[slot];
-            break;
-          }
-
           /* Short circuit ops which push back one of their operands. */
 
           case JSOP_MOREITER:
             stack[stackDepth - 2] = code->poppedValues[0];
             break;
 
           case JSOP_INITPROP:
           case JSOP_INITMETHOD:
@@ -1854,31 +1846,16 @@ CrossScriptSSA::foldValue(const CrossSSA
                     if (analysis->maybeCode(pc) && JSOp(*pc) == JSOP_RETURN)
                         return foldValue(CrossSSAValue(calleeFrame, analysis->poppedValue(pc, 0)));
                     offset += GetBytecodeLength(pc);
                 }
             }
             break;
           }
 
-          case JSOP_CALLPROP: {
-            /*
-             * The second value pushed by CALLPROP is the same as its popped
-             * value. We don't do this folding during the SSA analysis itself
-             * as we still need to distinguish the two values during type
-             * inference --- any popped null or undefined value will throw an
-             * exception, and not actually end up in the pushed set.
-             */
-            if (v.pushedIndex() == 1) {
-                ScriptAnalysis *analysis = frame.script->analysis();
-                return foldValue(CrossSSAValue(cv.frame, analysis->poppedValue(pc, 0)));
-            }
-            break;
-          }
-
           case JSOP_TOID: {
             /*
              * TOID acts as identity for integers, so to get better precision
              * we should propagate its popped values forward if it acted as
              * identity.
              */
             ScriptAnalysis *analysis = frame.script->analysis();
             SSAValue toidv = analysis->poppedValue(pc, 0);
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -1062,19 +1062,22 @@ class ScriptAnalysis
         JS_ASSERT(offset < script->length);
         return getCode(offset).loop;
     }
     LoopAnalysis *getLoop(const jsbytecode *pc) { return getLoop(pc - script->code); }
 
     /* For a JSOP_CALL* op, get the pc of the corresponding JSOP_CALL/NEW/etc. */
     jsbytecode *getCallPC(jsbytecode *pc)
     {
-        JS_ASSERT(js_CodeSpec[*pc].format & JOF_CALLOP);
-        SSAUseChain *uses = useChain(SSAValue::PushedValue(pc - script->code, 1));
-        JS_ASSERT(uses && !uses->next && uses->popped);
+        SSAUseChain *uses = useChain(SSAValue::PushedValue(pc - script->code, 0));
+        JS_ASSERT(uses && uses->popped);
+        JS_ASSERT_IF(uses->next,
+                     !uses->next->next &&
+                     uses->next->popped &&
+                     script->code[uses->next->offset] == JSOP_SWAP);
         return script->code + uses->offset;
     }
 
     /* Accessors for local variable information. */
 
     /*
      * Escaping slots include all slots that can be accessed in ways other than
      * through the corresponding LOCAL/ARG opcode. This includes all closed
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3567,20 +3567,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         if (id == ATOM_TO_JSID(cx->runtime->atomState.NaNAtom))
             seen->addType(cx, Type::DoubleType());
         if (id == ATOM_TO_JSID(cx->runtime->atomState.InfinityAtom))
             seen->addType(cx, Type::DoubleType());
 
         /* Handle as a property access. */
         PropertyAccess(cx, script, pc, script->global()->getType(cx), false, seen, id);
 
-        if (op == JSOP_CALLGNAME) {
-            pushed[1].addType(cx, Type::UnknownType());
+        if (op == JSOP_CALLGNAME)
             pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
-        }
 
         if (CheckNextTest(pc))
             pushed[0].addType(cx, Type::UndefinedType());
         break;
       }
 
       case JSOP_NAME:
       case JSOP_CALLNAME: {
@@ -3598,20 +3596,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         NameAccess access = resolveNameAccess(cx, id);
         if (access.script && !access.script->typesPurged) {
             TypeSet *types = TypeScript::SlotTypes(access.script, access.slot);
             types->addSubsetBarrier(cx, script, pc, seen);
         } else {
             addTypeBarrier(cx, pc, seen, Type::UnknownType());
         }
 
-        if (op == JSOP_CALLNAME) {
-            pushed[1].addType(cx, Type::UnknownType());
+        if (op == JSOP_CALLNAME)
             pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
-        }
         break;
       }
 
       case JSOP_BINDGNAME:
       case JSOP_BINDNAME:
         break;
 
       case JSOP_SETGNAME: {
@@ -3641,20 +3637,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         break;
 
       case JSOP_GETXPROP:
       case JSOP_GETFCSLOT:
       case JSOP_CALLFCSLOT: {
         TypeSet *seen = bytecodeTypes(pc);
         addTypeBarrier(cx, pc, seen, Type::UnknownType());
         seen->addSubset(cx, &pushed[0]);
-        if (op == JSOP_CALLFCSLOT) {
-            pushed[1].addType(cx, Type::UndefinedType());
+        if (op == JSOP_CALLFCSLOT)
             pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType());
-        }
         break;
       }
 
       case JSOP_GETARG:
       case JSOP_CALLARG:
       case JSOP_GETLOCAL:
       case JSOP_CALLLOCAL: {
         uint32_t slot = GetBytecodeSlot(script, pc);
@@ -3667,20 +3661,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
             poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
         } else if (slot < TotalSlots(script)) {
             TypeSet *types = TypeScript::SlotTypes(script, slot);
             types->addSubset(cx, &pushed[0]);
         } else {
             /* Local 'let' variable. Punt on types for these, for now. */
             pushed[0].addType(cx, Type::UnknownType());
         }
-        if (op == JSOP_CALLARG || op == JSOP_CALLLOCAL) {
-            pushed[1].addType(cx, Type::UndefinedType());
+        if (op == JSOP_CALLARG || op == JSOP_CALLLOCAL)
             pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType());
-        }
         break;
       }
 
       case JSOP_SETARG:
       case JSOP_SETLOCAL:
       case JSOP_SETLOCALPOP: {
         uint32_t slot = GetBytecodeSlot(script, pc);
         if (!trackSlot(slot) && slot < TotalSlots(script)) {
@@ -3747,18 +3739,16 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         jsid id = GetAtomId(cx, script, pc, 0);
         TypeSet *seen = script->analysis()->bytecodeTypes(pc);
 
         poppedTypes(pc, 0)->addGetProperty(cx, script, pc, seen, id);
         if (op == JSOP_CALLPROP)
             poppedTypes(pc, 0)->addCallProperty(cx, script, pc, id);
 
         seen->addSubset(cx, &pushed[0]);
-        if (op == JSOP_CALLPROP)
-            poppedTypes(pc, 0)->addFilterPrimitives(cx, &pushed[1], TypeSet::FILTER_NULL_VOID);
         if (CheckNextTest(pc))
             pushed[0].addType(cx, Type::UndefinedType());
         break;
       }
 
       /*
        * We only consider ELEM accesses on integers below. Any element access
        * which is accessing a non-integer property must be monitored.
@@ -3766,20 +3756,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
 
       case JSOP_GETELEM:
       case JSOP_CALLELEM: {
         TypeSet *seen = script->analysis()->bytecodeTypes(pc);
 
         poppedTypes(pc, 1)->addGetProperty(cx, script, pc, seen, JSID_VOID);
 
         seen->addSubset(cx, &pushed[0]);
-        if (op == JSOP_CALLELEM) {
-            poppedTypes(pc, 1)->addFilterPrimitives(cx, &pushed[1], TypeSet::FILTER_NULL_VOID);
-            pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType(), &pushed[1]);
-        }
+        if (op == JSOP_CALLELEM)
+            pushed[0].addPropagateThis(cx, script, pc, Type::UndefinedType(), poppedTypes(pc, 1));
         if (CheckNextTest(pc))
             pushed[0].addType(cx, Type::UndefinedType());
         break;
       }
 
       case JSOP_SETELEM:
         poppedTypes(pc, 1)->addSetElement(cx, script, pc, poppedTypes(pc, 2), poppedTypes(pc, 0));
         poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
@@ -4041,16 +4029,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_THROW:
         /* There will be a monitor on the bytecode catching the exception. */
         break;
 
       case JSOP_FINALLY:
         /* Pushes information about whether an exception was thrown. */
         break;
 
+      case JSOP_IMPLICITTHIS:
       case JSOP_EXCEPTION:
         pushed[0].addType(cx, Type::UnknownType());
         break;
 
       case JSOP_DELPROP:
       case JSOP_DELELEM:
       case JSOP_DELNAME:
         pushed[0].addType(cx, Type::BooleanType());
@@ -4083,20 +4072,18 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
             }
         }
         break;
 
       case JSOP_YIELD:
         pushed[0].addType(cx, Type::UnknownType());
         break;
 
+      case JSOP_XMLNAME:
       case JSOP_CALLXMLNAME:
-        pushed[1].addType(cx, Type::UnknownType());
-        /* FALLTHROUGH */
-      case JSOP_XMLNAME:
         pushed[0].addType(cx, Type::UnknownType());
         break;
 
       case JSOP_SETXMLNAME:
         cx->compartment->types.monitorBytecode(cx, script, offset);
         poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
         break;
 
@@ -4662,47 +4649,47 @@ AnalyzeNewScriptProperties(JSContext *cx
              * particular script, removing definite properties from the result
              */
 
             /* Callee/this must have been pushed by a CALLPROP. */
             SSAValue calleev = analysis->poppedValue(pc, GET_ARGC(pc) + 1);
             if (calleev.kind() != SSAValue::PUSHED)
                 return false;
             jsbytecode *calleepc = script->code + calleev.pushedOffset();
-            if (JSOp(*calleepc) != JSOP_CALLPROP || calleev.pushedIndex() != 0)
+            if (JSOp(*calleepc) != JSOP_CALLPROP)
                 return false;
 
             /*
              * This code may not have run yet, break any type barriers involved
              * in performing the call (for the greater good!).
              */
             analysis->breakTypeBarriersSSA(cx, analysis->poppedValue(calleepc, 0));
             analysis->breakTypeBarriers(cx, calleepc - script->code, true);
 
-            TypeSet *funcallTypes = analysis->pushedTypes(calleepc, 0);
-            TypeSet *scriptTypes = analysis->pushedTypes(calleepc, 1);
+            TypeSet *funcallTypes = analysis->poppedTypes(pc, GET_ARGC(pc) + 1);
+            TypeSet *scriptTypes = analysis->poppedTypes(pc, GET_ARGC(pc));
 
             /* Need to definitely be calling Function.call on a specific script. */
             JSObject *funcallObj = funcallTypes->getSingleton(cx, false);
             JSObject *scriptObj = scriptTypes->getSingleton(cx, false);
             if (!funcallObj || !scriptObj || !scriptObj->isFunction() ||
                 !scriptObj->toFunction()->isInterpreted()) {
                 return false;
             }
 
             JSFunction *function = scriptObj->toFunction();
             JS_ASSERT(!function->script()->isInnerFunction);
 
             /*
              * Generate constraints to clear definite properties from the type
              * should the Function.call or callee itself change in the future.
              */
-            analysis->pushedTypes(calleev.pushedOffset(), 0)->add(cx,
+            funcallTypes->add(cx,
                 cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
-            analysis->pushedTypes(calleev.pushedOffset(), 1)->add(cx,
+            scriptTypes->add(cx,
                 cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
 
             TypeNewScript::Initializer pushframe(TypeNewScript::Initializer::FRAME_PUSH, uses->offset);
             if (!initializerList->append(pushframe)) {
                 cx->compartment->types.setPendingNukeTypes(cx);
                 *pbaseobj = NULL;
                 return false;
             }
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -381,46 +381,43 @@ Class js_NoSuchMethodClass = {
  *
  *   this.__noSuchMethod__(id, args)
  *
  * where id is the name of the method that this invocation attempted to
  * call by name, and args is an Array containing this invocation's actual
  * parameters.
  */
 bool
-js::OnUnknownMethod(JSContext *cx, Value *vp)
+js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
 {
-    JS_ASSERT(!vp[1].isPrimitive());
-
-    JSObject *obj = &vp[1].toObject();
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
     AutoValueRooter tvr(cx);
     if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr()))
         return false;
     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
 
     if (tvr.value().isPrimitive()) {
-        vp[0] = tvr.value();
+        *vp = tvr.value();
     } else {
 #if JS_HAS_XML_SUPPORT
         /* Extract the function name from function::name qname. */
-        if (vp[0].isObject()) {
-            obj = &vp[0].toObject();
+        if (idval.isObject()) {
+            obj = &idval.toObject();
             if (js_GetLocalNameFromFunctionQName(obj, &id, cx))
-                vp[0] = IdToValue(id);
+                idval = IdToValue(id);
         }
 #endif
 
         obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
         if (!obj)
             return false;
 
         obj->setSlot(JSSLOT_FOUND_FUNCTION, tvr.value());
-        obj->setSlot(JSSLOT_SAVED_ID, vp[0]);
-        vp[0].setObject(*obj);
+        obj->setSlot(JSSLOT_SAVED_ID, idval);
+        vp->setObject(*obj);
     }
     return true;
 }
 
 static JSBool
 NoSuchMethod(JSContext *cx, uintN argc, Value *vp)
 {
     InvokeArgsGuard args;
@@ -1257,35 +1254,25 @@ inline InterpreterFrames::InterpreterFra
     JS_THREAD_DATA(cx)->interpreterFrames = this;
 }
  
 inline InterpreterFrames::~InterpreterFrames()
 {
     JS_THREAD_DATA(context)->interpreterFrames = older;
 }
 
-/*
- * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
- * single-thread DEBUG js shell testing to verify property cache hits.
- */
-#if defined DEBUG && !defined JS_THREADSAFE
-
-# define ASSERT_VALID_PROPERTY_CACHE_HIT(obj,pobj,entry)                      \
-    JS_BEGIN_MACRO                                                            \
-        if (!AssertValidPropertyCacheHit(cx, script, regs, obj, pobj,         \
-                                         entry)) {                            \
-            goto error;                                                       \
-        }                                                                     \
-    JS_END_MACRO
-
-static bool
-AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, FrameRegs& regs,
-                            JSObject *start, JSObject *found,
-                            PropertyCacheEntry *entry)
+#if defined(DEBUG) && !defined(JS_THREADSAFE)
+void
+js::AssertValidPropertyCacheHit(JSContext *cx,
+                                JSObject *start, JSObject *found,
+                                PropertyCacheEntry *entry)
 {
+    JSScript *script = cx->fp()->script();
+    FrameRegs& regs = cx->regs();
+
     uint32_t sample = cx->runtime->gcNumber;
     PropertyCacheEntry savedEntry = *entry;
 
     PropertyName *name;
     GET_NAME_FROM_BYTECODE(script, regs.pc, 0, name);
 
     JSObject *obj, *pobj;
     JSProperty *prop;
@@ -1293,32 +1280,27 @@ AssertValidPropertyCacheHit(JSContext *c
 
     if (JOF_OPMODE(*regs.pc) == JOF_NAME) {
         bool global = js_CodeSpec[*regs.pc].format & JOF_GNAME;
         ok = FindProperty(cx, name, global, &obj, &pobj, &prop);
     } else {
         obj = start;
         ok = LookupProperty(cx, obj, name, &pobj, &prop);
     }
-    if (!ok)
-        return false;
+    JS_ASSERT(ok);
+
     if (cx->runtime->gcNumber != sample)
         JS_PROPERTY_CACHE(cx).restore(&savedEntry);
     JS_ASSERT(prop);
     JS_ASSERT(pobj == found);
 
     const Shape *shape = (Shape *) prop;
     JS_ASSERT(entry->prop == shape);
-
-    return true;
 }
-
-#else
-# define ASSERT_VALID_PROPERTY_CACHE_HIT(obj,pobj,entry) ((void) 0)
-#endif
+#endif /* DEBUG && !JS_THREADSAFE */
 
 /*
  * Ensure that the intrepreter switch can close call-bytecode cases in the
  * same way as non-call bytecodes.
  */
 JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETFCSLOT_LENGTH == JSOP_CALLFCSLOT_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
@@ -2232,45 +2214,16 @@ BEGIN_CASE(JSOP_PICK)
     jsint i = regs.pc[1];
     JS_ASSERT(regs.sp - (i+1) >= regs.fp()->base());
     Value lval = regs.sp[-(i+1)];
     memmove(regs.sp - (i+1), regs.sp - i, sizeof(Value)*i);
     regs.sp[-1] = lval;
 }
 END_CASE(JSOP_PICK)
 
-#define NATIVE_GET(cx,obj,pobj,shape,getHow,vp)                               \
-    JS_BEGIN_MACRO                                                            \
-        if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {         \
-            /* Fast path for Object instance properties. */                   \
-            JS_ASSERT((shape)->slot() != SHAPE_INVALID_SLOT ||                \
-                      !shape->hasDefaultSetter());                            \
-            if (((shape)->slot() != SHAPE_INVALID_SLOT))                      \
-                *(vp) = (pobj)->nativeGetSlot((shape)->slot());               \
-            else                                                              \
-                (vp)->setUndefined();                                         \
-        } else {                                                              \
-            if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp))              \
-                goto error;                                                   \
-        }                                                                     \
-    JS_END_MACRO
-
-#define NATIVE_SET(cx,obj,shape,entry,strict,vp)                              \
-    JS_BEGIN_MACRO                                                            \
-        if (shape->hasDefaultSetter() &&                                      \
-            (shape)->hasSlot() &&                                             \
-            !(shape)->isMethod()) {                                           \
-            /* Fast path for, e.g., plain Object instance properties. */      \
-            (obj)->nativeSetSlotWithType(cx, shape, *vp);                     \
-        } else {                                                              \
-            if (!js_NativeSet(cx, obj, shape, false, strict, vp))             \
-                goto error;                                                   \
-        }                                                                     \
-    JS_END_MACRO
-
 BEGIN_CASE(JSOP_SETCONST)
 {
     PropertyName *name;
     LOAD_NAME(0, name);
     JSObject &obj = regs.fp()->varObj();
     const Value &ref = regs.sp[-1];
     if (!obj.defineProperty(cx, name, ref,
                             JS_PropertyStub, JS_StrictPropertyStub,
@@ -2321,24 +2274,18 @@ BEGIN_CASE(JSOP_BINDNAME)
          * object reference, which also calls the hooks only after evaluating
          * the rhs. We desire such resolve hook equivalence between the two
          * forms.
          */
         obj = &regs.fp()->scopeChain();
         if (obj->isGlobal())
             break;
 
-        PropertyCacheEntry *entry;
-        JSObject *obj2;
         PropertyName *name;
-        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, name);
-        if (!name) {
-            ASSERT_VALID_PROPERTY_CACHE_HIT(obj, obj2, entry);
-            break;
-        }
+        LOAD_NAME(0, name);
 
         obj = FindIdentifierBase(cx, &regs.fp()->scopeChain(), name);
         if (!obj)
             goto error;
     } while (0);
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_BINDNAME)
@@ -2898,261 +2845,39 @@ BEGIN_CASE(JSOP_THIS)
     if (!ComputeThis(cx, regs.fp()))
         goto error;
     PUSH_COPY(regs.fp()->thisValue());
 END_CASE(JSOP_THIS)
 
 BEGIN_CASE(JSOP_GETPROP)
 BEGIN_CASE(JSOP_GETXPROP)
 BEGIN_CASE(JSOP_LENGTH)
+BEGIN_CASE(JSOP_CALLPROP)
 {
     Value rval;
-    do {
-        Value *vp = &regs.sp[-1];
-
-        if (op == JSOP_LENGTH) {
-            /* Optimize length accesses on strings, arrays, and arguments. */
-            if (vp->isString()) {
-                rval = Int32Value(vp->toString()->length());
-                break;
-            }
-            if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
-                rval = Int32Value(regs.fp()->numActualArgs());
-                break;
-            }
-            if (vp->isObject()) {
-                JSObject *obj = &vp->toObject();
-                if (obj->isArray()) {
-                    jsuint length = obj->getArrayLength();
-                    rval = NumberValue(length);
-                    break;
-                }
-
-                if (obj->isArguments()) {
-                    ArgumentsObject &argsobj = obj->asArguments();
-                    if (!argsobj.hasOverriddenLength()) {
-                        uint32_t length = argsobj.initialLength();
-                        JS_ASSERT(length < INT32_MAX);
-                        rval = Int32Value(int32_t(length));
-                        break;
-                    }
-                }
-
-                if (js_IsTypedArray(obj)) {
-                    JSObject *tarray = TypedArray::getTypedArray(obj);
-                    rval = Int32Value(TypedArray::getLength(tarray));
-                    break;
-                }
-            }
-        }
-
-        JSObject *obj;
-        VALUE_TO_OBJECT(cx, vp, obj);
-        JSObject *aobj = js_GetProtoIfDenseArray(obj);
-
-        PropertyCacheEntry *entry;
-        JSObject *obj2;
-        PropertyName *name;
-        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, name);
-        if (!name) {
-            ASSERT_VALID_PROPERTY_CACHE_HIT(aobj, obj2, entry);
-            NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval);
-            break;
-        }
-
-        if (JS_LIKELY(!aobj->getOps()->getProperty)
-            ? !GetPropertyHelper(cx, obj, name,
-                                 (regs.pc[JSOP_GETPROP_LENGTH] == JSOP_IFEQ)
-                                 ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                                 : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
-                                 &rval)
-            : !obj->getProperty(cx, name, &rval))
-        {
-            goto error;
-        }
-    } while (0);
+    if (!GetPropertyOperation(cx, regs.pc, regs.sp[-1], &rval))
+        goto error;
 
     TypeScript::Monitor(cx, script, regs.pc, rval);
 
     regs.sp[-1] = rval;
     assertSameCompartment(cx, regs.sp[-1]);
 }
 END_CASE(JSOP_GETPROP)
 
-BEGIN_CASE(JSOP_CALLPROP)
-{
-    Value lval = regs.sp[-1];
-
-    Value objv;
-    if (lval.isObject()) {
-        objv = lval;
-    } else {
-        GlobalObject &global = regs.fp()->scopeChain().global();
-        JSObject *pobj;
-        if (lval.isString()) {
-            pobj = global.getOrCreateStringPrototype(cx);
-        } else if (lval.isNumber()) {
-            pobj = global.getOrCreateNumberPrototype(cx);
-        } else if (lval.isBoolean()) {
-            pobj = global.getOrCreateBooleanPrototype(cx);
-        } else {
-            JS_ASSERT(lval.isNull() || lval.isUndefined());
-            js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
-            goto error;
-        }
-        if (!pobj)
-            goto error;
-        objv.setObject(*pobj);
-    }
-
-    JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
-    Value rval;
-
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name;
-    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, name);
-    if (!name) {
-        ASSERT_VALID_PROPERTY_CACHE_HIT(aobj, obj2, entry);
-        NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval);
-        regs.sp[-1] = rval;
-        assertSameCompartment(cx, regs.sp[-1]);
-        PUSH_COPY(lval);
-    } else {
-        /* Cache miss: use the name loaded for us under PropertyCache::test. */
-        PUSH_NULL();
-        if (lval.isObject()) {
-            if (!GetMethod(cx, &objv.toObject(), name,
-                           JS_LIKELY(!aobj->getOps()->getProperty)
-                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                           : JSGET_NO_METHOD_BARRIER,
-                           &rval))
-            {
-                goto error;
-            }
-            regs.sp[-1] = objv;
-            regs.sp[-2] = rval;
-        } else {
-            JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!GetPropertyHelper(cx, &objv.toObject(), name,
-                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER, &rval))
-            {
-                goto error;
-            }
-            regs.sp[-1] = lval;
-            regs.sp[-2] = rval;
-        }
-        assertSameCompartment(cx, regs.sp[-1], regs.sp[-2]);
-    }
-#if JS_HAS_NO_SUCH_METHOD
-    if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        LOAD_NAME(0, name);
-        regs.sp[-2].setString(name);
-        if (!OnUnknownMethod(cx, regs.sp - 2))
-            goto error;
-    }
-#endif
-    TypeScript::Monitor(cx, script, regs.pc, rval);
-}
-END_CASE(JSOP_CALLPROP)
-
 BEGIN_CASE(JSOP_SETGNAME)
 BEGIN_CASE(JSOP_SETNAME)
 BEGIN_CASE(JSOP_SETPROP)
 BEGIN_CASE(JSOP_SETMETHOD)
 {
-    Value rval = regs.sp[-1];
-    JS_ASSERT_IF(op == JSOP_SETMETHOD, IsFunctionObject(rval));
-    Value &lref = regs.sp[-2];
-    JS_ASSERT_IF(op == JSOP_SETNAME, lref.isObject());
-    JSObject *obj;
-    VALUE_TO_OBJECT(cx, &lref, obj);
-
-    JS_ASSERT_IF(op == JSOP_SETGNAME, obj == &regs.fp()->scopeChain().global());
-
-    do {
-        PropertyCache *cache = &JS_PROPERTY_CACHE(cx);
-
-        /*
-         * Probe the property cache, specializing for two important
-         * set-property cases. First:
-         *
-         *   function f(a, b, c) {
-         *     var o = {p:a, q:b, r:c};
-         *     return o;
-         *   }
-         *
-         * or similar real-world cases, which evolve a newborn native
-         * object predicatably through some bounded number of property
-         * additions. And second:
-         *
-         *   o.p = x;
-         *
-         * in a frequently executed method or loop body, where p will
-         * (possibly after the first iteration) always exist in native
-         * object o.
-         */
-        PropertyCacheEntry *entry;
-        JSObject *obj2;
-        PropertyName *name;
-        if (cache->testForSet(cx, regs.pc, obj, &entry, &obj2, &name)) {
-            /*
-             * Property cache hit, only partially confirmed by testForSet. We
-             * know that the entry applies to regs.pc and that obj's shape
-             * matches.
-             *
-             * The entry predicts a set either an existing "own" property, or
-             * on a prototype property that has a setter.
-             */
-            const Shape *shape = entry->prop;
-
-            if (entry->isOwnPropertyHit() ||
-                ((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape))
-            {
-                JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
-                JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
-
-#ifdef DEBUG
-                if (entry->isOwnPropertyHit()) {
-                    JS_ASSERT(obj->nativeContains(cx, *shape));
-                } else {
-                    JS_ASSERT(obj2->nativeContains(cx, *shape));
-                    JS_ASSERT(entry->isPrototypePropertyHit());
-                    JS_ASSERT(entry->kshape != entry->pshape);
-                    JS_ASSERT(!shape->hasSlot());
-                }
-#endif
-
-                PCMETER(cache->pchits++);
-                PCMETER(cache->setpchits++);
-                NATIVE_SET(cx, obj, shape, entry, script->strictModeCode, &rval);
-                break;
-            }
-            PCMETER(cache->setpcmisses++);
-
-            LOAD_NAME(0, name);
-        } else {
-            JS_ASSERT(name);
-        }
-
-        if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
-            uintN defineHow;
-            if (op == JSOP_SETMETHOD)
-                defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
-            else if (op == JSOP_SETNAME)
-                defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
-            else
-                defineHow = DNP_CACHE_RESULT;
-            if (!SetPropertyHelper(cx, obj, name, defineHow, &rval, script->strictModeCode))
-                goto error;
-        } else {
-            if (!obj->setProperty(cx, name, &rval, script->strictModeCode))
-                goto error;
-        }
-    } while (0);
+    const Value &rval = regs.sp[-1];
+    const Value &lval = regs.sp[-2];
+
+    if (!SetPropertyOperation(cx, regs.pc, lval, rval))
+        goto error;
 
     regs.sp[-2] = regs.sp[-1];
     regs.sp--;
 }
 END_CASE(JSOP_SETPROP)
 
 BEGIN_CASE(JSOP_GETELEM)
 {
@@ -3247,28 +2972,24 @@ BEGIN_CASE(JSOP_CALLELEM)
     FETCH_ELEMENT_ID(thisObj, -1, id);
 
     /* Get the method. */
     if (!js_GetMethod(cx, thisObj, id, JSGET_NO_METHOD_BARRIER, &regs.sp[-2]))
         goto error;
 
 #if JS_HAS_NO_SUCH_METHOD
     if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) {
-        /* For OnUnknownMethod, sp[-2] is the index, and sp[-1] is the object missing it. */
-        regs.sp[-2] = regs.sp[-1];
-        regs.sp[-1].setObject(*thisObj);
-        if (!OnUnknownMethod(cx, regs.sp - 2))
+        if (!OnUnknownMethod(cx, &thisv.toObject(), regs.sp[-1], regs.sp - 2))
             goto error;
-    } else
+    }
 #endif
-    {
-        regs.sp[-1] = thisv;
-    }
-
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
+
+    regs.sp--;
+
+    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_CALLELEM)
 
 BEGIN_CASE(JSOP_SETELEM)
 {
     JSObject *obj;
     FETCH_OBJECT(cx, -3, obj);
     jsid id;
@@ -3424,92 +3145,44 @@ BEGIN_CASE(JSOP_FUNAPPLY)
 
 BEGIN_CASE(JSOP_SETCALL)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_LEFTSIDE_OF_ASS);
     goto error;
 }
 END_CASE(JSOP_SETCALL)
 
-#define PUSH_IMPLICIT_THIS(cx, obj, funval)                                   \
-    JS_BEGIN_MACRO                                                            \
-        Value v;                                                              \
-        if (!ComputeImplicitThis(cx, obj, funval, &v))                        \
-            goto error;                                                       \
-        PUSH_COPY(v);                                                         \
-    JS_END_MACRO                                                              \
+BEGIN_CASE(JSOP_IMPLICITTHIS)
+{
+    PropertyName *name;
+    LOAD_NAME(0, name);
+
+    JSObject *obj, *obj2;
+    JSProperty *prop;
+    if (!FindPropertyHelper(cx, name, false, false, &obj, &obj2, &prop))
+        goto error;
+
+    Value v;
+    if (!ComputeImplicitThis(cx, obj, &v))
+        goto error;
+    PUSH_COPY(v);
+}
+END_CASE(JSOP_IMPLICITTHIS)
 
 BEGIN_CASE(JSOP_GETGNAME)
 BEGIN_CASE(JSOP_CALLGNAME)
 BEGIN_CASE(JSOP_NAME)
 BEGIN_CASE(JSOP_CALLNAME)
 {
-    JSObject *obj = &regs.fp()->scopeChain();
-
-    bool global = js_CodeSpec[op].format & JOF_GNAME;
-    if (global)
-        obj = &obj->global();
-
     Value rval;
-
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name;
-    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, name);
-    if (!name) {
-        ASSERT_VALID_PROPERTY_CACHE_HIT(obj, obj2, entry);
-        NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval);
-        PUSH_COPY(rval);
-
-        TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
-
-        JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
-        if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
-            PUSH_IMPLICIT_THIS(cx, obj, regs.sp[-1]);
-        len = JSOP_NAME_LENGTH;
-        DO_NEXT_OP(len);
-    }
-
-    JSProperty *prop;
-    if (!FindPropertyHelper(cx, name, true, global, &obj, &obj2, &prop))
+    if (!NameOperation(cx, regs.pc, &rval))
         goto error;
-    if (!prop) {
-        /* Kludge to allow (typeof foo == "undefined") tests. */
-        JSOp op2 = JSOp(regs.pc[JSOP_NAME_LENGTH]);
-        if (op2 == JSOP_TYPEOF) {
-            PUSH_UNDEFINED();
-            TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
-            len = JSOP_NAME_LENGTH;
-            DO_NEXT_OP(len);
-        }
-
-        JSAutoByteString bytes;
-        if (js_AtomToPrintableString(cx, name, &bytes))
-            js_ReportIsNotDefined(cx, bytes.ptr());
-        goto error;
-    }
-
-    /* Take the slow path if prop was not found in a native object. */
-    if (!obj->isNative() || !obj2->isNative()) {
-        if (!obj->getProperty(cx, name, &rval))
-            goto error;
-    } else {
-        Shape *shape = (Shape *)prop;
-        JSObject *normalized = obj;
-        if (normalized->isWith() && !shape->hasDefaultGetter())
-            normalized = &normalized->asWith().object();
-        NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval);
-    }
 
     PUSH_COPY(rval);
     TypeScript::Monitor(cx, script, regs.pc, rval);
-
-    /* obj must be on the scope chain, thus not a function. */
-    if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
-        PUSH_IMPLICIT_THIS(cx, obj, rval);
 }
 END_CASE(JSOP_NAME)
 
 BEGIN_CASE(JSOP_UINT16)
     PUSH_INT32((int32_t) GET_UINT16(regs.pc));
 END_CASE(JSOP_UINT16)
 
 BEGIN_CASE(JSOP_UINT24)
@@ -3776,30 +3449,29 @@ BEGIN_CASE(JSOP_ARGUMENTS)
 END_CASE(JSOP_ARGUMENTS)
 
 BEGIN_CASE(JSOP_GETARG)
 BEGIN_CASE(JSOP_CALLARG)
 {
     uint32_t slot = GET_ARGNO(regs.pc);
     JS_ASSERT(slot < regs.fp()->numFormalArgs());
     PUSH_COPY(argv[slot]);
-    if (op == JSOP_CALLARG)
-        PUSH_UNDEFINED();
 }
 END_CASE(JSOP_GETARG)
 
 BEGIN_CASE(JSOP_SETARG)
 {
     uint32_t slot = GET_ARGNO(regs.pc);
     JS_ASSERT(slot < regs.fp()->numFormalArgs());
     argv[slot] = regs.sp[-1];
 }
 END_CASE(JSOP_SETARG)
 
 BEGIN_CASE(JSOP_GETLOCAL)
+BEGIN_CASE(JSOP_CALLLOCAL)
 {
     /*
      * Skip the same-compartment assertion if the local will be immediately
      * popped. We do not guarantee sync for dead locals when coming in from the
      * method JIT, and a GETLOCAL followed by POP is not considered to be
      * a use of the variable.
      */
      uint32_t slot = GET_SLOTNO(regs.pc);
@@ -3808,25 +3480,16 @@ BEGIN_CASE(JSOP_GETLOCAL)
 
 #ifdef DEBUG
     if (regs.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
         assertSameCompartment(cx, regs.sp[-1]);
 #endif
 }
 END_CASE(JSOP_GETLOCAL)
 
-BEGIN_CASE(JSOP_CALLLOCAL)
-{
-    uint32_t slot = GET_SLOTNO(regs.pc);
-    JS_ASSERT(slot < script->nslots);
-    PUSH_COPY(regs.fp()->slots()[slot]);
-    PUSH_UNDEFINED();
-}
-END_CASE(JSOP_CALLLOCAL)
-
 BEGIN_CASE(JSOP_SETLOCAL)
 {
     uint32_t slot = GET_SLOTNO(regs.pc);
     JS_ASSERT(slot < script->nslots);
     regs.fp()->slots()[slot] = regs.sp[-1];
 }
 END_CASE(JSOP_SETLOCAL)
 
@@ -3834,18 +3497,16 @@ BEGIN_CASE(JSOP_GETFCSLOT)
 BEGIN_CASE(JSOP_CALLFCSLOT)
 {
     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
     uintN index = GET_UINT16(regs.pc);
     JSObject *obj = &argv[-2].toObject();
 
     PUSH_COPY(obj->toFunction()->getFlatClosureUpvar(index));
     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
-    if (op == JSOP_CALLFCSLOT)
-        PUSH_UNDEFINED();
 }
 END_CASE(JSOP_GETFCSLOT)
 
 BEGIN_CASE(JSOP_DEFCONST)
 BEGIN_CASE(JSOP_DEFVAR)
 {
     uint32_t index = GET_INDEX(regs.pc);
     PropertyName *name = atoms[index]->asPropertyName();
@@ -4391,47 +4052,28 @@ BEGIN_CASE(JSOP_INITMETHOD)
     /* Load the property's initial value into rval. */
     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
     Value rval = regs.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
     JSObject *obj = &regs.sp[-2].toObject();
     JS_ASSERT(obj->isObject());
 
-    /*
-     * Probe the property cache to see if this is a set on an existing property
-     * added by a NEWOBJECT or a previous INITPROP. If the cached shape has a
-     * non-default setter, it must be __proto__, so don't handle this.
-     */
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name;
-    if (JS_PROPERTY_CACHE(cx).testForSet(cx, regs.pc, obj, &entry, &obj2, &name) &&
-        entry->prop->hasDefaultSetter() &&
-        entry->isOwnPropertyHit())
-    {
-        JS_ASSERT(obj == obj2);
-        /* Fast path. Property cache hit. */
-        obj->nativeSetSlotWithType(cx, entry->prop, rval);
-    } else {
-        PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
-        LOAD_NAME(0, name);
-
-        uintN defineHow = (op == JSOP_INITMETHOD)
-                          ? DNP_CACHE_RESULT | DNP_SET_METHOD
-                          : DNP_CACHE_RESULT;
-        if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
-            ? !SetPropertyHelper(cx, obj, name, defineHow, &rval, script->strictModeCode)
-            : !DefineNativeProperty(cx, obj, name, rval, NULL, NULL,
-                                    JSPROP_ENUMERATE, 0, 0, defineHow)) {
-            goto error;
-        }
+    JSAtom *atom;
+    LOAD_ATOM(0, atom);
+    jsid id = ATOM_TO_JSID(atom);
+
+    uintN defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0;
+    if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
+        ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)
+        : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
+                                JSPROP_ENUMERATE, 0, 0, defineHow)) {
+        goto error;
     }
 
-    /* Common tail for property cache hit and miss cases. */
     regs.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
 BEGIN_CASE(JSOP_INITELEM)
 {
     /* Pop the element's value into rval. */
     JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
@@ -4827,18 +4469,22 @@ BEGIN_CASE(JSOP_XMLNAME)
     JSObject *obj;
     jsid id;
     if (!js_FindXMLProperty(cx, lval, &obj, &id))
         goto error;
     Value rval;
     if (!obj->getGeneric(cx, id, &rval))
         goto error;
     regs.sp[-1] = rval;
-    if (op == JSOP_CALLXMLNAME)
-        PUSH_IMPLICIT_THIS(cx, obj, rval);
+    if (op == JSOP_CALLXMLNAME) {
+        Value v;
+        if (!ComputeImplicitThis(cx, obj, &v))
+            goto error;
+        PUSH_COPY(v);
+    }
 }
 END_CASE(JSOP_XMLNAME)
 
 BEGIN_CASE(JSOP_DESCENDANTS)
 BEGIN_CASE(JSOP_DELDESC)
 {
     JS_ASSERT(!script->strictModeCode);
 
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -320,17 +320,17 @@ class InterpreterFrames {
 /*
  * Unwind block and scope chains to match the given depth. The function sets
  * fp->sp on return to stackDepth.
  */
 extern void
 UnwindScope(JSContext *cx, uint32_t stackDepth);
 
 extern bool
-OnUnknownMethod(JSContext *cx, js::Value *vp);
+OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp);
 
 extern bool
 IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);
 
 /************************************************************************/
 
 /*
  * To really poison a set of values, using 'magic' or 'undefined' isn't good
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -46,16 +46,18 @@
 #include "jscompartment.h"
 #include "jsinterp.h"
 #include "jsnum.h"
 #include "jsprobes.h"
 #include "jsstr.h"
 #include "methodjit/MethodJIT.h"
 
 #include "jsfuninlines.h"
+#include "jspropertycacheinlines.h"
+#include "jstypedarrayinlines.h"
 
 #include "vm/Stack-inl.h"
 
 namespace js {
 
 class AutoPreserveEnumerators {
     JSContext *cx;
     JSObject *enumerators;
@@ -74,44 +76,38 @@ class AutoPreserveEnumerators {
 /*
  * Compute the implicit |this| parameter for a call expression where the callee
  * funval was resolved from an unqualified name reference to a property on obj
  * (an object on the scope chain).
  *
  * We can avoid computing |this| eagerly and push the implicit callee-coerced
  * |this| value, undefined, if any of these conditions hold:
  *
- * 1. The callee funval is not an object.
+ * 1. The nominal |this|, obj, is a global object.
  *
- * 2. The nominal |this|, obj, is a global object.
- *
- * 3. The nominal |this|, obj, has one of Block, Call, or DeclEnv class (this
+ * 2. The nominal |this|, obj, has one of Block, Call, or DeclEnv class (this
  *    is what IsCacheableNonGlobalScope tests). Such objects-as-scopes must be
  *    censored with undefined.
  *
- * Only if funval is an object and obj is neither a declarative scope object to
- * be censored, nor a global object, do we bind |this| to obj->thisObject().
- * Only |with| statements and embedding-specific scope objects fall into this
- * last ditch.
+ * Otherwise, we bind |this| to obj->thisObject(). Only names inside |with|
+ * statements and embedding-specific scope objects fall into this category.
  *
- * If funval is a strict mode function, then code implementing JSOP_THIS in the
- * interpreter and JITs will leave undefined as |this|. If funval is a function
- * not in strict mode, JSOP_THIS code replaces undefined with funval's global.
+ * If the callee is a strict mode function, then code implementing JSOP_THIS
+ * in the interpreter and JITs will leave undefined as |this|. If funval is a
+ * function not in strict mode, JSOP_THIS code replaces undefined with funval's
+ * global.
  *
  * We set *vp to undefined early to reduce code size and bias this code for the
  * common and future-friendly cases.
  */
 inline bool
-ComputeImplicitThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
+ComputeImplicitThis(JSContext *cx, JSObject *obj, Value *vp)
 {
     vp->setUndefined();
 
-    if (!funval.isObject())
-        return true;
-
     if (obj->isGlobal())
         return true;
 
     if (IsCacheableNonGlobalScope(obj))
         return true;
 
     obj = obj->thisObject(cx);
     if (!obj)
@@ -174,16 +170,274 @@ ValuePropertyBearer(JSContext *cx, const
 
     JSObject *pobj;
     if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
         return NULL;
     return pobj;
 }
 
 inline bool
+NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *shape, uintN getHow, Value *vp)
+{
+    if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {
+        /* Fast path for Object instance properties. */
+        JS_ASSERT(shape->hasSlot());
+        *vp = pobj->nativeGetSlot(shape->slot());
+    } else {
+        if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp))
+            return false;
+    }
+    return true;
+}
+
+#if defined(DEBUG) && !defined(JS_THREADSAFE)
+extern void
+AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
+                            PropertyCacheEntry *entry);
+#else
+inline void
+AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
+                            PropertyCacheEntry *entry)
+{}
+#endif
+
+inline bool
+GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, JSObject *obj, jsid id, Value *vp)
+{
+    /*
+     * Various XML properties behave differently when accessed in a
+     * call vs. normal context, and getGeneric will not work right.
+     */
+#if JS_HAS_XML_SUPPORT
+    if (op == JSOP_CALLPROP && obj->isXML())
+        return js_GetXMLMethod(cx, obj, id, vp);
+#endif
+
+    return obj->getGeneric(cx, id, vp);
+}
+
+inline bool
+GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp)
+{
+    JS_ASSERT(vp != &lval);
+
+    JSOp op = JSOp(*pc);
+
+    if (op == JSOP_LENGTH) {
+        /* Optimize length accesses on strings, arrays, and arguments. */
+        if (lval.isString()) {
+            *vp = Int32Value(lval.toString()->length());
+            return true;
+        }
+        if (lval.isMagic(JS_LAZY_ARGUMENTS)) {
+            *vp = Int32Value(cx->fp()->numActualArgs());
+            return true;
+        }
+        if (lval.isObject()) {
+            JSObject *obj = &lval.toObject();
+            if (obj->isArray()) {
+                jsuint length = obj->getArrayLength();
+                *vp = NumberValue(length);
+                return true;
+            }
+
+            if (obj->isArguments()) {
+                ArgumentsObject *argsobj = &obj->asArguments();
+                if (!argsobj->hasOverriddenLength()) {
+                    uint32_t length = argsobj->initialLength();
+                    JS_ASSERT(length < INT32_MAX);
+                    *vp = Int32Value(int32_t(length));
+                    return true;
+                }
+            }
+
+            if (js_IsTypedArray(obj)) {
+                JSObject *tarray = TypedArray::getTypedArray(obj);
+                *vp = Int32Value(TypedArray::getLength(tarray));
+                return true;
+            }
+        }
+    }
+
+    JSObject *obj = ValueToObjectOrPrototype(cx, lval);
+    if (!obj)
+        return false;
+
+    uintN flags = (op == JSOP_CALLPROP)
+                  ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
+                  : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER;
+
+    PropertyCacheEntry *entry;
+    JSObject *obj2;
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name);
+    if (!name) {
+        AssertValidPropertyCacheHit(cx, obj, obj2, entry);
+        if (!NativeGet(cx, obj, obj2, entry->prop, flags, vp))
+            return false;
+        return true;
+    }
+
+    jsid id = ATOM_TO_JSID(name);
+
+    if (obj->getOps()->getProperty) {
+        if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp))
+            return false;
+    } else {
+        if (!GetPropertyHelper(cx, obj, id, flags, vp))
+            return false;
+    }
+
+#if JS_HAS_NO_SUCH_METHOD
+    if (op == JSOP_CALLPROP &&
+        JS_UNLIKELY(vp->isPrimitive()) &&
+        lval.isObject())
+    {
+        if (!OnUnknownMethod(cx, obj, IdToValue(id), vp))
+            return false;
+    }
+#endif
+
+    return true;
+}
+
+inline bool
+SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Value &rval)
+{
+    JSObject *obj = ValueToObject(cx, lval);
+    if (!obj)
+        return false;
+
+    JS_ASSERT_IF(*pc == JSOP_SETMETHOD, IsFunctionObject(rval));
+    JS_ASSERT_IF(*pc == JSOP_SETNAME || *pc == JSOP_SETGNAME, lval.isObject());
+    JS_ASSERT_IF(*pc == JSOP_SETGNAME, obj == &cx->fp()->scopeChain().global());
+
+    PropertyCacheEntry *entry;
+    JSObject *obj2;
+    PropertyName *name;
+    if (JS_PROPERTY_CACHE(cx).testForSet(cx, pc, obj, &entry, &obj2, &name)) {
+        /*
+         * Property cache hit, only partially confirmed by testForSet. We
+         * know that the entry applies to regs.pc and that obj's shape
+         * matches.
+         *
+         * The entry predicts a set either an existing "own" property, or
+         * on a prototype property that has a setter.
+         */
+        const Shape *shape = entry->prop;
+        JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
+        JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
+
+        if (entry->isOwnPropertyHit() ||
+            ((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
+#ifdef DEBUG
+            if (entry->isOwnPropertyHit()) {
+                JS_ASSERT(obj->nativeContains(cx, *shape));
+            } else {
+                JS_ASSERT(obj2->nativeContains(cx, *shape));
+                JS_ASSERT(entry->isPrototypePropertyHit());
+                JS_ASSERT(entry->kshape != entry->pshape);
+                JS_ASSERT(!shape->hasSlot());
+            }
+#endif
+
+            if (shape->hasDefaultSetter() && shape->hasSlot() && !shape->isMethod()) {
+                /* Fast path for, e.g., plain Object instance properties. */
+                obj->nativeSetSlotWithType(cx, shape, rval);
+            } else {
+                Value rref = rval;
+                bool strict = cx->stack.currentScript()->strictModeCode;
+                if (!js_NativeSet(cx, obj, shape, false, strict, &rref))
+                    return false;
+            }
+            return true;
+        }
+
+        GET_NAME_FROM_BYTECODE(cx->stack.currentScript(), pc, 0, name);
+    }
+
+    bool strict = cx->stack.currentScript()->strictModeCode;
+    Value rref = rval;
+
+    JSOp op = JSOp(*pc);
+
+    jsid id = ATOM_TO_JSID(name);
+    if (JS_LIKELY(!obj->getOps()->setProperty)) {
+        uintN defineHow;
+        if (op == JSOP_SETMETHOD)
+            defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
+        else if (op == JSOP_SETNAME)
+            defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
+        else
+            defineHow = DNP_CACHE_RESULT;
+        if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rref, strict))
+            return false;
+    } else {
+        if (!obj->setGeneric(cx, id, &rref, strict))
+            return false;
+    }
+
+    return true;
+}
+
+inline bool
+NameOperation(JSContext *cx, jsbytecode *pc, Value *vp)
+{
+    JSObject *obj = cx->stack.currentScriptedScopeChain();
+
+    bool global = js_CodeSpec[*pc].format & JOF_GNAME;
+    if (global)
+        obj = &obj->global();
+
+    PropertyCacheEntry *entry;
+    JSObject *obj2;
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name);
+    if (!name) {
+        AssertValidPropertyCacheHit(cx, obj, obj2, entry);
+        if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, vp))
+            return false;
+        return true;
+    }
+
+    jsid id = ATOM_TO_JSID(name);
+
+    JSProperty *prop;
+    if (!FindPropertyHelper(cx, name, true, global, &obj, &obj2, &prop))
+        return false;
+    if (!prop) {
+        /* Kludge to allow (typeof foo == "undefined") tests. */
+        JSOp op2 = JSOp(pc[JSOP_NAME_LENGTH]);
+        if (op2 == JSOP_TYPEOF) {
+            vp->setUndefined();
+            return true;
+        }
+        JSAutoByteString printable;
+        if (js_AtomToPrintableString(cx, name, &printable))
+            js_ReportIsNotDefined(cx, printable.ptr());
+        return false;
+    }
+
+    /* Take the slow path if prop was not found in a native object. */
+    if (!obj->isNative() || !obj2->isNative()) {
+        if (!obj->getGeneric(cx, id, vp))
+            return false;
+    } else {
+        Shape *shape = (Shape *)prop;
+        JSObject *normalized = obj;
+        if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
+            normalized = &normalized->asWith().object();
+        if (!NativeGet(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, vp))
+            return false;
+    }
+
+    return true;
+}
+
+inline bool
 FunctionNeedsPrologue(JSContext *cx, JSFunction *fun)
 {
     /* Heavyweight functions need call objects created. */
     if (fun->isHeavyweight())
         return true;
 
     /* Outer and inner functions need to preserve nesting invariants. */
     if (cx->typeInferenceEnabled() && fun->script()->nesting())
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4660,17 +4660,16 @@ PurgeProtoChain(JSContext *cx, JSObject 
 
     while (obj) {
         if (!obj->isNative()) {
             obj = obj->getProto();
             continue;
         }
         shape = obj->nativeLookup(cx, id);
         if (shape) {
-            PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++);
             if (!obj->shadowingShapeChange(cx, *shape))
                 return false;
 
             obj->shadowingShapeChange(cx, *shape);
             return true;
         }
         obj = obj->getProto();
     }
@@ -5101,23 +5100,22 @@ js::LookupPropertyWithFlags(JSContext *c
                             JSObject **objp, JSProperty **propp)
 {
     /* Convert string indices to integers if appropriate. */
     id = js_CheckForStringIndex(id);
 
     return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp);
 }
 
-PropertyCacheEntry *
+bool
 js::FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, bool global,
                        JSObject **objp, JSObject **pobjp, JSProperty **propp)
 {
     jsid id = ATOM_TO_JSID(name);
     JSObject *scopeChain, *obj, *parent, *pobj;
-    PropertyCacheEntry *entry;
     int scopeIndex;
     JSProperty *prop;
 
     scopeChain = cx->stack.currentScriptedScopeChain();
 
     if (global) {
         /*
          * Skip along the scope chain to the enclosing global object. This is
@@ -5127,26 +5125,25 @@ js::FindPropertyHelper(JSContext *cx, Pr
          * accessing the global object, and the inferred behavior should match
          * the actual behavior even if the id could be found on the scope chain
          * before the global object.
          */
         scopeChain = &scopeChain->global();
     }
 
     /* Scan entries on the scope chain that we can cache across. */
-    entry = JS_NO_PROP_CACHE_FILL;
     obj = scopeChain;
     parent = obj->enclosingScope();
     for (scopeIndex = 0;
          parent
          ? IsCacheableNonGlobalScope(obj)
          : !obj->getOps()->lookupProperty;
          ++scopeIndex) {
         if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop))
-            return NULL;
+            return false;
 
         if (prop) {
 #ifdef DEBUG
             if (parent) {
                 JS_ASSERT(pobj->isNative());
                 JS_ASSERT(pobj->getClass() == obj->getClass());
                 if (obj->isBlock()) {
                     /*
@@ -5159,42 +5156,42 @@ js::FindPropertyHelper(JSContext *cx, Pr
                     /* Call and DeclEnvClass objects have no prototypes. */
                     JS_ASSERT(!obj->getProto());
                 }
                 JS_ASSERT(pobj == obj);
             } else {
                 JS_ASSERT(obj->isNative());
             }
 #endif
+
             /*
              * We must check if pobj is native as a global object can have
              * non-native prototype.
              */
             if (cacheResult && pobj->isNative()) {
-                entry = JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj,
-                                                   (Shape *) prop);
+                JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj,
+                                           (Shape *) prop);
             }
+
             goto out;
         }
 
         if (!parent) {
             pobj = NULL;
             goto out;
         }
         obj = parent;
         parent = obj->enclosingScope();
     }
 
     for (;;) {
         if (!obj->lookupGeneric(cx, id, &pobj, &prop))
-            return NULL;
-        if (prop) {
-            PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+            return false;
+        if (prop)
             goto out;
-        }
 
         /*
          * We conservatively assume that a resolve hook could mutate the scope
          * chain during JSObject::lookupGeneric. So we read parent here again.
          */
         parent = obj->enclosingScope();
         if (!parent) {
             pobj = NULL;
@@ -5203,17 +5200,17 @@ js::FindPropertyHelper(JSContext *cx, Pr
         obj = parent;
     }
 
   out:
     JS_ASSERT(!!pobj == !!prop);
     *objp = obj;
     *pobjp = pobj;
     *propp = prop;
-    return entry;
+    return true;
 }
 
 /*
  * On return, if |*pobjp| is a native object, then |*propp| is a |Shape *|.
  * Otherwise, its type and meaning depends on the host object's implementation.
  */
 bool
 js::FindProperty(JSContext *cx, PropertyName *name, bool global,
@@ -5250,19 +5247,17 @@ js::FindIdentifierBase(JSContext *cx, JS
         if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &prop))
             return NULL;
         if (prop) {
             if (!pobj->isNative()) {
                 JS_ASSERT(obj->isGlobal());
                 return obj;
             }
             JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
-            DebugOnly<PropertyCacheEntry*> entry =
-                JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
-            JS_ASSERT(entry);
+            JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
             return obj;
         }
 
         JSObject *parent = obj->enclosingScope();
         if (!parent)
             return obj;
         obj = parent;
     }
@@ -5401,18 +5396,16 @@ js_GetPropertyHelperInline(JSContext *cx
         return false;
 
     if (!prop) {
         vp->setUndefined();
 
         if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp))
             return JS_FALSE;
 
-        PCMETER(getHow & JSGET_CACHE_RESULT && JS_PROPERTY_CACHE(cx).nofills++);
-
         /* Record non-undefined values produced by the class getter hook. */
         if (!vp->isUndefined())
             AddTypePropertyId(cx, obj, id, *vp);
 
         /*
          * Give a strict warning if foo.bar is evaluated by a script for an
          * object foo with no property named 'bar'.
          */
@@ -5529,17 +5522,16 @@ js_GetMethod(JSContext *cx, JSObject *ob
 
     GenericIdOp op = obj->getOps()->getGeneric;
     if (!op) {
 #if JS_HAS_XML_SUPPORT
         JS_ASSERT(!obj->isXML());
 #endif
         return GetPropertyHelper(cx, obj, id, getHow, vp);
     }
-    JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, obj->isDenseArray());
 #if JS_HAS_XML_SUPPORT
     if (obj->isXML())
         return js_GetXMLMethod(cx, obj, id, vp);
 #endif
     return op(cx, obj, obj, id, vp);
 }
 
 JS_FRIEND_API(bool)
@@ -5692,18 +5684,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
         /* ES5 8.12.4 [[Put]] step 2. */
         if (shape->isAccessorDescriptor()) {
             if (shape->hasDefaultSetter())
                 return js_ReportGetterOnlyAssignment(cx);
         } else {
             JS_ASSERT(shape->isDataDescriptor());
 
             if (!shape->writable()) {
-                PCMETER((defineHow & JSDNP_CACHE_RESULT) && JS_PROPERTY_CACHE(cx).rofills++);
-
                 /* Error in strict mode code, warn with strict option, otherwise do nothing. */
                 if (strict)
                     return obj->reportReadOnly(cx, id);
                 if (cx->hasStrictOption())
                     return obj->reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
                 return JS_TRUE;
             }
         }
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1823,17 +1823,17 @@ ReadPropertyDescriptors(JSContext *cx, J
  * Constant to pass to js_LookupPropertyWithFlags to infer bits from current
  * bytecode.
  */
 static const uintN RESOLVE_INFER = 0xffff;
 
 /*
  * If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
  */
-extern PropertyCacheEntry *
+extern bool
 FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, bool global,
                    JSObject **objp, JSObject **pobjp, JSProperty **propp);
 
 /*
  * Search for name either on the current scope chain or on the scope chain's
  * global object, per the global parameter.
  */
 extern bool
@@ -1856,19 +1856,19 @@ js_FindVariableScope(JSContext *cx, JSFu
  * default we assume our caller won't leak a joined callee to script, where it
  * would create hazardous mutable object sharing as well as observable identity
  * according to == and ===.
  *
  * JSGET_NO_METHOD_BARRIER avoids the performance overhead of the method read
  * barrier, which is not needed when invoking a lambda that otherwise does not
  * leak its callee reference (via arguments.callee or its name).
  */
-const uintN JSGET_CACHE_RESULT      = 1; // from a caching interpreter opcode
 const uintN JSGET_METHOD_BARRIER    = 0; // get can leak joined function object
-const uintN JSGET_NO_METHOD_BARRIER = 2; // call to joined function can't leak
+const uintN JSGET_NO_METHOD_BARRIER = 1; // call to joined function can't leak
+const uintN JSGET_CACHE_RESULT      = 2; // from a caching interpreter opcode
 
 /*
  * NB: js_NativeGet and js_NativeSet are called with the scope containing shape
  * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
  * scope is again locked.  But on failure, both functions return false with the
  * scope containing shape unlocked.
  */
 extern JSBool
@@ -1942,23 +1942,23 @@ js_IsDelegate(JSContext *cx, JSObject *o
 
 /*
  * Wrap boolean, number or string as Boolean, Number or String object.
  * *vp must not be an object, null or undefined.
  */
 extern JSBool
 js_PrimitiveToObject(JSContext *cx, js::Value *vp);
 
-/*
- * v and vp may alias. On successful return, vp->isObjectOrNull(). If vp is not
- * rooted, the caller must root vp before the next possible GC.
- */
 extern JSBool
 js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, JSObject **objp);
 
+/* Throws if v could not be converted to an object. */
+extern JSObject *
+js_ValueToNonNullObject(JSContext *cx, const js::Value &v);
+
 namespace js {
 
 /*
  * Invokes the ES5 ToObject algorithm on *vp, writing back the object to vp.
  * If *vp might already be an object, use ToObject.
  */
 extern JSObject *
 ToObjectSlow(JSContext *cx, Value *vp);
@@ -1966,24 +1966,26 @@ ToObjectSlow(JSContext *cx, Value *vp);
 JS_ALWAYS_INLINE JSObject *
 ToObject(JSContext *cx, Value *vp)
 {
     if (vp->isObject())
         return &vp->toObject();
     return ToObjectSlow(cx, vp);
 }
 
-} /* namespace js */
+/* As for ToObject, but preserves the original value. */
+inline JSObject *
+ValueToObject(JSContext *cx, const Value &v)
+{
+    if (v.isObject())
+        return &v.toObject();
+    return js_ValueToNonNullObject(cx, v);
+}
 
-/*
- * v and vp may alias. On successful return, vp->isObject(). If vp is not
- * rooted, the caller must root vp before the next possible GC.
- */
-extern JSObject *
-js_ValueToNonNullObject(JSContext *cx, const js::Value &v);
+} /* namespace js */
 
 extern JSBool
 js_XDRObject(JSXDRState *xdr, JSObject **objp);
 
 extern void
 js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
 
 extern bool
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -629,16 +629,33 @@ inline bool
 JSObject::denseArrayHasInlineSlots() const
 {
     JS_ASSERT(isDenseArray());
     return elements == fixedElements();
 }
 
 namespace js {
 
+inline JSObject *
+ValueToObjectOrPrototype(JSContext *cx, const Value &v)
+{
+    if (v.isObject())
+        return &v.toObject();
+    GlobalObject *global = &cx->fp()->scopeChain().global();
+    if (v.isString())
+        return global->getOrCreateStringPrototype(cx);
+    if (v.isNumber())
+        return global->getOrCreateNumberPrototype(cx);
+    if (v.isBoolean())
+        return global->getOrCreateBooleanPrototype(cx);
+    JS_ASSERT(v.isNull() || v.isUndefined());
+    js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL);
+    return NULL;
+}
+
 /*
  * Any name atom for a function which will be added as a DeclEnv object to the
  * scope chain above call objects for fun.
  */
 static inline JSAtom *
 CallObjectLambdaName(JSFunction *fun)
 {
     return (fun->flags & JSFUN_LAMBDA) ? fun->atom : NULL;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2462,16 +2462,25 @@ InitSprintStack(JSContext *cx, SprintSta
     ss->bytecodes = (jsbytecode **) ((char *)space + offsetsz + opcodesz);
 
     ss->top = ss->inArrayInit = 0;
     ss->inGenExp = JS_FALSE;
     ss->printer = jp;
     return JS_TRUE;
 }
 
+template <typename T>
+void
+Swap(T &a, T &b)
+{
+    T tmp = a;
+    a = b;
+    b = tmp;
+}
+
 /*
  * If nb is non-negative, decompile nb bytecodes starting at pc.  Otherwise
  * the decompiler starts at pc and continues until it reaches an opcode for
  * which decompiling would result in the stack depth equaling -(nb + 1).
  */
 static jsbytecode *
 Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
 {
@@ -4203,16 +4212,23 @@ Decompile(SprintStack *ss, jsbytecode *p
                 }
 #endif
 
                 rval = GetStr(ss, ss->top-1);
                 saveop = (JSOp) ss->opcodes[ss->top-1];
                 todo = SprintCString(&ss->sprinter, rval);
                 break;
 
+              case JSOP_SWAP:
+                Swap(ss->offsets[ss->top-1], ss->offsets[ss->top-2]);
+                Swap(ss->opcodes[ss->top-1], ss->opcodes[ss->top-2]);
+                Swap(ss->bytecodes[ss->top-1], ss->bytecodes[ss->top-2]);
+                todo = -2;
+                break;
+
               case JSOP_SETARG:
                 atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
                 LOCAL_ASSERT(atom);
                 goto do_setname;
 
               case JSOP_SETCONST:
               case JSOP_SETNAME:
               case JSOP_SETGNAME:
@@ -4284,17 +4300,18 @@ Decompile(SprintStack *ss, jsbytecode *p
                  */
                 op = (JSOp) ss->opcodes[ss->top - 1];
                 argv[0] = PopStrDupe(ss,
                                      (saveop == JSOP_NEW &&
                                       (op == JSOP_CALL ||
                                        op == JSOP_EVAL ||
                                        op == JSOP_FUNCALL ||
                                        op == JSOP_FUNAPPLY ||
-                                       (js_CodeSpec[op].format & JOF_CALLOP)))
+                                       op == JSOP_CALLPROP ||
+                                       op == JSOP_CALLELEM))
                                      ? JSOP_NAME
                                      : saveop,
                                      &lvalpc);
                 op = saveop;
 
                 lval = "(", rval = ")";
                 todo = ss->sprinter.offset;
                 if (op == JSOP_NEW) {
@@ -5372,22 +5389,16 @@ Decompile(SprintStack *ss, jsbytecode *p
             if (!UpdateDecompiledText(ss, pushpc, todo))
                 return NULL;
             if (!PushOff(ss, todo, saveop, pushpc))
                 return NULL;
             if (js_CodeSpec[*pc].format & JOF_DECOMPOSE)
                 CopyDecompiledTextForDecomposedOp(jp, pc);
         }
 
-        if (cs->format & JOF_CALLOP) {
-            todo = Sprint(&ss->sprinter, "");
-            if (todo < 0 || !PushOff(ss, todo, saveop))
-                return NULL;
-        }
-
         pc += len;
     }
 
 /*
  * Undefine local macros.
  */
 #undef inXML
 #undef DECOMPILE_CODE
@@ -5803,16 +5814,26 @@ DecompileExpression(JSContext *cx, JSScr
             break;
           default:
             return FAILED_EXPRESSION_DECOMPILER;
         }
         break;
       }
       default:;
     }
+
+    /*
+     * Include the trailing SWAP when decompiling CALLPROP or CALLELEM ops,
+     * so that the result is the entire access rather than the lvalue.
+     */
+    if (op == JSOP_CALLPROP || op == JSOP_CALLELEM) {
+        JS_ASSERT(*end == JSOP_SWAP);
+        end += JSOP_SWAP_LENGTH;
+    }
+
     ptrdiff_t len = end - begin;
     if (len <= 0)
         return FAILED_EXPRESSION_DECOMPILER;
 
     struct Guard {
         jsbytecode **pcstack;
         JSPrinter *printer;
         Guard() : pcstack(NULL), printer(NULL) {}
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -112,18 +112,16 @@ typedef enum JSOp {
 #define JOF_POST         (1U<<12) /* postorder increment or decrement */
 #define JOF_ASSIGNING     JOF_SET /* hint for Class.resolve, used for ops
                                      that do simplex assignment */
 #define JOF_DETECTING    (1U<<14) /* object detection for JSNewResolveOp */
 #define JOF_BACKPATCH    (1U<<15) /* backpatch placeholder during codegen */
 #define JOF_LEFTASSOC    (1U<<16) /* left-associative operator */
 #define JOF_DECLARING    (1U<<17) /* var, const, or function declaration op */
 #define JOF_INDEXBASE    (1U<<18) /* atom segment base setting prefix op */
-#define JOF_CALLOP       (1U<<19) /* call operation that pushes function and
-                                     this */
 #define JOF_PARENHEAD    (1U<<20) /* opcode consumes value of expression in
                                      parenthesized statement head */
 #define JOF_INVOKE       (1U<<21) /* JSOP_CALL, JSOP_NEW, JSOP_EVAL */
 #define JOF_TMPSLOT      (1U<<22) /* interpreter uses extra temporary slot
                                      to root intermediate objects besides
                                      the slots opcode uses */
 #define JOF_TMPSLOT2     (2U<<22) /* interpreter uses extra 2 temporary slot
                                      besides the slots opcode uses */
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -171,17 +171,17 @@ OPDEF(JSOP_ELEMINC,   49, "eleminc",    
 OPDEF(JSOP_NAMEDEC,   50, "namedec",    NULL,         4,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_PROPDEC,   51, "propdec",    NULL,         4,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_ELEMDEC,   52, "elemdec",    NULL,         2,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE)
 
 OPDEF(JSOP_GETPROP,   53, "getprop",    NULL,         3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
 OPDEF(JSOP_SETPROP,   54, "setprop",    NULL,         3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_GETELEM,   55, "getelem",    NULL,         1,  2,  1, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
 OPDEF(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1,  3,  JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
-OPDEF(JSOP_CALLNAME,  57, "callname",   NULL,         3,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
+OPDEF(JSOP_CALLNAME,  57, "callname",   NULL,         3,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_CALL,      58, "call",       NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 OPDEF(JSOP_NAME,      59, "name",       NULL,         3,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_DOUBLE,    60, "double",     NULL,         3,  0,  1, 16,  JOF_ATOM)
 OPDEF(JSOP_STRING,    61, "string",     NULL,         3,  0,  1, 19,  JOF_ATOM)
 OPDEF(JSOP_ZERO,      62, "zero",       "0",          1,  0,  1, 16,  JOF_BYTE)
 OPDEF(JSOP_ONE,       63, "one",        "1",          1,  0,  1, 16,  JOF_BYTE)
 OPDEF(JSOP_NULL,      64, js_null_str,  js_null_str,  1,  0,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_THIS,      65, js_this_str,  js_this_str,  1,  0,  1, 19,  JOF_BYTE)
@@ -362,21 +362,20 @@ OPDEF(JSOP_PICK,        133, "pick",    
  * srcnote-annotated JSOP_NOPs and to simply stack balance handling.
  */
 OPDEF(JSOP_TRY,         134,"try",        NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_FINALLY,     135,"finally",    NULL,       1,  0,  2,  0,  JOF_BYTE)
 
 /*
  * Get a slot from a flat closure function object that contains a snapshot of
  * the closure-invariant upvar values. The immediate operand indexes the upvar
- * in the function's u.i.script->upvars() array. The CALL variant computes the
- * callee and this-object in preparation for a JSOP_CALL.
+ * in the function's u.i.script->upvars() array.
  */
 OPDEF(JSOP_GETFCSLOT,   136,"getfcslot",  NULL,       3,  0,  1, 19,  JOF_UINT16|JOF_NAME|JOF_TYPESET)
-OPDEF(JSOP_CALLFCSLOT,  137,"callfcslot", NULL,       3,  0,  2, 19,  JOF_UINT16|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
+OPDEF(JSOP_CALLFCSLOT,  137,"callfcslot", NULL,       3,  0,  1, 19,  JOF_UINT16|JOF_NAME|JOF_TYPESET)
 
 /*
  * Define a local function object as a local variable.
  * The local variable's slot number is the first immediate two-byte operand.
  * The function object's atom index is the second immediate operand.
  */
 OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL,       5,  0,  0,  0,  JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
 
@@ -434,17 +433,17 @@ OPDEF(JSOP_TOXML,         176,"toxml",  
 OPDEF(JSOP_TOXMLLIST,     177,"toxmllist",  NULL,     1,  1,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_XMLTAGEXPR,    178,"xmltagexpr", NULL,     1,  1,  1,  0,  JOF_BYTE)
 OPDEF(JSOP_XMLELTEXPR,    179,"xmleltexpr", NULL,     1,  1,  1,  0,  JOF_BYTE)
 OPDEF(JSOP_XMLCDATA,      180,"xmlcdata",   NULL,     3,  0,  1, 19,  JOF_ATOM)
 OPDEF(JSOP_XMLCOMMENT,    181,"xmlcomment", NULL,     3,  0,  1, 19,  JOF_ATOM)
 OPDEF(JSOP_XMLPI,         182,"xmlpi",      NULL,     3,  1,  1, 19,  JOF_ATOM)
 OPDEF(JSOP_DELDESC,       183,"deldesc",    NULL,     1,  2,  1, 15,  JOF_BYTE|JOF_ELEM|JOF_DEL)
 
-OPDEF(JSOP_CALLPROP,      184,"callprop",   NULL,     3,  1,  2, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_CALLOP|JOF_TMPSLOT3)
+OPDEF(JSOP_CALLPROP,      184,"callprop",   NULL,     3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3)
 
 /* Enter a let block/expr whose slots are at the top of the stack. */
 OPDEF(JSOP_ENTERLET0,     185,"enterlet0",  NULL,     3, -1, -1,  0,  JOF_OBJECT)
 
 /* Enter a let block/expr whose slots are 1 below the top of the stack. */
 OPDEF(JSOP_ENTERLET1,     186,"enterlet1",  NULL,     3, -1, -1,  0,  JOF_OBJECT)
 
 /*
@@ -463,31 +462,31 @@ OPDEF(JSOP_RESETBASE,     189,"resetbase
 OPDEF(JSOP_RESETBASE0,    190,"resetbase0", NULL,     1,  0,  0,  0,  JOF_BYTE)
 
 /*
  * Opcodes to help the decompiler deal with XML.
  */
 OPDEF(JSOP_STARTXML,      191,"startxml",    NULL,    1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_STARTXMLEXPR,  192,"startxmlexpr",NULL,    1,  0,  0,  0,  JOF_BYTE)
 
-OPDEF(JSOP_CALLELEM,      193, "callelem",   NULL,    1,  2,  2, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC|JOF_CALLOP)
+OPDEF(JSOP_CALLELEM,      193, "callelem",   NULL,    1,  2,  1, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
 
 /*
  * Stop interpretation, emitted at end of script to save the threaded bytecode
  * interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c).
  */
 OPDEF(JSOP_STOP,          194,"stop",        NULL,    1,  0,  0,  0,  JOF_BYTE)
 
 /*
  * Get an extant property value, throwing ReferenceError if the identified
  * property does not exist.
  */
 OPDEF(JSOP_GETXPROP,      195,"getxprop",    NULL,    3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
 
-OPDEF(JSOP_CALLXMLNAME,   196, "callxmlname",  NULL,  1,  1,  2, 19,  JOF_BYTE|JOF_CALLOP)
+OPDEF(JSOP_CALLXMLNAME,   196, "callxmlname",  NULL,  1,  1,  2, 19,  JOF_BYTE)
 
 /*
  * Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef).
  */
 OPDEF(JSOP_TYPEOFEXPR,    197,"typeofexpr",  NULL,    1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
 
 /*
  * Block-local scope support.
@@ -525,19 +524,19 @@ OPDEF(JSOP_LEAVEBLOCKEXPR,207,"leavebloc
 /*
  * Optimize atom segments 1-3.  These must be followed by JSOP_RESETBASE0 after
  * the opcode that they prefix.
  */
 OPDEF(JSOP_INDEXBASE1,    208,"indexbase1",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
 OPDEF(JSOP_INDEXBASE2,    209,"indexbase2",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
 OPDEF(JSOP_INDEXBASE3,    210,"indexbase3",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
 
-OPDEF(JSOP_CALLGNAME,     211, "callgname",    NULL,  3,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP|JOF_GNAME)
-OPDEF(JSOP_CALLLOCAL,     212, "calllocal",    NULL,  3,  0,  2, 19,  JOF_LOCAL|JOF_NAME|JOF_CALLOP)
-OPDEF(JSOP_CALLARG,       213, "callarg",      NULL,  3,  0,  2, 19,  JOF_QARG |JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLGNAME,     211, "callgname",    NULL,  3,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME)
+OPDEF(JSOP_CALLLOCAL,     212, "calllocal",    NULL,  3,  0,  1, 19,  JOF_LOCAL|JOF_NAME)
+OPDEF(JSOP_CALLARG,       213, "callarg",      NULL,  3,  0,  1, 19,  JOF_QARG |JOF_NAME)
 OPDEF(JSOP_BINDGNAME,     214, "bindgname",    NULL,  3,  0,  1,  0,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME)
 
 /*
  * Opcodes to hold 8-bit and 32-bit immediate integer operands.
  */
 OPDEF(JSOP_INT8,          215, "int8",         NULL,  2,  0,  1, 16,  JOF_INT8)
 OPDEF(JSOP_INT32,         216, "int32",        NULL,  5,  0,  1, 16,  JOF_INT32)
 
@@ -565,8 +564,11 @@ OPDEF(JSOP_LAMBDA_FC,     221,"lambda_fc
  */
 OPDEF(JSOP_SETMETHOD,     222,"setmethod",     NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_INITMETHOD,    223,"initmethod",    NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 
 OPDEF(JSOP_SHARPINIT,     224,"sharpinit",     NULL,  3,  0,  0,  0,  JOF_UINT16|JOF_SHARPSLOT)
 
 /* Pop the stack, convert to a jsid (int or string), and push back. */
 OPDEF(JSOP_TOID,          225, "toid",         NULL,  1,  1,  1,  0,  JOF_BYTE)
+
+/* Push the implicit 'this' value for calls to the associated name. */
+OPDEF(JSOP_IMPLICITTHIS,  226, "implicitthis", "",    3,  0,  1,  0,  JOF_ATOM)
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -194,19 +194,16 @@ class GlobalObject;
 
 template <typename K,
           typename V,
           size_t InlineElems>
 class InlineMap;
 
 class LifoAlloc;
 
-class PropertyCache;
-struct PropertyCacheEntry;
-
 class BaseShape;
 class UnownedBaseShape;
 struct Shape;
 struct EmptyShape;
 class ShapeKindArray;
 class Bindings;
 
 struct StackBaseShape;
--- a/js/src/jsxdrapi.h
+++ b/js/src/jsxdrapi.h
@@ -221,17 +221,17 @@ JS_XDRFindClassById(JSXDRState *xdr, uin
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 101)
+#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 102)
 
 /*
  * 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
@@ -1343,18 +1343,17 @@ mjit::Compiler::finishThisUp(JITScript *
         JS_ASSERT(jitPics[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) -
                                            masm.distanceOf(pics[i].fastPathStart));
         jitPics[i].shapeRegHasBaseShape = true;
         jitPics[i].pc = pics[i].pc;
 
         if (pics[i].kind == ic::PICInfo::SET ||
             pics[i].kind == ic::PICInfo::SETMETHOD) {
             jitPics[i].u.vr = pics[i].vr;
-        } else if (pics[i].kind != ic::PICInfo::NAME &&
-                   pics[i].kind != ic::PICInfo::CALLNAME) {
+        } else if (pics[i].kind != ic::PICInfo::NAME) {
             if (pics[i].hasTypeCheck) {
                 int32_t distance = stubcc.masm.distanceOf(pics[i].typeCheck) -
                                  stubcc.masm.distanceOf(pics[i].slowPathStart);
                 JS_ASSERT(distance <= 0);
                 jitPics[i].u.get.typeCheckOffset = distance;
             }
         }
         stubCode.patch(pics[i].paramAddr, &jitPics[i]);
@@ -2003,25 +2002,27 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_TYPEOF)
 
           BEGIN_CASE(JSOP_VOID)
             frame.pop();
             frame.push(UndefinedValue());
           END_CASE(JSOP_VOID)
 
           BEGIN_CASE(JSOP_GETPROP)
+          BEGIN_CASE(JSOP_CALLPROP)
           BEGIN_CASE(JSOP_LENGTH)
             if (!jsop_getprop(script->getName(fullAtomIndex(PC)), knownPushedType(0)))
                 return Compile_Error;
           END_CASE(JSOP_GETPROP)
 
           BEGIN_CASE(JSOP_GETELEM)
+          BEGIN_CASE(JSOP_CALLELEM)
             if (script->pcCounters)
                 updateElemCounters(PC, frame.peek(-2), frame.peek(-1));
-            if (!jsop_getelem(false))
+            if (!jsop_getelem())
                 return Compile_Error;
           END_CASE(JSOP_GETELEM)
 
           BEGIN_CASE(JSOP_TOID)
             jsop_toid();
           END_CASE(JSOP_TOID)
 
           BEGIN_CASE(JSOP_SETELEM)
@@ -2078,30 +2079,32 @@ mjit::Compiler::generateMethod()
                 if (!inlineCallHelper(GET_ARGC(PC), callingNew, frameSize))
                     return Compile_Error;
                 JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n");
             }
           }
           END_CASE(JSOP_CALL)
 
           BEGIN_CASE(JSOP_NAME)
+          BEGIN_CASE(JSOP_CALLNAME)
           {
             PropertyName *name = script->getName(fullAtomIndex(PC));
-            jsop_name(name, knownPushedType(0), false);
+            jsop_name(name, knownPushedType(0));
             frame.extra(frame.peek(-1)).name = name;
           }
           END_CASE(JSOP_NAME)
 
-          BEGIN_CASE(JSOP_CALLNAME)
+          BEGIN_CASE(JSOP_IMPLICITTHIS)
           {
-            PropertyName *name = script->getName(fullAtomIndex(PC));
-            jsop_name(name, knownPushedType(0), true);
-            frame.extra(frame.peek(-2)).name = name;
+            prepareStubCall(Uses(0));
+            masm.move(ImmPtr(script->getName(fullAtomIndex(PC))), Registers::ArgReg1);
+            INLINE_STUBCALL(stubs::ImplicitThis, REJOIN_FALLTHROUGH);
+            frame.pushSynced(JSVAL_TYPE_UNKNOWN);
           }
-          END_CASE(JSOP_CALLNAME)
+          END_CASE(JSOP_IMPLICITTHIS)
 
           BEGIN_CASE(JSOP_DOUBLE)
           {
             uint32_t index = fullAtomIndex(PC);
             double d = script->getConst(index).toDouble();
             frame.push(Value(DoubleValue(d)));
           }
           END_CASE(JSOP_DOUBLE)
@@ -2240,32 +2243,24 @@ mjit::Compiler::generateMethod()
             iterEnd();
           END_CASE(JSOP_ENDITER)
 
           BEGIN_CASE(JSOP_POP)
             frame.pop();
           END_CASE(JSOP_POP)
 
           BEGIN_CASE(JSOP_GETARG)
-          {
-            restoreVarType();
-            uint32_t arg = GET_SLOTNO(PC);
-            frame.pushArg(arg);
-          }
-          END_CASE(JSOP_GETARG)
-
           BEGIN_CASE(JSOP_CALLARG)
           {
             restoreVarType();
             uint32_t arg = GET_SLOTNO(PC);
             if (JSObject *singleton = pushedSingleton(0))
                 frame.push(ObjectValue(*singleton));
             else
                 frame.pushArg(arg);
-            frame.push(UndefinedValue());
           }
           END_CASE(JSOP_GETARG)
 
           BEGIN_CASE(JSOP_BINDGNAME)
             jsop_bindgname();
           END_CASE(JSOP_BINDGNAME)
 
           BEGIN_CASE(JSOP_SETARG)
@@ -2279,27 +2274,31 @@ mjit::Compiler::generateMethod()
                 frame.pop();
                 PC += JSOP_SETARG_LENGTH + JSOP_POP_LENGTH;
                 break;
             }
           }
           END_CASE(JSOP_SETARG)
 
           BEGIN_CASE(JSOP_GETLOCAL)
+          BEGIN_CASE(JSOP_CALLLOCAL)
           {
             /*
              * Update the var type unless we are about to pop the variable.
              * Sync is not guaranteed for types of dead locals, and GETLOCAL
              * followed by POP is not regarded as a use of the variable.
              */
             jsbytecode *next = &PC[JSOP_GETLOCAL_LENGTH];
             if (JSOp(*next) != JSOP_POP || analysis->jumpTarget(next))
                 restoreVarType();
             uint32_t slot = GET_SLOTNO(PC);
-            frame.pushLocal(slot);
+            if (JSObject *singleton = pushedSingleton(0))
+                frame.push(ObjectValue(*singleton));
+            else
+                frame.pushLocal(slot);
           }
           END_CASE(JSOP_GETLOCAL)
 
           BEGIN_CASE(JSOP_SETLOCAL)
           {
             jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
             frame.storeLocal(GET_SLOTNO(PC), pop);
@@ -2397,34 +2396,34 @@ mjit::Compiler::generateMethod()
             if (script->pcCounters) {
                 FrameEntry *fe = frame.getLocal(GET_SLOTNO(PC));
                 updateArithCounters(PC, fe, arithFirstUseType, JSVAL_TYPE_INT32);
                 arithUpdated = true;
             }
           END_CASE(JSOP_LOCALDEC)
 
           BEGIN_CASE(JSOP_BINDNAME)
-            jsop_bindname(script->getName(fullAtomIndex(PC)), true);
+            jsop_bindname(script->getName(fullAtomIndex(PC)));
           END_CASE(JSOP_BINDNAME)
 
           BEGIN_CASE(JSOP_SETPROP)
           {
             jsbytecode *next = &PC[JSOP_SETPROP_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), true, pop))
+            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), pop))
                 return Compile_Error;
           }
           END_CASE(JSOP_SETPROP)
 
           BEGIN_CASE(JSOP_SETNAME)
           BEGIN_CASE(JSOP_SETMETHOD)
           {
             jsbytecode *next = &PC[JSOP_SETNAME_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), true, pop))
+            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), pop))
                 return Compile_Error;
           }
           END_CASE(JSOP_SETNAME)
 
           BEGIN_CASE(JSOP_THROW)
             prepareStubCall(Uses(1));
             INLINE_STUBCALL(stubs::Throw, REJOIN_NONE);
             frame.pop();
@@ -2597,19 +2596,16 @@ mjit::Compiler::generateMethod()
             // obj->getFlatClosureUpvars()
             Address upvarAddress(reg, JSFunction::getFlatClosureUpvarsOffset());
             masm.loadPrivate(upvarAddress, reg);
             // push ((Value *) reg)[index]
 
             BarrierState barrier = pushAddressMaybeBarrier(Address(reg, index * sizeof(Value)),
                                                            knownPushedType(0), true);
             finishBarrier(barrier, REJOIN_GETTER, 0);
-
-            if (op == JSOP_CALLFCSLOT)
-                frame.push(UndefinedValue());
           }
           END_CASE(JSOP_CALLFCSLOT)
 
           BEGIN_CASE(JSOP_DEFLOCALFUN)
           {
             uint32_t slot = GET_SLOTNO(PC);
             JSFunction *fun = script->getFunction(fullAtomIndex(&PC[SLOTNO_LEN]));
             prepareStubCall(Uses(0));
@@ -2629,26 +2625,24 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_RETRVAL)
 
           BEGIN_CASE(JSOP_GETGNAME)
           BEGIN_CASE(JSOP_CALLGNAME)
           {
             uint32_t index = fullAtomIndex(PC);
             jsop_getgname(index);
             frame.extra(frame.peek(-1)).name = script->getName(index);
-            if (op == JSOP_CALLGNAME)
-                jsop_callgname_epilogue();
           }
           END_CASE(JSOP_GETGNAME)
 
           BEGIN_CASE(JSOP_SETGNAME)
           {
             jsbytecode *next = &PC[JSOP_SETGNAME_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            jsop_setgname(script->getName(fullAtomIndex(PC)), true, pop);
+            jsop_setgname(script->getName(fullAtomIndex(PC)), pop);
           }
           END_CASE(JSOP_SETGNAME)
 
           BEGIN_CASE(JSOP_REGEXP)
             if (!jsop_regexp())
                 return Compile_Error;
           END_CASE(JSOP_REGEXP)
 
@@ -2656,31 +2650,20 @@ mjit::Compiler::generateMethod()
           {
             JSObject *object = script->getObject(fullAtomIndex(PC));
             RegisterID reg = frame.allocReg();
             masm.move(ImmPtr(object), reg);
             frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
           }
           END_CASE(JSOP_OBJECT)
 
-          BEGIN_CASE(JSOP_CALLPROP)
-            if (!jsop_callprop(script->getName(fullAtomIndex(PC))))
-                return Compile_Error;
-          END_CASE(JSOP_CALLPROP)
-
           BEGIN_CASE(JSOP_UINT24)
             frame.push(Value(Int32Value((int32_t) GET_UINT24(PC))));
           END_CASE(JSOP_UINT24)
 
-          BEGIN_CASE(JSOP_CALLELEM)
-            if (script->pcCounters)
-                updateElemCounters(PC, frame.peek(-2), frame.peek(-1));
-            jsop_getelem(true);
-          END_CASE(JSOP_CALLELEM)
-
           BEGIN_CASE(JSOP_STOP)
             if (script->pcCounters)
                 updatePCCounters(PC, &codeStart, &countersUpdated);
             emitReturn(NULL);
             goto done;
           END_CASE(JSOP_STOP)
 
           BEGIN_CASE(JSOP_GETXPROP)
@@ -2693,28 +2676,16 @@ mjit::Compiler::generateMethod()
           BEGIN_CASE(JSOP_ENTERLET1)
             enterBlock(script->getObject(fullAtomIndex(PC)));
           END_CASE(JSOP_ENTERBLOCK);
 
           BEGIN_CASE(JSOP_LEAVEBLOCK)
             leaveBlock();
           END_CASE(JSOP_LEAVEBLOCK)
 
-          BEGIN_CASE(JSOP_CALLLOCAL)
-          {
-            restoreVarType();
-            uint32_t slot = GET_SLOTNO(PC);
-            if (JSObject *singleton = pushedSingleton(0))
-                frame.push(ObjectValue(*singleton));
-            else
-                frame.pushLocal(slot);
-            frame.push(UndefinedValue());
-          }
-          END_CASE(JSOP_CALLLOCAL)
-
           BEGIN_CASE(JSOP_INT8)
             frame.push(Value(Int32Value(GET_INT8(PC))));
           END_CASE(JSOP_INT8)
 
           BEGIN_CASE(JSOP_INT32)
             frame.push(Value(Int32Value(GET_INT32(PC))));
           END_CASE(JSOP_INT32)
 
@@ -4385,67 +4356,47 @@ mjit::Compiler::emitStubCmpOp(BoolStub s
 
     JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE);
     Jump j = masm.branchTest32(GetStubCompareCondition(fused), Registers::ReturnReg,
                                Registers::ReturnReg);
     return jumpAndRun(j, target);
 }
 
 void
-mjit::Compiler::jsop_setprop_slow(PropertyName *name, bool usePropCache)
+mjit::Compiler::jsop_setprop_slow(PropertyName *name)
 {
     prepareStubCall(Uses(2));
     masm.move(ImmPtr(name), Registers::ArgReg1);
-    if (usePropCache)
-        INLINE_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
-    else
-        INLINE_STUBCALL(STRICT_VARIANT(stubs::SetPropNoCache), REJOIN_FALLTHROUGH);
+    INLINE_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
     JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
     frame.shimmy(1);
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 }
 
 void
-mjit::Compiler::jsop_getprop_slow(PropertyName *name, bool usePropCache)
+mjit::Compiler::jsop_getprop_slow(PropertyName *name, bool forPrototype)
 {
     /* See ::jsop_getprop */
-    RejoinState rejoin = usePropCache ? REJOIN_GETTER : REJOIN_THIS_PROTOTYPE;
+    RejoinState rejoin = forPrototype ? REJOIN_THIS_PROTOTYPE : REJOIN_GETTER;
 
     prepareStubCall(Uses(1));
-    if (usePropCache) {
-        INLINE_STUBCALL(stubs::GetProp, rejoin);
+    masm.move(ImmPtr(name), Registers::ArgReg1);
+    INLINE_STUBCALL(forPrototype ? stubs::GetPropNoCache : stubs::GetProp, rejoin);
+
+    if (!forPrototype)
         testPushedType(rejoin, -1, /* ool = */ false);
-    } else {
-        masm.move(ImmPtr(name), Registers::ArgReg1);
-        INLINE_STUBCALL(stubs::GetPropNoCache, rejoin);
-    }
 
     frame.pop();
     frame.pushSynced(JSVAL_TYPE_UNKNOWN);
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 }
 
-bool
-mjit::Compiler::jsop_callprop_slow(PropertyName *name)
-{
-    prepareStubCall(Uses(1));
-    masm.move(ImmPtr(name), Registers::ArgReg1);
-    INLINE_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
-    testPushedType(REJOIN_FALLTHROUGH, -1, /* ool = */ false);
-    frame.pop();
-    pushSyncedEntry(0);
-    pushSyncedEntry(1);
-    if (script->pcCounters)
-        bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
-    return true;
-}
-
 #ifdef JS_MONOIC
 void
 mjit::Compiler::passMICAddress(GlobalNameICInfo &ic)
 {
     ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 #endif
 
@@ -4453,27 +4404,27 @@ mjit::Compiler::passMICAddress(GlobalNam
 void
 mjit::Compiler::passICAddress(BaseICInfo *ic)
 {
     ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 
 bool
 mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType,
-                             bool doTypeCheck, bool usePropCache)
+                             bool doTypeCheck, bool forPrototype)
 {
     FrameEntry *top = frame.peek(-1);
 
     /*
      * Use a different rejoin for GETPROP computing the 'this' object, as we
      * can't use the current bytecode within InternalInterpret to tell this is
      * fetching the 'this' value.
      */
     RejoinState rejoin = REJOIN_GETTER;
-    if (!usePropCache) {
+    if (forPrototype) {
         JS_ASSERT(top->isType(JSVAL_TYPE_OBJECT) &&
                   name == cx->runtime->atomState.classPrototypeAtom);
         rejoin = REJOIN_THIS_PROTOTYPE;
     }
 
     /* Handle length accesses on known strings without using a PIC. */
     if (name == cx->runtime->atomState.lengthAtom &&
         top->isType(JSVAL_TYPE_STRING) &&
@@ -4489,25 +4440,18 @@ mjit::Compiler::jsop_getprop(PropertyNam
             masm.loadPtr(Address(str, JSString::offsetOfLengthAndFlags()), str);
             masm.urshift32(Imm32(JSString::LENGTH_SHIFT), str);
             frame.pop();
             frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
         }
         return true;
     }
 
-    /* If the incoming type will never PIC, take slow path. */
-    if (top->isNotType(JSVAL_TYPE_OBJECT)) {
-        jsop_getprop_slow(name, usePropCache);
-        return true;
-    }
-
-    frame.forgetMismatchedObject(top);
-
-    if (JSOp(*PC) == JSOP_LENGTH && cx->typeInferenceEnabled() &&
+    if (top->mightBeType(JSVAL_TYPE_OBJECT) &&
+        JSOp(*PC) == JSOP_LENGTH && cx->typeInferenceEnabled() &&
         !hasTypeBarriers(PC) && knownPushedType(0) == JSVAL_TYPE_INT32) {
         /* Check if this is an array we can make a loop invariant entry for. */
         if (loop && loop->generatingInvariants()) {
             CrossSSAValue topv(a->inlineIndex, analysis->poppedValue(PC, 0));
             FrameEntry *fe = loop->invariantLength(topv);
             if (fe) {
                 frame.learnType(fe, JSVAL_TYPE_INT32, false);
                 frame.pop();
@@ -4526,16 +4470,17 @@ mjit::Compiler::jsop_getprop(PropertyNam
          * must fit in an int32.
          */
         if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) {
             bool isObject = top->isTypeKnown();
             if (!isObject) {
                 Jump notObject = frame.testObject(Assembler::NotEqual, top);
                 stubcc.linkExit(notObject, Uses(1));
                 stubcc.leave();
+                stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
                 OOL_STUBCALL(stubs::GetProp, rejoin);
                 if (rejoin == REJOIN_GETTER)
                     testPushedType(rejoin, -1);
             }
             RegisterID result = frame.allocReg();
             RegisterID reg = frame.tempRegForData(top);
             frame.pop();
             masm.loadPtr(Address(reg, JSObject::offsetOfElements()), result);
@@ -4553,16 +4498,17 @@ mjit::Compiler::jsop_getprop(PropertyNam
          * The typed array length always fits in an int32.
          */
         if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
             bool isObject = top->isTypeKnown();
             if (!isObject) {
                 Jump notObject = frame.testObject(Assembler::NotEqual, top);
                 stubcc.linkExit(notObject, Uses(1));
                 stubcc.leave();
+                stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
                 OOL_STUBCALL(stubs::GetProp, rejoin);
                 if (rejoin == REJOIN_GETTER)
                     testPushedType(rejoin, -1);
             }
             RegisterID reg = frame.copyDataIntoReg(top);
             frame.pop();
             masm.loadPayload(Address(reg, TypedArray::lengthOffset()), reg);
             frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
@@ -4582,56 +4528,92 @@ mjit::Compiler::jsop_getprop(PropertyNam
             frame.pop();
             frame.pushWord(Address(JSFrameReg, StackFrame::offsetOfArgs()), JSVAL_TYPE_INT32);
             if (script->pcCounters)
                 bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE);
             return true;
         }
     }
 
+    /* If the access will definitely be fetching a particular value, nop it. */
+    bool testObject;
+    JSObject *singleton =
+        (*PC == JSOP_GETPROP || *PC == JSOP_CALLPROP) ? pushedSingleton(0) : NULL;
+    if (singleton && singleton->isFunction() && !hasTypeBarriers(PC) &&
+        testSingletonPropertyTypes(top, ATOM_TO_JSID(name), &testObject)) {
+        if (testObject) {
+            Jump notObject = frame.testObject(Assembler::NotEqual, top);
+            stubcc.linkExit(notObject, Uses(1));
+            stubcc.leave();
+            stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
+            OOL_STUBCALL(stubs::GetProp, REJOIN_FALLTHROUGH);
+            testPushedType(REJOIN_FALLTHROUGH, -1);
+        }
+
+        frame.pop();
+        frame.push(ObjectValue(*singleton));
+
+        if (script->pcCounters && cx->typeInferenceEnabled())
+            bumpPropCounter(PC, OpcodeCounts::PROP_STATIC);
+
+        if (testObject)
+            stubcc.rejoin(Changes(1));
+
+        return true;
+    }
+
     /* Check if this is a property access we can make a loop invariant entry for. */
     if (loop && loop->generatingInvariants() && !hasTypeBarriers(PC)) {
         CrossSSAValue topv(a->inlineIndex, analysis->poppedValue(PC, 0));
         if (FrameEntry *fe = loop->invariantProperty(topv, ATOM_TO_JSID(name))) {
             if (knownType != JSVAL_TYPE_UNKNOWN && knownType != JSVAL_TYPE_DOUBLE)
                 frame.learnType(fe, knownType, false);
             frame.pop();
             frame.pushCopyOf(fe);
             if (script->pcCounters)
                 bumpPropCounter(PC, OpcodeCounts::PROP_STATIC);
             return true;
         }
     }
 
+    /* If the incoming type will never PIC, take slow path. */
+    if (top->isNotType(JSVAL_TYPE_OBJECT)) {
+        jsop_getprop_slow(name, forPrototype);
+        return true;
+    }
+
+    frame.forgetMismatchedObject(top);
+
     /*
      * Check if we are accessing a known type which always has the property
      * in a particular inline slot. Get the property directly in this case,
      * without using an IC.
      */
     jsid id = ATOM_TO_JSID(name);
     types::TypeSet *types = frame.extra(top).types;
     if (types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties() &&
         id == types::MakeTypeId(cx, id)) {
-        JS_ASSERT(usePropCache);
+        JS_ASSERT(!forPrototype);
         types::TypeObject *object = types->getTypeObject(0);
         types::TypeSet *propertyTypes = object->getProperty(cx, id, false);
         if (!propertyTypes)
             return false;
         if (propertyTypes->isDefiniteProperty() &&
             !propertyTypes->isOwnProperty(cx, object, true)) {
             types->addFreeze(cx);
             uint32_t slot = propertyTypes->definiteSlot();
             bool isObject = top->isTypeKnown();
             if (!isObject) {
                 Jump notObject = frame.testObject(Assembler::NotEqual, top);
                 stubcc.linkExit(notObject, Uses(1));
                 stubcc.leave();
+                stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
                 OOL_STUBCALL(stubs::GetProp, rejoin);
                 if (rejoin == REJOIN_GETTER)
                     testPushedType(rejoin, -1);
             }
             RegisterID reg = frame.tempRegForData(top);
             frame.pop();
 
             if (script->pcCounters)
@@ -4642,34 +4624,36 @@ mjit::Compiler::jsop_getprop(PropertyNam
             if (!isObject)
                 stubcc.rejoin(Changes(1));
             finishBarrier(barrier, rejoin, 0);
 
             return true;
         }
     }
 
+    /* Check for a dynamic dispatch. */
+    if (cx->typeInferenceEnabled()) {
+        if (*PC == JSOP_CALLPROP && jsop_getprop_dispatch(name))
+            return true;
+    }
+
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 
     /*
      * 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 (name == cx->runtime->atomState.lengthAtom) {
-        objReg = frame.copyDataIntoReg(top);
-        shapeReg = frame.allocReg();
-    }
+    RegisterID objReg = frame.copyDataIntoReg(top);
+    RegisterID shapeReg = frame.allocReg();
 
     RESERVE_IC_SPACE(masm);
 
-    PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache);
+    PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC));
 
     /* Guard that the type is an object. */
     Label typeCheck;
     if (doTypeCheck && !top->isTypeKnown()) {
         RegisterID reg = frame.tempRegForType(top);
         pic.typeReg = reg;
 
         /* Start the hot path where it's easy to patch it. */
@@ -4681,31 +4665,26 @@ mjit::Compiler::jsop_getprop(PropertyNam
         pic.typeCheck = stubcc.linkExit(j, Uses(1));
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
         pic.hasTypeCheck = false;
         pic.typeReg = Registers::ReturnReg;
     }
 
-    if (name != cx->runtime->atomState.lengthAtom) {
-        objReg = frame.copyDataIntoReg(top);
-        shapeReg = frame.allocReg();
-    }
-
     /*
      * If this access has been on a shape with a getter hook, make preparations
      * so that we can generate a stub to call the hook directly (rather than be
      * forced to make a stub call). Sync the stack up front and kill all
      * registers so that PIC stubs can contain calls, and always generate a
      * type barrier if inference is enabled (known property types do not
      * reflect properties with getter hooks).
      */
     pic.canCallHook = pic.forcedTypeBarrier =
-        usePropCache &&
+        !forPrototype &&
         JSOp(*PC) == JSOP_GETPROP &&
         name != cx->runtime->atomState.lengthAtom &&
         analysis->getCode(PC).accessGetter;
     if (pic.canCallHook)
         frame.syncAndKillEverything();
 
     pic.shapeReg = shapeReg;
     pic.name = name;
@@ -4719,17 +4698,17 @@ mjit::Compiler::jsop_getprop(PropertyNam
                                      inlineShapeLabel, ImmPtr(NULL));
     Label inlineShapeJump = masm.label();
 
     RESERVE_OOL_SPACE(stubcc.masm);
     pic.slowPathStart = stubcc.linkExit(j, Uses(1));
 
     stubcc.leave();
     passICAddress(&pic);
-    pic.slowPathCall = OOL_STUBCALL(usePropCache ? ic::GetProp : ic::GetPropNoCache, rejoin);
+    pic.slowPathCall = OOL_STUBCALL(forPrototype ? ic::GetPropNoCache : ic::GetProp, rejoin);
     CHECK_OOL_SPACE();
     if (rejoin == REJOIN_GETTER)
         testPushedType(rejoin, -1);
 
     /* Load the base slot address. */
     Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, JSObject::offsetOfSlots()),
                                                                objReg);
 
@@ -4762,287 +4741,16 @@ mjit::Compiler::jsop_getprop(PropertyNam
     stubcc.rejoin(Changes(1));
     pics.append(pic);
 
     finishBarrier(barrier, rejoin, 0);
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop_generic(PropertyName *name)
-{
-    FrameEntry *top = frame.peek(-1);
-
-    if (script->pcCounters)
-        bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
-
-    /*
-     * 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, JSOp(*PC), true);
-
-    pic.pc = PC;
-
-    /* Guard that the type is an object. */
-    pic.typeReg = frame.copyTypeIntoReg(top);
-
-    pic.canCallHook = pic.forcedTypeBarrier = analysis->getCode(PC).accessGetter;
-    if (pic.canCallHook)
-        frame.syncAndKillEverything();
-
-    RESERVE_IC_SPACE(masm);
-
-    /* Start the hot path where it's easy to patch it. */
-    pic.fastPathStart = masm.label();
-
-    /*
-     * Guard that the value is an object. This part needs some extra gunk
-     * because the leave() after the shape guard will emit a jump from this
-     * path to the final call. We need a label in between that jump, which
-     * will be the target of patched jumps in the PIC.
-     */
-    Jump typeCheckJump = masm.testObject(Assembler::NotEqual, pic.typeReg);
-    Label typeCheck = masm.label();
-    RETURN_IF_OOM(false);
-
-    pic.typeCheck = stubcc.linkExit(typeCheckJump, Uses(1));
-    pic.hasTypeCheck = true;
-    pic.objReg = objReg;
-    pic.shapeReg = shapeReg;
-    pic.name = name;
-
-    /*
-     * Store the type and object back. Don't bother keeping them in registers,
-     * since a sync will be needed for the upcoming call.
-     */
-    uint32_t thisvSlot = frame.totalDepth();
-    Address thisv = Address(JSFrameReg, sizeof(StackFrame) + thisvSlot * sizeof(Value));
-
-#if defined JS_NUNBOX32
-    masm.storeValueFromComponents(pic.typeReg, pic.objReg, thisv);
-#elif defined JS_PUNBOX64
-    masm.orPtr(pic.objReg, pic.typeReg);
-    masm.storePtr(pic.typeReg, thisv);
-#endif
-
-    frame.freeReg(pic.typeReg);
-
-    /* Guard on shape. */
-    masm.loadShape(objReg, shapeReg);
-    pic.shapeGuard = masm.label();
-
-    DataLabelPtr inlineShapeLabel;
-    Jump j = masm.branchPtrWithPatch(Assembler::NotEqual, shapeReg,
-                                     inlineShapeLabel, ImmPtr(NULL));
-    Label inlineShapeJump = masm.label();
-
-    /* Slow path. */
-    RESERVE_OOL_SPACE(stubcc.masm);
-    pic.slowPathStart = stubcc.linkExit(j, Uses(1));
-    stubcc.leave();
-    passICAddress(&pic);
-    pic.slowPathCall = OOL_STUBCALL(ic::CallProp, REJOIN_FALLTHROUGH);
-    CHECK_OOL_SPACE();
-
-    testPushedType(REJOIN_FALLTHROUGH, -1);
-
-    /* Load the base slot address. */
-    Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, JSObject::offsetOfSlots()),
-                                                               objReg);
-
-    /* Copy the slot value to the expression stack. */
-    Address slot(objReg, 1 << 24);
-
-    Label fastValueLoad = masm.loadValueWithAddressOffsetPatch(slot, shapeReg, objReg);
-    pic.fastPathRejoin = masm.label();
-
-    RETURN_IF_OOM(false);
-
-    /*
-     * Initialize op labels. We use GetPropLabels here because we have the same patching
-     * requirements for CallProp.
-     */
-    GetPropLabels &labels = pic.getPropLabels();
-    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
-    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
-    labels.setValueLoad(masm, pic.fastPathRejoin, fastValueLoad);
-    labels.setInlineTypeJump(masm, pic.fastPathStart, typeCheck);
-    labels.setInlineShapeJump(masm, pic.shapeGuard, inlineShapeJump);
-
-    CHECK_IC_SPACE();
-
-    /* Adjust the frame. */
-    frame.pop();
-    frame.pushRegs(shapeReg, objReg, knownPushedType(0));
-    BarrierState barrier = testBarrier(pic.shapeReg, pic.objReg, false, false,
-                                       /* force = */ pic.canCallHook);
-
-    pushSyncedEntry(1);
-
-    stubcc.rejoin(Changes(2));
-    pics.append(pic);
-
-    finishBarrier(barrier, REJOIN_FALLTHROUGH, 1);
-    return true;
-}
-
-bool
-mjit::Compiler::jsop_callprop_str(PropertyName *name)
-{
-    if (!globalObj) {
-        jsop_callprop_slow(name);
-        return true;
-    }
-
-    /* Bake in String.prototype. This is safe because of compileAndGo. */
-    JSObject *obj = globalObj->getOrCreateStringPrototype(cx);
-    if (!obj)
-        return false;
-
-    /* Force into a register because getprop won't expect a constant. */
-    RegisterID reg = frame.allocReg();
-
-    masm.move(ImmPtr(obj), reg);
-    frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
-
-    /* Get the property. */
-    if (!jsop_getprop(name, knownPushedType(0)))
-        return false;
-
-    /* Perform a swap. */
-    frame.dup2();
-    frame.shift(-3);
-    frame.shift(-1);
-
-    /*
-     * See bug 584579 - need to forget string type, since wrapping could
-     * create an object. forgetType() alone is not valid because it cannot be
-     * used on copies or constants.
-     */
-    RegisterID strReg;
-    FrameEntry *strFe = frame.peek(-1);
-    if (strFe->isConstant()) {
-        strReg = frame.allocReg();
-        masm.move(ImmPtr(strFe->getValue().toString()), strReg);
-    } else {
-        strReg = frame.ownRegForData(strFe);
-    }
-    frame.pop();
-    frame.pushTypedPayload(JSVAL_TYPE_STRING, strReg);
-    frame.forgetType(frame.peek(-1));
-
-    return true;
-}
-
-bool
-mjit::Compiler::jsop_callprop_obj(PropertyName *name)
-{
-    FrameEntry *top = frame.peek(-1);
-
-    if (script->pcCounters)
-        bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
-
-    PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true);
-
-    JS_ASSERT(top->isTypeKnown());
-    JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT);
-
-    RESERVE_IC_SPACE(masm);
-
-    pic.pc = PC;
-    pic.fastPathStart = masm.label();
-    pic.hasTypeCheck = false;
-    pic.typeReg = Registers::ReturnReg;
-
-    RegisterID shapeReg = frame.allocReg();
-    pic.shapeReg = shapeReg;
-    pic.name = name;
-
-    RegisterID objReg;
-    if (top->isConstant()) {
-        objReg = frame.allocReg();
-        masm.move(ImmPtr(&top->getValue().toObject()), objReg);
-    } else {
-        objReg = frame.copyDataIntoReg(top);
-    }
-
-    pic.canCallHook = pic.forcedTypeBarrier = analysis->getCode(PC).accessGetter;
-    if (pic.canCallHook)
-        frame.syncAndKillEverything();
-
-    /* Guard on shape. */
-    masm.loadShape(objReg, shapeReg);
-    pic.shapeGuard = masm.label();
-
-    DataLabelPtr inlineShapeLabel;
-    Jump j = masm.branchPtrWithPatch(Assembler::NotEqual, shapeReg,
-                                     inlineShapeLabel, ImmPtr(NULL));
-    Label inlineShapeJump = masm.label();
-
-    /* Slow path. */
-    RESERVE_OOL_SPACE(stubcc.masm);
-    pic.slowPathStart = stubcc.linkExit(j, Uses(1));
-    stubcc.leave();
-    passICAddress(&pic);
-    pic.slowPathCall = OOL_STUBCALL(ic::CallProp, REJOIN_FALLTHROUGH);
-    CHECK_OOL_SPACE();
-
-    testPushedType(REJOIN_FALLTHROUGH, -1);
-
-    /* Load the base slot address. */
-    Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, JSObject::offsetOfSlots()),
-                                                               objReg);
-
-    /* Copy the slot value to the expression stack. */
-    Address slot(objReg, 1 << 24);
-
-    Label fastValueLoad = masm.loadValueWithAddressOffsetPatch(slot, shapeReg, objReg);
-
-    pic.fastPathRejoin = masm.label();
-    pic.objReg = objReg;
-
-    CHECK_IC_SPACE();
-
-    /*
-     * 1) Dup the |this| object.
-     * 2) Store the property value below the |this| value.
-     * This is safe as a stack transition, because JSOP_CALLPROP has
-     * JOF_TMPSLOT. It is also safe for correctness, because if we know the LHS
-     * is an object, it is the resulting vp[1].
-     */
-    frame.dup();
-    frame.storeRegs(-2, shapeReg, objReg, knownPushedType(0));
-    BarrierState barrier = testBarrier(shapeReg, objReg, false, false,
-                                       /* force = */ pic.canCallHook);
-
-    /*
-     * Assert correctness of hardcoded offsets.
-     * No type guard: type is asserted.
-     */
-    RETURN_IF_OOM(false);
-
-    GetPropLabels &labels = pic.getPropLabels();
-    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
-    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
-    labels.setValueLoad(masm, pic.fastPathRejoin, fastValueLoad);
-    labels.setInlineShapeJump(masm, pic.shapeGuard, inlineShapeJump);
-
-    stubcc.rejoin(Changes(2));
-    pics.append(pic);
-
-    finishBarrier(barrier, REJOIN_FALLTHROUGH, 1);
-    return true;
-}
-
-bool
 mjit::Compiler::testSingletonProperty(JSObject *obj, jsid id)
 {
     /*
      * We would like to completely no-op property/global accesses which can
      * produce only a particular JSObject or undefined, provided we can
      * determine the pushed value must not be undefined (or, if it could be
      * undefined, a recompilation will be triggered).
      *
@@ -5138,17 +4846,17 @@ mjit::Compiler::testSingletonPropertyTyp
     JSObject *proto;
     if (!js_GetClassPrototype(cx, globalObj, key, &proto, NULL))
         return NULL;
 
     return testSingletonProperty(proto, id);
 }
 
 bool
-mjit::Compiler::jsop_callprop_dispatch(PropertyName *name)
+mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
 {
     /*
      * Check for a CALLPROP which is a dynamic dispatch: every value it can
      * push is a singleton, and the pushed value is determined by the type of
      * the object being accessed. Return true if the CALLPROP has been fully
      * processed, false if no code was generated.
      */
     FrameEntry *top = frame.peek(-1);
@@ -5273,101 +4981,38 @@ mjit::Compiler::jsop_callprop_dispatch(P
         }
     }
 
     for (unsigned i = 0; i < rejoins.length(); i++)
         rejoins[i].linkTo(masm.label(), &masm);
 
     stubcc.leave();
     stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
-    OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
+    OOL_STUBCALL(stubs::GetProp, REJOIN_FALLTHROUGH);
     testPushedType(REJOIN_FALLTHROUGH, -1);
 
-    frame.dup();
-    // THIS THIS
-
+    frame.pop();
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, pushreg);
-    // THIS THIS FUN
-
-    frame.shift(-2);
-    // FUN THIS
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE);
 
     stubcc.rejoin(Changes(2));
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop(PropertyName *name)
-{
-    FrameEntry *top = frame.peek(-1);
-
-    /* If the CALLPROP will definitely be fetching a particular value, nop it. */
-    bool testObject;
-    JSObject *singleton = pushedSingleton(0);
-    if (singleton && singleton->isFunction() && !hasTypeBarriers(PC) &&
-        testSingletonPropertyTypes(top, ATOM_TO_JSID(name), &testObject)) {
-        if (testObject) {
-            Jump notObject = frame.testObject(Assembler::NotEqual, top);
-            stubcc.linkExit(notObject, Uses(1));
-            stubcc.leave();
-            stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
-            OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
-            testPushedType(REJOIN_FALLTHROUGH, -1);
-        }
-
-        // THIS
-
-        frame.dup();
-        // THIS THIS
-
-        frame.push(ObjectValue(*singleton));
-        // THIS THIS FUN
-
-        frame.shift(-2);
-        // FUN THIS
-
-        if (script->pcCounters && cx->typeInferenceEnabled())
-            bumpPropCounter(PC, OpcodeCounts::PROP_STATIC);
-
-        if (testObject)
-            stubcc.rejoin(Changes(2));
-
-        return true;
-    }
-
-    /* Check for a dynamic dispatch. */
-    if (cx->typeInferenceEnabled()) {
-        if (jsop_callprop_dispatch(name))
-            return true;
-    }
-
-    /* If the incoming type will never PIC, take slow path. */
-    if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
-        if (top->getKnownType() == JSVAL_TYPE_STRING)
-            return jsop_callprop_str(name);
-        return jsop_callprop_slow(name);
-    }
-
-    if (top->isTypeKnown())
-        return jsop_callprop_obj(name);
-    return jsop_callprop_generic(name);
-}
-
-bool
-mjit::Compiler::jsop_setprop(PropertyName *name, bool usePropCache, bool popGuaranteed)
+mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
 {
     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(name, usePropCache);
+        jsop_setprop_slow(name);
         return true;
     }
 
     /*
      * If this is a SETNAME to a variable of a non-reentrant outer function,
      * set the variable's slot directly for the active call object.
      */
     if (cx->typeInferenceEnabled() && js_CodeSpec[*PC].format & JOF_NAME) {
@@ -5402,17 +5047,16 @@ mjit::Compiler::jsop_setprop(PropertyNam
      */
     jsid id = ATOM_TO_JSID(name);
     types::TypeSet *types = frame.extra(lhs).types;
     if (JSOp(*PC) == JSOP_SETPROP && id == types::MakeTypeId(cx, id) &&
         types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties()) {
-        JS_ASSERT(usePropCache);
         types::TypeObject *object = types->getTypeObject(0);
         types::TypeSet *propertyTypes = object->getProperty(cx, id, false);
         if (!propertyTypes)
             return false;
         if (propertyTypes->isDefiniteProperty() &&
             !propertyTypes->isOwnProperty(cx, object, true)) {
             types->addFreeze(cx);
             uint32_t slot = propertyTypes->definiteSlot();
@@ -5452,27 +5096,27 @@ mjit::Compiler::jsop_setprop(PropertyNam
     }
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
     if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, id))) {
-        jsop_setprop_slow(name, usePropCache);
+        jsop_setprop_slow(name);
         return true;
     }
 #endif
 
     JSOp op = JSOp(*PC);
 
     ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD)
                              ? ic::PICInfo::SETMETHOD
                              : ic::PICInfo::SET;
-    PICGenInfo pic(kind, op, usePropCache);
+    PICGenInfo pic(kind, op);
     pic.name = name;
 
     if (monitored(PC)) {
         pic.typeMonitored = true;
         types::TypeSet *types = frame.extra(rhs).types;
         if (!types) {
             /* Handle FORNAME and other compound opcodes. Yuck. */
             types = types::TypeSet::make(cx, "unknownRHS");
@@ -5498,20 +5142,18 @@ mjit::Compiler::jsop_setprop(PropertyNam
         /* 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();
 
         stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
-        if (usePropCache)
-            OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
-        else
-            OOL_STUBCALL(STRICT_VARIANT(stubs::SetPropNoCache), REJOIN_FALLTHROUGH);
+        OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
+
         typeCheck = stubcc.masm.jump();
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
         pic.hasTypeCheck = false;
         pic.typeReg = Registers::ReturnReg;
     }
 
@@ -5579,62 +5221,58 @@ mjit::Compiler::jsop_setprop(PropertyNam
     labels.setInlineValueStore(masm, pic.fastPathRejoin, inlineValueStore);
     labels.setInlineShapeJump(masm, pic.shapeGuard, afterInlineShapeJump);
 
     pics.append(pic);
     return true;
 }
 
 void
-mjit::Compiler::jsop_name(PropertyName *name, JSValueType type, bool isCall)
+mjit::Compiler::jsop_name(PropertyName *name, JSValueType type)
 {
     /*
      * If this is a NAME for a variable of a non-reentrant outer function, get
      * the variable's slot directly for the active call object. We always need
      * to check for undefined, however.
      */
     if (cx->typeInferenceEnabled()) {
         ScriptAnalysis::NameAccess access =
             analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
         if (access.nesting) {
             Address address = frame.loadNameAddress(access);
             JSValueType type = knownPushedType(0);
             BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
                                                            /* testUndefined = */ true);
             finishBarrier(barrier, REJOIN_GETTER, 0);
-            if (isCall)
-                jsop_callgname_epilogue();
             return;
         }
     }
 
-    PICGenInfo pic(isCall ? ic::PICInfo::CALLNAME : ic::PICInfo::NAME, JSOp(*PC), true);
+    PICGenInfo pic(ic::PICInfo::NAME, JSOp(*PC));
 
     RESERVE_IC_SPACE(masm);
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.allocReg();
     pic.typeReg = Registers::ReturnReg;
     pic.name = name;
     pic.hasTypeCheck = false;
     pic.fastPathStart = masm.label();
 
-    RejoinState rejoin = isCall ? REJOIN_FALLTHROUGH : REJOIN_GETTER;
-
     /* There is no inline implementation, so we always jump to the slow path or to a stub. */
     pic.shapeGuard = masm.label();
     Jump inlineJump = masm.jump();
     {
         RESERVE_OOL_SPACE(stubcc.masm);
         pic.slowPathStart = stubcc.linkExit(inlineJump, Uses(0));
         stubcc.leave();
         passICAddress(&pic);
-        pic.slowPathCall = OOL_STUBCALL(isCall ? ic::CallName : ic::Name, rejoin);
+        pic.slowPathCall = OOL_STUBCALL(ic::Name, REJOIN_GETTER);
         CHECK_OOL_SPACE();
-        testPushedType(rejoin, 0);
+        testPushedType(REJOIN_GETTER, 0);
     }
     pic.fastPathRejoin = masm.label();
 
     /* Initialize op labels. */
     ScopeNameLabels &labels = pic.scopeNameLabels();
     labels.setInlineJump(masm, pic.fastPathStart, inlineJump);
 
     CHECK_IC_SPACE();
@@ -5647,25 +5285,23 @@ mjit::Compiler::jsop_name(PropertyName *
     JSObject *singleton = pushedSingleton(0);
     if (singleton) {
         frame.push(ObjectValue(*singleton));
         frame.freeReg(pic.shapeReg);
         frame.freeReg(pic.objReg);
     } else {
         frame.pushRegs(pic.shapeReg, pic.objReg, type);
     }
-    if (isCall)
-        frame.pushSynced(JSVAL_TYPE_UNKNOWN);
     BarrierState barrier = testBarrier(pic.shapeReg, pic.objReg, /* testUndefined = */ true);
 
-    stubcc.rejoin(Changes(isCall ? 2 : 1));
+    stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 
-    finishBarrier(barrier, rejoin, isCall ? 1 : 0);
+    finishBarrier(barrier, REJOIN_GETTER, 0);
 }
 
 bool
 mjit::Compiler::jsop_xname(PropertyName *name)
 {
     /*
      * If this is a GETXPROP for a variable of a non-reentrant outer function,
      * treat in the same way as a NAME.
@@ -5679,17 +5315,17 @@ mjit::Compiler::jsop_xname(PropertyName 
             JSValueType type = knownPushedType(0);
             BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
                                                            /* testUndefined = */ true);
             finishBarrier(barrier, REJOIN_GETTER, 0);
             return true;
         }
     }
 
-    PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true);
+    PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC));
 
     FrameEntry *fe = frame.peek(-1);
     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
         return jsop_getprop(name, knownPushedType(0));
     }
 
     if (!fe->isTypeKnown()) {
         Jump notObject = frame.testObject(Assembler::NotEqual, fe);
@@ -5739,17 +5375,17 @@ mjit::Compiler::jsop_xname(PropertyName 
 
     pics.append(pic);
 
     finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
     return true;
 }
 
 void
-mjit::Compiler::jsop_bindname(PropertyName *name, bool usePropCache)
+mjit::Compiler::jsop_bindname(PropertyName *name)
 {
     /*
      * If this is a BINDNAME for a variable of a non-reentrant outer function,
      * the object is definitely the outer function's active call object.
      */
     if (cx->typeInferenceEnabled()) {
         ScriptAnalysis::NameAccess access =
             analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
@@ -5758,17 +5394,17 @@ mjit::Compiler::jsop_bindname(PropertyNa
             JSObject **pobj = &access.nesting->activeCall;
             masm.move(ImmPtr(pobj), reg);
             masm.loadPtr(Address(reg), reg);
             frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
             return;
         }
     }
 
-    PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC), usePropCache);
+    PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC));
 
     // This code does not check the frame flags to see if scopeChain has been
     // set. Rather, it relies on the up-front analysis statically determining
     // whether BINDNAME can be used, which reifies the scope chain at the
     // prologue.
     JS_ASSERT(analysis->usesScopeChain());
 
     pic.shapeReg = frame.allocReg();
@@ -5826,54 +5462,44 @@ mjit::Compiler::jsop_name(PropertyName *
 bool
 mjit::Compiler::jsop_xname(PropertyName *name)
 {
     return jsop_getprop(name, knownPushedType(0), pushedTypeSet(0));
 }
 
 bool
 mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType, types::TypeSet *typeSet,
-                             bool typecheck, bool usePropCache)
+                             bool typecheck, bool forPrototype)
 {
-    jsop_getprop_slow(name, usePropCache);
+    jsop_getprop_slow(name, forPrototype);
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop(PropertyName *name)
+mjit::Compiler::jsop_setprop(PropertyName *name)
 {
-    return jsop_callprop_slow(name);
-}
-
-bool
-mjit::Compiler::jsop_setprop(PropertyName *name, bool usePropCache)
-{
-    jsop_setprop_slow(name, usePropCache);
+    jsop_setprop_slow(name);
     return true;
 }
 
 void
-mjit::Compiler::jsop_bindname(PropertyName *name, bool usePropCache)
+mjit::Compiler::jsop_bindname(PropertyName *name)
 {
     RegisterID reg = frame.allocReg();
     Address scopeChain(JSFrameReg, StackFrame::offsetOfScopeChain());
     masm.loadPtr(scopeChain, reg);
 
     Address address(reg, offsetof(JSObject, parent));
 
     Jump j = masm.branchPtr(Assembler::NotEqual, address, ImmPtr(0));
 
     stubcc.linkExit(j, Uses(0));
     stubcc.leave();
-    if (usePropCache) {
-        OOL_STUBCALL(stubs::BindName, REJOIN_FALLTHROUGH);
-    } else {
-        stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
-        OOL_STUBCALL(stubs::BindNameNoCache, REJOIN_FALLTHROUGH);
-    }
+    stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
+    OOL_STUBCALL(stubs::BindName, REJOIN_FALLTHROUGH);
 
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     stubcc.rejoin(Changes(1));
 }
 #endif
 
 void
@@ -6196,17 +5822,17 @@ mjit::Compiler::iterEnd()
 
     stubcc.rejoin(Changes(1));
 }
 
 void
 mjit::Compiler::jsop_getgname_slow(uint32_t index)
 {
     prepareStubCall(Uses(0));
-    INLINE_STUBCALL(stubs::GetGlobalName, REJOIN_GETTER);
+    INLINE_STUBCALL(stubs::Name, REJOIN_GETTER);
     testPushedType(REJOIN_GETTER, 0, /* ool = */ false);
     frame.pushSynced(JSVAL_TYPE_UNKNOWN);
 }
 
 void
 mjit::Compiler::jsop_bindgname()
 {
     if (globalObj) {
@@ -6281,18 +5907,16 @@ mjit::Compiler::jsop_getgname(uint32_t i
     FrameEntry *fe = frame.peek(-1);
     JS_ASSERT(fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_OBJECT);
 
     GetGlobalNameICInfo ic;
     RESERVE_IC_SPACE(masm);
     RegisterID objReg;
     Jump shapeGuard;
 
-    ic.usePropertyCache = true;
-
     ic.fastPathStart = masm.label();
     if (fe->isConstant()) {
         JSObject *obj = &fe->getValue().toObject();
         frame.pop();
         JS_ASSERT(obj->isNative());
 
         objReg = frame.allocReg();
 
@@ -6348,135 +5972,32 @@ mjit::Compiler::jsop_getgname(uint32_t i
     getGlobalNames.append(ic);
     finishBarrier(barrier, REJOIN_GETTER, 0);
 #else
     jsop_getgname_slow(index);
 #endif
 
 }
 
-/*
- * Generate just the epilogue code that is specific to callgname. The rest
- * is shared with getgname.
- */
 void
-mjit::Compiler::jsop_callgname_epilogue()
-{
-    /*
-     * This slow path does the same thing as the interpreter.
-     */
-    if (!globalObj) {
-        prepareStubCall(Uses(1));
-        INLINE_STUBCALL(stubs::PushImplicitThisForGlobal, REJOIN_NONE);
-        frame.pushSynced(JSVAL_TYPE_UNKNOWN);
-        return;
-    }
-
-    /* Fast path for known-not-an-object callee. */
-    FrameEntry *fval = frame.peek(-1);
-    if (fval->isNotType(JSVAL_TYPE_OBJECT)) {
-        frame.push(UndefinedValue());
-        return;
-    }
-
-    /* Paths for known object callee. */
-    if (fval->isConstant()) {
-        JSObject *obj = &fval->getValue().toObject();
-        if (&obj->global() == globalObj) {
-            frame.push(UndefinedValue());
-        } else {
-            prepareStubCall(Uses(1));
-            INLINE_STUBCALL(stubs::PushImplicitThisForGlobal, REJOIN_NONE);
-            frame.pushSynced(JSVAL_TYPE_UNKNOWN);
-        }
-        return;
-    }
-
-    /*
-     * Fast path for functions whose global is statically known to be the
-     * current global. This is primarily for calls on inner functions within
-     * nestings, whose direct parent is a call object rather than the global
-     * and which will make a stub call in the path below.
-     */
-    if (cx->typeInferenceEnabled()) {
-        types::TypeSet *types = analysis->pushedTypes(PC, 0);
-        if (types->hasGlobalObject(cx, globalObj)) {
-            frame.push(UndefinedValue());
-            return;
-        }
-    }
-
-    /*
-     * Optimized version. This inlines the common case, calling a
-     * (non-proxied) function that has the same global as the current
-     * script. To make the code simpler, we:
-     *      1. test the stronger property that the callee's parent is
-     *         equal to the global of the current script, and
-     *      2. bake in the global of the current script, which is why
-     *         this optimized path requires compile-and-go.
-     */
-
-    /* If the callee is not an object, jump to the inline fast path. */
-    MaybeRegisterID typeReg = frame.maybePinType(fval);
-    RegisterID objReg = frame.copyDataIntoReg(fval);
-    RegisterID tempReg = frame.allocReg();
-
-    MaybeJump isNotObj;
-    if (!fval->isType(JSVAL_TYPE_OBJECT)) {
-        isNotObj = frame.testObject(Assembler::NotEqual, fval);
-        frame.maybeUnpinReg(typeReg);
-    }
-
-    /*
-     * If the callee is not a function, jump to OOL slow path.
-     */
-    Jump notFunction = masm.testFunction(Assembler::NotEqual, objReg, tempReg);
-    stubcc.linkExit(notFunction, Uses(1));
-
-    /*
-     * If the callee's parent is not equal to the global, jump to
-     * OOL slow path.
-     */
-    masm.loadPtr(Address(objReg, JSFunction::offsetOfEnvironment()), objReg);
-    Jump globalMismatch = masm.branchPtr(Assembler::NotEqual, objReg, ImmPtr(globalObj));
-    stubcc.linkExit(globalMismatch, Uses(1));
-    frame.freeReg(objReg);
-    frame.freeReg(tempReg);
-
-    /* OOL stub call path. */
-    stubcc.leave();
-    OOL_STUBCALL(stubs::PushImplicitThisForGlobal, REJOIN_NONE);
-
-    /* Fast path. */
-    if (isNotObj.isSet())
-        isNotObj.getJump().linkTo(masm.label(), &masm);
-    frame.pushUntypedValue(UndefinedValue());
-
-    stubcc.rejoin(Changes(1));
-}
-
-void
-mjit::Compiler::jsop_setgname_slow(PropertyName *name, bool usePropertyCache)
+mjit::Compiler::jsop_setgname_slow(PropertyName *name)
 {
     prepareStubCall(Uses(2));
     masm.move(ImmPtr(name), Registers::ArgReg1);
-    if (usePropertyCache)
-        INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalName), REJOIN_FALLTHROUGH);
-    else
-        INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalNameNoCache), REJOIN_FALLTHROUGH);
+    INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalName), REJOIN_FALLTHROUGH);
     frame.popn(2);
     pushSyncedEntry(0);
 }
 
 void
-mjit::Compiler::jsop_setgname(PropertyName *name, bool usePropertyCache, bool popGuaranteed)
+mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
 {
     if (monitored(PC)) {
         /* Global accesses are monitored only for a few names like __proto__. */
-        jsop_setgname_slow(name, usePropertyCache);
+        jsop_setgname_slow(name);
         return;
     }
 
     jsid id = ATOM_TO_JSID(name);
     if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
         !globalObj->getType(cx)->unknownProperties()) {
         /*
          * Note: object branding is disabled when inference is enabled. With
@@ -6510,17 +6031,17 @@ mjit::Compiler::jsop_setgname(PropertyNa
             frame.freeReg(reg);
             return;
         }
     }
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
     if (cx->compartment->needsBarrier()) {
-        jsop_setgname_slow(name, usePropertyCache);
+        jsop_setgname_slow(name);
         return;
     }
 #endif
 
 #if defined JS_MONOIC
     FrameEntry *objFe = frame.peek(-2);
     FrameEntry *fe = frame.peek(-1);
     JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT);
@@ -6563,18 +6084,16 @@ mjit::Compiler::jsop_setgname(PropertyNa
 
     stubcc.leave();
     passMICAddress(ic);
     ic.slowPathCall = OOL_STUBCALL(ic::SetGlobalName, REJOIN_FALLTHROUGH);
 
     /* Garbage value. */
     uint32_t slot = 1 << 24;
 
-    ic.usePropertyCache = usePropertyCache;
-
     masm.loadPtr(Address(ic.objReg, JSObject::offsetOfSlots()), ic.objReg);
     Address address(ic.objReg, slot);
 
     if (ic.vr.isConstant()) {
         ic.store = masm.storeValueWithAddressOffsetPatch(ic.vr.value(), address);
     } else if (ic.vr.isTypeKnown()) {
         ic.store = masm.storeValueWithAddressOffsetPatch(ImmType(ic.vr.knownType()),
                                                           ic.vr.dataReg(), address);
@@ -6586,17 +6105,17 @@ mjit::Compiler::jsop_setgname(PropertyNa
     frame.unpinEntry(ic.vr);
     frame.shimmy(1);
 
     stubcc.rejoin(Changes(1));
 
     ic.fastPathRejoin = masm.label();
     setGlobalNames.append(ic);
 #else
-    jsop_setgname_slow(name, usePropertyCache);
+    jsop_setgname_slow(name);
 #endif
 }
 
 void
 mjit::Compiler::jsop_setelem_slow()
 {
     prepareStubCall(Uses(3));
     INLINE_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH);
@@ -6657,17 +6176,17 @@ mjit::Compiler::jsop_instanceof()
         firstSlow = stubcc.masm.jump();
     }
 
     frame.freeReg(tmp);
 
     /* This is sadly necessary because the error case needs the object. */
     frame.dup();
 
-    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN, false))
+    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN))
         return false;
 
     /* Primitive prototypes are invalid. */
     rhs = frame.peek(-1);
     Jump j = frame.testPrimitive(Assembler::Equal, rhs);
     stubcc.linkExit(j, Uses(3));
 
     /* Allocate registers up front, because of branchiness. */
@@ -7235,17 +6754,17 @@ mjit::Compiler::constructThis()
         stubcc.rejoin(Changes(1));
         return true;
     } while (false);
 
     // Load the callee.
     frame.pushCallee();
 
     // Get callee.prototype.
-    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN, false, false))
+    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN, false, /* forPrototype = */ true))
         return false;
 
     // 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.
     JS_ASSERT_IF(protoFe->isTypeKnown(), protoFe->isType(JSVAL_TYPE_OBJECT));
@@ -7353,27 +6872,16 @@ mjit::Compiler::jsop_tableswitch(jsbytec
         stubcc.masm.jump(Registers::ReturnReg);
     }
     frame.pop();
     return jumpAndRun(defaultCase, originalPC + defaultTarget);
 #endif
 }
 
 void
-mjit::Compiler::jsop_callelem_slow()
-{
-    prepareStubCall(Uses(2));
-    INLINE_STUBCALL(stubs::CallElem, REJOIN_FALLTHROUGH);
-    testPushedType(REJOIN_FALLTHROUGH, -2, /* ool = */ false);
-    frame.popn(2);
-    pushSyncedEntry(0);
-    pushSyncedEntry(1);
-}
-
-void
 mjit::Compiler::jsop_toid()
 {
     /* Leave integers alone, stub everything else. */
     FrameEntry *top = frame.peek(-1);
 
     if (top->isType(JSVAL_TYPE_INT32))
         return;
 
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -98,27 +98,25 @@ class Compiler : public BaseCompiler
     };
 
 #if defined JS_MONOIC
     struct GlobalNameICInfo {
         Label fastPathStart;
         Call slowPathCall;
         DataLabelPtr shape;
         DataLabelPtr addrLabel;
-        bool usePropertyCache;
 
         void copyTo(ic::GlobalNameIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) {
             to.fastPathStart = full.locationOf(fastPathStart);
 
             int offset = full.locationOf(shape) - to.fastPathStart;
             to.shapeOffset = offset;
             JS_ASSERT(to.shapeOffset == offset);
 
             to.slowPathCall = stub.locationOf(slowPathCall);
-            to.usePropertyCache = usePropertyCache;
         }
     };
 
     struct GetGlobalNameICInfo : public GlobalNameICInfo {
         Label load;
     };
 
     struct SetGlobalNameICInfo : public GlobalNameICInfo {
@@ -232,63 +230,61 @@ class Compiler : public BaseCompiler
         Jump        capacityGuard;
         Jump        shapeGuard;
         Jump        holeGuard;
         Int32Key    key;
         uint32_t    volatileMask;
     };
 
     struct PICGenInfo : public BaseICInfo {
-        PICGenInfo(ic::PICInfo::Kind kind, JSOp op, bool usePropCache)
-          : BaseICInfo(op), kind(kind), usePropCache(usePropCache), typeMonitored(false)
+        PICGenInfo(ic::PICInfo::Kind kind, JSOp op)
+          : BaseICInfo(op), kind(kind), typeMonitored(false)
         { }
         ic::PICInfo::Kind kind;
         Label typeCheck;
         RegisterID shapeReg;
         RegisterID objReg;
         RegisterID typeReg;
-        bool usePropCache;
         Label shapeGuard;
         jsbytecode *pc;
         PropertyName *name;
         bool hasTypeCheck;
         bool typeMonitored;
         types::TypeSet *rhsTypes;
         ValueRemat vr;
         union {
             ic::GetPropLabels getPropLabels_;
             ic::SetPropLabels setPropLabels_;
             ic::BindNameLabels bindNameLabels_;
             ic::ScopeNameLabels scopeNameLabels_;
         };
 
         ic::GetPropLabels &getPropLabels() {
-            JS_ASSERT(kind == ic::PICInfo::GET || kind == ic::PICInfo::CALL);
+            JS_ASSERT(kind == ic::PICInfo::GET);
             return getPropLabels_;
         }
         ic::SetPropLabels &setPropLabels() {
             JS_ASSERT(kind == ic::PICInfo::SET || kind == ic::PICInfo::SETMETHOD);
             return setPropLabels_;
         }
         ic::BindNameLabels &bindNameLabels() {
             JS_ASSERT(kind == ic::PICInfo::BIND);
             return bindNameLabels_;
         }
         ic::ScopeNameLabels &scopeNameLabels() {
-            JS_ASSERT(kind == ic::PICInfo::NAME || kind == ic::PICInfo::CALLNAME ||
+            JS_ASSERT(kind == ic::PICInfo::NAME ||
                       kind == ic::PICInfo::XNAME);
             return scopeNameLabels_;
         }
 
         void copySimpleMembersTo(ic::PICInfo &ic) {
             ic.kind = kind;
             ic.shapeReg = shapeReg;
             ic.objReg = objReg;
             ic.name = name;
-            ic.usePropCache = usePropCache;
             if (ic.isSet()) {
                 ic.u.vr = vr;
             } else if (ic.isGet()) {
                 ic.u.get.typeReg = typeReg;
                 ic.u.get.hasTypeCheck = hasTypeCheck;
             }
             ic.typeMonitored = typeMonitored;
             ic.rhsTypes = rhsTypes;
@@ -593,19 +589,19 @@ private:
      * or jump to the slow path per uses.
      */
     void tryConvertInteger(FrameEntry *fe, Uses uses);
 
     /* Opcode handlers. */
     bool jumpAndRun(Jump j, jsbytecode *target, Jump *slow = NULL, bool *trampoline = NULL);
     bool startLoop(jsbytecode *head, Jump entry, jsbytecode *entryTarget);
     bool finishLoop(jsbytecode *head);
-    void jsop_bindname(PropertyName *name, bool usePropCache);
+    void jsop_bindname(PropertyName *name);
     void jsop_setglobal(uint32_t index);
-    void jsop_getprop_slow(PropertyName *name, bool usePropCache = true);
+    void jsop_getprop_slow(PropertyName *name, bool forPrototype = false);
     void jsop_getarg(uint32_t slot);
     void jsop_setarg(uint32_t slot, bool popped);
     void jsop_this();
     void emitReturn(FrameEntry *fe);
     void emitFinalReturn(Assembler &masm);
     void loadReturnValue(Assembler *masm, FrameEntry *fe);
     void emitReturnValue(Assembler *masm, FrameEntry *fe);
     void emitInlineReturnValue(FrameEntry *fe);
@@ -617,35 +613,28 @@ private:
                                    FrameEntry *origCallee, FrameEntry *origThis,
                                    MaybeRegisterID origCalleeType, RegisterID origCalleeData,
                                    MaybeRegisterID origThisType, RegisterID origThisData,
                                    Jump *uncachedCallSlowRejoin, CallPatchInfo *uncachedCallPatch);
     bool inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &callFrameSize);
     void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
     void jsop_getgname(uint32_t index);
     void jsop_getgname_slow(uint32_t index);
-    void jsop_callgname_epilogue();
-    void jsop_setgname(PropertyName *name, bool usePropertyCache, bool popGuaranteed);
-    void jsop_setgname_slow(PropertyName *name, bool usePropertyCache);
+    void jsop_setgname(PropertyName *name, bool popGuaranteed);
+    void jsop_setgname_slow(PropertyName *name);
     void jsop_bindgname();
     void jsop_setelem_slow();
     void jsop_getelem_slow();
-    void jsop_callelem_slow();
     bool jsop_getprop(PropertyName *name, JSValueType type,
-                      bool typeCheck = true, bool usePropCache = true);
-    bool jsop_setprop(PropertyName *name, bool usePropCache, bool popGuaranteed);
-    void jsop_setprop_slow(PropertyName *name, bool usePropCache = true);
-    bool jsop_callprop_slow(PropertyName *name);
-    bool jsop_callprop(PropertyName *name);
-    bool jsop_callprop_obj(PropertyName *name);
-    bool jsop_callprop_str(PropertyName *name);
-    bool jsop_callprop_generic(PropertyName *name);
-    bool jsop_callprop_dispatch(PropertyName *name);
+                      bool typeCheck = true, bool forPrototype = false);
+    bool jsop_getprop_dispatch(PropertyName *name);
+    bool jsop_setprop(PropertyName *name, bool popGuaranteed);
+    void jsop_setprop_slow(PropertyName *name);
     bool jsop_instanceof();
-    void jsop_name(PropertyName *name, JSValueType type, bool isCall);
+    void jsop_name(PropertyName *name, JSValueType type);
     bool jsop_xname(PropertyName *name);
     void enterBlock(JSObject *obj);
     void leaveBlock();
     void emitEval(uint32_t argc);
     void jsop_arguments(RejoinState rejoin);
     bool jsop_tableswitch(jsbytecode *pc);
 
     /* Fast arithmetic. */
@@ -693,17 +682,17 @@ private:
     void jsop_initprop();
     void jsop_initelem();
     void jsop_setelem_dense();
 #ifdef JS_METHODJIT_TYPED_ARRAY
     void jsop_setelem_typed(int atype);
     void convertForTypedArray(int atype, ValueRemat *vr, bool *allocated);
 #endif
     bool jsop_setelem(bool popGuaranteed);
-    bool jsop_getelem(bool isCall);
+    bool jsop_getelem();
     void jsop_getelem_dense(bool isPacked);
     void jsop_getelem_args();
 #ifdef JS_METHODJIT_TYPED_ARRAY
     bool jsop_getelem_typed(int atype);
 #endif
     void jsop_toid();
     bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id);
     void jsop_stricteq(JSOp op);
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -2083,32 +2083,29 @@ mjit::Compiler::jsop_getelem_typed(int a
 
     finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
 
     return true;
 }
 #endif /* JS_METHODJIT_TYPED_ARRAY */
 
 bool
-mjit::Compiler::jsop_getelem(bool isCall)
+mjit::Compiler::jsop_getelem()
 {
     FrameEntry *obj = frame.peek(-2);
     FrameEntry *id = frame.peek(-1);
 
     if (!IsCacheableGetElem(obj, id)) {
-        if (isCall)
-            jsop_callelem_slow();
-        else
-            jsop_getelem_slow();
+        jsop_getelem_slow();
         return true;
     }
 
     // If the object is definitely an arguments object, a dense array or a typed array
     // we can generate code directly without using an inline cache.
-    if (cx->typeInferenceEnabled() && !id->isType(JSVAL_TYPE_STRING) && !isCall) {
+    if (cx->typeInferenceEnabled() && !id->isType(JSVAL_TYPE_STRING)) {
         types::TypeSet *types = analysis->poppedTypes(PC, 1);
         if (types->isLazyArguments(cx) && !outerScript->analysis()->modifiesArguments()) {
             // Inline arguments path.
             jsop_getelem_args();
             return true;
         }
 
         if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
@@ -2132,20 +2129,17 @@ mjit::Compiler::jsop_getelem(bool isCall
             }
         }
 #endif
     }
 
     frame.forgetMismatchedObject(obj);
 
     if (id->isType(JSVAL_TYPE_DOUBLE) || !globalObj) {
-        if (isCall)
-            jsop_callelem_slow();
-        else
-            jsop_getelem_slow();
+        jsop_getelem_slow();
         return true;
     }
 
     GetElementICInfo ic = GetElementICInfo(JSOp(*PC));
 
     // Pin the top of the stack to avoid spills, before allocating registers.
     MaybeRegisterID pinnedIdData = frame.maybePinData(id);
     MaybeRegisterID pinnedIdType = frame.maybePinType(id);
@@ -2163,24 +2157,16 @@ mjit::Compiler::jsop_getelem(bool isCall
         // that needs to change is a little code movement.
         stubcc.linkExit(guard, Uses(2));
         objTypeGuard = stubcc.masm.jump();
     }
 
     // Get a mutable register for the object. This will be the data reg.
     ic.objReg = frame.copyDataIntoReg(obj);
 
-    // For potential dense array calls, grab an extra reg to save the
-    // outgoing object.
-    MaybeRegisterID thisReg;
-    if (isCall && id->mightBeType(JSVAL_TYPE_INT32)) {
-        thisReg = frame.allocReg();
-        masm.move(ic.objReg, thisReg.reg());
-    }
-
     // Get a mutable register for pushing the result type. We kill two birds
     // with one stone by making sure, if the key type is not known, to be loaded
     // into this register. In this case it is both an input and an output.
     frame.maybeUnpinReg(pinnedIdType);
     if (id->isConstant() || id->isTypeKnown())
         ic.typeReg = frame.allocReg();
     else
         ic.typeReg = frame.copyTypeIntoReg(id);
@@ -2221,71 +2207,55 @@ mjit::Compiler::jsop_getelem(bool isCall
 
         Int32Key key = id->isConstant()
                        ? Int32Key::FromConstant(id->getValue().toInt32())
                        : Int32Key::FromRegister(ic.id.dataReg());
 
         Assembler::FastArrayLoadFails fails =
             masm.fastArrayLoad(ic.objReg, key, ic.typeReg, ic.objReg);
 
-        // Store the object back to sp[-1] for calls. This must occur after
-        // all guards because otherwise sp[-1] will be clobbered.
-        if (isCall) {
-            Address thisSlot = frame.addressOf(id);
-            masm.storeValueFromComponents(ImmType(JSVAL_TYPE_OBJECT), thisReg.reg(), thisSlot);
-            frame.freeReg(thisReg.reg());
-        }
-
         stubcc.linkExitDirect(fails.rangeCheck, ic.slowPathStart);
         stubcc.linkExitDirect(fails.holeCheck, ic.slowPathStart);
     } else {
         // The type is known to not be dense-friendly ahead of time, so always
         // fall back to a slow path.
         ic.shapeGuard = masm.jump();
         stubcc.linkExitDirect(ic.shapeGuard, ic.slowPathStart);
     }
 
     stubcc.leave();
     if (objTypeGuard.isSet())
         objTypeGuard.get().linkTo(stubcc.masm.label(), &stubcc.masm);
 #ifdef JS_POLYIC
     passICAddress(&ic);
-    if (isCall)
-        ic.slowPathCall = OOL_STUBCALL(ic::CallElement, REJOIN_FALLTHROUGH);
-    else
-        ic.slowPathCall = OOL_STUBCALL(ic::GetElement, REJOIN_FALLTHROUGH);
+    ic.slowPathCall = OOL_STUBCALL(ic::GetElement, REJOIN_FALLTHROUGH);
 #else
-    if (isCall)
-        ic.slowPathCall = OOL_STUBCALL(stubs::CallElem, REJOIN_FALLTHROUGH);
-    else
-        ic.slowPathCall = OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
+    ic.slowPathCall = OOL_STUBCALL(stubs::GetElem, REJOIN_FALLTHROUGH);
 #endif
 
     testPushedType(REJOIN_FALLTHROUGH, -2);
 
     ic.fastPathRejoin = masm.label();
     ic.forcedTypeBarrier = analysis->getCode(PC).getStringElement;
 
     CHECK_IC_SPACE();
 
     frame.popn(2);
     frame.pushRegs(ic.typeReg, ic.objReg, knownPushedType(0));
     BarrierState barrier = testBarrier(ic.typeReg, ic.objReg, false, false,
                                        /* force = */ ic.forcedTypeBarrier);
-    if (isCall)
-        frame.pushSynced(knownPushedType(1));
-
-    stubcc.rejoin(Changes(isCall ? 2 : 1));
+
+    stubcc.rejoin(Changes(1));
 
 #ifdef JS_POLYIC
     if (!getElemICs.append(ic))
         return false;
 #endif
 
-    finishBarrier(barrier, REJOIN_FALLTHROUGH, isCall ? 1 : 0);
+    finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
     return true;
 }
 
 static inline bool
 ReallySimpleStrictTest(FrameEntry *fe)
 {
     if (!fe->isTypeKnown())
         return false;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -46,25 +46,23 @@
 #include "jsnum.h"
 #include "jsxml.h"
 #include "jsbool.h"
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 #include "assembler/assembler/CodeLocation.h"
 #include "jsiter.h"
 #include "jstypes.h"
 #include "methodjit/StubCalls.h"
-#include "jspropertycache.h"
 #include "methodjit/MonoIC.h"
 #include "jsanalyze.h"
 #include "methodjit/BaseCompiler.h"
 #include "methodjit/ICRepatcher.h"
 #include "vm/Debugger.h"
 
 #include "jsinterpinlines.h"
-#include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsobjinlines.h"
 #include "jscntxtinlines.h"
 #include "jsatominlines.h"
 #include "StubCalls-inl.h"
 #include "MethodJIT-inl.h"
 
@@ -857,35 +855,20 @@ js_InternalInterpret(void *returnData, v
         break;
 
       case REJOIN_NATIVE:
       case REJOIN_NATIVE_LOWERED:
       case REJOIN_NATIVE_GETTER: {
         /*
          * We don't rejoin until after the native stub finishes execution, in
          * which case the return value will be in memory. For lowered natives,
-         * the return value will be in the 'this' value's slot. For getters,
-         * the result is at nextsp[0] (see ic::CallProp).
+         * the return value will be in the 'this' value's slot.
          */
-        if (rejoin == REJOIN_NATIVE_LOWERED) {
+        if (rejoin != REJOIN_NATIVE)
             nextsp[-1] = nextsp[0];
-        } else if (rejoin == REJOIN_NATIVE_GETTER) {
-            if (js_CodeSpec[op].format & JOF_CALLOP) {
-                /*
-                 * If we went through jsop_callprop_obj then the 'this' value
-                 * is still in its original slot and hasn't been shifted yet,
-                 * so fix that now. Yuck.
-                 */
-                if (nextsp[-2].isObject())
-                    nextsp[-1] = nextsp[-2];
-                nextsp[-2] = nextsp[0];
-            } else {
-                nextsp[-1] = nextsp[0];
-            }
-        }
 
         /* Release this reference on the orphaned native stub. */
         RemoveOrphanedNative(cx, fp);
 
         f.regs.pc = nextpc;
         break;
       }
 
@@ -1024,69 +1007,34 @@ js_InternalInterpret(void *returnData, v
       }
 
       case REJOIN_GETTER:
         /*
          * Match the PC to figure out whether this property fetch is part of a
          * fused opcode which needs to be finished.
          */
         switch (op) {
-          case JSOP_NAME:
-          case JSOP_GETGNAME:
-          case JSOP_GETFCSLOT:
-          case JSOP_GETPROP:
-          case JSOP_GETXPROP:
-          case JSOP_LENGTH:
-            /* Non-fused opcode, state is already correct for the next op. */
-            f.regs.pc = nextpc;
-            break;
-
-          case JSOP_CALLGNAME:
-          case JSOP_CALLNAME:
-            if (!ComputeImplicitThis(cx, &fp->scopeChain(), nextsp[-2], &nextsp[-1]))
-                return js_InternalThrow(f);
-            f.regs.pc = nextpc;
-            break;
-
-          case JSOP_CALLFCSLOT:
-            /* |this| is always undefined for CALLGLOBAL/CALLFCSLOT. */
-            nextsp[-1].setUndefined();
-            f.regs.pc = nextpc;
-            break;
-
-          case JSOP_CALLPROP: {
-            /*
-             * CALLPROP is compiled in terms of GETPROP for known strings.
-             * In such cases the top two entries are in place, but are swapped.
-             */
-            JS_ASSERT(nextsp[-2].isString());
-            Value tmp = nextsp[-2];
-            nextsp[-2] = nextsp[-1];
-            nextsp[-1] = tmp;
-            f.regs.pc = nextpc;
-            break;
-          }
-
           case JSOP_INSTANCEOF: {
             /*
              * If we recompiled from a getprop used within JSOP_INSTANCEOF,
              * the stack looks like 'LHS RHS protov'. Inline the remaining
              * portion of fun_hasInstance.
              */
             if (f.regs.sp[0].isPrimitive()) {
                 js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, f.regs.sp[-1], NULL);
                 return js_InternalThrow(f);
             }
             nextsp[-1].setBoolean(js_IsDelegate(cx, &f.regs.sp[0].toObject(), f.regs.sp[-2]));
             f.regs.pc = nextpc;
             break;
           }
 
           default:
-            JS_NOT_REACHED("Bad rejoin getter op");
+            f.regs.pc = nextpc;
+            break;
         }
         break;
 
       case REJOIN_POS:
         /* Convert-to-number which might be part of an INC* op. */
         JS_ASSERT(op == JSOP_POS);
         f.regs.pc = nextpc;
         break;
@@ -1131,20 +1079,18 @@ js_InternalInterpret(void *returnData, v
         nextDepth = analysis->getCode(f.regs.pc).stackDepth;
     f.regs.sp = fp->base() + nextDepth;
 
     /*
      * Monitor the result of the previous op when finishing a JOF_TYPESET op.
      * The result may not have been marked if we bailed out while inside a stub
      * for the op.
      */
-    if (f.regs.pc == nextpc && (js_CodeSpec[op].format & JOF_TYPESET)) {
-        int which = (js_CodeSpec[op].format & JOF_CALLOP) ? -2 : -1;  /* Yuck. */
-        types::TypeScript::Monitor(cx, script, pc, f.regs.sp[which]);
-    }
+    if (f.regs.pc == nextpc && (js_CodeSpec[op].format & JOF_TYPESET))
+        types::TypeScript::Monitor(cx, script, pc, f.regs.sp[-1]);
 
     /* Mark the entry frame as unfinished, and update the regs to resume at. */
     JaegerStatus status = skipTrap ? Jaeger_UnfinishedAtTrap : Jaeger_Unfinished;
     cx->compartment->jaegerCompartment()->setLastUnfinished(status);
     *f.oldregs = f.regs;
 
     return NULL;
 }
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1358,19 +1358,16 @@ mjit::ProfileStubCall(VMFrame &f)
 
 #ifdef JS_POLYIC
 static int
 PICPCComparator(const void *key, const void *entry)
 {
     const jsbytecode *pc = (const jsbytecode *)key;
     const ic::PICInfo *pic = (const ic::PICInfo *)entry;
 
-    if (ic::PICInfo::CALL != pic->kind)
-        return ic::PICInfo::CALL - pic->kind;
-
     /*
      * We can't just return |pc - pic->pc| because the pointers may be
      * far apart and an int (or even a ptrdiff_t) may not be large
      * enough to hold the difference. C says that pointer subtraction
      * is only guaranteed to work for two pointers into the same array.
      */
     if (pc < pic->pc)
         return -1;
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -74,87 +74,75 @@ typedef JSC::MacroAssembler::DataLabel32
 typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
 
 #if defined JS_MONOIC
 
 static void
 PatchGetFallback(VMFrame &f, ic::GetGlobalNameIC *ic)
 {
     Repatcher repatch(f.jit());
-    JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stubs::GetGlobalName));
+    JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stubs::Name));
     repatch.relink(ic->slowPathCall, fptr);
 }
 
 void JS_FASTCALL
 ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
 {
     JSObject &obj = f.fp()->scopeChain().global();
     PropertyName *name = f.script()->getName(GET_INDEX(f.pc()));
 
     RecompilationMonitor monitor(f.cx);
 
     const Shape *shape = obj.nativeLookup(f.cx, js_CheckForStringIndex(ATOM_TO_JSID(name)));
 
     if (monitor.recompiled()) {
-        stubs::GetGlobalName(f);
+        stubs::Name(f);
         return;
     }
 
     if (!shape ||
         !shape->hasDefaultGetterOrIsMethod() ||
         !shape->hasSlot())
     {
         if (shape)
             PatchGetFallback(f, ic);
-        stubs::GetGlobalName(f);
+        stubs::Name(f);
         return;
     }
     uint32_t slot = shape->slot();
 
     /* Patch shape guard. */
     Repatcher repatcher(f.jit());
     repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj.lastProperty());
 
     /* Patch loads. */
     uint32_t index = obj.dynamicSlotIndex(slot);
     JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
     repatcher.patchAddressOffsetForValueLoad(label, index * sizeof(Value));
 
     /* Do load anyway... this time. */
-    stubs::GetGlobalName(f);
+    stubs::Name(f);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetGlobal(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
     stubs::SetGlobalName<strict>(f, f.script()->getName(GET_INDEX(f.pc())));
 }
 
 template void JS_FASTCALL DisabledSetGlobal<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
 template void JS_FASTCALL DisabledSetGlobal<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
 
-template <JSBool strict>
-static void JS_FASTCALL
-DisabledSetGlobalNoCache(VMFrame &f, ic::SetGlobalNameIC *ic)
-{
-    stubs::SetGlobalNameNoCache<strict>(f, f.script()->getName(GET_INDEX(f.pc())));
-}
-
-template void JS_FASTCALL DisabledSetGlobalNoCache<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
-template void JS_FASTCALL DisabledSetGlobalNoCache<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
-
 static void
 PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
     JSScript *script = f.script();
     Repatcher repatch(f.jit());
-    VoidStubSetGlobal stub = ic->usePropertyCache
-                             ? STRICT_VARIANT(DisabledSetGlobal)
-                             : STRICT_VARIANT(DisabledSetGlobalNoCache);
+    VoidStubSetGlobal stub = STRICT_VARIANT(DisabledSetGlobal);
     JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stub));
     repatch.relink(ic->slowPathCall, fptr);
 }
 
 void
 SetGlobalNameIC::patchExtraShapeGuard(Repatcher &repatcher, const Shape *shape)
 {
     JS_ASSERT(hasExtraStub);
@@ -212,20 +200,17 @@ ic::SetGlobalName(VMFrame &f, ic::SetGlo
     const Shape *shape = obj.nativeLookup(f.cx, ATOM_TO_JSID(name));
 
     if (!monitor.recompiled()) {
         LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape);
         if (status == Lookup_Error)
             THROW();
     }
 
-    if (ic->usePropertyCache)
-        STRICT_VARIANT(stubs::SetGlobalName)(f, name);
-    else
-        STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, name);
+    STRICT_VARIANT(stubs::SetGlobalName)(f, name);
 }
 
 class EqualityICLinker : public LinkerHelper
 {
     VMFrame &f;
 
   public:
     EqualityICLinker(Assembler &masm, VMFrame &f)
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -123,17 +123,16 @@ struct GlobalNameIC
      *   on x64 it points to the instruction after it.
      * - For x86, the label "load" points to the start of the load/store
      *   sequence, which may consist of one or two "mov" instructions. Because
      *   of this, x86 is the only platform which requires non-trivial patching
      *   code.
      */
     int32_t loadStoreOffset   : 15;
     int32_t shapeOffset       : 15;
-    bool usePropertyCache   : 1;
 };
 
 struct GetGlobalNameIC : public GlobalNameIC
 {
 };
 
 struct SetGlobalNameIC : public GlobalNameIC
 {
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -44,18 +44,16 @@
 #include "assembler/assembler/LinkBuffer.h"
 #include "TypedArrayIC.h"
 #include "jsscope.h"
 #include "jsnum.h"
 #include "jstypedarray.h"
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
-#include "jspropertycache.h"
-#include "jspropertycacheinlines.h"
 #include "jsinterpinlines.h"
 #include "jsautooplen.h"
 
 #include "vm/ScopeObject-inl.h"
 
 #if defined JS_POLYIC
 
 using namespace js;
@@ -108,22 +106,16 @@ class PICStubCompiler : public BaseCompi
   public:
     bool canCallHook;
 
     PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic, void *stub)
       : BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic), stub(stub),
         gcNumber(f.cx->runtime->gcNumber), canCallHook(pic.canCallHook)
     { }
 
-    bool isCallOp() const {
-        if (pic.kind == ic::PICInfo::CALL)
-            return true;
-        return !!(js_CodeSpec[pic.op].format & JOF_CALLOP);
-    }
-
     LookupStatus error() {
         /*
          * N.B. Do not try to disable the IC, we do not want to guard on
          * whether the IC has been recompiled when propagating errors.
          */
         return Lookup_Error;
     }
 
@@ -779,17 +771,17 @@ struct GetPropHelper {
             return ic.disable(cx, "non-native holder");
         shape = (const Shape *)prop;
         return Lookup_Cacheable;
     }
 
     LookupStatus testForGet() {
         if (!shape->hasDefaultGetter()) {
             if (shape->isMethod()) {
-                if (!ic.isCallOp())
+                if (JSOp(*f.pc()) != JSOP_CALLPROP)
                     return ic.disable(cx, "method valued shape");
             } else {
                 if (shape->hasGetterValue())
                     return ic.disable(cx, "getter value shape");
                 if (shape->hasSlot() && holder != obj)
                     return ic.disable(cx, "slotful getter hook through prototype");
                 if (!ic.canCallHook)
                     return ic.disable(cx, "can't call getter hook");
@@ -822,19 +814,19 @@ struct GetPropHelper {
 
 class GetPropCompiler : public PICStubCompiler
 {
     JSObject    *obj;
     PropertyName *name;
     int         lastStubSecondShapeGuard;
 
   public:
-    GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic,
-                    PropertyName *name, VoidStubPIC stub)
-      : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic,
+    GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, PropertyName *name,
+                    VoidStubPIC stub)
+      : PICStubCompiler("getprop", f, script, pic,
                         JS_FUNC_TO_DATA_PTR(void *, stub)),
         obj(obj),
         name(name),
         lastStubSecondShapeGuard(pic.secondShapeGuard)
     { }
 
     int getLastStubSecondShapeGuard() const {
         return lastStubSecondShapeGuard ? POST_INST_OFFSET(lastStubSecondShapeGuard) : 0;
@@ -847,30 +839,19 @@ class GetPropCompiler : public PICStubCo
         repatcher.repatch(labels.getInlineShapeData(pic.getFastShapeGuard()), NULL);
         repatcher.relink(labels.getInlineShapeJump(pic.getFastShapeGuard()), pic.slowPathStart);
 
         if (pic.hasTypeCheck()) {
             /* TODO: combine pic.u.get into ICLabels? */
             repatcher.relink(labels.getInlineTypeJump(pic.fastPathStart), pic.getSlowTypeCheck());
         }
 
-        VoidStubPIC stub;
-        switch (pic.kind) {
-          case ic::PICInfo::GET:
-            stub = ic::GetProp;
-            break;
-          case ic::PICInfo::CALL:
-            stub = ic::CallProp;
-            break;
-          default:
-            JS_NOT_REACHED("invalid pic kind for GetPropCompiler::reset");
-            return;
-        }
-
-        FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, stub));
+        JS_ASSERT(pic.kind == ic::PICInfo::GET);
+
+        FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetProp));
         repatcher.relink(pic.slowPathCall, target);
     }
 
     LookupStatus generateArgsLengthStub()
     {
         Assembler masm;
 
         Jump notArgs = masm.guardShape(pic.objReg, obj);
@@ -983,24 +964,30 @@ class GetPropCompiler : public PICStubCo
 
         patchPreviousToHere(start);
 
         disable("string object length done");
 
         return Lookup_Cacheable;
     }
 
-    LookupStatus generateStringCallStub()
+    LookupStatus generateStringPropertyStub()
     {
-        JS_ASSERT(pic.hasTypeCheck());
-        JS_ASSERT(pic.kind == ic::PICInfo::CALL);
-
         if (!f.fp()->script()->hasGlobal())
             return disable("String.prototype without compile-and-go global");
 
+        RecompilationMonitor monitor(f.cx);
+
+        JSObject *obj = f.fp()->scopeChain().global().getOrCreateStringPrototype(f.cx);
+        if (!obj)
+            return error();
+
+        if (monitor.recompiled())
+            return Lookup_Uncacheable;
+
         GetPropHelper<GetPropCompiler> getprop(cx, obj, name, *this, f);
         LookupStatus status = getprop.lookupAndTest();
         if (status != Lookup_Cacheable)
             return status;
         if (getprop.obj != getprop.holder)
             return disable("proto walk on String.prototype");
         if (!getprop.shape->hasDefaultGetterOrIsMethod())
             return disable("getter hook on String.prototype");
@@ -1009,28 +996,16 @@ class GetPropCompiler : public PICStubCo
 
         Assembler masm;
 
         /* Only strings are allowed. */
         Jump notString = masm.branchPtr(Assembler::NotEqual, pic.typeReg(),
                                         ImmType(JSVAL_TYPE_STRING));
 
         /*
-         * Sink pic.objReg, since we're about to lose it.
-         *
-         * Note: This is really hacky, and relies on f.regs.sp being set
-         * correctly in ic::CallProp. Should we just move the store higher
-         * up in the fast path, or put this offset in PICInfo?
-         */
-        uint32_t thisvOffset = uint32_t(f.regs.sp - f.fp()->slots()) - 1;
-        Address thisv(JSFrameReg, sizeof(StackFrame) + thisvOffset * sizeof(Value));
-        masm.storeValueFromComponents(ImmType(JSVAL_TYPE_STRING),
-                                      pic.objReg, thisv);
-
-        /*
          * Clobber objReg with String.prototype and do some PIC stuff. Well,
          * really this is now a MIC, except it won't ever be patched, so we
          * just disable the PIC at the end. :FIXME:? String.prototype probably
          * does not get random shape changes.
          */
         masm.move(ImmPtr(obj), pic.objReg);
         masm.loadShape(pic.objReg, pic.shapeReg);
         Jump shapeMismatch = masm.branchPtr(Assembler::NotEqual, pic.shapeReg,
@@ -1061,17 +1036,16 @@ class GetPropCompiler : public PICStubCo
         /* Patch the type check to jump here. */
         if (pic.hasTypeCheck()) {
             Repatcher repatcher(f.jit());
             repatcher.relink(pic.getPropLabels().getInlineTypeJump(pic.fastPathStart), cs);
         }
 
         /* Disable the PIC so we don't keep generating stubs on the above shape mismatch. */
         disable("generated string call stub");
-
         return Lookup_Cacheable;
     }
 
     LookupStatus generateStringLengthStub()
     {
         JS_ASSERT(pic.hasTypeCheck());
 
         Assembler masm;
@@ -1467,66 +1441,51 @@ class ScopeNameCompiler : public PICStub
         VoidStubPIC stub;
         switch (pic.kind) {
           case ic::PICInfo::NAME:
             stub = ic::Name;
             break;
           case ic::PICInfo::XNAME:
             stub = ic::XName;
             break;
-          case ic::PICInfo::CALLNAME:
-            stub = ic::CallName;
-            break;
           default:
             JS_NOT_REACHED("Invalid pic kind in ScopeNameCompiler::reset");
             return;
         }
         FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, stub));
         repatcher.relink(pic.slowPathCall, target);
     }
 
     LookupStatus generateGlobalStub(JSObject *obj)
     {
         Assembler masm;
         JumpList fails(cx);
         ScopeNameLabels &labels = pic.scopeNameLabels();
 
         /* For GETXPROP, the object is already in objReg. */
-        if (pic.kind == ic::PICInfo::NAME || pic.kind == ic::PICInfo::CALLNAME)
+        if (pic.kind == ic::PICInfo::NAME)
             masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
 
         JS_ASSERT(obj == getprop.holder);
         JS_ASSERT(getprop.holder == &scopeChain->global());
 
         LookupStatus status = walkScopeChain(masm, fails);
         if (status != Lookup_Cacheable)
             return status;
 
         /* If a scope chain walk was required, the final object needs a NULL test. */
         MaybeJump finalNull;
-        if (pic.kind == ic::PICInfo::NAME || pic.kind == ic::PICInfo::CALLNAME)
+        if (pic.kind == ic::PICInfo::NAME)
             finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg);
         masm.loadShape(pic.objReg, pic.shapeReg);
         Jump finalShape = masm.branchPtr(Assembler::NotEqual, pic.shapeReg,
                                          ImmPtr(getprop.holder->lastProperty()));
 
         masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg);
 
-        /*
-         * For CALLNAME we must store undefined as the this-value. A non-strict
-         * mode callee function replaces undefined with its global on demand in
-         * code generated for JSOP_THIS.
-         */
-        if (pic.kind == ic::PICInfo::CALLNAME) {
-            /* Store undefined this-value. */
-            Value *thisVp = &cx->regs().sp[1];
-            Address thisSlot(JSFrameReg, StackFrame::offsetOfFixed(thisVp - cx->fp()->slots()));
-            masm.storeValue(UndefinedValue(), thisSlot);
-        }
-
         Jump done = masm.jump();
 
         /* All failures flow to here, so there is a common point to patch. */
         for (Jump *pj = fails.begin(); pj != fails.end(); ++pj)
             pj->linkTo(masm.label(), &masm);
         if (finalNull.isSet())
             finalNull.get().linkTo(masm.label(), &masm);
         finalShape.linkTo(masm.label(), &masm);
@@ -1569,17 +1528,17 @@ class ScopeNameCompiler : public PICStub
 
     LookupStatus generateCallStub(JSObject *obj)
     {
         Assembler masm;
         Vector<Jump, 8> fails(cx);
         ScopeNameLabels &labels = pic.scopeNameLabels();
 
         /* For GETXPROP, the object is already in objReg. */
-        if (pic.kind == ic::PICInfo::NAME || pic.kind == ic::PICInfo::CALLNAME)
+        if (pic.kind == ic::PICInfo::NAME)
             masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
 
         JS_ASSERT(obj == getprop.holder);
         JS_ASSERT(getprop.holder != &scopeChain->global());
 
         CallObjPropKind kind;
         const Shape *shape = getprop.shape;
         if (shape->getterOp() == GetCallArg) {
@@ -1591,34 +1550,22 @@ class ScopeNameCompiler : public PICStub
         }
 
         LookupStatus status = walkScopeChain(masm, fails);
         if (status != Lookup_Cacheable)
             return status;
 
         /* If a scope chain walk was required, the final object needs a NULL test. */
         MaybeJump finalNull;
-        if (pic.kind == ic::PICInfo::NAME || pic.kind == ic::PICInfo::CALLNAME)
+        if (pic.kind == ic::PICInfo::NAME)
             finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg);
         masm.loadShape(pic.objReg, pic.shapeReg);
         Jump finalShape = masm.branchPtr(Assembler::NotEqual, pic.shapeReg,
                                          ImmPtr(getprop.holder->lastProperty()));
 
-        /*
-         * For CALLNAME we have to store the this-value. Since we guarded on
-         * IsCacheableNonGlobalScope it's always undefined. This matches the decision
-         * tree in ComputeImplicitThis.
-         */
-        if (pic.kind == ic::PICInfo::CALLNAME) {
-            JS_ASSERT(obj->isCall());
-            Value *thisVp = &cx->regs().sp[1];
-            Address thisSlot(JSFrameReg, StackFrame::offsetOfFixed(thisVp - cx->fp()->slots()));
-            masm.storeValue(UndefinedValue(), thisSlot);
-        }
-
         /* Get callobj's stack frame. */
         masm.loadObjPrivate(pic.objReg, pic.shapeReg, getprop.holder->numFixedSlots());
 
         JSFunction *fun = getprop.holder->asCall().getCalleeFunction();
         uint16_t slot = uint16_t(shape->shortid());
 
         Jump skipOver;
         Jump escapedFrame = masm.branchTestPtr(Assembler::Zero, pic.shapeReg, pic.shapeReg);
@@ -1719,17 +1666,17 @@ class ScopeNameCompiler : public PICStub
             return status;
 
         if (obj->isGlobal())
             return generateGlobalStub(obj);
 
         return disable("scope object not handled yet");
     }
 
-    bool retrieve(Value *vp, Value *thisvp, PICInfo::Kind kind)
+    bool retrieve(Value *vp, PICInfo::Kind kind)
     {
         JSObject *obj = getprop.obj;
         JSObject *holder = getprop.holder;
         const JSProperty *prop = getprop.prop;
 
         if (!prop) {
             /* Kludge to allow (typeof foo == "undefined") tests. */
             if (kind == ic::PICInfo::NAME) {
@@ -1743,28 +1690,24 @@ class ScopeNameCompiler : public PICStub
             return false;
         }
 
         // If the property was found, but we decided not to cache it, then
         // take a slow path and do a full property fetch.
         if (!getprop.shape) {
             if (!obj->getProperty(cx, name, vp))
                 return false;
-            if (thisvp)
-                return ComputeImplicitThis(cx, obj, *vp, thisvp);
             return true;
         }
 
         const Shape *shape = getprop.shape;
         JSObject *normalized = obj;
         if (obj->isWith() && !shape->hasDefaultGetter())
             normalized = &obj->asWith().object();
         NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false);
-        if (thisvp)
-            return ComputeImplicitThis(cx, normalized, *vp, thisvp);
         return true;
     }
 };
 
 class BindNameCompiler : public PICStubCompiler
 {
     JSObject *scopeChain;
     PropertyName *name;
@@ -1887,52 +1830,32 @@ class BindNameCompiler : public PICStubC
         LookupStatus status = generateStub(obj);
         if (status == Lookup_Error)
             return NULL;
 
         return obj;
     }
 };
 
-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->name);
-}
-
-void JS_FASTCALL
-ic::GetProp(VMFrame &f, ic::PICInfo *pic)
+static inline void
+GetPropWithStub(VMFrame &f, ic::PICInfo *pic, VoidStubPIC stub)
 {
     JSScript *script = f.fp()->script();
 
     PropertyName *name = pic->name;
     if (name == f.cx->runtime->atomState.lengthAtom) {
-        if (f.regs.sp[-1].isString()) {
-            GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledGetPropIC);
-            LookupStatus status = cc.generateStringLengthStub();
-            if (status == Lookup_Error)
-                THROW();
-            JSString *str = f.regs.sp[-1].toString();
-            f.regs.sp[-1].setInt32(str->length());
-            return;
-        } else if (f.regs.sp[-1].isMagic(JS_LAZY_ARGUMENTS)) {
+        if (f.regs.sp[-1].isMagic(JS_LAZY_ARGUMENTS)) {
             f.regs.sp[-1].setInt32(f.regs.fp()->numActualArgs());
             return;
         } else if (!f.regs.sp[-1].isPrimitive()) {
             JSObject *obj = &f.regs.sp[-1].toObject();
             if (obj->isArray() ||
                 (obj->isArguments() && !obj->asArguments().hasOverriddenLength()) ||
                 obj->isString()) {
-                GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledGetPropIC);
+                GetPropCompiler cc(f, script, obj, *pic, NULL, stub);
                 if (obj->isArray()) {
                     LookupStatus status = cc.generateArrayLengthStub();
                     if (status == Lookup_Error)
                         THROW();
                     f.regs.sp[-1].setNumber(obj->getArrayLength());
                 } else if (obj->isArguments()) {
                     LookupStatus status = cc.generateArgsLengthStub();
                     if (status == Lookup_Error)
@@ -1943,231 +1866,129 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
                     if (status == Lookup_Error)
                         THROW();
                     JSString *str = obj->getPrimitiveThis().toString();
                     f.regs.sp[-1].setInt32(str->length());
                 }
                 return;
             }
         }
-        name = f.cx->runtime->atomState.lengthAtom;
     }
 
-    /*
-     * ValueToObject can trigger recompilations if it lazily initializes any
-     * of the primitive classes (Boolean, Number, String). :XXX: if these
-     * classes are made eager then this monitoring is not necessary.
-     */
+    if (f.regs.sp[-1].isString()) {
+        GetPropCompiler cc(f, script, NULL, *pic, name, stub);
+        if (name == f.cx->runtime->atomState.lengthAtom) {
+            LookupStatus status = cc.generateStringLengthStub();
+            if (status == Lookup_Error)
+                THROW();
+            JSString *str = f.regs.sp[-1].toString();
+            f.regs.sp[-1].setInt32(str->length());
+        } else {
+            LookupStatus status = cc.generateStringPropertyStub();
+            if (status == Lookup_Error)
+                THROW();
+            JSObject *obj = ValueToObject(f.cx, f.regs.sp[-1]);
+            if (!obj)
+                THROW();
+            if (!obj->getProperty(f.cx, name, &f.regs.sp[-1]))
+                THROW();
+        }
+        return;
+    }
+
     RecompilationMonitor monitor(f.cx);
 
-    JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-1]);
+    JSObject *obj = ValueToObject(f.cx, f.regs.sp[-1]);
     if (!obj)
         THROW();
 
     if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
-        VoidStubPIC stub = pic->usePropCache
-                           ? DisabledGetPropIC
-                           : DisabledGetPropICNoCache;
         GetPropCompiler cc(f, script, obj, *pic, name, stub);
         if (!cc.update())
             THROW();
     }
 
     Value v;
-    if (!obj->getProperty(f.cx, name, &v))
+    if (!GetPropertyGenericMaybeCallXML(f.cx, JSOp(*f.pc()), obj, ATOM_TO_JSID(name), &v))
         THROW();
 
     f.regs.sp[-1] = v;
 }
 
+static void JS_FASTCALL
+DisabledGetPropIC(VMFrame &f, ic::PICInfo *pic)
+{
+    stubs::GetProp(f, pic->name);
+}
+
+static void JS_FASTCALL
+DisabledGetPropNoCacheIC(VMFrame &f, ic::PICInfo *pic)
+{
+    stubs::GetPropNoCache(f, pic->name);
+}
+
+void JS_FASTCALL
+ic::GetProp(VMFrame &f, ic::PICInfo *pic)
+{
+    GetPropWithStub(f, pic, DisabledGetPropIC);
+}
+
 void JS_FASTCALL
 ic::GetPropNoCache(VMFrame &f, ic::PICInfo *pic)
 {
-    /*
-     * The PIC stores whether to use the property cache or not. We use two different
-     * stub calls so we can distinguish uncached calls made to construct this from
-     * any cached calls at the first opcode in a script.
-     */
-    GetProp(f, pic);
+    GetPropWithStub(f, pic, DisabledGetPropNoCacheIC);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::SetName<strict>(f, pic->name);
 }
 
-template <JSBool strict>
-static void JS_FASTCALL
-DisabledSetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::SetPropNoCache<strict>(f, pic->name);
-}
-
 void JS_FASTCALL
 ic::SetProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
     JS_ASSERT(pic->isSet());
 
-    VoidStubPIC stub = pic->usePropCache
-                       ? STRICT_VARIANT(DisabledSetPropIC)
-                       : STRICT_VARIANT(DisabledSetPropICNoCache);
+    VoidStubPIC stub = STRICT_VARIANT(DisabledSetPropIC);
 
     // Save this in case the compiler triggers a recompilation of this script.
     PropertyName *name = pic->name;
-    VoidStubName nstub = pic->usePropCache
-                         ? STRICT_VARIANT(stubs::SetName)
-                         : STRICT_VARIANT(stubs::SetPropNoCache);
+    VoidStubName nstub = STRICT_VARIANT(stubs::SetName);
 
     RecompilationMonitor monitor(f.cx);
 
-    JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
+    JSObject *obj = ValueToObject(f.cx, f.regs.sp[-2]);
     if (!obj)
         THROW();
 
     // 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.
     if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
         SetPropCompiler cc(f, script, obj, *pic, name, stub);
         LookupStatus status = cc.update();
         if (status == Lookup_Error)
             THROW();
     }
 
     nstub(f, name);
 }
 
 static void JS_FASTCALL
-DisabledCallPropIC(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::CallProp(f, pic->name);
-}
-
-void JS_FASTCALL
-ic::CallProp(VMFrame &f, ic::PICInfo *pic)
-{
-    JSContext *cx = f.cx;
-    FrameRegs &regs = f.regs;
-
-    JSScript *script = f.fp()->script();
-    RecompilationMonitor monitor(cx);
-
-    Value lval;
-    lval = regs.sp[-1];
-
-    // Do this first in case js_GetClassPrototype triggers a recompilation.
-    PropertyName *name = pic->name;
-
-    Value objv;
-    if (lval.isObject()) {
-        objv = lval;
-    } else {
-        GlobalObject &global = f.fp()->scopeChain().global();
-        JSObject *pobj;
-        if (lval.isString()) {
-            pobj = global.getOrCreateStringPrototype(cx);
-        } else if (lval.isNumber()) {
-            pobj = global.getOrCreateNumberPrototype(cx);
-        } else if (lval.isBoolean()) {
-            pobj = global.getOrCreateBooleanPrototype(cx);
-        } else {
-            JS_ASSERT(lval.isNull() || lval.isUndefined());
-            js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
-            THROW();
-        }
-        if (!pobj)
-            THROW();
-        objv.setObject(*pobj);
-    }
-
-    JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
-    Value rval;
-
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name_;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name_);
-    if (!name_) {
-        NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval,
-                   THROW());
-        /*
-         * Adjust the stack to reflect the height after the GETPROP, here and
-         * below. Getter hook ICs depend on this to know which value of sp they
-         * are updating for consistent rejoins, don't modify this!
-         */
-        regs.sp++;
-        regs.sp[-2] = rval;
-        regs.sp[-1] = lval;
-    } else {
-        /* Cache miss: use the name loaded for us under PropertyCache::test. */
-        regs.sp++;
-        regs.sp[-1].setNull();
-        if (lval.isObject()) {
-            if (!GetMethod(cx, &objv.toObject(), name,
-                           JS_LIKELY(!objv.toObject().getOps()->getProperty)
-                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                           : JSGET_NO_METHOD_BARRIER,
-                           &rval))
-            {
-                THROW();
-            }
-            regs.sp[-1] = objv;
-            regs.sp[-2] = rval;
-        } else {
-            JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!GetPropertyHelper(cx, &objv.toObject(), name,
-                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
-                                   &rval))
-            {
-                THROW();
-            }
-            regs.sp[-1] = lval;
-            regs.sp[-2] = rval;
-        }
-    }
-
-#if JS_HAS_NO_SUCH_METHOD
-    if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        regs.sp[-2].setString(name);
-        if (!OnUnknownMethod(cx, regs.sp - 2))
-            THROW();
-    }
-#endif
-
-    if (monitor.recompiled())
-        return;
-
-    GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->name, DisabledCallPropIC);
-    if (lval.isObject()) {
-        if (pic->shouldUpdate(cx)) {
-            LookupStatus status = cc.update();
-            if (status == Lookup_Error)
-                THROW();
-        }
-    } else if (lval.isString()) {
-        LookupStatus status = cc.generateStringCallStub();
-        if (status == Lookup_Error)
-            THROW();
-    } else {
-        cc.disable("non-string primitive");
-    }
-}
-
-static void JS_FASTCALL
 DisabledNameIC(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::Name(f);
 }
 
 static void JS_FASTCALL
 DisabledXNameIC(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::GetProp(f);
+    stubs::GetProp(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::XName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
     /* GETXPROP is guaranteed to have an object. */
@@ -2175,98 +1996,59 @@ ic::XName(VMFrame &f, ic::PICInfo *pic)
 
     ScopeNameCompiler cc(f, script, obj, *pic, pic->name, DisabledXNameIC);
 
     LookupStatus status = cc.updateForXName();
     if (status == Lookup_Error)
         THROW();
 
     Value rval;
-    if (!cc.retrieve(&rval, NULL, PICInfo::XNAME))
+    if (!cc.retrieve(&rval, PICInfo::XNAME))
         THROW();
     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->name, DisabledNameIC);
 
     LookupStatus status = cc.updateForName();
     if (status == Lookup_Error)
         THROW();
 
     Value rval;
-    if (!cc.retrieve(&rval, NULL, PICInfo::NAME))
+    if (!cc.retrieve(&rval, PICInfo::NAME))
         THROW();
     f.regs.sp[0] = rval;
 }
 
 static void JS_FASTCALL
-DisabledCallNameIC(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::CallName(f);
-}
-
-void JS_FASTCALL
-ic::CallName(VMFrame &f, ic::PICInfo *pic)
-{
-    JSScript *script = f.fp()->script();
-
-    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->name, DisabledCallNameIC);
-
-    LookupStatus status = cc.updateForName();
-    if (status == Lookup_Error)
-        THROW();
-
-    Value rval, thisval;
-    if (!cc.retrieve(&rval, &thisval, PICInfo::CALLNAME))
-        THROW();
-
-    f.regs.sp[0] = rval;
-    f.regs.sp[1] = thisval;
-}
-
-static void JS_FASTCALL
 DisabledBindNameIC(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::BindName(f);
-}
-
-static void JS_FASTCALL
-DisabledBindNameICNoCache(VMFrame &f, ic::PICInfo *pic)
-{
-    stubs::BindNameNoCache(f, pic->name);
+    stubs::BindName(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::BindName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    VoidStubPIC stub = pic->usePropCache
-                       ? DisabledBindNameIC
-                       : DisabledBindNameICNoCache;
+    VoidStubPIC stub = DisabledBindNameIC;
     BindNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->name, stub);
 
     JSObject *obj = cc.update();
     if (!obj)
         THROW();
 
     f.regs.sp[0].setObject(*obj);
 }
 
-bool
-BaseIC::isCallOp()
-{
-    return !!(js_CodeSpec[op].format & JOF_CALLOP);
-}
-
 void
 BaseIC::spew(JSContext *cx, const char *event, const char *message)
 {
 #ifdef JS_METHODJIT_SPEW
     JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n",
                js_CodeName[op], event, message, cx->fp()->script()->filename, CurrentLine(cx));
 #endif
 }
@@ -2328,41 +2110,33 @@ BaseIC::shouldUpdate(JSContext *cx)
 }
 
 static void JS_FASTCALL
 DisabledGetElem(VMFrame &f, ic::GetElementIC *ic)
 {
     stubs::GetElem(f);
 }
 
-static void JS_FASTCALL
-DisabledCallElem(VMFrame &f, ic::GetElementIC *ic)
-{
-    stubs::CallElem(f);
-}
-
 bool
 GetElementIC::shouldUpdate(JSContext *cx)
 {
     if (!hit) {
         hit = true;
         spew(cx, "ignored", "first hit");
         return false;
     }
     JS_ASSERT(stubsGenerated < MAX_GETELEM_IC_STUBS);
     return true;
 }
 
 LookupStatus
 GetElementIC::disable(JSContext *cx, const char *reason)
 {
     slowCallPatched = true;
-    void *stub = (op == JSOP_GETELEM)
-                 ? JS_FUNC_TO_DATA_PTR(void *, DisabledGetElem)
-                 : JS_FUNC_TO_DATA_PTR(void *, DisabledCallElem);
+    void *stub = JS_FUNC_TO_DATA_PTR(void *, DisabledGetElem);
     BaseIC::disable(cx, reason, stub);
     return Lookup_Uncacheable;
 }
 
 LookupStatus
 GetElementIC::error(JSContext *cx)
 {
     return Lookup_Error;
@@ -2373,23 +2147,18 @@ GetElementIC::purge(Repatcher &repatcher
 {
     // Repatch the inline jumps.
     if (inlineTypeGuardPatched)
         repatcher.relink(fastPathStart.jumpAtOffset(inlineTypeGuard), slowPathStart);
     if (inlineShapeGuardPatched)
         repatcher.relink(fastPathStart.jumpAtOffset(inlineShapeGuard), slowPathStart);
 
     if (slowCallPatched) {
-        if (op == JSOP_GETELEM) {
-            repatcher.relink(slowPathCall,
-                             FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::GetElement)));
-        } else if (op == JSOP_CALLELEM) {
-            repatcher.relink(slowPathCall,
-                             FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::CallElement)));
-        }
+        repatcher.relink(slowPathCall,
+                         FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::GetElement)));
     }
 
     reset();
 }
 
 LookupStatus
 GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyName *name,
                             Value *vp)
@@ -2837,91 +2606,32 @@ GetElementIC::update(VMFrame &f, JSObjec
     if (!f.cx->typeInferenceEnabled() && js_IsTypedArray(obj))
         return attachTypedArray(f, obj, v, id, vp);
 #endif
 
     return disable(f.cx, "unhandled object and key type");
 }
 
 void JS_FASTCALL
-ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
-{
-    JSContext *cx = f.cx;
-
-    // Right now, we don't optimize for strings.
-    if (!f.regs.sp[-2].isObject()) {
-        ic->disable(cx, "non-object");
-        stubs::CallElem(f);
-        return;
-    }
-
-    RecompilationMonitor monitor(cx);
-
-    Value thisv = f.regs.sp[-2];
-    JSObject *thisObj = ValuePropertyBearer(cx, thisv, -2);
-    if (!thisObj)
-        THROW();
-
-    jsid id;
-    Value idval = f.regs.sp[-1];
-    if (idval.isInt32() && INT_FITS_IN_JSID(idval.toInt32()))
-        id = INT_TO_JSID(idval.toInt32());
-    else if (!js_InternNonIntElementId(cx, thisObj, idval, &id))
-        THROW();
-
-    if (!monitor.recompiled() && ic->shouldUpdate(cx)) {
-#ifdef DEBUG
-        f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
-#endif
-        LookupStatus status = ic->update(f, thisObj, idval, id, &f.regs.sp[-2]);
-        if (status != Lookup_Uncacheable) {
-            if (status == Lookup_Error)
-                THROW();
-
-            // If the result can be cached, the value was already retrieved.
-            JS_ASSERT(!f.regs.sp[-2].isMagic());
-            f.regs.sp[-1].setObject(*thisObj);
-            return;
-        }
-    }
-
-    /* Get or set the element. */
-    if (!js_GetMethod(cx, thisObj, id, JSGET_NO_METHOD_BARRIER, &f.regs.sp[-2]))
-        THROW();
-
-#if JS_HAS_NO_SUCH_METHOD
-    if (JS_UNLIKELY(f.regs.sp[-2].isPrimitive()) && thisv.isObject()) {
-        f.regs.sp[-2] = f.regs.sp[-1];
-        f.regs.sp[-1].setObject(*thisObj);
-        if (!OnUnknownMethod(cx, f.regs.sp - 2))
-            THROW();
-    } else
-#endif
-    {
-        f.regs.sp[-1] = thisv;
-    }
-}
-
-void JS_FASTCALL
 ic::GetElement(VMFrame &f, ic::GetElementIC *ic)
 {
     JSContext *cx = f.cx;
 
     // Right now, we don't optimize for strings or lazy arguments.
     if (!f.regs.sp[-2].isObject()) {
         ic->disable(cx, "non-object");
         stubs::GetElem(f);
         return;
     }
 
     Value idval = f.regs.sp[-1];
 
     RecompilationMonitor monitor(cx);
 
-    JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]);
+    JSObject *obj = ValueToObject(cx, f.regs.sp[-2]);
     if (!obj)
         THROW();
 
     jsid id;
     if (idval.isInt32() && INT_FITS_IN_JSID(idval.toInt32())) {
         id = INT_TO_JSID(idval.toInt32());
     } else {
         if (!js_InternNonIntElementId(cx, obj, idval, &id))
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -379,23 +379,21 @@ struct PICInfo : public BasePolyIC {
 
     // Operation this is a PIC for.
     enum Kind
 #ifdef _MSC_VER
     : uint8_t
 #endif
     {
         GET,        // JSOP_GETPROP
-        CALL,       // JSOP_CALLPROP
         SET,        // JSOP_SETPROP, JSOP_SETNAME
         SETMETHOD,  // JSOP_SETMETHOD
         NAME,       // JSOP_NAME
         BIND,       // JSOP_BINDNAME
-        XNAME,      // JSOP_GETXPROP
-        CALLNAME    // JSOP_CALLNAME
+        XNAME       // JSOP_GETXPROP
     };
 
     union {
         struct {
             RegisterID typeReg  : 5;  // reg used for checking type
             bool hasTypeCheck   : 1;  // type check and reg are present
 
             // Reverse offset from slowPathStart to the type check slow path.
@@ -462,39 +460,35 @@ struct PICInfo : public BasePolyIC {
 
     // Possible types of the RHS, for monitored SETPROP PICs.
     types::TypeSet *rhsTypes;
     
     inline bool isSet() const {
         return kind == SET || kind == SETMETHOD;
     }
     inline bool isGet() const {
-        return kind == GET || kind == CALL;
+        return kind == GET;
     }
     inline bool isBind() const {
         return kind == BIND;
     }
     inline bool isScopeName() const {
-        return kind == NAME || kind == CALLNAME || kind == XNAME;
+        return kind == NAME || kind == XNAME;
     }
     inline RegisterID typeReg() {
         JS_ASSERT(isGet());
         return u.get.typeReg;
     }
     inline bool hasTypeCheck() {
         JS_ASSERT(isGet());
         return u.get.hasTypeCheck;
     }
     inline bool shapeNeedsRemat() {
         return !shapeRegHasBaseShape;
     }
-    inline bool isFastCall() {
-        JS_ASSERT(kind == CALL);
-        return !hasTypeCheck();
-    }
 
     union {
         GetPropLabels getPropLabels_;
         SetPropLabels setPropLabels_;
         BindNameLabels bindNameLabels_;
         ScopeNameLabels scopeNameLabels_;
     };
     void setLabels(const ic::GetPropLabels &labels) {
@@ -505,34 +499,34 @@ struct PICInfo : public BasePolyIC {
         JS_ASSERT(isSet());
         setPropLabels_ = labels;
     }
     void setLabels(const ic::BindNameLabels &labels) {
         JS_ASSERT(kind == BIND);
         bindNameLabels_ = labels;
     }
     void setLabels(const ic::ScopeNameLabels &labels) {
-        JS_ASSERT(kind == NAME || kind == CALLNAME || kind == XNAME);
+        JS_ASSERT(kind == NAME || kind == XNAME);
         scopeNameLabels_ = labels;
     }
 
     GetPropLabels &getPropLabels() {
         JS_ASSERT(isGet());
         return getPropLabels_;
     }
     SetPropLabels &setPropLabels() {
         JS_ASSERT(isSet());
         return setPropLabels_;
     }
     BindNameLabels &bindNameLabels() {
         JS_ASSERT(kind == BIND);
         return bindNameLabels_;
     }
     ScopeNameLabels &scopeNameLabels() {
-        JS_ASSERT(kind == NAME || kind == CALLNAME || kind == XNAME);
+        JS_ASSERT(kind == NAME || kind == XNAME);
         return scopeNameLabels_;
     }
 
     // Where in the script did we generate this PIC?
     jsbytecode *pc;
     
     // Index into the script's atom table.
     PropertyName *name;
@@ -545,23 +539,20 @@ struct PICInfo : public BasePolyIC {
         shapeRegHasBaseShape = true;
     }
 };
 
 #ifdef JS_POLYIC
 void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL GetPropNoCache(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL SetProp(VMFrame &f, ic::PICInfo *);
-void JS_FASTCALL CallProp(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL Name(VMFrame &f, ic::PICInfo *);
-void JS_FASTCALL CallName(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL XName(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL BindName(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL GetElement(VMFrame &f, ic::GetElementIC *);
-void JS_FASTCALL CallElement(VMFrame &f, ic::GetElementIC *);
 template <JSBool strict> void JS_FASTCALL SetElement(VMFrame &f, ic::SetElementIC *);
 #endif
 
 } /* namespace ic */
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jsjaeger_poly_ic_h__ */
--- a/js/src/methodjit/StubCalls-inl.h
+++ b/js/src/methodjit/StubCalls-inl.h
@@ -49,24 +49,16 @@ ThrowException(VMFrame &f)
 {
     void *ptr = JS_FUNC_TO_DATA_PTR(void *, JaegerThrowpoline);
     *f.returnAddressLocation() = ptr;
 }
 
 #define THROW()   do { mjit::ThrowException(f); return; } while (0)
 #define THROWV(v) do { mjit::ThrowException(f); return v; } while (0)
 
-static inline JSObject *
-ValueToObject(JSContext *cx, Value *vp)
-{
-    if (vp->isObject())
-        return &vp->toObject();
-    return js_ValueToNonNullObject(cx, *vp);
-}
-
 static inline void
 ReportAtomNotDefined(JSContext *cx, JSAtom *atom)
 {
     JSAutoByteString printable;
     if (js_AtomToPrintableString(cx, atom, &printable))
         js_ReportIsNotDefined(cx, printable.ptr());
 }
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -52,18 +52,16 @@
 #include "jstypes.h"
 #include "vm/Debugger.h"
 #include "vm/String.h"
 #include "methodjit/Compiler.h"
 #include "methodjit/StubCalls.h"
 #include "methodjit/Retcon.h"
 
 #include "jsinterpinlines.h"
-#include "jspropertycache.h"
-#include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsnuminlines.h"
 #include "jsobjinlines.h"
 #include "jscntxtinlines.h"
 #include "jsatominlines.h"
 #include "StubCalls-inl.h"
 #include "jsfuninlines.h"
@@ -79,282 +77,65 @@
 #include "jsautooplen.h"
 
 using namespace js;
 using namespace js::mjit;
 using namespace js::types;
 using namespace JSC;
 
 void JS_FASTCALL
-stubs::BindName(VMFrame &f)
-{
-    PropertyCacheEntry *entry;
-
-    /* Fast-path should have caught this. See comment in interpreter. */
-    JS_ASSERT(!f.fp()->scopeChain().isGlobal());
-
-    PropertyName *name;
-    JSObject *obj2;
-    JSContext *cx = f.cx;
-    JSObject *obj = &f.fp()->scopeChain();
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, name);
-    if (name) {
-        obj = FindIdentifierBase(cx, &f.fp()->scopeChain(), name);
-        if (!obj)
-            THROW();
-    }
-    f.regs.sp++;
-    f.regs.sp[-1].setObject(*obj);
-}
-
-void JS_FASTCALL
-stubs::BindNameNoCache(VMFrame &f, PropertyName *name)
+stubs::BindName(VMFrame &f, PropertyName *name)
 {
     JSObject *obj = FindIdentifierBase(f.cx, &f.fp()->scopeChain(), name);
     if (!obj)
         THROW();
     f.regs.sp[0].setObject(*obj);
 }
 
 JSObject * JS_FASTCALL
 stubs::BindGlobalName(VMFrame &f)
 {
     return &f.fp()->scopeChain().global();
 }
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetName(VMFrame &f, PropertyName *origName)
+stubs::SetName(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
-
-    Value rval = f.regs.sp[-1];
-    Value &lref = f.regs.sp[-2];
-    JSObject *obj = ValueToObject(cx, &lref);
-    if (!obj)
-        THROW();
-
-    do {
-        PropertyCache *cache = &JS_PROPERTY_CACHE(cx);
-
-        /*
-         * Probe the property cache, specializing for two important
-         * set-property cases. First:
-         *
-         *   function f(a, b, c) {
-         *     var o = {p:a, q:b, r:c};
-         *     return o;
-         *   }
-         *
-         * or similar real-world cases, which evolve a newborn native
-         * object predicatably through some bounded number of property
-         * additions. And second:
-         *
-         *   o.p = x;
-         *
-         * in a frequently executed method or loop body, where p will
-         * (possibly after the first iteration) always exist in native
-         * object o.
-         */
-        PropertyCacheEntry *entry;
-        JSObject *obj2;
-        PropertyName *name;
-        if (cache->testForSet(cx, f.pc(), obj, &entry, &obj2, &name)) {
-            /*
-             * Property cache hit, only partially confirmed by testForSet. We
-             * know that the entry applies to regs.pc and that obj's shape
-             * matches.
-             *
-             * The entry predicts a set either an existing "own" property, or
-             * on a prototype property that has a setter.
-             */
-            const Shape *shape = entry->prop;
+    const Value &rval = f.regs.sp[-1];
+    const Value &lval = f.regs.sp[-2];
 
-            if (entry->isOwnPropertyHit() ||
-                ((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape))
-            {
-                JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
-                JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
-
-#ifdef DEBUG
-                if (entry->isOwnPropertyHit()) {
-                    JS_ASSERT(obj->nativeContains(cx, *shape));
-                } else {
-                    JS_ASSERT(obj2->nativeContains(cx, *shape));
-                    JS_ASSERT(entry->isPrototypePropertyHit());
-                    JS_ASSERT(entry->kshape != entry->pshape);
-                    JS_ASSERT(!shape->hasSlot());
-                }
-#endif
-
-                PCMETER(cache->pchits++);
-                PCMETER(cache->setpchits++);
-                NATIVE_SET(cx, obj, shape, entry, strict, &rval);
-                break;
-            }
-            PCMETER(cache->setpcmisses++);
-
-            name = origName;
-        } else {
-            JS_ASSERT(name);
-        }
-
-        if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
-            uintN defineHow;
-            JSOp op = JSOp(*f.pc());
-            if (op == JSOP_SETMETHOD)
-                defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
-            else if (op == JSOP_SETNAME)
-                defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
-            else
-                defineHow = DNP_CACHE_RESULT;
-            if (!SetPropertyHelper(cx, obj, name, defineHow, &rval, strict))
-                THROW();
-        } else {
-            if (!obj->setProperty(cx, name, &rval, strict))
-                THROW();
-        }
-    } while (0);
+    if (!SetPropertyOperation(cx, f.pc(), lval, rval))
+        THROW();
 
     f.regs.sp[-2] = f.regs.sp[-1];
 }
 
 template void JS_FASTCALL stubs::SetName<true>(VMFrame &f, PropertyName *origName);
 template void JS_FASTCALL stubs::SetName<false>(VMFrame &f, PropertyName *origName);
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetPropNoCache(VMFrame &f, PropertyName *name)
-{
-    JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
-    if (!obj)
-         THROW();
-    Value rval = f.regs.sp[-1];
-
-    if (!obj->setProperty(f.cx, name, &f.regs.sp[-1], strict))
-        THROW();
-    f.regs.sp[-2] = rval;
-}
-
-template void JS_FASTCALL stubs::SetPropNoCache<true>(VMFrame &f, PropertyName *name);
-template void JS_FASTCALL stubs::SetPropNoCache<false>(VMFrame &f, PropertyName *name);
-
-template<JSBool strict>
-void JS_FASTCALL
-stubs::SetGlobalNameNoCache(VMFrame &f, PropertyName *name)
-{
-    JSContext *cx = f.cx;
-
-    Value rval = f.regs.sp[-1];
-    Value &lref = f.regs.sp[-2];
-    JSObject *obj = ValueToObject(cx, &lref);
-    if (!obj || !obj->setProperty(cx, name, &rval, strict))
-        THROW();
-
-    f.regs.sp[-2] = f.regs.sp[-1];
-}
-
-template void JS_FASTCALL stubs::SetGlobalNameNoCache<true>(VMFrame &f, PropertyName *name);
-template void JS_FASTCALL stubs::SetGlobalNameNoCache<false>(VMFrame &f, PropertyName *name);
-
-template<JSBool strict>
-void JS_FASTCALL
 stubs::SetGlobalName(VMFrame &f, PropertyName *name)
 {
     SetName<strict>(f, name);
 }
 
 template void JS_FASTCALL stubs::SetGlobalName<true>(VMFrame &f, PropertyName *name);
 template void JS_FASTCALL stubs::SetGlobalName<false>(VMFrame &f, PropertyName *name);
 
-static inline void
-PushImplicitThis(VMFrame &f, JSObject *obj, Value &rval)
-{
-    Value thisv;
-
-    if (!ComputeImplicitThis(f.cx, obj, rval, &thisv))
-        return;
-    *f.regs.sp++ = thisv;
-}
-
-static JSObject *
-NameOp(VMFrame &f, JSObject *obj, bool callname)
-{
-    JSContext *cx = f.cx;
-
-    Value rval;
-
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, name);
-    if (!name) {
-        NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval, return NULL);
-        JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
-    } else {
-        JSProperty *prop;
-        bool global = (js_CodeSpec[*f.pc()].format & JOF_GNAME);
-        if (!FindPropertyHelper(cx, name, true, global, &obj, &obj2, &prop))
-            return NULL;
-        if (!prop) {
-            /* Kludge to allow (typeof foo == "undefined") tests. */
-            JSOp op2 = JSOp(f.pc()[JSOP_NAME_LENGTH]);
-            if (op2 == JSOP_TYPEOF) {
-                f.regs.sp++;
-                f.regs.sp[-1].setUndefined();
-                return obj;
-            }
-            ReportAtomNotDefined(cx, name);
-            return NULL;
-        }
-
-        /* Take the slow path if prop was not found in a native object. */
-        if (!obj->isNative() || !obj2->isNative()) {
-            if (!obj->getProperty(cx, name, &rval))
-                return NULL;
-        } else {
-            Shape *shape = (Shape *)prop;
-            JSObject *normalized = obj;
-            if (normalized->isWith() && !shape->hasDefaultGetter())
-                normalized = &normalized->asWith().object();
-            NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
-        }
-
-        /*
-         * If this is an incop, update the property's types themselves,
-         * to capture the type effect on the intermediate value.
-         */
-        if (rval.isUndefined() && (js_CodeSpec[*f.pc()].format & (JOF_INC|JOF_DEC)))
-            AddTypePropertyId(cx, obj, ATOM_TO_JSID(name), Type::UndefinedType());
-    }
-
-    *f.regs.sp++ = rval;
-
-    if (callname)
-        PushImplicitThis(f, obj, rval);
-
-    return obj;
-}
-
 void JS_FASTCALL
 stubs::Name(VMFrame &f)
 {
-    if (!NameOp(f, &f.fp()->scopeChain(), false))
+    if (!NameOperation(f.cx, f.pc(), &f.regs.sp[0]))
         THROW();
 }
 
 void JS_FASTCALL
-stubs::GetGlobalName(VMFrame &f)
-{
-    JSObject *globalObj = &f.fp()->scopeChain().global();
-    if (!NameOp(f, globalObj, false))
-         THROW();
-}
-
-void JS_FASTCALL
 stubs::GetElem(VMFrame &f)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     Value &lref = regs.sp[-2];
     Value &rref = regs.sp[-1];
     Value &rval = regs.sp[-2];
@@ -374,17 +155,18 @@ stubs::GetElem(VMFrame &f)
         if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
             rval = regs.fp()->canonicalActualArg(rref.toInt32());
             return;
         }
         MarkArgumentsCreated(cx, f.script());
         JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
     }
 
-    JSObject *obj = ValueToObject(cx, &lref);
+    bool isObject = lref.isObject();
+    JSObject *obj = ValueToObject(cx, lref);
     if (!obj)
         THROW();
 
     uint32_t index;
     if (IsDefinitelyIndex(rref, &index)) {
         if (obj->isDenseArray()) {
             if (index < obj->getDenseArrayInitializedLength()) {
                 rval = obj->getDenseArrayElement(index);
@@ -412,78 +194,51 @@ stubs::GetElem(VMFrame &f)
                 if (!obj->getElement(cx, index, &rval))
                     THROW();
             } else {
                 if (!obj->getProperty(cx, name->asPropertyName(), &rval))
                     THROW();
             }
         }
     }
+
+#if JS_HAS_NO_SUCH_METHOD
+    if (*f.pc() == JSOP_CALLELEM && JS_UNLIKELY(rval.isPrimitive()) && isObject) {
+        if (!OnUnknownMethod(cx, obj, rref, &rval))
+            THROW();
+    }
+#endif
 }
 
 static inline bool
 FetchElementId(VMFrame &f, JSObject *obj, const Value &idval, jsid &id, Value *vp)
 {
     int32_t i_;
     if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
         id = INT_TO_JSID(i_);
         return true;
     }
     return !!js_InternNonIntElementId(f.cx, obj, idval, &id, vp);
 }
 
-void JS_FASTCALL
-stubs::CallElem(VMFrame &f)
-{
-    JSContext *cx = f.cx;
-    FrameRegs &regs = f.regs;
-
-    /* Find the object on which to look for |this|'s properties. */
-    Value thisv = regs.sp[-2];
-    JSObject *thisObj = ValuePropertyBearer(cx, thisv, -2);
-    if (!thisObj)
-        THROW();
-
-    /* Fetch index and convert it to id suitable for use with thisObj. */
-    jsid id;
-    if (!FetchElementId(f, thisObj, regs.sp[-1], id, &regs.sp[-2]))
-        THROW();
-
-    /* Get or set the element. */
-    if (!js_GetMethod(cx, thisObj, id, JSGET_NO_METHOD_BARRIER, &regs.sp[-2]))
-        THROW();
-
-#if JS_HAS_NO_SUCH_METHOD
-    if (JS_UNLIKELY(regs.sp[-2].isPrimitive()) && thisv.isObject()) {
-        regs.sp[-2] = regs.sp[-1];
-        regs.sp[-1].setObject(*thisObj);
-        if (!OnUnknownMethod(cx, regs.sp - 2))
-            THROW();
-    } else
-#endif
-    {
-        regs.sp[-1] = thisv;
-    }
-}
-
 template<JSBool strict>
 void JS_FASTCALL
 stubs::SetElem(VMFrame &f)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     Value &objval = regs.sp[-3];
     Value &idval  = regs.sp[-2];
     Value rval    = regs.sp[-1];
 
     JSObject *obj;
     jsid id;
 
-    obj = ValueToObject(cx, &objval);
+    obj = ValueToObject(cx, objval);
     if (!obj)
         THROW();
 
     if (!FetchElementId(f, obj, idval, id, &regs.sp[-2]))
         THROW();
 
     TypeScript::MonitorAssign(cx, f.script(), f.pc(), obj, id, rval);
 
@@ -520,45 +275,38 @@ template void JS_FASTCALL stubs::SetElem
 template void JS_FASTCALL stubs::SetElem<false>(VMFrame &f);
 
 void JS_FASTCALL
 stubs::ToId(VMFrame &f)
 {
     Value &objval = f.regs.sp[-2];
     Value &idval  = f.regs.sp[-1];
 
-    JSObject *obj = ValueToObject(f.cx, &objval);
+    JSObject *obj = ValueToObject(f.cx, objval);
     if (!obj)
         THROW();
 
     jsid id;
     if (!FetchElementId(f, obj, idval, id, &idval))
         THROW();
 
     if (!idval.isInt32())
         TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
 }
 
 void JS_FASTCALL
-stubs::CallName(VMFrame &f)
+stubs::ImplicitThis(VMFrame &f, PropertyName *name)
 {
-    JSObject *obj = NameOp(f, &f.fp()->scopeChain(), true);
-    if (!obj)
+    JSObject *obj, *obj2;
+    JSProperty *prop;
+    if (!FindPropertyHelper(f.cx, name, false, false, &obj, &obj2, &prop))
         THROW();
-}
 
-/*
- * Push the implicit this value, with the assumption that the callee
- * (which is on top of the stack) was read as a property from the
- * global object.
- */
-void JS_FASTCALL
-stubs::PushImplicitThisForGlobal(VMFrame &f)
-{
-    return PushImplicitThis(f, &f.fp()->scopeChain().global(), f.regs.sp[-1]);
+    if (!ComputeImplicitThis(f.cx, obj, &f.regs.sp[0]))
+        THROW();
 }
 
 void JS_FASTCALL
 stubs::BitOr(VMFrame &f)
 {
     int32_t i, j;
 
     if (!ToInt32(f.cx, f.regs.sp[-2], &i) || !ToInt32(f.cx, f.regs.sp[-1], &j))
@@ -1446,160 +1194,48 @@ stubs::Lambda(VMFrame &f, JSFunction *fu
     JSObject *obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent);
     if (!obj)
         THROWV(NULL);
 
     JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
     return obj;
 }
 
-static bool JS_ALWAYS_INLINE
-InlineGetProp(VMFrame &f)
+void JS_FASTCALL
+stubs::GetProp(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
-    Value *vp = &f.regs.sp[-1];
-
-    if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
-        JS_ASSERT(JSOp(*f.pc()) == JSOP_LENGTH);
-        regs.sp[-1] = Int32Value(regs.fp()->numActualArgs());
-        return true;
-    }
-
-    JSObject *obj = ValueToObject(f.cx, vp);
-    if (!obj)
-        return false;
-
     Value rval;
-    do {
-        JSObject *aobj = js_GetProtoIfDenseArray(obj);
-
-        PropertyCacheEntry *entry;
-        JSObject *obj2;
-        PropertyName *name;
-        JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name);
-        if (!name) {
-            NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval, return false);
-            break;
-        }
-
-        if (JS_LIKELY(!aobj->getOps()->getProperty)
-            ? !GetPropertyHelper(cx, obj, name, JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER, &rval)
-            : !obj->getProperty(cx, name, &rval))
-        {
-            return false;
-        }
-    } while (false);
+    if (!GetPropertyOperation(cx, f.pc(), f.regs.sp[-1], &rval))
+        THROW();
 
     regs.sp[-1] = rval;
-    return true;
-}
-
-void JS_FASTCALL
-stubs::GetProp(VMFrame &f)
-{
-    if (!InlineGetProp(f))
-        THROW();
 }
 
 void JS_FASTCALL
 stubs::GetPropNoCache(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
-
-    Value *vp = &f.regs.sp[-1];
-    JSObject *obj = ValueToObject(cx, vp);
-    if (!obj)
-        THROW();
-
-    if (!obj->getProperty(cx, name, vp))
-        THROW();
-
-    /* Don't check for undefined, this is only used for 'prototype'. See ic::GetProp. */
-}
-
-void JS_FASTCALL
-stubs::CallProp(VMFrame &f, PropertyName *origName)
-{
-    JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
-    Value lval;
-    lval = regs.sp[-1];
+    const Value &lval = f.regs.sp[-1];
 
-    Value objv;
-    if (lval.isObject()) {
-        objv = lval;
-    } else {
-        GlobalObject &global = f.fp()->scopeChain().global();
-        JSObject *pobj;
-        if (lval.isString()) {
-            pobj = global.getOrCreateStringPrototype(cx);
-        } else if (lval.isNumber()) {
-            pobj = global.getOrCreateNumberPrototype(cx);
-        } else if (lval.isBoolean()) {
-            pobj = global.getOrCreateBooleanPrototype(cx);
-        } else {
-            JS_ASSERT(lval.isNull() || lval.isUndefined());
-            js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
-            THROW();
-        }
-        if (!pobj)
-            THROW();
-        objv.setObject(*pobj);
-    }
-
-    JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
-    Value rval;
+    // Uncached lookups are only used for .prototype accesses at the start of constructors.
+    JS_ASSERT(lval.isObject());
+    JS_ASSERT(name == cx->runtime->atomState.classPrototypeAtom);
 
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name);
-    if (!name) {
-        NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval,
-                   THROW());
-        regs.sp++;
-        regs.sp[-2] = rval;
-        regs.sp[-1] = lval;
-    } else {
-        /* Cache miss: use the name loaded for us under PropertyCache::test. */
-        regs.sp++;
-        regs.sp[-1].setNull();
-        if (lval.isObject()) {
-            if (!GetMethod(cx, &objv.toObject(), name,
-                           JS_LIKELY(!aobj->getOps()->getProperty)
-                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                           : JSGET_NO_METHOD_BARRIER,
-                           &rval))
-            {
-                THROW();
-            }
-            regs.sp[-1] = objv;
-            regs.sp[-2] = rval;
-        } else {
-            JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!GetPropertyHelper(cx, &objv.toObject(), name,
-                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
-                                   &rval))
-            {
-                THROW();
-            }
-            regs.sp[-1] = lval;
-            regs.sp[-2] = rval;
-        }
-    }
-#if JS_HAS_NO_SUCH_METHOD
-    if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        regs.sp[-2].setString(origName);
-        if (!OnUnknownMethod(cx, regs.sp - 2))
-            THROW();
-    }
-#endif
+    JSObject *obj = &lval.toObject();
+
+    Value rval;
+    if (!obj->getProperty(cx, name, &rval))
+        THROW();
+
+    regs.sp[-1] = rval;
 }
 
 void JS_FASTCALL
 stubs::Iter(VMFrame &f, uint32_t flags)
 {
     if (!js_ValueToIterator(f.cx, flags, &f.regs.sp[-1]))
         THROW();
     JS_ASSERT(!f.regs.sp[-1].isPrimitive());
@@ -1615,50 +1251,25 @@ InitPropOrMethod(VMFrame &f, PropertyNam
     JS_ASSERT(regs.sp - f.fp()->base() >= 2);
     Value rval;
     rval = regs.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
     JSObject *obj = &regs.sp[-2].toObject();
     JS_ASSERT(obj->isNative());
 
-    /*
-     * Probe the property cache.
-     *
-     * We can not assume that the object created by JSOP_NEWINIT is still
-     * single-threaded as the debugger can access it from other threads.
-     * So check first.
-     *
-     * On a hit, if the cached shape has a non-default setter, it must be
-     * __proto__. If shape->previous() != obj->lastProperty(), there must be a
-     * repeated property name. The fast path does not handle these two cases.
-     */
-    PropertyCacheEntry *entry;
-    JSObject *obj2;
-    PropertyName *name2;
-    if (JS_PROPERTY_CACHE(cx).testForSet(cx, f.pc(), obj, &entry, &obj2, &name2) &&
-        entry->prop->hasDefaultSetter() &&
-        entry->isOwnPropertyHit())
-    {
-        JS_ASSERT(obj == obj2);
-        /* Fast path. Property cache hit. */
-        obj->nativeSetSlotWithType(cx, entry->prop, rval);
-    } else {
-        PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
+    /* Get the immediate property name into id. */
+    jsid id = ATOM_TO_JSID(name);
 
-        uintN defineHow = (op == JSOP_INITMETHOD)
-                          ? DNP_CACHE_RESULT | DNP_SET_METHOD
-                          : DNP_CACHE_RESULT;
-        if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
-            ? !SetPropertyHelper(cx, obj, name, defineHow, &rval, false)
-            : !DefineNativeProperty(cx, obj, name, rval, NULL, NULL,
-                                    JSPROP_ENUMERATE, 0, 0, defineHow))
-        {
-            THROW();
-        }
+    uintN defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0;
+    if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
+        ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, false)
+        : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
+                                JSPROP_ENUMERATE, 0, 0, defineHow)) {
+        THROW();
     }
 }
 
 void JS_FASTCALL
 stubs::InitProp(VMFrame &f, PropertyName *name)
 {
     InitPropOrMethod(f, name, JSOP_INITPROP);
 }
@@ -2025,17 +1636,17 @@ stubs::DelName(VMFrame &f, PropertyName 
 }
 
 template<JSBool strict>
 void JS_FASTCALL
 stubs::DelProp(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
 
-    JSObject *obj = ValueToObject(cx, &f.regs.sp[-1]);
+    JSObject *obj = ValueToObject(cx, f.regs.sp[-1]);
     if (!obj)
         THROW();
 
     Value rval;
     if (!obj->deleteProperty(cx, name, &rval, strict))
         THROW();
 
     f.regs.sp[-1] = rval;
@@ -2045,17 +1656,17 @@ template void JS_FASTCALL stubs::DelProp
 template void JS_FASTCALL stubs::DelProp<false>(VMFrame &f, PropertyName *name);
 
 template<JSBool strict>
 void JS_FASTCALL
 stubs::DelElem(VMFrame &f)
 {
     JSContext *cx = f.cx;
 
-    JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]);
+    JSObject *obj = ValueToObject(cx, f.regs.sp[-2]);
     if (!obj)
         THROW();
 
     const Value &propval = f.regs.sp[-1];
     Value &rval = f.regs.sp[-2];
 
     if (!obj->deleteByValue(cx, propval, &rval, strict))
         THROW();
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -110,36 +110,29 @@ void UncachedCallHelper(VMFrame &f, uint
 void UncachedNewHelper(VMFrame &f, uint32_t argc, UncachedCallResult *ucr);
 
 void JS_FASTCALL CreateThis(VMFrame &f, JSObject *proto);
 void JS_FASTCALL Throw(VMFrame &f);
 
 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, PropertyName *name);
+void JS_FASTCALL BindName(VMFrame &f, PropertyName *name);
 JSObject * JS_FASTCALL BindGlobalName(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetName(VMFrame &f, PropertyName *name);
-template<JSBool strict> void JS_FASTCALL SetPropNoCache(VMFrame &f, PropertyName *name);
 template<JSBool strict> void JS_FASTCALL SetGlobalName(VMFrame &f, PropertyName *name);
-template<JSBool strict> void JS_FASTCALL SetGlobalNameNoCache(VMFrame &f, PropertyName *name);
 void JS_FASTCALL Name(VMFrame &f);
-void JS_FASTCALL GetProp(VMFrame &f);
+void JS_FASTCALL GetProp(VMFrame &f, PropertyName *name);
 void JS_FASTCALL GetPropNoCache(VMFrame &f, PropertyName *name);
 void JS_FASTCALL GetElem(VMFrame &f);
-void JS_FASTCALL CallElem(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetElem(VMFrame &f);
 void JS_FASTCALL ToId(VMFrame &f);
-void JS_FASTCALL CallName(VMFrame &f);
-void JS_FASTCALL PushImplicitThisForGlobal(VMFrame &f);
+void JS_FASTCALL ImplicitThis(VMFrame &f, PropertyName *name);
 void JS_FASTCALL GetUpvar(VMFrame &f, uint32_t index);
-void JS_FASTCALL GetGlobalName(VMFrame &f);
 
-void JS_FASTCALL CallProp(VMFrame &f, PropertyName *name);
 template <JSBool strict> void JS_FASTCALL DelProp(VMFrame &f, PropertyName *name);
 template <JSBool strict> void JS_FASTCALL DelElem(VMFrame &f);
 void JS_FASTCALL DelName(VMFrame &f, PropertyName *name);
 JSBool JS_FASTCALL In(VMFrame &f);
 
 void JS_FASTCALL DefVarOrConst(VMFrame &f, PropertyName *name);
 void JS_FASTCALL SetConst(VMFrame &f, PropertyName *name);
 template<JSBool strict> void JS_FASTCALL DefFun(VMFrame &f, JSFunction *fun);