Remove JOF_CALLOP, bug 712714. r=dvander
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 05 Jan 2012 11:08:38 -0800
changeset 86340 78d17e22a223f7ea26c2dc5379f0f53bebb0b96a
parent 86334 0ac1cbff2a676dd6312e9ee2dcd813e14645fcc8
child 86341 ed6e4d7917fb02f6850eb515e19b5540b2d02d90
push idunknown
push userunknown
push dateunknown
reviewersdvander
bugs712714
milestone12.0a1
Remove JOF_CALLOP, bug 712714. r=dvander
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)
@@ -2900,261 +2847,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)
 {
@@ -3249,28 +2974,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;
@@ -3426,92 +3147,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)
@@ -3778,30 +3451,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);
@@ -3810,25 +3482,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)
 
@@ -3836,18 +3499,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();
@@ -4393,47 +4054,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);
@@ -4829,18 +4471,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,271 @@ 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
+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 JS_HAS_XML_SUPPORT
+        if (op == JSOP_CALLPROP && obj->isXML()) {
+            /*
+             * Various XML properties behave differently when accessed in a
+             * call vs. normal context, and getGeneric will not work right.
+             */
+            if (!js_GetXMLMethod(cx, obj, id, vp))
+                return false;
+        } else
+#endif
+        {
+            if (!obj->getGeneric(cx, 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
@@ -4594,17 +4594,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();
     }
@@ -5035,23 +5034,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
@@ -5061,26 +5059,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()) {
                     /*
@@ -5093,42 +5090,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;
@@ -5137,17 +5134,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,
@@ -5184,19 +5181,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;
     }
@@ -5335,18 +5330,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'.
          */
@@ -5463,17 +5456,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)
@@ -5626,18 +5618,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
@@ -1815,17 +1815,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
@@ -1848,19 +1848,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
@@ -1934,23 +1934,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);
@@ -1958,24 +1958,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)
 
@@ -4381,67 +4352,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
 
@@ -4449,27 +4400,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) &&
@@ -4485,25 +4436,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();
@@ -4522,16 +4466,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);
@@ -4549,16 +4494,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);
@@ -4578,56 +4524,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)
@@ -4638,34 +4620,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. */
@@ -4677,31 +4661,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;
@@ -4715,17 +4694,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);
 
@@ -4758,287 +4737,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).
      *
@@ -5134,17 +4842,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);
@@ -5269,101 +4977,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) {
@@ -5398,17 +5043,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();
@@ -5448,27 +5092,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");
@@ -5494,20 +5138,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;
     }
 
@@ -5575,62 +5217,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();
@@ -5643,25 +5281,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.
@@ -5675,17 +5311,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);
@@ -5735,17 +5371,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);
@@ -5754,17 +5390,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();
@@ -5822,54 +5458,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
@@ -6192,17 +5818,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) {
@@ -6277,18 +5903,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();
 
@@ -6344,135 +5968,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
@@ -6506,17 +6027,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);
@@ -6559,18 +6080,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);
@@ -6582,17 +6101,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);
@@ -6653,17 +6172,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. */
@@ -7231,17 +6750,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));
@@ -7349,27 +6868,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))
         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,280 +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);
+    const Value &rval = f.regs.sp[-1];
+    const Value &lval = f.regs.sp[-2];
 
-        /*
-         * 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;
-            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
-
-                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];
@@ -372,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);
@@ -410,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);
 
@@ -518,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))
@@ -1444,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());
@@ -1613,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);
 }
@@ -2023,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;
@@ -2043,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();
 
     jsid id;
     if (!FetchElementId(f, obj, f.regs.sp[-1], id, &f.regs.sp[-1]))
         THROW();
 
     if (!obj->deleteGeneric(cx, id, &f.regs.sp[-2], strict))
--- 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);