Merge backout (a=blocking).
authorDavid Anderson <danderson@mozilla.com>
Tue, 02 Nov 2010 10:56:48 -0700
changeset 56832 b192fa5cfffc8ded1790eb8d10b7c5955cf53fc1
parent 56830 46a81506595f8e03894e743c276c762922948479 (current diff)
parent 56831 fa28bf70d2a41e376a482f9a82421d787432f5f6 (diff)
child 56833 bcad241e5c22bf7d617a68927d07dda9ed452f4e
push id16698
push userdanderson@mozilla.com
push dateTue, 02 Nov 2010 17:57:49 +0000
treeherdermozilla-central@b192fa5cfffc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblocking
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge backout (a=blocking).
js/src/jit-test/tests/jaeger/testDenseCallElem.js
js/src/jit-test/tests/jaeger/testPropCallElem.js
js/src/jit-test/tests/jaeger/testPropCallElem2.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/testDenseCallElem.js
+++ /dev/null
@@ -1,89 +0,0 @@
-// vim: set ts=4 sw=4 tw=99 et:
-
-function fillDense(a) {
-}
-
-function testDenseUKeyUArray(a, key) {
-    a.push(function () { return this[3]; });
-    a.push(function () { return this[4]; });
-    a.push(function() { return this[5]; });
-    a.push(20);
-    a.push("hi");
-    a.push(500);
-    assertEq(a[key](), 20);
-    assertEq(a[key + 1](), "hi");
-    assertEq(a[key + 2](), 500);
-}
-
-function testDenseVKeyUArray(a) {
-    a.push(function () { return this[3]; });
-    a.push(function () { return this[4]; });
-    a.push(function() { return this[5]; });
-    a.push(20);
-    a.push("hi");
-    a.push(500);
-    var key = a.length & 1;
-    assertEq(a[key](), 20);
-    assertEq(a[(key + 1) & 3](), "hi");
-    assertEq(a[(key + 2) & 3](), 500);
-}
-
-function testDenseKKeyUArray(a, key) {
-    a.push(function () { return this[3]; });
-    a.push(function () { return this[4]; });
-    a.push(function() { return this[5]; });
-    a.push(20);
-    a.push("hi");
-    a.push(500);
-    assertEq(a[0](), 20);
-    assertEq(a[1](), "hi");
-    assertEq(a[2](), 500);
-}
-
-function testDenseUKeyVArray(key) {
-    var a = [function () { return this[3]; },
-             function () { return this[4]; },
-             function() { return this[5]; },
-             20,
-             "hi",
-             500];
-    assertEq(a[key](), 20);
-    assertEq(a[key + 1](), "hi");
-    assertEq(a[key + 2](), 500);
-}
-
-function testDenseVKeyVArray() {
-    var a = [function () { return this[3]; },
-             function () { return this[4]; },
-             function() { return this[5]; },
-             20,
-             "hi",
-             500];
-    var key = a.length & 1;
-    assertEq(a[key](), 20);
-    assertEq(a[(key + 1) & 3](), "hi");
-    assertEq(a[(key + 2) & 3](), 500);
-}
-
-function testDenseKKeyVArray() {
-    var a = [function () { return this[3]; },
-             function () { return this[4]; },
-             function() { return this[5]; },
-             20,
-             "hi",
-             500];
-    assertEq(a[0](), 20);
-    assertEq(a[1](), "hi");
-    assertEq(a[2](), 500);
-}
-
-for (var i = 0; i < 5; i++) {
-    testDenseUKeyUArray([], 0);
-    testDenseVKeyUArray([]);
-    testDenseKKeyUArray([]);
-    testDenseUKeyVArray(0);
-    testDenseVKeyVArray();
-    testDenseKKeyVArray();
-}
-
-
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/testPropCallElem.js
+++ /dev/null
@@ -1,93 +0,0 @@
-// vim: set ts=4 sw=4 tw=99 et:
-
-function testUKeyUObject(a, key1, key2, key3) {
-    a.a = function () { return this.d; }
-    a.b = function () { return this.e; }
-    a.c = function() { return this.f; }
-    a.d = 20;
-    a.e = "hi";
-    a.f = 500;
-    assertEq(a[key1](), 20);
-    assertEq(a[key2](), "hi");
-    assertEq(a[key3](), 500);
-}
-
-function testVKeyUObject(a, key1, key2, key3) {
-    a.a = function () { return this.d; }
-    a.b = function () { return this.e; }
-    a.c = function() { return this.f; }
-    a.d = 20;
-    a.e = "hi";
-    a.f = 500;
-    assertEq(a["" + key1](), 20);
-    assertEq(a["" + key2](), "hi");
-    assertEq(a["" + key3](), 500);
-}
-
-function testKKeyUObject(a) {
-    a.a = function () { return this.d; }
-    a.b = function () { return this.e; }
-    a.c = function() { return this.f; }
-    a.d = 20;
-    a.e = "hi";
-    a.f = 500;
-    var key1 = "a";
-    var key2 = "b";
-    var key3 = "c";
-    assertEq(a[key1](), 20);
-    assertEq(a[key2](), "hi");
-    assertEq(a[key3](), 500);
-}
-
-function testUKeyVObject(key1, key2, key3) {
-    a = { a: function () { return this.d; },
-          b: function () { return this.e; },
-          c: function () { return this.f; },
-          d: 20,
-          e: "hi",
-          f: 500
-    };
-    assertEq(a[key1](), 20);
-    assertEq(a[key2](), "hi");
-    assertEq(a[key3](), 500);
-}
-
-function testVKeyVObject(key1, key2, key3) {
-    a = { a: function () { return this.d; },
-          b: function () { return this.e; },
-          c: function () { return this.f; },
-          d: 20,
-          e: "hi",
-          f: 500
-    };
-    assertEq(a["" + key1](), 20);
-    assertEq(a["" + key2](), "hi");
-    assertEq(a["" + key3](), 500);
-}
-
-function testKKeyVObject(a) {
-    a = { a: function () { return this.d; },
-          b: function () { return this.e; },
-          c: function () { return this.f; },
-          d: 20,
-          e: "hi",
-          f: 500
-    };
-    var key1 = "a";
-    var key2 = "b";
-    var key3 = "c";
-    assertEq(a[key1](), 20);
-    assertEq(a[key2](), "hi");
-    assertEq(a[key3](), 500);
-}
-
-for (var i = 0; i < 5; i++) {
-    testUKeyUObject({}, "a", "b", "c");
-    testVKeyUObject({}, "a", "b", "c");
-    testKKeyUObject({});
-    testUKeyVObject("a", "b", "c");
-    testVKeyVObject("a", "b", "c");
-    testKKeyVObject();
-}
-
-
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/testPropCallElem2.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// vim: set ts=4 sw=4 tw=99 et:
-
-function testUKeyUObject(a, key1, key2, key3) {
-    a.a = function () { return this.d; }
-    a.b = function () { return this.e; }
-    a.c = function() { return this.f; }
-    a.d = 20;
-    a.e = "hi";
-    a.f = 500;
-    delete a["b"];
-    Object.defineProperty(a, "b", { get: function () { return function () { return this.e; } } });
-    assertEq(a[key1](), 20);
-    assertEq(a[key2](), "hi");
-    assertEq(a[key3](), 500);
-}
-
-for (var i = 0; i < 5; i++)
-    testUKeyUObject({}, "a", "b", "c");
-
-
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1189,17 +1189,17 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_GETPROP)
 
           BEGIN_CASE(JSOP_LENGTH)
             if (!jsop_length())
                 return Compile_Error;
           END_CASE(JSOP_LENGTH)
 
           BEGIN_CASE(JSOP_GETELEM)
-            if (!jsop_getelem(false))
+            if (!jsop_getelem())
                 return Compile_Error;
           END_CASE(JSOP_GETELEM)
 
           BEGIN_CASE(JSOP_SETELEM)
             jsop_setelem();
           END_CASE(JSOP_SETELEM);
 
           BEGIN_CASE(JSOP_CALLNAME)
@@ -1771,17 +1771,21 @@ mjit::Compiler::generateMethod()
           }
           END_CASE(JSOP_CALLUPVAR)
 
           BEGIN_CASE(JSOP_UINT24)
             frame.push(Value(Int32Value((int32_t) GET_UINT24(PC))));
           END_CASE(JSOP_UINT24)
 
           BEGIN_CASE(JSOP_CALLELEM)
-            jsop_getelem(true);
+            prepareStubCall(Uses(2));
+            stubCall(stubs::CallElem);
+            frame.popn(2);
+            frame.pushSynced();
+            frame.pushSynced();
           END_CASE(JSOP_CALLELEM)
 
           BEGIN_CASE(JSOP_STOP)
             /* Safe point! */
             emitReturn(NULL);
             goto done;
           END_CASE(JSOP_STOP)
 
@@ -4508,18 +4512,8 @@ mjit::Compiler::constructThis()
     prepareStubCall(Uses(0));
     if (protoReg != Registers::ArgReg1)
         masm.move(protoReg, Registers::ArgReg1);
     stubCall(stubs::CreateThis);
     frame.freeReg(protoReg);
     return true;
 }
 
-void
-mjit::Compiler::jsop_callelem_slow()
-{
-    prepareStubCall(Uses(2));
-    stubCall(stubs::CallElem);
-    frame.popn(2);
-    frame.pushSynced();
-    frame.pushSynced();
-}
-
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -347,17 +347,16 @@ class Compiler : public BaseCompiler
     void jsop_eleminc(JSOp op, VoidStub);
     void jsop_getgname(uint32 index);
     void jsop_getgname_slow(uint32 index);
     void jsop_setgname(uint32 index);
     void jsop_setgname_slow(uint32 index);
     void jsop_bindgname();
     void jsop_setelem_slow();
     void jsop_getelem_slow();
-    void jsop_callelem_slow();
     void jsop_unbrand();
     bool jsop_getprop(JSAtom *atom, bool typeCheck = true, bool usePropCache = true);
     bool jsop_length();
     bool jsop_setprop(JSAtom *atom, bool usePropCache = true);
     void jsop_setprop_slow(JSAtom *atom, bool usePropCache = true);
     bool jsop_callprop_slow(JSAtom *atom);
     bool jsop_callprop(JSAtom *atom);
     bool jsop_callprop_obj(JSAtom *atom);
@@ -413,18 +412,17 @@ class Compiler : public BaseCompiler
     void jsop_not();
     void jsop_typeof();
     bool booleanJumpScript(JSOp op, jsbytecode *target);
     bool jsop_ifneq(JSOp op, jsbytecode *target);
     bool jsop_andor(JSOp op, jsbytecode *target);
     void jsop_arginc(JSOp op, uint32 slot, bool popped);
     void jsop_localinc(JSOp op, uint32 slot, bool popped);
     void jsop_setelem();
-    bool jsop_getelem(bool isCall);
-    bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id);
+    bool jsop_getelem();
     void jsop_stricteq(JSOp op);
     bool jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     bool jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     void jsop_pos();
 
 #define STUB_CALL_TYPE(type)                                            \
     Call stubCall(type stub) {                                          \
         return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub));             \
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -1354,49 +1354,40 @@ mjit::Compiler::jsop_setelem()
         frame.freeReg(T1);
     }
     frame.freeReg(objReg);
 
     frame.shimmy(2);
     stubcc.rejoin(Changes(0));
 }
 
-static inline bool
-IsCacheableGetElem(FrameEntry *obj, FrameEntry *id)
+bool
+mjit::Compiler::jsop_getelem()
 {
-    if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT)
-        return false;
+    FrameEntry *obj = frame.peek(-2);
+    FrameEntry *id = frame.peek(-1);
+
+    if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) {
+        jsop_getelem_slow();
+        return true;
+    }
+
     if (id->isTypeKnown() &&
         !(id->getKnownType() == JSVAL_TYPE_INT32
 #ifdef JS_POLYIC
           || id->getKnownType() == JSVAL_TYPE_STRING
 #endif
          )) {
-        return false;
+        jsop_getelem_slow();
+        return true;
     }
 
     if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_INT32 && id->isConstant() &&
         id->getValue().toInt32() < 0) {
-        return false;
-    }
-
-    return true;
-}
-
-bool
-mjit::Compiler::jsop_getelem(bool isCall)
-{
-    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;
     }
 
     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);
@@ -1414,24 +1405,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);
@@ -1467,55 +1450,39 @@ 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.claspGuard = masm.jump();
         stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart);
     }
 
     stubcc.leave();
     if (objTypeGuard.isSet())
         objTypeGuard.get().linkTo(stubcc.masm.label(), &stubcc.masm);
 #ifdef JS_POLYIC
     passICAddress(&ic);
-    if (isCall)
-        ic.slowPathCall = stubcc.call(ic::CallElement);
-    else
-        ic.slowPathCall = stubcc.call(ic::GetElement);
+    ic.slowPathCall = stubcc.call(ic::GetElement);
 #else
-    if (isCall)
-        ic.slowPathCall = stubcc.call(stubs::CallElem);
-    else
-        ic.slowPathCall = stubcc.call(stubs::GetElem);
+    ic.slowPathCall = stubcc.call(stubs::GetElem);
 #endif
 
     ic.fastPathRejoin = masm.label();
 
     frame.popn(2);
     frame.pushRegs(ic.typeReg, ic.objReg);
-    if (isCall)
-        frame.pushSynced();
 
     stubcc.rejoin(Changes(2));
 
 #ifdef JS_POLYIC
     if (!getElemICs.append(ic))
         return false;
 #endif
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -45,17 +45,16 @@
 #include "assembler/assembler/RepatchBuffer.h"
 #include "jsscope.h"
 #include "jsnum.h"
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jspropertycache.h"
 #include "jspropertycacheinlines.h"
-#include "jsinterpinlines.h"
 #include "jsautooplen.h"
 
 #if defined JS_POLYIC
 
 using namespace js;
 using namespace js::mjit;
 using namespace js::mjit::ic;
 
@@ -1940,42 +1939,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);
-    BaseIC::disable(cx, reason, stub);
+    BaseIC::disable(cx, reason, JS_FUNC_TO_DATA_PTR(void *, DisabledGetElem));
     return Lookup_Uncacheable;
 }
 
 LookupStatus
 GetElementIC::error(JSContext *cx)
 {
     disable(cx, "error");
     return Lookup_Error;
@@ -2058,23 +2048,16 @@ GetElementIC::attachGetProp(JSContext *c
         holderReg = typeReg;
         masm.move(ImmPtr(holder), holderReg);
         typeRegHasBaseShape = false;
 
         // Guard on the holder's shape.
         protoGuard = masm.guardShape(holderReg, holder);
     }
 
-    if (op == JSOP_CALLELEM) {
-        // Emit a write of |obj| to the top of the stack, before we lose it.
-        Value *thisVp = &cx->regs->sp[-1];
-        Address thisSlot(JSFrameReg, JSStackFrame::offsetOfFixed(thisVp - cx->fp()->slots()));
-        masm.storeValueFromComponents(ImmType(JSVAL_TYPE_OBJECT), objReg, thisSlot);
-    }
-
     // Load the value.
     const Shape *shape = getprop.shape;
     masm.loadObjProp(holder, holderReg, shape, typeReg, objReg);
 
     Jump done = masm.jump();
 
     PICLinker buffer(cx, *this);
     if (!buffer.init(masm))
@@ -2085,19 +2068,19 @@ GetElementIC::attachGetProp(JSContext *c
     buffer.maybeLink(atomTypeGuard, slowPathStart);
     buffer.link(shapeGuard, slowPathStart);
     buffer.maybeLink(protoGuard, slowPathStart);
     buffer.link(done, fastPathRejoin);
 
     CodeLocationLabel cs = buffer.finalizeCodeAddendum();
 #if DEBUG
     char *chars = js_DeflateString(cx, v.toString()->chars(), v.toString()->length());
-    JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n",
-               js_CodeName[op], cs.executableAddress(), id, chars, holder->shape(),
-               cx->fp()->script()->filename, js_FramePCToLineNumber(cx, cx->fp()));
+    JaegerSpew(JSpew_PICs, "generated getelem stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n",
+               cs.executableAddress(), id, chars, holder->shape(), cx->fp()->script()->filename,
+               js_FramePCToLineNumber(cx, cx->fp()));
     cx->free(chars);
 #endif
 
     // Update the inline guards, if needed.
     if (shouldPatchInlineTypeGuard() || shouldPatchUnconditionalClaspGuard()) {
         PICRepatchBuffer repatcher(*this, fastPathStart);
 
         if (shouldPatchInlineTypeGuard()) {
@@ -2171,73 +2154,16 @@ LookupStatus
 GetElementIC::update(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
 {
     if (v.isString())
         return attachGetProp(cx, obj, v, id, vp);
     return disable(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;
-    }
-
-    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 (ic->shouldUpdate(cx)) {
-#ifdef DEBUG
-        f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
-#endif
-        LookupStatus status = ic->update(cx, 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].isUndefined()) && thisv.isObject()) {
-        f.regs.sp[-2] = f.regs.sp[-1];
-        f.regs.sp[-1].setObject(*thisObj);
-        if (!js_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.
     if (!f.regs.sp[-2].isObject()) {
         ic->disable(cx, "non-object");
         stubs::GetElem(f);
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -438,17 +438,16 @@ struct PICInfo : public BaseIC {
 void PurgePICs(JSContext *cx, JSScript *script);
 void JS_FASTCALL GetProp(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 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 *);
 #endif
 
 } /* namespace ic */
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jsjaeger_poly_ic_h__ */