diff --git a/js/src/jit-test/tests/jaeger/testDenseCallElem.js b/js/src/jit-test/tests/jaeger/testDenseCallElem.js deleted file mode 100644 index eadb77f55b9f..000000000000 --- 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(); -} - - diff --git a/js/src/jit-test/tests/jaeger/testPropCallElem.js b/js/src/jit-test/tests/jaeger/testPropCallElem.js deleted file mode 100644 index fd067bbf7a50..000000000000 --- 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(); -} - - diff --git a/js/src/jit-test/tests/jaeger/testPropCallElem2.js b/js/src/jit-test/tests/jaeger/testPropCallElem2.js deleted file mode 100644 index 328193ae4b21..000000000000 --- 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"); - - diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 121facbc12c6..aa4f8a170826 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1194,7 +1194,7 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_LENGTH) BEGIN_CASE(JSOP_GETELEM) - if (!jsop_getelem(false)) + if (!jsop_getelem()) return Compile_Error; END_CASE(JSOP_GETELEM) @@ -1776,7 +1776,11 @@ mjit::Compiler::generateMethod() 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) @@ -4513,13 +4517,3 @@ mjit::Compiler::constructThis() return true; } -void -mjit::Compiler::jsop_callelem_slow() -{ - prepareStubCall(Uses(2)); - stubCall(stubs::CallElem); - frame.popn(2); - frame.pushSynced(); - frame.pushSynced(); -} - diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index d6bd98c41a67..1df3c2b4f1f2 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -352,7 +352,6 @@ class Compiler : public BaseCompiler 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(); @@ -418,8 +417,7 @@ class Compiler : public BaseCompiler 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); diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index 2e5a3a7ebf0a..31d844b59749 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1359,39 +1359,30 @@ mjit::Compiler::jsop_setelem() 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; } @@ -1419,14 +1410,6 @@ mjit::Compiler::jsop_getelem(bool isCall) // 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. @@ -1472,14 +1455,6 @@ mjit::Compiler::jsop_getelem(bool isCall) 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 { @@ -1494,23 +1469,15 @@ mjit::Compiler::jsop_getelem(bool isCall) 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)); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 0c051bdad2db..df2b29e24e5b 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -50,7 +50,6 @@ #include "jsscopeinlines.h" #include "jspropertycache.h" #include "jspropertycacheinlines.h" -#include "jsinterpinlines.h" #include "jsautooplen.h" #if defined JS_POLYIC @@ -1945,12 +1944,6 @@ 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) { @@ -1967,10 +1960,7 @@ 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; } @@ -2063,13 +2053,6 @@ GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid i 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); @@ -2090,9 +2073,9 @@ GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid i 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 @@ -2175,63 +2158,6 @@ GetElementIC::update(JSContext *cx, JSObject *obj, const Value &v, jsid id, Valu 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) { diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 31341e53c9dc..dad2448aedd9 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -443,7 +443,6 @@ 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 */