From 4b0eff1f2b2de2432202ba24e2d87c8cf17d277f Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 15 Oct 2010 11:45:31 +0200 Subject: [PATCH 001/263] Bug 583209 - Use ctypes.libraryName and don't use a full path to load libnss3 from weavecrypto. [r=dwitte] --- services/crypto/modules/WeaveCrypto.js | 39 +++++++++----------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/services/crypto/modules/WeaveCrypto.js b/services/crypto/modules/WeaveCrypto.js index ae7dbf819f8..de16f36437b 100644 --- a/services/crypto/modules/WeaveCrypto.js +++ b/services/crypto/modules/WeaveCrypto.js @@ -108,34 +108,21 @@ WeaveCrypto.prototype = { Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports); // Open the NSS library. - let nssfile = Services.dirsvc.get("GreD", Ci.nsILocalFile); - let os = Services.appinfo.OS; - switch (os) { - case "WINNT": - case "WINMO": - case "WINCE": - nssfile.append("nss3.dll"); - break; - case "Darwin": - nssfile.append("libnss3.dylib"); - break; - case "Linux": - case "SunOS": - case "WebOS": // Palm Pre - nssfile.append("libnss3.so"); - break; - case "Android": - // Android uses a $GREDIR/lib/ subdir. - nssfile.append("lib"); - nssfile.append("libnss3.so"); - break; - default: - throw this.makeException("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED); - } - this.log("Using NSS library " + nssfile.path); + let path = ctypes.libraryName("nss3"); // XXX really want to be able to pass specific dlopen flags here. - let nsslib = ctypes.open(nssfile.path); + var nsslib; + try { + this.log("Trying NSS library without path"); + nsslib = ctypes.open(path); + } catch(e) { + // In case opening the library without a full path fails, + // try again with a full path. + let file = Services.dirsvc.get("GreD", Ci.nsILocalFile); + file.append(path); + this.log("Trying again with path " + file.path); + nsslib = ctypes.open(file.path); + } this.log("Initializing NSS types and function declarations..."); From f0c657cf0a61f1b019ae5887342ea989f54b0c2b Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 15:06:07 -0700 Subject: [PATCH 002/263] Bug 605274 part 1: add OOM checks to JM use of vectors, r=dvander --- js/src/methodjit/BaseAssembler.h | 1 + js/src/methodjit/Compiler.cpp | 83 +++++++++++++++++------------ js/src/methodjit/Compiler.h | 26 ++++----- js/src/methodjit/FastArithmetic.cpp | 31 ++++++----- js/src/methodjit/FastOps.cpp | 65 +++++++++++----------- js/src/methodjit/StubCompiler.cpp | 10 ++-- js/src/methodjit/StubCompiler.h | 2 +- 7 files changed, 121 insertions(+), 97 deletions(-) diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 04f3d9c90b5..0faab4206f2 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -360,6 +360,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste Call call(void *fun) { Call cl = JSC::MacroAssembler::call(); + // XXX callPatches.append(CallPatch(cl, fun)); return cl; } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 66d4cd004f8..0a6a1675561 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -826,13 +826,15 @@ mjit::Compiler::generateMethod() /* :XXX: this isn't really necessary if we follow the branch. */ frame.syncAndForgetEverything(); Jump j = masm.jump(); - jumpAndTrace(j, PC + GET_JUMP_OFFSET(PC)); + if (!jumpAndTrace(j, PC + GET_JUMP_OFFSET(PC))) + return Compile_Error; } END_CASE(JSOP_GOTO) BEGIN_CASE(JSOP_IFEQ) BEGIN_CASE(JSOP_IFNE) - jsop_ifneq(op, PC + GET_JUMP_OFFSET(PC)); + if (!jsop_ifneq(op, PC + GET_JUMP_OFFSET(PC))) + return Compile_Error; END_CASE(JSOP_IFNE) BEGIN_CASE(JSOP_ARGUMENTS) @@ -935,15 +937,18 @@ mjit::Compiler::generateMethod() if (result) { frame.syncAndForgetEverything(); Jump j = masm.jump(); - jumpAndTrace(j, target); + if (!jumpAndTrace(j, target)) + return Compile_Error; } } } else { - emitStubCmpOp(stub, target, fused); + if (!emitStubCmpOp(stub, target, fused)) + return Compile_Error; } } else { /* Anything else should go through the fast path generator. */ - jsop_relational(op, stub, target, fused); + if (!jsop_relational(op, stub, target, fused)) + return Compile_Error; } /* Advance PC manually. */ @@ -1264,7 +1269,8 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_OR) BEGIN_CASE(JSOP_AND) - jsop_andor(op, PC + GET_JUMP_OFFSET(PC)); + if (!jsop_andor(op, PC + GET_JUMP_OFFSET(PC))) + return Compile_Error; END_CASE(JSOP_AND) BEGIN_CASE(JSOP_TABLESWITCH) @@ -1962,17 +1968,16 @@ mjit::Compiler::findCallSite(const CallSite &callSite) return NULL; } -void +bool mjit::Compiler::jumpInScript(Jump j, jsbytecode *pc) { JS_ASSERT(pc >= script->code && uint32(pc - script->code) < script->length); - /* :TODO: OOM failure possible here. */ - - if (pc < PC) + if (pc < PC) { j.linkTo(jumpMap[uint32(pc - script->code)], &masm); - else - branchPatches.append(BranchPatch(j, pc)); + return true; + } + return branchPatches.append(BranchPatch(j, pc)); } void @@ -2513,7 +2518,7 @@ mjit::Compiler::compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const return false; } -void +bool mjit::Compiler::emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused) { prepareStubCall(Uses(2)); @@ -2524,17 +2529,17 @@ mjit::Compiler::emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused) if (!target) { frame.takeReg(Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg); - } else { - JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE); - - frame.syncAndForgetEverything(); - Assembler::Condition cond = (fused == JSOP_IFEQ) - ? Assembler::Zero - : Assembler::NonZero; - Jump j = masm.branchTest32(cond, Registers::ReturnReg, - Registers::ReturnReg); - jumpAndTrace(j, target); + return true; } + + JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE); + frame.syncAndForgetEverything(); + Assembler::Condition cond = (fused == JSOP_IFEQ) + ? Assembler::Zero + : Assembler::NonZero; + Jump j = masm.branchTest32(cond, Registers::ReturnReg, + Registers::ReturnReg); + return jumpAndTrace(j, target); } void @@ -3855,7 +3860,7 @@ mjit::Compiler::iterNext() stubcc.rejoin(Changes(1)); } -void +bool mjit::Compiler::iterMore() { FrameEntry *fe= frame.peek(-1); @@ -3897,7 +3902,7 @@ mjit::Compiler::iterMore() stubcc.rejoin(Changes(1)); - jumpAndTrace(jFast, target, &j); + return jumpAndTrace(jFast, target, &j); } void @@ -4336,13 +4341,18 @@ mjit::Compiler::jsop_eval() * hopelessly corrupted. Take care to only call this before linkExits() and * after rejoin()s. */ -void +bool mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) { + // XXX refactor this little bit #ifndef JS_TRACER - jumpInScript(j, target); - if (slow) - stubcc.jumpInScript(*slow, target); + if (!jumpInScript(j, target)) + return false; + + if (slow) { + if (!stubcc.jumpInScript(*slow, target)) + return false; + } #else if (!addTraceHints || target >= PC || JSOp(*target) != JSOP_TRACE #ifdef JS_MONOIC @@ -4350,10 +4360,13 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) #endif ) { - jumpInScript(j, target); - if (slow) - stubcc.jumpInScript(*slow, target); - return; + if (!jumpInScript(j, target)) + return false; + if (slow) { + if (!stubcc.jumpInScript(*slow, target)) + stubcc.jumpInScript(*slow, target); + } + return true; } # if JS_MONOIC @@ -4396,8 +4409,10 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) restoreFrameRegs(stubcc.masm); stubcc.masm.jump(Registers::ReturnReg); no.linkTo(stubcc.masm.label(), &stubcc.masm); - stubcc.jumpInScript(stubcc.masm.jump(), target); + if (!stubcc.jumpInScript(stubcc.masm.jump(), target)) + return false; #endif + return true; } void diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 6307aa8513d..e2d1dc7b338 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -302,16 +302,16 @@ class Compiler : public BaseCompiler /* Non-emitting helpers. */ uint32 fullAtomIndex(jsbytecode *pc); - void jumpInScript(Jump j, jsbytecode *pc); + bool jumpInScript(Jump j, jsbytecode *pc); bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs); void addCallSite(uint32 id, bool stub); /* Emitting helpers. */ void restoreFrameRegs(Assembler &masm); - void emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused); + bool emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused); void iter(uintN flags); void iterNext(); - void iterMore(); + bool iterMore(); void iterEnd(); MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg); #ifdef JS_POLYIC @@ -323,7 +323,7 @@ class Compiler : public BaseCompiler bool constructThis(); /* Opcode handlers. */ - void jumpAndTrace(Jump j, jsbytecode *target, Jump *slow = NULL); + bool jumpAndTrace(Jump j, jsbytecode *target, Jump *slow = NULL); void jsop_bindname(uint32 index, bool usePropCache); void jsop_setglobal(uint32 index); void jsop_getglobal(uint32 index); @@ -380,10 +380,10 @@ class Compiler : public BaseCompiler MaybeRegisterID &mreg); void maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry *fe, MaybeRegisterID &mreg); - void jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); - void jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); - void jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); - void jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); + bool jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); + bool jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); + bool jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); + bool jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void emitLeftDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc ®s, MaybeJump &lhsNotDouble, MaybeJump &rhsNotNumber, @@ -411,17 +411,17 @@ class Compiler : public BaseCompiler void jsop_bitnot(); void jsop_not(); void jsop_typeof(); - void booleanJumpScript(JSOp op, jsbytecode *target); - void jsop_ifneq(JSOp op, jsbytecode *target); - void jsop_andor(JSOp op, jsbytecode *target); + 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); void jsop_stricteq(JSOp op); - void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); - void jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); + 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) \ diff --git a/js/src/methodjit/FastArithmetic.cpp b/js/src/methodjit/FastArithmetic.cpp index 500748b43dd..ce1b336428a 100644 --- a/js/src/methodjit/FastArithmetic.cpp +++ b/js/src/methodjit/FastArithmetic.cpp @@ -941,7 +941,7 @@ mjit::Compiler::jsop_mod() #endif } -void +bool mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { FrameEntry *rhs = frame.peek(-1); @@ -972,7 +972,7 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar break; default: JS_NOT_REACHED("wat"); - return; + return false; } if (target) { @@ -1068,7 +1068,8 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar else fast = masm.branch32(cond, lvr.dataReg(), rvr.dataReg()); - jumpInScript(fast, target); + if (!jumpInScript(fast, target)) + return false; } else { Jump j = masm.jump(); stubcc.linkExitDirect(j, stubEntry); @@ -1094,7 +1095,8 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar * NB: jumpAndTrace emits to the OOL path, so make sure not to use it * in the middle of an in-progress slow path. */ - jumpAndTrace(fast, target, &stubBranch); + if (!jumpAndTrace(fast, target, &stubBranch)) + return false; } else { /* No fusing. Compare, set, and push a boolean. */ @@ -1144,6 +1146,7 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, resultReg); stubcc.rejoin(Changes(1)); } + return true; } /* @@ -1250,7 +1253,7 @@ DoubleCondForOp(JSOp op, JSOp fused) } } -void +bool mjit::Compiler::jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { FrameEntry *rhs = frame.peek(-1); @@ -1296,7 +1299,8 @@ mjit::Compiler::jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *targe * NB: jumpAndTrace emits to the OOL path, so make sure not to use it * in the middle of an in-progress slow path. */ - jumpAndTrace(j, target, &sj); + if (!jumpAndTrace(j, target, &sj)) + return false; } else { if (lhsNotNumber.isSet()) stubcc.linkExit(lhsNotNumber.get(), Uses(2)); @@ -1319,9 +1323,10 @@ mjit::Compiler::jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *targe stubcc.rejoin(Changes(1)); } + return true; } -void +bool mjit::Compiler::jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { #ifdef DEBUG @@ -1332,11 +1337,11 @@ mjit::Compiler::jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, #endif /* :TODO: optimize this? */ - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } /* See jsop_binary_full() for more information on how this works. */ -void +bool mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { FrameEntry *rhs = frame.peek(-1); @@ -1467,7 +1472,7 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, break; default: JS_NOT_REACHED("unrecognized op"); - return; + return false; } /* Emit the i32 path. */ @@ -1501,7 +1506,8 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, * NB: jumpAndTrace emits to the OOL path, so make sure not to use it * in the middle of an in-progress slow path. */ - jumpAndTrace(fast, target, &j); + if (!jumpAndTrace(fast, target, &j)) + return false; /* Rejoin from the double path. */ if (hasDoublePath) @@ -1557,7 +1563,7 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, break; default: JS_NOT_REACHED("unrecognized op"); - return; + return false; } /* Emit the compare & set. */ @@ -1586,5 +1592,6 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, stubcc.crossJump(doubleDone.get(), masm.label()); stubcc.rejoin(Changes(1)); } + return true; } diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index f9abaea567a..2e5a3a7ebf0 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -644,7 +644,7 @@ CheckNullOrUndefined(FrameEntry *fe) return type == JSVAL_TYPE_NULL || type == JSVAL_TYPE_UNDEFINED; } -void +bool mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { FrameEntry *rhs = frame.peek(-1); @@ -658,10 +658,8 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f /* What's the other mask? */ FrameEntry *test = lhsTest ? rhs : lhs; - if (test->isTypeKnown()) { - emitStubCmpOp(stub, target, fused); - return; - } + if (test->isTypeKnown()) + return emitStubCmpOp(stub, target, fused); /* The other side must be null or undefined. */ RegisterID reg = frame.ownRegForType(test); @@ -691,12 +689,14 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f b1.linkTo(masm.label(), &masm); b2.linkTo(masm.label(), &masm); Jump j2 = masm.jump(); - jumpAndTrace(j2, target); + if (!jumpAndTrace(j2, target)) + return false; j1.linkTo(masm.label(), &masm); } else { Jump j = masm.branchPtr(Assembler::Equal, reg, ImmType(JSVAL_TYPE_UNDEFINED)); Jump j2 = masm.branchPtr(Assembler::NotEqual, reg, ImmType(JSVAL_TYPE_NULL)); - jumpAndTrace(j2, target); + if (!jumpAndTrace(j2, target)) + return false; j.linkTo(masm.label(), &masm); } } else { @@ -710,13 +710,13 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f j3.linkTo(masm.label(), &masm); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, reg); } - return; + return true; } - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } -void +bool mjit::Compiler::jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused) { FrameEntry *rhs = frame.peek(-1); @@ -731,34 +731,31 @@ mjit::Compiler::jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp (rhs->isNotType(JSVAL_TYPE_INT32) && rhs->isNotType(JSVAL_TYPE_DOUBLE) && rhs->isNotType(JSVAL_TYPE_STRING))) { if (op == JSOP_EQ || op == JSOP_NE) - jsop_equality(op, stub, target, fused); - else - emitStubCmpOp(stub, target, fused); - return; + return jsop_equality(op, stub, target, fused); + return emitStubCmpOp(stub, target, fused); } if (op == JSOP_EQ || op == JSOP_NE) { if ((lhs->isNotType(JSVAL_TYPE_INT32) && lhs->isNotType(JSVAL_TYPE_STRING)) || (rhs->isNotType(JSVAL_TYPE_INT32) && rhs->isNotType(JSVAL_TYPE_STRING))) { - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } else if (!target && (lhs->isType(JSVAL_TYPE_STRING) || rhs->isType(JSVAL_TYPE_STRING))) { - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } else if (frame.haveSameBacking(lhs, rhs)) { - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } else { - jsop_equality_int_string(op, stub, target, fused); + return jsop_equality_int_string(op, stub, target, fused); } - return; } if (frame.haveSameBacking(lhs, rhs)) { - jsop_relational_self(op, stub, target, fused); + return jsop_relational_self(op, stub, target, fused); } else if (lhs->isType(JSVAL_TYPE_STRING) || rhs->isType(JSVAL_TYPE_STRING)) { - emitStubCmpOp(stub, target, fused); + return emitStubCmpOp(stub, target, fused); } else if (lhs->isType(JSVAL_TYPE_DOUBLE) || rhs->isType(JSVAL_TYPE_DOUBLE)) { - jsop_relational_double(op, stub, target, fused); + return jsop_relational_double(op, stub, target, fused); } else { - jsop_relational_full(op, stub, target, fused); + return jsop_relational_full(op, stub, target, fused); } } @@ -922,7 +919,7 @@ mjit::Compiler::jsop_typeof() frame.pushTypedPayload(JSVAL_TYPE_STRING, Registers::ReturnReg); } -void +bool mjit::Compiler::booleanJumpScript(JSOp op, jsbytecode *target) { FrameEntry *fe = frame.peek(-1); @@ -1005,10 +1002,10 @@ mjit::Compiler::booleanJumpScript(JSOp op, jsbytecode *target) frame.pop(); - jumpAndTrace(j, target); + return jumpAndTrace(j, target); } -void +bool mjit::Compiler::jsop_ifneq(JSOp op, jsbytecode *target) { FrameEntry *fe = frame.peek(-1); @@ -1022,15 +1019,16 @@ mjit::Compiler::jsop_ifneq(JSOp op, jsbytecode *target) b = !b; if (b) { frame.syncAndForgetEverything(); - jumpAndTrace(masm.jump(), target); + if (!jumpAndTrace(masm.jump(), target)) + return false; } - return; + return true; } - booleanJumpScript(op, target); + return booleanJumpScript(op, target); } -void +bool mjit::Compiler::jsop_andor(JSOp op, jsbytecode *target) { FrameEntry *fe = frame.peek(-1); @@ -1042,14 +1040,15 @@ mjit::Compiler::jsop_andor(JSOp op, jsbytecode *target) if ((op == JSOP_OR && b == JS_TRUE) || (op == JSOP_AND && b == JS_FALSE)) { frame.syncAndForgetEverything(); - jumpAndTrace(masm.jump(), target); + if (!jumpAndTrace(masm.jump(), target)) + return false; } frame.pop(); - return; + return true; } - booleanJumpScript(op, target); + return booleanJumpScript(op, target); } void diff --git a/js/src/methodjit/StubCompiler.cpp b/js/src/methodjit/StubCompiler.cpp index d2f2d972ccd..85ab00c9035 100644 --- a/js/src/methodjit/StubCompiler.cpp +++ b/js/src/methodjit/StubCompiler.cpp @@ -240,12 +240,14 @@ StubCompiler::crossJump(Jump j, Label L) joins.append(CrossPatch(j, L)); } -void +bool StubCompiler::jumpInScript(Jump j, jsbytecode *target) { - if (cc.knownJump(target)) + if (cc.knownJump(target)) { crossJump(j, cc.labelOf(target)); - else - scriptJoins.append(CrossJumpInScript(j, target)); + return true; + } else { + return scriptJoins.append(CrossJumpInScript(j, target)); + } } diff --git a/js/src/methodjit/StubCompiler.h b/js/src/methodjit/StubCompiler.h index 9d3099ac83c..b4f04f60ab9 100644 --- a/js/src/methodjit/StubCompiler.h +++ b/js/src/methodjit/StubCompiler.h @@ -170,7 +170,7 @@ class StubCompiler /* Finish all native code patching. */ void fixCrossJumps(uint8 *ncode, size_t offset, size_t total); - void jumpInScript(Jump j, jsbytecode *target); + bool jumpInScript(Jump j, jsbytecode *target); void crossJump(Jump j, Label l); private: From 1932408866f9df0f7a9fb895a989c87399d042a0 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 15:37:13 -0700 Subject: [PATCH 003/263] Bug 604798: move JM global data to compartment, r=dvander --HG-- extra : rebase_source : 459bbec8a3f8ab3739806da7336a0a10cee9bcd1 --- js/src/jscntxt.cpp | 6 --- js/src/jscntxt.h | 43 +++----------------- js/src/jscntxtinlines.h | 8 ++++ js/src/jscompartment.cpp | 15 ++++++- js/src/jscompartment.h | 39 +++++++++++------- js/src/jsdbgapi.cpp | 4 +- js/src/methodjit/BaseCompiler.h | 3 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- js/src/methodjit/MethodJIT.cpp | 13 +++--- js/src/methodjit/MethodJIT.h | 64 ++++++++++++++++++++++++++++++ js/src/methodjit/Retcon.cpp | 2 +- js/src/methodjit/StubCalls.cpp | 8 ++-- 12 files changed, 129 insertions(+), 78 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index aec05b196c6..b5d40cce86e 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -495,9 +495,6 @@ JSThreadData::init() return false; #ifdef JS_TRACER InitJIT(&traceMonitor); -#endif -#ifdef JS_METHODJIT - jmData.Initialize(); #endif dtoaState = js_NewDtoaState(); if (!dtoaState) { @@ -533,9 +530,6 @@ JSThreadData::finish() propertyCache.~PropertyCache(); #if defined JS_TRACER FinishJIT(&traceMonitor); -#endif -#if defined JS_METHODJIT - jmData.Finish(); #endif stackSpace.finish(); delete mathCache; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index f598696023c..38f71028276 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -128,10 +128,6 @@ namespace JSC { namespace js { -#ifdef JS_METHODJIT -struct VMFrame; -#endif - /* Tracer constants. */ static const size_t MONITOR_N_GLOBAL_STATES = 4; static const size_t FRAGMENT_TABLE_SIZE = 512; @@ -163,7 +159,7 @@ typedef nanojit::HashMap > FragStat #endif namespace mjit { -class CallStackIterator; +class JaegerCompartment; } /* @@ -227,34 +223,6 @@ struct TracerState ~TracerState(); }; -#ifdef JS_METHODJIT -namespace mjit { - struct Trampolines - { - typedef void (*TrampolinePtr)(); - TrampolinePtr forceReturn; - JSC::ExecutablePool *forceReturnPool; -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - TrampolinePtr forceReturnFast; - JSC::ExecutablePool *forceReturnFastPool; -#endif - }; - - struct ThreadData - { - JSC::ExecutableAllocator *execAlloc; - - // Trampolines for JIT code. - Trampolines trampolines; - - VMFrame *activeFrame; - - bool Initialize(); - void Finish(); - }; -} -#endif /* JS_METHODJIT */ - /* * Storage for the execution state and store during trace execution. Generated * code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS| @@ -1158,10 +1126,6 @@ struct JSThreadData { unsigned iterationCounter; #endif -#ifdef JS_METHODJIT - js::mjit::ThreadData jmData; -#endif - /* Lock-free hashed lists of scripts created by eval to garbage-collect. */ JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; @@ -1757,7 +1721,6 @@ struct JSRuntime { #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) #define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) -#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData) #define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) #ifdef DEBUG @@ -2254,6 +2217,10 @@ struct JSContext js::Vector genStack; public: +#ifdef JS_METHODJIT + inline js::mjit::JaegerCompartment *jaegerCompartment(); +#endif + /* Return the generator object for the given generator frame. */ JSGenerator *generatorFor(JSStackFrame *fp) const; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index d3b05b813e8..646468df6c4 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -47,6 +47,7 @@ #include "jsxml.h" #include "jsregexp.h" #include "jsgc.h" +#include "jscompartment.h" namespace js { @@ -77,6 +78,13 @@ GetGlobalForScopeChain(JSContext *cx) } +#ifdef JS_METHODJIT +inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment() +{ + return compartment->jaegerCompartment; +} +#endif + inline bool JSContext::ensureGeneratorStackSpace() { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 70593387089..d75088c2ba5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -44,6 +44,7 @@ #include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" +#include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" #include "methodjit/MonoIC.h" @@ -61,6 +62,9 @@ JSCompartment::JSCompartment(JSRuntime *rt) JSCompartment::~JSCompartment() { +#ifdef JS_METHODJIT + delete jaegerCompartment; +#endif } bool @@ -74,7 +78,16 @@ JSCompartment::init() #ifdef JS_GCMETER memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT); #endif - return crossCompartmentWrappers.init(); + if (!crossCompartmentWrappers.init()) + return false; + +#ifdef JS_METHODJIT + if (!(jaegerCompartment = new mjit::JaegerCompartment)) + return false; + return jaegerCompartment->Initialize(); +#else + return true; +#endif } bool diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 709f0eccce1..2cd3bea9e9e 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -54,25 +54,34 @@ #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */ #endif -struct JS_FRIEND_API(JSCompartment) { - JSRuntime *rt; - JSPrincipals *principals; - js::gc::Chunk *chunk; +namespace js { +namespace mjit { +class JaegerCompartment; +} +} - js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; - js::gc::FreeLists freeLists; +struct JS_FRIEND_API(JSCompartment) { + JSRuntime *rt; + JSPrincipals *principals; + js::gc::Chunk *chunk; + + js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; + js::gc::FreeLists freeLists; #ifdef JS_GCMETER - js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; + js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; #endif - void *data; - bool marked; - js::WrapperMap crossCompartmentWrappers; - bool debugMode; + void *data; + bool marked; + js::WrapperMap crossCompartmentWrappers; - /* List all scripts in this compartment. */ - JSCList scripts; +#ifdef JS_METHODJIT + js::mjit::JaegerCompartment *jaegerCompartment; +#endif + + bool debugMode; // true iff debug mode on + JSCList scripts; // scripts in this compartment /* * Weak references to lazily-created, well-known XML singletons. @@ -81,8 +90,8 @@ struct JS_FRIEND_API(JSCompartment) { * the object graph usually associated with a JSContext's global object, * including the set of standard class objects. See jsxml.c for details. */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; + JSObject *anynameObject; + JSObject *functionNamespaceObject; JSCompartment(JSRuntime *cx); ~JSCompartment(); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 05d03e5eab4..15a31f8e921 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) * correctness. We set the debug flag to false so that the caller * will not later attempt to use debugging features. */ - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) { cx->compartment->debugMode = JS_FALSE; return JS_FALSE; @@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, #ifdef JS_METHODJIT if (script->hasJITCode()) { - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) return JS_FALSE; } diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index d4ccce0ca1e..6063fedcfaf 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -93,8 +93,7 @@ class BaseCompiler : public MacroAssemblerTypedefs public: static JSC::ExecutablePool * GetExecPool(JSContext *cx, size_t size) { - ThreadData *jaegerData = &JS_METHODJIT_DATA(cx); - JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size); + JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size); if (!pool) js_ReportOutOfMemory(cx); return pool; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 7adac76021a..f659c9b6679 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f) cx->throwing = JS_FALSE; cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(cx).trampolines.forceReturn); + cx->jaegerCompartment()->forceReturnTrampoline()); case JSTRAP_THROW: cx->exception = rval; diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index ae9ad37af7f..a10be74eefc 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -116,17 +116,14 @@ extern "C" void JaegerTrampolineReturn(); extern "C" void JS_FASTCALL PushActiveVMFrame(VMFrame &f) { - f.previous = JS_METHODJIT_DATA(f.cx).activeFrame; - JS_METHODJIT_DATA(f.cx).activeFrame = &f; - + f.cx->jaegerCompartment()->pushActiveFrame(&f); f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn)); } extern "C" void JS_FASTCALL PopActiveVMFrame(VMFrame &f) { - JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame); - JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous; + f.cx->jaegerCompartment()->popActiveFrame(); } extern "C" void JS_FASTCALL @@ -683,7 +680,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL); #endif /* _MSC_VER */ bool -ThreadData::Initialize() +JaegerCompartment::Initialize() { execAlloc = new JSC::ExecutableAllocator(); if (!execAlloc) @@ -700,13 +697,13 @@ ThreadData::Initialize() StubCallsForOp[i] = 0; #endif - activeFrame = NULL; + activeFrame_ = NULL; return true; } void -ThreadData::Finish() +JaegerCompartment::Finish() { TrampolineCompiler::release(&trampolines); delete execAlloc; diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 1bcca198b9b..9fa39dd71d9 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -140,6 +140,70 @@ extern "C" void JaegerStubVeneer(void); #endif namespace mjit { + +/* + * Trampolines to force returns from jit code. + * See also TrampolineCompiler::generateForceReturn(Fast). + */ +struct Trampolines { + typedef void (*TrampolinePtr)(); + + TrampolinePtr forceReturn; + JSC::ExecutablePool *forceReturnPool; + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + TrampolinePtr forceReturnFast; + JSC::ExecutablePool *forceReturnFastPool; +#endif +}; + +/* + * Method JIT compartment data. Currently, there is exactly one per + * JS compartment. It would be safe for multiple JS compartments to + * share a JaegerCompartment as long as only one thread can enter + * the JaegerCompartment at a time. + */ +class JaegerCompartment { + JSC::ExecutableAllocator *execAlloc; // allocator for jit code + Trampolines trampolines; // force-return trampolines + VMFrame *activeFrame_; // current active VMFrame + + friend struct JSCompartment; + bool Initialize(); + void Finish(); + + ~JaegerCompartment() { Finish(); } + + public: + JSC::ExecutablePool *poolForSize(size_t size) { + return execAlloc->poolForSize(size); + } + + VMFrame *activeFrame() { + return activeFrame_; + } + + void pushActiveFrame(VMFrame *f) { + f->previous = activeFrame_; + activeFrame_ = f; + } + + void popActiveFrame() { + JS_ASSERT(activeFrame_); + activeFrame_ = activeFrame_->previous; + } + + Trampolines::TrampolinePtr forceReturnTrampoline() const { + return trampolines.forceReturn; + } + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + Trampolines::TrampolinePtr forceReturnFastTrampoline() const { + return trampolines.forceReturnFast; + } +#endif +}; + namespace ic { # if defined JS_POLYIC struct PICInfo; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index f5069e1f9cb..f09dda5209b 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -143,7 +143,7 @@ Recompiler::recompile() } /* Iterate over VMFrames saving the machine and scripted return. */ - for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame; + for (VMFrame *f = cx->jaegerCompartment()->activeFrame(); f != NULL; f = f->previous) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 659c76b76b0..64a999b30ad 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; @@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; From 867a8a9f10cfdee8274248e96360c0085a322d4f Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 16:08:47 -0700 Subject: [PATCH 004/263] Backed out changeset 394e0bd325b1: tinderbox bustage --- js/src/jscntxt.cpp | 6 +++ js/src/jscntxt.h | 43 +++++++++++++++++--- js/src/jscntxtinlines.h | 8 ---- js/src/jscompartment.cpp | 15 +------ js/src/jscompartment.h | 37 +++++++---------- js/src/jsdbgapi.cpp | 4 +- js/src/methodjit/BaseCompiler.h | 3 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- js/src/methodjit/MethodJIT.cpp | 13 +++--- js/src/methodjit/MethodJIT.h | 64 ------------------------------ js/src/methodjit/Retcon.cpp | 2 +- js/src/methodjit/StubCalls.cpp | 8 ++-- 12 files changed, 77 insertions(+), 128 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index b5d40cce86e..aec05b196c6 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -495,6 +495,9 @@ JSThreadData::init() return false; #ifdef JS_TRACER InitJIT(&traceMonitor); +#endif +#ifdef JS_METHODJIT + jmData.Initialize(); #endif dtoaState = js_NewDtoaState(); if (!dtoaState) { @@ -530,6 +533,9 @@ JSThreadData::finish() propertyCache.~PropertyCache(); #if defined JS_TRACER FinishJIT(&traceMonitor); +#endif +#if defined JS_METHODJIT + jmData.Finish(); #endif stackSpace.finish(); delete mathCache; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 38f71028276..f598696023c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -128,6 +128,10 @@ namespace JSC { namespace js { +#ifdef JS_METHODJIT +struct VMFrame; +#endif + /* Tracer constants. */ static const size_t MONITOR_N_GLOBAL_STATES = 4; static const size_t FRAGMENT_TABLE_SIZE = 512; @@ -159,7 +163,7 @@ typedef nanojit::HashMap > FragStat #endif namespace mjit { -class JaegerCompartment; +class CallStackIterator; } /* @@ -223,6 +227,34 @@ struct TracerState ~TracerState(); }; +#ifdef JS_METHODJIT +namespace mjit { + struct Trampolines + { + typedef void (*TrampolinePtr)(); + TrampolinePtr forceReturn; + JSC::ExecutablePool *forceReturnPool; +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + TrampolinePtr forceReturnFast; + JSC::ExecutablePool *forceReturnFastPool; +#endif + }; + + struct ThreadData + { + JSC::ExecutableAllocator *execAlloc; + + // Trampolines for JIT code. + Trampolines trampolines; + + VMFrame *activeFrame; + + bool Initialize(); + void Finish(); + }; +} +#endif /* JS_METHODJIT */ + /* * Storage for the execution state and store during trace execution. Generated * code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS| @@ -1126,6 +1158,10 @@ struct JSThreadData { unsigned iterationCounter; #endif +#ifdef JS_METHODJIT + js::mjit::ThreadData jmData; +#endif + /* Lock-free hashed lists of scripts created by eval to garbage-collect. */ JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; @@ -1721,6 +1757,7 @@ struct JSRuntime { #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) #define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) +#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData) #define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) #ifdef DEBUG @@ -2217,10 +2254,6 @@ struct JSContext js::Vector genStack; public: -#ifdef JS_METHODJIT - inline js::mjit::JaegerCompartment *jaegerCompartment(); -#endif - /* Return the generator object for the given generator frame. */ JSGenerator *generatorFor(JSStackFrame *fp) const; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 646468df6c4..d3b05b813e8 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -47,7 +47,6 @@ #include "jsxml.h" #include "jsregexp.h" #include "jsgc.h" -#include "jscompartment.h" namespace js { @@ -78,13 +77,6 @@ GetGlobalForScopeChain(JSContext *cx) } -#ifdef JS_METHODJIT -inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment() -{ - return compartment->jaegerCompartment; -} -#endif - inline bool JSContext::ensureGeneratorStackSpace() { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d75088c2ba5..70593387089 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -44,7 +44,6 @@ #include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" -#include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" #include "methodjit/MonoIC.h" @@ -62,9 +61,6 @@ JSCompartment::JSCompartment(JSRuntime *rt) JSCompartment::~JSCompartment() { -#ifdef JS_METHODJIT - delete jaegerCompartment; -#endif } bool @@ -78,16 +74,7 @@ JSCompartment::init() #ifdef JS_GCMETER memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT); #endif - if (!crossCompartmentWrappers.init()) - return false; - -#ifdef JS_METHODJIT - if (!(jaegerCompartment = new mjit::JaegerCompartment)) - return false; - return jaegerCompartment->Initialize(); -#else - return true; -#endif + return crossCompartmentWrappers.init(); } bool diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 2cd3bea9e9e..709f0eccce1 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -54,34 +54,25 @@ #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */ #endif -namespace js { -namespace mjit { -class JaegerCompartment; -} -} - struct JS_FRIEND_API(JSCompartment) { - JSRuntime *rt; - JSPrincipals *principals; - js::gc::Chunk *chunk; + JSRuntime *rt; + JSPrincipals *principals; + js::gc::Chunk *chunk; - js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; - js::gc::FreeLists freeLists; + js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; + js::gc::FreeLists freeLists; #ifdef JS_GCMETER - js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; + js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; #endif - void *data; - bool marked; - js::WrapperMap crossCompartmentWrappers; + void *data; + bool marked; + js::WrapperMap crossCompartmentWrappers; + bool debugMode; -#ifdef JS_METHODJIT - js::mjit::JaegerCompartment *jaegerCompartment; -#endif - - bool debugMode; // true iff debug mode on - JSCList scripts; // scripts in this compartment + /* List all scripts in this compartment. */ + JSCList scripts; /* * Weak references to lazily-created, well-known XML singletons. @@ -90,8 +81,8 @@ struct JS_FRIEND_API(JSCompartment) { * the object graph usually associated with a JSContext's global object, * including the set of standard class objects. See jsxml.c for details. */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; + JSObject *anynameObject; + JSObject *functionNamespaceObject; JSCompartment(JSRuntime *cx); ~JSCompartment(); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 15a31f8e921..05d03e5eab4 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) * correctness. We set the debug flag to false so that the caller * will not later attempt to use debugging features. */ - js::mjit::Recompiler recompiler(cx, script); + mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) { cx->compartment->debugMode = JS_FALSE; return JS_FALSE; @@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, #ifdef JS_METHODJIT if (script->hasJITCode()) { - js::mjit::Recompiler recompiler(cx, script); + mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) return JS_FALSE; } diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index 6063fedcfaf..d4ccce0ca1e 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -93,7 +93,8 @@ class BaseCompiler : public MacroAssemblerTypedefs public: static JSC::ExecutablePool * GetExecPool(JSContext *cx, size_t size) { - JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size); + ThreadData *jaegerData = &JS_METHODJIT_DATA(cx); + JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size); if (!pool) js_ReportOutOfMemory(cx); return pool; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index f659c9b6679..7adac76021a 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f) cx->throwing = JS_FALSE; cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, - cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(cx).trampolines.forceReturn); case JSTRAP_THROW: cx->exception = rval; diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index a10be74eefc..ae9ad37af7f 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -116,14 +116,17 @@ extern "C" void JaegerTrampolineReturn(); extern "C" void JS_FASTCALL PushActiveVMFrame(VMFrame &f) { - f.cx->jaegerCompartment()->pushActiveFrame(&f); + f.previous = JS_METHODJIT_DATA(f.cx).activeFrame; + JS_METHODJIT_DATA(f.cx).activeFrame = &f; + f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn)); } extern "C" void JS_FASTCALL PopActiveVMFrame(VMFrame &f) { - f.cx->jaegerCompartment()->popActiveFrame(); + JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame); + JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous; } extern "C" void JS_FASTCALL @@ -680,7 +683,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL); #endif /* _MSC_VER */ bool -JaegerCompartment::Initialize() +ThreadData::Initialize() { execAlloc = new JSC::ExecutableAllocator(); if (!execAlloc) @@ -697,13 +700,13 @@ JaegerCompartment::Initialize() StubCallsForOp[i] = 0; #endif - activeFrame_ = NULL; + activeFrame = NULL; return true; } void -JaegerCompartment::Finish() +ThreadData::Finish() { TrampolineCompiler::release(&trampolines); delete execAlloc; diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 9fa39dd71d9..1bcca198b9b 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -140,70 +140,6 @@ extern "C" void JaegerStubVeneer(void); #endif namespace mjit { - -/* - * Trampolines to force returns from jit code. - * See also TrampolineCompiler::generateForceReturn(Fast). - */ -struct Trampolines { - typedef void (*TrampolinePtr)(); - - TrampolinePtr forceReturn; - JSC::ExecutablePool *forceReturnPool; - -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - TrampolinePtr forceReturnFast; - JSC::ExecutablePool *forceReturnFastPool; -#endif -}; - -/* - * Method JIT compartment data. Currently, there is exactly one per - * JS compartment. It would be safe for multiple JS compartments to - * share a JaegerCompartment as long as only one thread can enter - * the JaegerCompartment at a time. - */ -class JaegerCompartment { - JSC::ExecutableAllocator *execAlloc; // allocator for jit code - Trampolines trampolines; // force-return trampolines - VMFrame *activeFrame_; // current active VMFrame - - friend struct JSCompartment; - bool Initialize(); - void Finish(); - - ~JaegerCompartment() { Finish(); } - - public: - JSC::ExecutablePool *poolForSize(size_t size) { - return execAlloc->poolForSize(size); - } - - VMFrame *activeFrame() { - return activeFrame_; - } - - void pushActiveFrame(VMFrame *f) { - f->previous = activeFrame_; - activeFrame_ = f; - } - - void popActiveFrame() { - JS_ASSERT(activeFrame_); - activeFrame_ = activeFrame_->previous; - } - - Trampolines::TrampolinePtr forceReturnTrampoline() const { - return trampolines.forceReturn; - } - -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - Trampolines::TrampolinePtr forceReturnFastTrampoline() const { - return trampolines.forceReturnFast; - } -#endif -}; - namespace ic { # if defined JS_POLYIC struct PICInfo; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index f09dda5209b..f5069e1f9cb 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -143,7 +143,7 @@ Recompiler::recompile() } /* Iterate over VMFrames saving the machine and scripted return. */ - for (VMFrame *f = cx->jaegerCompartment()->activeFrame(); + for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame; f != NULL; f = f->previous) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 64a999b30ad..659c76b76b0 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnFastTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); #endif break; @@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnFastTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); #endif break; From 77791140016875a35c59a1e24e74c659074f4564 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 15:37:13 -0700 Subject: [PATCH 005/263] Bug 604798: move JM global data to compartment, r=dvander --- js/src/jscntxt.cpp | 6 --- js/src/jscntxt.h | 43 +++----------------- js/src/jscntxtinlines.h | 8 ++++ js/src/jscompartment.cpp | 15 ++++++- js/src/jscompartment.h | 39 +++++++++++------- js/src/jsdbgapi.cpp | 4 +- js/src/methodjit/BaseCompiler.h | 3 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- js/src/methodjit/MethodJIT.cpp | 13 +++--- js/src/methodjit/MethodJIT.h | 64 ++++++++++++++++++++++++++++++ js/src/methodjit/Retcon.cpp | 2 +- js/src/methodjit/StubCalls.cpp | 8 ++-- 12 files changed, 129 insertions(+), 78 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index aec05b196c6..b5d40cce86e 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -495,9 +495,6 @@ JSThreadData::init() return false; #ifdef JS_TRACER InitJIT(&traceMonitor); -#endif -#ifdef JS_METHODJIT - jmData.Initialize(); #endif dtoaState = js_NewDtoaState(); if (!dtoaState) { @@ -533,9 +530,6 @@ JSThreadData::finish() propertyCache.~PropertyCache(); #if defined JS_TRACER FinishJIT(&traceMonitor); -#endif -#if defined JS_METHODJIT - jmData.Finish(); #endif stackSpace.finish(); delete mathCache; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index f598696023c..38f71028276 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -128,10 +128,6 @@ namespace JSC { namespace js { -#ifdef JS_METHODJIT -struct VMFrame; -#endif - /* Tracer constants. */ static const size_t MONITOR_N_GLOBAL_STATES = 4; static const size_t FRAGMENT_TABLE_SIZE = 512; @@ -163,7 +159,7 @@ typedef nanojit::HashMap > FragStat #endif namespace mjit { -class CallStackIterator; +class JaegerCompartment; } /* @@ -227,34 +223,6 @@ struct TracerState ~TracerState(); }; -#ifdef JS_METHODJIT -namespace mjit { - struct Trampolines - { - typedef void (*TrampolinePtr)(); - TrampolinePtr forceReturn; - JSC::ExecutablePool *forceReturnPool; -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - TrampolinePtr forceReturnFast; - JSC::ExecutablePool *forceReturnFastPool; -#endif - }; - - struct ThreadData - { - JSC::ExecutableAllocator *execAlloc; - - // Trampolines for JIT code. - Trampolines trampolines; - - VMFrame *activeFrame; - - bool Initialize(); - void Finish(); - }; -} -#endif /* JS_METHODJIT */ - /* * Storage for the execution state and store during trace execution. Generated * code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS| @@ -1158,10 +1126,6 @@ struct JSThreadData { unsigned iterationCounter; #endif -#ifdef JS_METHODJIT - js::mjit::ThreadData jmData; -#endif - /* Lock-free hashed lists of scripts created by eval to garbage-collect. */ JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; @@ -1757,7 +1721,6 @@ struct JSRuntime { #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) #define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) -#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData) #define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) #ifdef DEBUG @@ -2254,6 +2217,10 @@ struct JSContext js::Vector genStack; public: +#ifdef JS_METHODJIT + inline js::mjit::JaegerCompartment *jaegerCompartment(); +#endif + /* Return the generator object for the given generator frame. */ JSGenerator *generatorFor(JSStackFrame *fp) const; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index d3b05b813e8..646468df6c4 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -47,6 +47,7 @@ #include "jsxml.h" #include "jsregexp.h" #include "jsgc.h" +#include "jscompartment.h" namespace js { @@ -77,6 +78,13 @@ GetGlobalForScopeChain(JSContext *cx) } +#ifdef JS_METHODJIT +inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment() +{ + return compartment->jaegerCompartment; +} +#endif + inline bool JSContext::ensureGeneratorStackSpace() { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 70593387089..d75088c2ba5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -44,6 +44,7 @@ #include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" +#include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" #include "methodjit/MonoIC.h" @@ -61,6 +62,9 @@ JSCompartment::JSCompartment(JSRuntime *rt) JSCompartment::~JSCompartment() { +#ifdef JS_METHODJIT + delete jaegerCompartment; +#endif } bool @@ -74,7 +78,16 @@ JSCompartment::init() #ifdef JS_GCMETER memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT); #endif - return crossCompartmentWrappers.init(); + if (!crossCompartmentWrappers.init()) + return false; + +#ifdef JS_METHODJIT + if (!(jaegerCompartment = new mjit::JaegerCompartment)) + return false; + return jaegerCompartment->Initialize(); +#else + return true; +#endif } bool diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 709f0eccce1..2cd3bea9e9e 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -54,25 +54,34 @@ #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */ #endif -struct JS_FRIEND_API(JSCompartment) { - JSRuntime *rt; - JSPrincipals *principals; - js::gc::Chunk *chunk; +namespace js { +namespace mjit { +class JaegerCompartment; +} +} - js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; - js::gc::FreeLists freeLists; +struct JS_FRIEND_API(JSCompartment) { + JSRuntime *rt; + JSPrincipals *principals; + js::gc::Chunk *chunk; + + js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; + js::gc::FreeLists freeLists; #ifdef JS_GCMETER - js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; + js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; #endif - void *data; - bool marked; - js::WrapperMap crossCompartmentWrappers; - bool debugMode; + void *data; + bool marked; + js::WrapperMap crossCompartmentWrappers; - /* List all scripts in this compartment. */ - JSCList scripts; +#ifdef JS_METHODJIT + js::mjit::JaegerCompartment *jaegerCompartment; +#endif + + bool debugMode; // true iff debug mode on + JSCList scripts; // scripts in this compartment /* * Weak references to lazily-created, well-known XML singletons. @@ -81,8 +90,8 @@ struct JS_FRIEND_API(JSCompartment) { * the object graph usually associated with a JSContext's global object, * including the set of standard class objects. See jsxml.c for details. */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; + JSObject *anynameObject; + JSObject *functionNamespaceObject; JSCompartment(JSRuntime *cx); ~JSCompartment(); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 05d03e5eab4..15a31f8e921 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) * correctness. We set the debug flag to false so that the caller * will not later attempt to use debugging features. */ - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) { cx->compartment->debugMode = JS_FALSE; return JS_FALSE; @@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, #ifdef JS_METHODJIT if (script->hasJITCode()) { - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) return JS_FALSE; } diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index d4ccce0ca1e..6063fedcfaf 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -93,8 +93,7 @@ class BaseCompiler : public MacroAssemblerTypedefs public: static JSC::ExecutablePool * GetExecPool(JSContext *cx, size_t size) { - ThreadData *jaegerData = &JS_METHODJIT_DATA(cx); - JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size); + JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size); if (!pool) js_ReportOutOfMemory(cx); return pool; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 7adac76021a..f659c9b6679 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f) cx->throwing = JS_FALSE; cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(cx).trampolines.forceReturn); + cx->jaegerCompartment()->forceReturnTrampoline()); case JSTRAP_THROW: cx->exception = rval; diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index ae9ad37af7f..a10be74eefc 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -116,17 +116,14 @@ extern "C" void JaegerTrampolineReturn(); extern "C" void JS_FASTCALL PushActiveVMFrame(VMFrame &f) { - f.previous = JS_METHODJIT_DATA(f.cx).activeFrame; - JS_METHODJIT_DATA(f.cx).activeFrame = &f; - + f.cx->jaegerCompartment()->pushActiveFrame(&f); f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn)); } extern "C" void JS_FASTCALL PopActiveVMFrame(VMFrame &f) { - JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame); - JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous; + f.cx->jaegerCompartment()->popActiveFrame(); } extern "C" void JS_FASTCALL @@ -683,7 +680,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL); #endif /* _MSC_VER */ bool -ThreadData::Initialize() +JaegerCompartment::Initialize() { execAlloc = new JSC::ExecutableAllocator(); if (!execAlloc) @@ -700,13 +697,13 @@ ThreadData::Initialize() StubCallsForOp[i] = 0; #endif - activeFrame = NULL; + activeFrame_ = NULL; return true; } void -ThreadData::Finish() +JaegerCompartment::Finish() { TrampolineCompiler::release(&trampolines); delete execAlloc; diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 1bcca198b9b..9fa39dd71d9 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -140,6 +140,70 @@ extern "C" void JaegerStubVeneer(void); #endif namespace mjit { + +/* + * Trampolines to force returns from jit code. + * See also TrampolineCompiler::generateForceReturn(Fast). + */ +struct Trampolines { + typedef void (*TrampolinePtr)(); + + TrampolinePtr forceReturn; + JSC::ExecutablePool *forceReturnPool; + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + TrampolinePtr forceReturnFast; + JSC::ExecutablePool *forceReturnFastPool; +#endif +}; + +/* + * Method JIT compartment data. Currently, there is exactly one per + * JS compartment. It would be safe for multiple JS compartments to + * share a JaegerCompartment as long as only one thread can enter + * the JaegerCompartment at a time. + */ +class JaegerCompartment { + JSC::ExecutableAllocator *execAlloc; // allocator for jit code + Trampolines trampolines; // force-return trampolines + VMFrame *activeFrame_; // current active VMFrame + + friend struct JSCompartment; + bool Initialize(); + void Finish(); + + ~JaegerCompartment() { Finish(); } + + public: + JSC::ExecutablePool *poolForSize(size_t size) { + return execAlloc->poolForSize(size); + } + + VMFrame *activeFrame() { + return activeFrame_; + } + + void pushActiveFrame(VMFrame *f) { + f->previous = activeFrame_; + activeFrame_ = f; + } + + void popActiveFrame() { + JS_ASSERT(activeFrame_); + activeFrame_ = activeFrame_->previous; + } + + Trampolines::TrampolinePtr forceReturnTrampoline() const { + return trampolines.forceReturn; + } + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + Trampolines::TrampolinePtr forceReturnFastTrampoline() const { + return trampolines.forceReturnFast; + } +#endif +}; + namespace ic { # if defined JS_POLYIC struct PICInfo; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index f5069e1f9cb..f09dda5209b 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -143,7 +143,7 @@ Recompiler::recompile() } /* Iterate over VMFrames saving the machine and scripted return. */ - for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame; + for (VMFrame *f = cx->jaegerCompartment()->activeFrame(); f != NULL; f = f->previous) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 659c76b76b0..64a999b30ad 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; @@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; From 747cf336865be2458ecf8d43e3a86a1ccd14d9bc Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 16:22:44 -0700 Subject: [PATCH 006/263] Backed out changeset ecd2f8753d5a: argh, fixes didn't land for some reason --- js/src/jscntxt.cpp | 6 +++ js/src/jscntxt.h | 43 +++++++++++++++++--- js/src/jscntxtinlines.h | 8 ---- js/src/jscompartment.cpp | 15 +------ js/src/jscompartment.h | 37 +++++++---------- js/src/jsdbgapi.cpp | 4 +- js/src/methodjit/BaseCompiler.h | 3 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- js/src/methodjit/MethodJIT.cpp | 13 +++--- js/src/methodjit/MethodJIT.h | 64 ------------------------------ js/src/methodjit/Retcon.cpp | 2 +- js/src/methodjit/StubCalls.cpp | 8 ++-- 12 files changed, 77 insertions(+), 128 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index b5d40cce86e..aec05b196c6 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -495,6 +495,9 @@ JSThreadData::init() return false; #ifdef JS_TRACER InitJIT(&traceMonitor); +#endif +#ifdef JS_METHODJIT + jmData.Initialize(); #endif dtoaState = js_NewDtoaState(); if (!dtoaState) { @@ -530,6 +533,9 @@ JSThreadData::finish() propertyCache.~PropertyCache(); #if defined JS_TRACER FinishJIT(&traceMonitor); +#endif +#if defined JS_METHODJIT + jmData.Finish(); #endif stackSpace.finish(); delete mathCache; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 38f71028276..f598696023c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -128,6 +128,10 @@ namespace JSC { namespace js { +#ifdef JS_METHODJIT +struct VMFrame; +#endif + /* Tracer constants. */ static const size_t MONITOR_N_GLOBAL_STATES = 4; static const size_t FRAGMENT_TABLE_SIZE = 512; @@ -159,7 +163,7 @@ typedef nanojit::HashMap > FragStat #endif namespace mjit { -class JaegerCompartment; +class CallStackIterator; } /* @@ -223,6 +227,34 @@ struct TracerState ~TracerState(); }; +#ifdef JS_METHODJIT +namespace mjit { + struct Trampolines + { + typedef void (*TrampolinePtr)(); + TrampolinePtr forceReturn; + JSC::ExecutablePool *forceReturnPool; +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + TrampolinePtr forceReturnFast; + JSC::ExecutablePool *forceReturnFastPool; +#endif + }; + + struct ThreadData + { + JSC::ExecutableAllocator *execAlloc; + + // Trampolines for JIT code. + Trampolines trampolines; + + VMFrame *activeFrame; + + bool Initialize(); + void Finish(); + }; +} +#endif /* JS_METHODJIT */ + /* * Storage for the execution state and store during trace execution. Generated * code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS| @@ -1126,6 +1158,10 @@ struct JSThreadData { unsigned iterationCounter; #endif +#ifdef JS_METHODJIT + js::mjit::ThreadData jmData; +#endif + /* Lock-free hashed lists of scripts created by eval to garbage-collect. */ JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; @@ -1721,6 +1757,7 @@ struct JSRuntime { #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) #define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) +#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData) #define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) #ifdef DEBUG @@ -2217,10 +2254,6 @@ struct JSContext js::Vector genStack; public: -#ifdef JS_METHODJIT - inline js::mjit::JaegerCompartment *jaegerCompartment(); -#endif - /* Return the generator object for the given generator frame. */ JSGenerator *generatorFor(JSStackFrame *fp) const; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 646468df6c4..d3b05b813e8 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -47,7 +47,6 @@ #include "jsxml.h" #include "jsregexp.h" #include "jsgc.h" -#include "jscompartment.h" namespace js { @@ -78,13 +77,6 @@ GetGlobalForScopeChain(JSContext *cx) } -#ifdef JS_METHODJIT -inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment() -{ - return compartment->jaegerCompartment; -} -#endif - inline bool JSContext::ensureGeneratorStackSpace() { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d75088c2ba5..70593387089 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -44,7 +44,6 @@ #include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" -#include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" #include "methodjit/MonoIC.h" @@ -62,9 +61,6 @@ JSCompartment::JSCompartment(JSRuntime *rt) JSCompartment::~JSCompartment() { -#ifdef JS_METHODJIT - delete jaegerCompartment; -#endif } bool @@ -78,16 +74,7 @@ JSCompartment::init() #ifdef JS_GCMETER memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT); #endif - if (!crossCompartmentWrappers.init()) - return false; - -#ifdef JS_METHODJIT - if (!(jaegerCompartment = new mjit::JaegerCompartment)) - return false; - return jaegerCompartment->Initialize(); -#else - return true; -#endif + return crossCompartmentWrappers.init(); } bool diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 2cd3bea9e9e..709f0eccce1 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -54,34 +54,25 @@ #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */ #endif -namespace js { -namespace mjit { -class JaegerCompartment; -} -} - struct JS_FRIEND_API(JSCompartment) { - JSRuntime *rt; - JSPrincipals *principals; - js::gc::Chunk *chunk; + JSRuntime *rt; + JSPrincipals *principals; + js::gc::Chunk *chunk; - js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; - js::gc::FreeLists freeLists; + js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; + js::gc::FreeLists freeLists; #ifdef JS_GCMETER - js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; + js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; #endif - void *data; - bool marked; - js::WrapperMap crossCompartmentWrappers; + void *data; + bool marked; + js::WrapperMap crossCompartmentWrappers; + bool debugMode; -#ifdef JS_METHODJIT - js::mjit::JaegerCompartment *jaegerCompartment; -#endif - - bool debugMode; // true iff debug mode on - JSCList scripts; // scripts in this compartment + /* List all scripts in this compartment. */ + JSCList scripts; /* * Weak references to lazily-created, well-known XML singletons. @@ -90,8 +81,8 @@ struct JS_FRIEND_API(JSCompartment) { * the object graph usually associated with a JSContext's global object, * including the set of standard class objects. See jsxml.c for details. */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; + JSObject *anynameObject; + JSObject *functionNamespaceObject; JSCompartment(JSRuntime *cx); ~JSCompartment(); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 15a31f8e921..05d03e5eab4 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) * correctness. We set the debug flag to false so that the caller * will not later attempt to use debugging features. */ - js::mjit::Recompiler recompiler(cx, script); + mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) { cx->compartment->debugMode = JS_FALSE; return JS_FALSE; @@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, #ifdef JS_METHODJIT if (script->hasJITCode()) { - js::mjit::Recompiler recompiler(cx, script); + mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) return JS_FALSE; } diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index 6063fedcfaf..d4ccce0ca1e 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -93,7 +93,8 @@ class BaseCompiler : public MacroAssemblerTypedefs public: static JSC::ExecutablePool * GetExecPool(JSContext *cx, size_t size) { - JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size); + ThreadData *jaegerData = &JS_METHODJIT_DATA(cx); + JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size); if (!pool) js_ReportOutOfMemory(cx); return pool; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index f659c9b6679..7adac76021a 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f) cx->throwing = JS_FALSE; cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, - cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(cx).trampolines.forceReturn); case JSTRAP_THROW: cx->exception = rval; diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index a10be74eefc..ae9ad37af7f 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -116,14 +116,17 @@ extern "C" void JaegerTrampolineReturn(); extern "C" void JS_FASTCALL PushActiveVMFrame(VMFrame &f) { - f.cx->jaegerCompartment()->pushActiveFrame(&f); + f.previous = JS_METHODJIT_DATA(f.cx).activeFrame; + JS_METHODJIT_DATA(f.cx).activeFrame = &f; + f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn)); } extern "C" void JS_FASTCALL PopActiveVMFrame(VMFrame &f) { - f.cx->jaegerCompartment()->popActiveFrame(); + JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame); + JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous; } extern "C" void JS_FASTCALL @@ -680,7 +683,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL); #endif /* _MSC_VER */ bool -JaegerCompartment::Initialize() +ThreadData::Initialize() { execAlloc = new JSC::ExecutableAllocator(); if (!execAlloc) @@ -697,13 +700,13 @@ JaegerCompartment::Initialize() StubCallsForOp[i] = 0; #endif - activeFrame_ = NULL; + activeFrame = NULL; return true; } void -JaegerCompartment::Finish() +ThreadData::Finish() { TrampolineCompiler::release(&trampolines); delete execAlloc; diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 9fa39dd71d9..1bcca198b9b 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -140,70 +140,6 @@ extern "C" void JaegerStubVeneer(void); #endif namespace mjit { - -/* - * Trampolines to force returns from jit code. - * See also TrampolineCompiler::generateForceReturn(Fast). - */ -struct Trampolines { - typedef void (*TrampolinePtr)(); - - TrampolinePtr forceReturn; - JSC::ExecutablePool *forceReturnPool; - -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - TrampolinePtr forceReturnFast; - JSC::ExecutablePool *forceReturnFastPool; -#endif -}; - -/* - * Method JIT compartment data. Currently, there is exactly one per - * JS compartment. It would be safe for multiple JS compartments to - * share a JaegerCompartment as long as only one thread can enter - * the JaegerCompartment at a time. - */ -class JaegerCompartment { - JSC::ExecutableAllocator *execAlloc; // allocator for jit code - Trampolines trampolines; // force-return trampolines - VMFrame *activeFrame_; // current active VMFrame - - friend struct JSCompartment; - bool Initialize(); - void Finish(); - - ~JaegerCompartment() { Finish(); } - - public: - JSC::ExecutablePool *poolForSize(size_t size) { - return execAlloc->poolForSize(size); - } - - VMFrame *activeFrame() { - return activeFrame_; - } - - void pushActiveFrame(VMFrame *f) { - f->previous = activeFrame_; - activeFrame_ = f; - } - - void popActiveFrame() { - JS_ASSERT(activeFrame_); - activeFrame_ = activeFrame_->previous; - } - - Trampolines::TrampolinePtr forceReturnTrampoline() const { - return trampolines.forceReturn; - } - -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - Trampolines::TrampolinePtr forceReturnFastTrampoline() const { - return trampolines.forceReturnFast; - } -#endif -}; - namespace ic { # if defined JS_POLYIC struct PICInfo; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index f09dda5209b..f5069e1f9cb 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -143,7 +143,7 @@ Recompiler::recompile() } /* Iterate over VMFrames saving the machine and scripted return. */ - for (VMFrame *f = cx->jaegerCompartment()->activeFrame(); + for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame; f != NULL; f = f->previous) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 64a999b30ad..659c76b76b0 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnFastTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); #endif break; @@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnFastTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - f.cx->jaegerCompartment()->forceReturnTrampoline()); + JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); #endif break; From 1f754fcd0fa842b1714da1712ce558e3ce43052d Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 15:37:13 -0700 Subject: [PATCH 007/263] Bug 604798: move JM global data to compartment, r=dvander --- js/src/jscntxt.cpp | 6 --- js/src/jscntxt.h | 43 +++----------------- js/src/jscntxtinlines.h | 8 ++++ js/src/jscompartment.cpp | 15 ++++++- js/src/jscompartment.h | 39 +++++++++++------- js/src/jsdbgapi.cpp | 4 +- js/src/methodjit/BaseCompiler.h | 3 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- js/src/methodjit/MethodJIT.cpp | 13 +++--- js/src/methodjit/MethodJIT.h | 64 ++++++++++++++++++++++++++++++ js/src/methodjit/Retcon.cpp | 2 +- js/src/methodjit/StubCalls.cpp | 8 ++-- 12 files changed, 129 insertions(+), 78 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index aec05b196c6..b5d40cce86e 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -495,9 +495,6 @@ JSThreadData::init() return false; #ifdef JS_TRACER InitJIT(&traceMonitor); -#endif -#ifdef JS_METHODJIT - jmData.Initialize(); #endif dtoaState = js_NewDtoaState(); if (!dtoaState) { @@ -533,9 +530,6 @@ JSThreadData::finish() propertyCache.~PropertyCache(); #if defined JS_TRACER FinishJIT(&traceMonitor); -#endif -#if defined JS_METHODJIT - jmData.Finish(); #endif stackSpace.finish(); delete mathCache; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index f598696023c..38f71028276 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -128,10 +128,6 @@ namespace JSC { namespace js { -#ifdef JS_METHODJIT -struct VMFrame; -#endif - /* Tracer constants. */ static const size_t MONITOR_N_GLOBAL_STATES = 4; static const size_t FRAGMENT_TABLE_SIZE = 512; @@ -163,7 +159,7 @@ typedef nanojit::HashMap > FragStat #endif namespace mjit { -class CallStackIterator; +class JaegerCompartment; } /* @@ -227,34 +223,6 @@ struct TracerState ~TracerState(); }; -#ifdef JS_METHODJIT -namespace mjit { - struct Trampolines - { - typedef void (*TrampolinePtr)(); - TrampolinePtr forceReturn; - JSC::ExecutablePool *forceReturnPool; -#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) - TrampolinePtr forceReturnFast; - JSC::ExecutablePool *forceReturnFastPool; -#endif - }; - - struct ThreadData - { - JSC::ExecutableAllocator *execAlloc; - - // Trampolines for JIT code. - Trampolines trampolines; - - VMFrame *activeFrame; - - bool Initialize(); - void Finish(); - }; -} -#endif /* JS_METHODJIT */ - /* * Storage for the execution state and store during trace execution. Generated * code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS| @@ -1158,10 +1126,6 @@ struct JSThreadData { unsigned iterationCounter; #endif -#ifdef JS_METHODJIT - js::mjit::ThreadData jmData; -#endif - /* Lock-free hashed lists of scripts created by eval to garbage-collect. */ JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE]; @@ -1757,7 +1721,6 @@ struct JSRuntime { #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache) #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache) #define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor) -#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData) #define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC) #ifdef DEBUG @@ -2254,6 +2217,10 @@ struct JSContext js::Vector genStack; public: +#ifdef JS_METHODJIT + inline js::mjit::JaegerCompartment *jaegerCompartment(); +#endif + /* Return the generator object for the given generator frame. */ JSGenerator *generatorFor(JSStackFrame *fp) const; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index d3b05b813e8..646468df6c4 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -47,6 +47,7 @@ #include "jsxml.h" #include "jsregexp.h" #include "jsgc.h" +#include "jscompartment.h" namespace js { @@ -77,6 +78,13 @@ GetGlobalForScopeChain(JSContext *cx) } +#ifdef JS_METHODJIT +inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment() +{ + return compartment->jaegerCompartment; +} +#endif + inline bool JSContext::ensureGeneratorStackSpace() { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 70593387089..d75088c2ba5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -44,6 +44,7 @@ #include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" +#include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" #include "methodjit/MonoIC.h" @@ -61,6 +62,9 @@ JSCompartment::JSCompartment(JSRuntime *rt) JSCompartment::~JSCompartment() { +#ifdef JS_METHODJIT + delete jaegerCompartment; +#endif } bool @@ -74,7 +78,16 @@ JSCompartment::init() #ifdef JS_GCMETER memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT); #endif - return crossCompartmentWrappers.init(); + if (!crossCompartmentWrappers.init()) + return false; + +#ifdef JS_METHODJIT + if (!(jaegerCompartment = new mjit::JaegerCompartment)) + return false; + return jaegerCompartment->Initialize(); +#else + return true; +#endif } bool diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 709f0eccce1..2cd3bea9e9e 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -54,25 +54,34 @@ #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */ #endif -struct JS_FRIEND_API(JSCompartment) { - JSRuntime *rt; - JSPrincipals *principals; - js::gc::Chunk *chunk; +namespace js { +namespace mjit { +class JaegerCompartment; +} +} - js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; - js::gc::FreeLists freeLists; +struct JS_FRIEND_API(JSCompartment) { + JSRuntime *rt; + JSPrincipals *principals; + js::gc::Chunk *chunk; + + js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT]; + js::gc::FreeLists freeLists; #ifdef JS_GCMETER - js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; + js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT]; #endif - void *data; - bool marked; - js::WrapperMap crossCompartmentWrappers; - bool debugMode; + void *data; + bool marked; + js::WrapperMap crossCompartmentWrappers; - /* List all scripts in this compartment. */ - JSCList scripts; +#ifdef JS_METHODJIT + js::mjit::JaegerCompartment *jaegerCompartment; +#endif + + bool debugMode; // true iff debug mode on + JSCList scripts; // scripts in this compartment /* * Weak references to lazily-created, well-known XML singletons. @@ -81,8 +90,8 @@ struct JS_FRIEND_API(JSCompartment) { * the object graph usually associated with a JSContext's global object, * including the set of standard class objects. See jsxml.c for details. */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; + JSObject *anynameObject; + JSObject *functionNamespaceObject; JSCompartment(JSRuntime *cx); ~JSCompartment(); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 05d03e5eab4..15a31f8e921 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) * correctness. We set the debug flag to false so that the caller * will not later attempt to use debugging features. */ - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) { cx->compartment->debugMode = JS_FALSE; return JS_FALSE; @@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, #ifdef JS_METHODJIT if (script->hasJITCode()) { - mjit::Recompiler recompiler(cx, script); + js::mjit::Recompiler recompiler(cx, script); if (!recompiler.recompile()) return JS_FALSE; } diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index d4ccce0ca1e..6063fedcfaf 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -93,8 +93,7 @@ class BaseCompiler : public MacroAssemblerTypedefs public: static JSC::ExecutablePool * GetExecPool(JSContext *cx, size_t size) { - ThreadData *jaegerData = &JS_METHODJIT_DATA(cx); - JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size); + JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size); if (!pool) js_ReportOutOfMemory(cx); return pool; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 7adac76021a..f659c9b6679 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f) cx->throwing = JS_FALSE; cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(cx).trampolines.forceReturn); + cx->jaegerCompartment()->forceReturnTrampoline()); case JSTRAP_THROW: cx->exception = rval; diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index ae9ad37af7f..a10be74eefc 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -116,17 +116,14 @@ extern "C" void JaegerTrampolineReturn(); extern "C" void JS_FASTCALL PushActiveVMFrame(VMFrame &f) { - f.previous = JS_METHODJIT_DATA(f.cx).activeFrame; - JS_METHODJIT_DATA(f.cx).activeFrame = &f; - + f.cx->jaegerCompartment()->pushActiveFrame(&f); f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn)); } extern "C" void JS_FASTCALL PopActiveVMFrame(VMFrame &f) { - JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame); - JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous; + f.cx->jaegerCompartment()->popActiveFrame(); } extern "C" void JS_FASTCALL @@ -683,7 +680,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL); #endif /* _MSC_VER */ bool -ThreadData::Initialize() +JaegerCompartment::Initialize() { execAlloc = new JSC::ExecutableAllocator(); if (!execAlloc) @@ -700,13 +697,13 @@ ThreadData::Initialize() StubCallsForOp[i] = 0; #endif - activeFrame = NULL; + activeFrame_ = NULL; return true; } void -ThreadData::Finish() +JaegerCompartment::Finish() { TrampolineCompiler::release(&trampolines); delete execAlloc; diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 1bcca198b9b..26e9d497e3e 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -140,6 +140,70 @@ extern "C" void JaegerStubVeneer(void); #endif namespace mjit { + +/* + * Trampolines to force returns from jit code. + * See also TrampolineCompiler::generateForceReturn(Fast). + */ +struct Trampolines { + typedef void (*TrampolinePtr)(); + + TrampolinePtr forceReturn; + JSC::ExecutablePool *forceReturnPool; + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + TrampolinePtr forceReturnFast; + JSC::ExecutablePool *forceReturnFastPool; +#endif +}; + +/* + * Method JIT compartment data. Currently, there is exactly one per + * JS compartment. It would be safe for multiple JS compartments to + * share a JaegerCompartment as long as only one thread can enter + * the JaegerCompartment at a time. + */ +class JaegerCompartment { + JSC::ExecutableAllocator *execAlloc; // allocator for jit code + Trampolines trampolines; // force-return trampolines + VMFrame *activeFrame_; // current active VMFrame + + void Finish(); + + public: + bool Initialize(); + + ~JaegerCompartment() { Finish(); } + + JSC::ExecutablePool *poolForSize(size_t size) { + return execAlloc->poolForSize(size); + } + + VMFrame *activeFrame() { + return activeFrame_; + } + + void pushActiveFrame(VMFrame *f) { + f->previous = activeFrame_; + activeFrame_ = f; + } + + void popActiveFrame() { + JS_ASSERT(activeFrame_); + activeFrame_ = activeFrame_->previous; + } + + Trampolines::TrampolinePtr forceReturnTrampoline() const { + return trampolines.forceReturn; + } + +#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) + Trampolines::TrampolinePtr forceReturnFastTrampoline() const { + return trampolines.forceReturnFast; + } +#endif +}; + namespace ic { # if defined JS_POLYIC struct PICInfo; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index f5069e1f9cb..f09dda5209b 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -143,7 +143,7 @@ Recompiler::recompile() } /* Iterate over VMFrames saving the machine and scripted return. */ - for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame; + for (VMFrame *f = cx->jaegerCompartment()->activeFrame(); f != NULL; f = f->previous) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 659c76b76b0..64a999b30ad 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; @@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc) f.cx->fp()->setReturnValue(rval); #if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64) *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast); + f.cx->jaegerCompartment()->forceReturnFastTrampoline()); #else *f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *, - JS_METHODJIT_DATA(f.cx).trampolines.forceReturn); + f.cx->jaegerCompartment()->forceReturnTrampoline()); #endif break; From d6fffb8112994c934c8824f7978c35e106a89098 Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Fri, 29 Oct 2010 16:37:43 -0700 Subject: [PATCH 008/263] Fix MSVC warnings. --- js/src/jsdbgapi.cpp | 2 +- js/src/methodjit/Compiler.cpp | 2 +- js/src/methodjit/Compiler.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 15a31f8e921..99a17bb6312 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -122,7 +122,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug) for (JSScript *script = (JSScript *)cx->compartment->scripts.next; &script->links != &cx->compartment->scripts; script = (JSScript *)script->links.next) { - if (script->debugMode != debug && + if (script->debugMode != (bool) debug && script->hasJITCode() && !IsScriptLive(cx, script)) { /* diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 0a6a1675561..aa6ef2456d0 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -108,7 +108,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp) callPatches(ContextAllocPolicy(cx)), callSites(ContextAllocPolicy(cx)), doubleList(ContextAllocPolicy(cx)), - stubcc(cx, *this, frame, script), + stubcc(cx, *thisFromCtor(), frame, script), debugMode(cx->compartment->debugMode) #if defined JS_TRACER ,addTraceHints(cx->traceJitEnabled) diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index e2d1dc7b338..2fe0d87ee63 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -277,6 +277,7 @@ class Compiler : public BaseCompiler bool debugMode; bool addTraceHints; + Compiler *thisFromCtor() { return this; } public: // Special atom index used to indicate that the atom is 'length'. This // follows interpreter usage in JSOP_LENGTH. From 630aabe3712e1b643cb1e6310ed2700efa701935 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 21 Oct 2010 14:31:29 -0700 Subject: [PATCH 009/263] Bug 604504 - Implement an eval kernel that obj_eval and JSOP_EVAL can each call. r=jorendorff,dvander --- js/src/jsinterp.cpp | 27 ++- js/src/jsinterp.h | 10 + js/src/jsobj.cpp | 182 +++++++++--------- js/src/jsobj.h | 16 ++ js/src/jsprobes.h | 19 ++ js/src/methodjit/Compiler.cpp | 20 +- js/src/methodjit/Compiler.h | 2 +- js/src/methodjit/InvokeHelpers.cpp | 24 +++ js/src/methodjit/StubCalls.h | 1 + .../eval-native-callback-is-indirect.js | 32 +++ js/src/tests/ecma_5/Global/jstests.list | 1 + .../eval-native-callback-is-indirect.js | 43 +++++ js/src/tests/ecma_5/extensions/jstests.list | 1 + 13 files changed, 277 insertions(+), 101 deletions(-) create mode 100644 js/src/tests/ecma_5/Global/eval-native-callback-is-indirect.js create mode 100644 js/src/tests/ecma_5/extensions/eval-native-callback-is-indirect.js diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b283cf1b7ad..8e12eaa8a93 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1327,6 +1327,27 @@ InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fv return ok; } +bool +DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp) +{ + JS_ASSERT(vp == cx->regs->sp - argc - 2); + JS_ASSERT(vp[0].isObject()); + JS_ASSERT(vp[0].toObject().isFunction()); + JS_ASSERT(vp[0].toObject().getFunctionPrivate() == evalfun); + JS_ASSERT(IsBuiltinEvalFunction(evalfun)); + + AutoFunctionCallProbe callProbe(cx, evalfun); + + JSStackFrame *caller = cx->fp(); + JS_ASSERT(caller->isScriptFrame()); + JSObject *scopeChain = + GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH); + if (!scopeChain || !EvalKernel(cx, argc, vp, DIRECT_EVAL, caller, scopeChain)) + return false; + cx->regs->sp = vp + 1; + return true; +} + bool ValueToId(JSContext *cx, const Value &v, jsid *idp) { @@ -4632,11 +4653,7 @@ BEGIN_CASE(JSOP_EVAL) if (!IsBuiltinEvalFunction(newfun)) goto not_direct_eval; - Probes::enterJSFun(cx, newfun); - JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp); - Probes::exitJSFun(cx, newfun); - regs.sp = vp + 1; - if (!ok) + if (!DirectEval(cx, newfun, argc, vp)) goto error; } END_CASE(JSOP_EVAL) diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index a0475135db2..f55ca717aa2 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -973,6 +973,16 @@ extern JS_REQUIRES_STACK bool InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval, uintN argc, Value *argv, Value *rval); +/* + * Performs a direct eval for the given arguments, which must correspond to the + * currently-executing stack frame, which must be a script frame. evalfun must + * be the built-in eval function and must correspond to the callee in vp[0]. + * When this function succeeds it returns the result in *vp, adjusts the JS + * stack pointer, and returns true. + */ +extern JS_REQUIRES_STACK bool +DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp); + /* * Executes a script with the given scope chain in the context of the given * frame. diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c21d73ec623..98f044cd2d4 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -931,33 +931,27 @@ js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, return JS_TRUE; } -static JSObject * -CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller) +static bool +CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj) { - JSObject *inner; - - if (!scopeobj) - goto bad; - - OBJ_TO_INNER_OBJECT(cx, scopeobj); - if (!scopeobj) - return NULL; + JSObject *inner = scopeobj; + OBJ_TO_INNER_OBJECT(cx, inner); + if (!inner) + return false; + JS_ASSERT(inner == scopeobj); /* XXX This is an awful gross hack. */ - inner = scopeobj; while (scopeobj) { JSObjectOp op = scopeobj->getClass()->ext.innerObject; - if (op && op(cx, scopeobj) != scopeobj) - goto bad; + if (op && op(cx, scopeobj) != scopeobj) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_INDIRECT_CALL, + js_eval_str); + return false; + } scopeobj = scopeobj->getParent(); } - return inner; - -bad: - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, caller); - return NULL; + return true; } const char * @@ -1093,12 +1087,14 @@ EvalCacheLookup(JSContext *cx, JSString *str, JSStackFrame *caller, uintN static static JSBool eval(JSContext *cx, uintN argc, Value *vp) { - if (argc < 1) { - vp->setUndefined(); - return true; - } + /* + * NB: This method handles only indirect eval: direct eval is handled by + * JSOP_EVAL. + */ JSStackFrame *caller = js_GetScriptedCaller(cx, NULL); + + /* FIXME Bug 602994: This really should be perfectly cromulent. */ if (!caller) { /* Eval code needs to inherit principals from the caller. */ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -1106,73 +1102,37 @@ eval(JSContext *cx, uintN argc, Value *vp) return false; } - jsbytecode *callerPC = caller->pc(cx); - bool directCall = (callerPC && js_GetOpcode(cx, caller->script(), callerPC) == JSOP_EVAL); + return EvalKernel(cx, argc, vp, INDIRECT_EVAL, caller, vp[0].toObject().getGlobal()); +} - /* - * If the callee was originally a cross-compartment wrapper, this is an - * indirect call. - */ - if (directCall && caller->scopeChain().compartment() != vp[0].toObject().compartment()) - directCall = false; +namespace js { +bool +EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame *caller, + JSObject *scopeobj) +{ /* - * Direct calls to eval are supposed to see the caller's |this|. If we - * haven't wrapped that yet, do so now, before we make a copy of it for - * the eval code to use. + * FIXME Bug 602994: Calls with no scripted caller should be permitted and + * should be implemented as indirect calls. */ - if (!caller->computeThis(cx)) - return false; - - Value *argv = JS_ARGV(cx, vp); - if (!argv[0].isString()) { - *vp = argv[0]; - return true; - } + JS_ASSERT(caller); + JS_ASSERT(scopeobj); /* * We once supported a second argument to eval to use as the scope chain * when evaluating the code string. Warn when such uses are seen so that * authors will know that support for eval(s, o) has been removed. */ - if (argc > 1 && !caller->script()->warnedAboutTwoArgumentEval) { + JSScript *callerScript = caller->script(); + if (argc > 1 && !callerScript->warnedAboutTwoArgumentEval) { static const char TWO_ARGUMENT_WARNING[] = "Support for eval(code, scopeObject) has been removed. " "Use |with (scopeObject) eval(code);| instead."; if (!JS_ReportWarning(cx, TWO_ARGUMENT_WARNING)) return false; - caller->script()->warnedAboutTwoArgumentEval = true; + callerScript->warnedAboutTwoArgumentEval = true; } - /* - * Per ES5, if we see an indirect call, then run in the global scope. - * (eval is specified this way so that the compiler can make assumptions - * about what bindings may or may not exist in the current frame if it - * doesn't see 'eval'.) - */ - uintN staticLevel; - JSObject *scopeobj; - if (directCall) { - /* Compile using the caller's current scope object. */ - staticLevel = caller->script()->staticLevel + 1; - scopeobj = GetScopeChainFast(cx, caller, JSOP_EVAL, - JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH); - if (!scopeobj) - return false; - - JS_ASSERT_IF(caller->isFunctionFrame(), caller->hasCallObj()); - } else { - /* Pretend that we're top level. */ - staticLevel = 0; - scopeobj = vp[0].toObject().getGlobal(); - } - - /* Ensure we compile this eval with the right object in the scope chain. */ - JSObject *result = CheckScopeChainValidity(cx, scopeobj, js_eval_str); - if (!result) - return false; - JS_ASSERT(result == scopeobj); - /* * CSP check: Is eval() allowed at all? * Report errors via CSP is done in the script security mgr. @@ -1182,13 +1142,47 @@ eval(JSContext *cx, uintN argc, Value *vp) return false; } - JSObject *callee = &vp[0].toObject(); - JSPrincipals *principals = js_EvalFramePrincipals(cx, callee, caller); - uintN line; - const char *file = js_ComputeFilename(cx, caller, principals, &line); + /* ES5 15.1.2.1 step 1. */ + if (argc < 1) { + vp->setUndefined(); + return true; + } + if (!vp[2].isString()) { + *vp = vp[2]; + return true; + } + JSString *str = vp[2].toString(); - JSString *str = argv[0].toString(); - JSScript *script = NULL; + /* ES5 15.1.2.1 steps 2-8. */ + JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, Jsvalify(vp))); + JS_ASSERT(IsBuiltinEvalFunction(callee->getFunctionPrivate())); + JSPrincipals *principals = js_EvalFramePrincipals(cx, callee, caller); + + /* + * Per ES5, indirect eval runs in the global scope. (eval is specified this + * way so that the compiler can make assumptions about what bindings may or + * may not exist in the current frame if it doesn't see 'eval'.) + */ + uintN staticLevel; + if (evalType == DIRECT_EVAL) { + staticLevel = caller->script()->staticLevel + 1; + +#ifdef DEBUG + jsbytecode *callerPC = caller->pc(cx); + JS_ASSERT_IF(caller->isFunctionFrame(), caller->hasCallObj()); + JS_ASSERT(callerPC && js_GetOpcode(cx, caller->script(), callerPC) == JSOP_EVAL); +#endif + } else { + /* Pretend that we're top level. */ + staticLevel = 0; + + JS_ASSERT(scopeobj == scopeobj->getGlobal()); + JS_ASSERT(scopeobj->isGlobal()); + } + + /* Ensure we compile this eval with the right object in the scope chain. */ + if (!CheckScopeChainValidity(cx, scopeobj)) + return false; const jschar *chars; size_t length; @@ -1200,34 +1194,44 @@ eval(JSContext *cx, uintN argc, Value *vp) * isn't JSON, JSON parsing will probably fail quickly, so little time * will be lost. */ - if (length > 2 && chars[0] == '(' && chars[length-1] == ')') { + if (length > 2 && chars[0] == '(' && chars[length - 1] == ')') { JSONParser *jp = js_BeginJSONParse(cx, vp, /* suppressErrors = */true); - JSBool ok = jp != NULL; - if (ok) { + if (jp != NULL) { /* Run JSON-parser on string inside ( and ). */ - ok = js_ConsumeJSONText(cx, jp, chars+1, length-2); + JSBool ok = js_ConsumeJSONText(cx, jp, chars + 1, length - 2); ok &= js_FinishJSONParse(cx, jp, NullValue()); if (ok) return true; } } + /* + * Direct calls to eval are supposed to see the caller's |this|. If we + * haven't wrapped that yet, do so now, before we make a copy of it for + * the eval code to use. + */ + if (evalType == DIRECT_EVAL && !caller->computeThis(cx)) + return false; + + JSScript *script = NULL; JSScript **bucket = EvalCacheHash(cx, str); - if (directCall && caller->isFunctionFrame()) + if (evalType == DIRECT_EVAL && caller->isFunctionFrame()) script = EvalCacheLookup(cx, str, caller, staticLevel, principals, scopeobj, bucket); /* - * We can't have a callerFrame (down in js_Execute's terms) if we're in - * global code. This includes indirect eval and direct eval called with a - * scope object parameter. + * We can't have a callerFrame (down in js::Execute's terms) if we're in + * global code (or if we're an indirect eval). */ JSStackFrame *callerFrame = (staticLevel != 0) ? caller : NULL; if (!script) { + uintN lineno; + const char *filename = js_ComputeFilename(cx, caller, principals, &lineno); + uint32 tcflags = TCF_COMPILE_N_GO | TCF_NEED_MUTABLE_SCRIPT | TCF_COMPILE_FOR_EVAL; script = Compiler::compileScript(cx, scopeobj, callerFrame, principals, tcflags, chars, length, - NULL, file, line, str, staticLevel); + NULL, filename, lineno, str, staticLevel); if (!script) return false; } @@ -1251,8 +1255,6 @@ eval(JSContext *cx, uintN argc, Value *vp) return ok; } -namespace js { - bool IsBuiltinEvalFunction(JSFunction *fun) { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2db2a05d0cd..42971355e04 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1717,6 +1717,22 @@ SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles); extern JSString * obj_toStringHelper(JSContext *cx, JSObject *obj); +enum EvalType { INDIRECT_EVAL, DIRECT_EVAL }; + +/* + * Common code implementing direct and indirect eval. + * + * Evaluate vp[2], if it is a string, in the context of the given calling + * frame, with the provided scope chain, with the semantics of either a direct + * or indirect eval (see ES5 10.4.2). If this is an indirect eval, scopeobj + * must be a global object. + * + * On success, store the completion value in *vp and return true. + */ +extern bool +EvalKernel(JSContext *cx, uintN argc, js::Value *vp, EvalType evalType, JSStackFrame *caller, + JSObject *scopeobj); + extern bool IsBuiltinEvalFunction(JSFunction *fun); diff --git a/js/src/jsprobes.h b/js/src/jsprobes.h index fefcdd0d425..02ded0a33e4 100644 --- a/js/src/jsprobes.h +++ b/js/src/jsprobes.h @@ -216,6 +216,25 @@ inline JSBool Probes::CustomMark(JSString *string) { return JS_TRUE; } inline JSBool Probes::CustomMark(const char *string) { return JS_TRUE; } inline JSBool Probes::CustomMark(int marker) { return JS_TRUE; } +struct AutoFunctionCallProbe { + JSContext * const cx; + JSFunction *fun; + js::Value *lval; + JS_DECL_USE_GUARD_OBJECT_NOTIFIER + + AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, js::Value *lval = NULL + JS_GUARD_OBJECT_NOTIFIER_PARAM) + : cx(cx), fun(fun), lval(lval) + { + JS_GUARD_OBJECT_NOTIFIER_INIT; + Probes::enterJSFun(cx, fun, lval); + } + + ~AutoFunctionCallProbe() { + Probes::exitJSFun(cx, fun, lval); + } +}; + } /* namespace js */ #endif /* _JSPROBES_H */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index aa6ef2456d0..121facbc12c 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1211,7 +1211,11 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_CALLNAME) BEGIN_CASE(JSOP_EVAL) - jsop_eval(); + { + JaegerSpew(JSpew_Insns, " --- EVAL --- \n"); + emitEval(GET_ARGC(PC)); + JaegerSpew(JSpew_Insns, " --- END EVAL --- \n"); + } END_CASE(JSOP_EVAL) BEGIN_CASE(JSOP_CALL) @@ -4328,11 +4332,17 @@ mjit::Compiler::jsop_instanceof() } void -mjit::Compiler::jsop_eval() +mjit::Compiler::emitEval(uint32 argc) { - JaegerSpew(JSpew_Insns, " --- SCRIPTED CALL --- \n"); - inlineCallHelper(GET_ARGC(PC), false); - JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n"); + /* Check for interrupts on function call */ + interruptCheckHelper(); + + frame.syncAndKill(Registers(Registers::AvailRegs), Uses(argc + 2)); + prepareStubCall(Uses(argc + 2)); + masm.move(Imm32(argc), Registers::ArgReg1); + stubCall(stubs::Eval); + frame.popn(argc + 2); + frame.pushSynced(); } /* diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 2fe0d87ee63..d6bd98c41a6 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -368,7 +368,7 @@ class Compiler : public BaseCompiler bool jsop_xname(JSAtom *atom); void enterBlock(JSObject *obj); void leaveBlock(); - void jsop_eval(); + void emitEval(uint32 argc); /* Fast arithmetic. */ void jsop_binary(JSOp op, VoidStub stub); diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index f659c9b6679..18881102cb4 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -442,6 +442,30 @@ stubs::UncachedCall(VMFrame &f, uint32 argc) return ucr.codeAddr; } +void JS_FASTCALL +stubs::Eval(VMFrame &f, uint32 argc) +{ + Value *vp = f.regs.sp - (argc + 2); + + JSObject *callee; + JSFunction *fun; + + if (!IsFunctionObject(*vp, &callee) || + !IsBuiltinEvalFunction((fun = callee->getFunctionPrivate()))) + { + if (!ComputeThisFromVpInPlace(f.cx, vp) || + !Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0)) + { + THROW(); + } + return; + } + + JS_ASSERT(f.regs.fp == f.cx->fp()); + if (!DirectEval(f.cx, fun, argc, vp)) + THROW(); +} + void stubs::UncachedCallHelper(VMFrame &f, uint32 argc, UncachedCallResult *ucr) { diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index 33897544dd6..7795418a9ce 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -65,6 +65,7 @@ void JS_FASTCALL SlowNew(VMFrame &f, uint32 argc); void JS_FASTCALL SlowCall(VMFrame &f, uint32 argc); void * JS_FASTCALL UncachedNew(VMFrame &f, uint32 argc); void * JS_FASTCALL UncachedCall(VMFrame &f, uint32 argc); +void JS_FASTCALL Eval(VMFrame &f, uint32 argc); void JS_FASTCALL EnterScript(VMFrame &f); void JS_FASTCALL LeaveScript(VMFrame &f); diff --git a/js/src/tests/ecma_5/Global/eval-native-callback-is-indirect.js b/js/src/tests/ecma_5/Global/eval-native-callback-is-indirect.js new file mode 100644 index 00000000000..bfc4a3489d0 --- /dev/null +++ b/js/src/tests/ecma_5/Global/eval-native-callback-is-indirect.js @@ -0,0 +1,32 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 604504; +var summary = "eval called from a native function is indirect"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var originalEval = eval; + +var global = this; +var directCheckCode = "this === global"; + +function testBound() +{ + var global = "psych!"; + var eval = originalEval.bind(undefined, directCheckCode); + assertEq(eval(), true); +} +testBound(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/ecma_5/Global/jstests.list b/js/src/tests/ecma_5/Global/jstests.list index ab7e789bfcb..1dbcce80da2 100644 --- a/js/src/tests/ecma_5/Global/jstests.list +++ b/js/src/tests/ecma_5/Global/jstests.list @@ -4,3 +4,4 @@ script eval-01.js script eval-02.js script eval-inside-with-is-direct.js script parenthesized-eval-is-direct.js +script eval-native-callback-is-indirect.js diff --git a/js/src/tests/ecma_5/extensions/eval-native-callback-is-indirect.js b/js/src/tests/ecma_5/extensions/eval-native-callback-is-indirect.js new file mode 100644 index 00000000000..662f619eed7 --- /dev/null +++ b/js/src/tests/ecma_5/extensions/eval-native-callback-is-indirect.js @@ -0,0 +1,43 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 604504; +var summary = "eval called from a native function is indirect"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var originalEval = eval; + +var global = this; +var directCheckCode = "this === global"; + +function testArrayGeneric() +{ + var global = "psych!"; + var eval = Array.map; + + var mapped = eval([directCheckCode], originalEval); + assertEq(mapped[0], true); +} + +function testStringGeneric() +{ + var global = "psych!"; + var eval = String.replace; + + var newString = eval(directCheckCode, directCheckCode, originalEval); + assertEq(newString, "true"); +} +testStringGeneric(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/ecma_5/extensions/jstests.list b/js/src/tests/ecma_5/extensions/jstests.list index 9c6c69db949..80254cded6f 100644 --- a/js/src/tests/ecma_5/extensions/jstests.list +++ b/js/src/tests/ecma_5/extensions/jstests.list @@ -7,4 +7,5 @@ script String-toSource.js script proxy-strict.js script regress-bug567606.js script string-literal-getter-setter-decompilation.js +script eval-native-callback-is-indirect.js script regress-bug607284.js From 09b4d445bb9cb72f884c853f7aa47e965b3a4909 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Thu, 28 Oct 2010 22:45:02 -0400 Subject: [PATCH 010/263] bug 606317 - Android crash only : Crash [@ libc.so@0x11cd0 ] occurs after opening an .ics r=doug a=blocking-fennec --- uriloader/exthandler/android/nsMIMEInfoAndroid.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp index 44745d3bba0..3281c0c1a02 100644 --- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp @@ -168,11 +168,7 @@ NS_IMETHODIMP nsMIMEInfoAndroid::GetPreferredApplicationHandler(nsIHandlerApp** aApp) { *aApp = mPrefApp; - if (*aApp) { - nsAutoString appName; - (*aApp)->GetName(appName); - } - + NS_IF_ADDREF(*aApp); return NS_OK; } From c2e94b6def3ef4306a2a83aad911e0b15ff95e01 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Oct 2010 16:06:35 +1300 Subject: [PATCH 011/263] Backed out changeset 069ccd107c32 --- browser/base/content/test/Makefile.in | 3 - browser/base/content/test/app_bug575561.html | 16 ---- .../content/test/app_subframe_bug575561.html | 12 --- .../base/content/test/browser_bug575561.js | 73 ------------------- .../content/tests/browser/browser_Services.js | 3 - 5 files changed, 107 deletions(-) delete mode 100644 browser/base/content/test/app_bug575561.html delete mode 100644 browser/base/content/test/app_subframe_bug575561.html delete mode 100644 browser/base/content/test/browser_bug575561.js diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 3492d16576f..6022529c7ac 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -145,7 +145,6 @@ _BROWSER_FILES = \ browser_bug561636.js \ browser_bug562649.js \ browser_bug563588.js \ - browser_bug575561.js \ browser_bug577121.js \ browser_bug579872.js \ browser_bug580956.js \ @@ -219,8 +218,6 @@ _BROWSER_FILES = \ file_bug550565_favicon.ico \ browser_overLinkInLocationBar.js \ browser_aboutHome.js \ - app_bug575561.html \ - app_subframe_bug575561.html \ $(NULL) # compartment-disabled diff --git a/browser/base/content/test/app_bug575561.html b/browser/base/content/test/app_bug575561.html deleted file mode 100644 index 60511f5dedd..00000000000 --- a/browser/base/content/test/app_bug575561.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - Test for links in app tabs - - - same domain - same domain (different subdomain) - different domain - different domain (with target) - - - diff --git a/browser/base/content/test/app_subframe_bug575561.html b/browser/base/content/test/app_subframe_bug575561.html deleted file mode 100644 index 754f3806e15..00000000000 --- a/browser/base/content/test/app_subframe_bug575561.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Test for links in app tab subframes - - - different domain - - diff --git a/browser/base/content/test/browser_bug575561.js b/browser/base/content/test/browser_bug575561.js deleted file mode 100644 index 131c06a47dd..00000000000 --- a/browser/base/content/test/browser_bug575561.js +++ /dev/null @@ -1,73 +0,0 @@ -function test() { - waitForExplicitFinish(); - - // Pinned: Link to the same domain should not open a new tab - // Tests link to http://example.com/browser/browser/base/content/test/dummy_page.html - testLink(0, true, false, function() { - // Pinned: Link to the same domain should not open a new tab - // Tests link to http://test1.example.com/browser/browser/base/content/test/dummy_page.html - testLink(1, true, false, function() { - // Pinned: Link to a different domain should open a new tab - // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html - testLink(2, true, true, function() { - // Not Pinned: Link to a different domain should not open a new tab - // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html - testLink(2, false, false, function() { - // Pinned: Targetted link should open a new tab - // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html with target="foo" - testLink(3, true, true, function() { - // Pinned: Link in a subframe should not open a new tab - // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html in subframe - testLink(0, true, false, finish, true); - }); - }); - }); - }); - }); -} - -function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) { - let appTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/app_bug575561.html", {skipAnimation: true}); - if (pinTab) - gBrowser.pinTab(appTab); - gBrowser.selectedTab = appTab; - appTab.linkedBrowser.addEventListener("load", onLoad, true); - - let loadCount = 0; - function onLoad() { - loadCount++; - if (loadCount < 2) - return; - - appTab.linkedBrowser.removeEventListener("load", onLoad, true); - - let browser = gBrowser.getBrowserForTab(appTab); - if (testSubFrame) - browser = browser.contentDocument.getElementsByTagName("iframe")[0]; - - let links = browser.contentDocument.getElementsByTagName("a"); - - if (expectNewTab) - gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true); - else - browser.addEventListener("load", onPageLoad, true); - - info("Clicking " + links[aLinkIndex].textContent); - EventUtils.sendMouseEvent({type:"click"}, links[aLinkIndex], browser.contentWindow); - - function onPageLoad() { - browser.removeEventListener("load", onPageLoad, true); - is(browser.contentDocument.location.href, links[aLinkIndex].href, "Link should not open in a new tab"); - gBrowser.removeTab(appTab); - nextTest(); - } - - function onTabOpen(event) { - gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true); - ok(true, "Link should open a new tab"); - gBrowser.removeTab(appTab); - gBrowser.removeCurrentTab(); - nextTest(); - } - } -} diff --git a/toolkit/content/tests/browser/browser_Services.js b/toolkit/content/tests/browser/browser_Services.js index 635e06d68aa..311de6a2e5a 100644 --- a/toolkit/content/tests/browser/browser_Services.js +++ b/toolkit/content/tests/browser/browser_Services.js @@ -50,7 +50,6 @@ function checkServices() { checkService("prefs", Ci.nsIPrefService); checkService("contentPrefs", Ci.nsIContentPrefService); checkService("wm", Ci.nsIWindowMediator); - checkService("obs", Ci.nsIObserverService); checkService("perms", Ci.nsIPermissionManager); checkService("io", Ci.nsIIOService); checkService("io", Ci.nsIIOService2); @@ -67,8 +66,6 @@ function checkServices() { checkService("scriptloader", Ci.mozIJSSubScriptLoader); checkService("ww", Ci.nsIWindowWatcher); checkService("tm", Ci.nsIThreadManager); - checkService("droppedLinkHandler", Ci.nsIDroppedLinkHandler); checkService("strings", Ci.nsIStringBundleService); checkService("urlFormatter", Ci.nsIURLFormatter); - checkService("eTLD", Ci.nsIEffectiveTLDService); } From 6bb7a02bbfb3cfdfc9b147d4fd6b302ee9d8f4c5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Oct 2010 16:07:46 +1300 Subject: [PATCH 012/263] Backed out changeset ecd1948992eb --- browser/base/content/browser.js | 21 ------ browser/base/content/tabbrowser.xml | 4 -- docshell/base/nsDocShell.cpp | 33 +--------- docshell/base/nsDocShell.h | 1 - docshell/base/nsIDocShell.idl | 10 +-- embedding/browser/webBrowser/Makefile.in | 1 - .../webBrowser/nsIWebBrowserChrome3.idl | 65 ------------------- toolkit/components/help/content/help.js | 3 +- toolkit/content/Services.jsm | 4 -- .../content/tests/chrome/findbar_window.xul | 4 +- xpfe/appshell/public/nsIXULBrowserWindow.idl | 10 --- xpfe/appshell/src/nsContentTreeOwner.cpp | 24 ------- xpfe/appshell/src/nsContentTreeOwner.h | 5 +- 13 files changed, 8 insertions(+), 177 deletions(-) delete mode 100644 embedding/browser/webBrowser/nsIWebBrowserChrome3.idl diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 65310db8558..006eec5f90c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3985,27 +3985,6 @@ var XULBrowserWindow = { encodeURIComponent); gURLBar.setOverLink(link); }, - - // Called before links are navigated to to allow us to retarget them if needed. - onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { - // Don't modify non-default targets or targets that aren't in top-level app - // tab docshells (isAppTab will be false for app tab subframes). - if (originalTarget != "" || !isAppTab) - return originalTarget; - - let docURI = linkNode.ownerDocument.documentURIObject; - try { - let docURIDomain = Services.eTLD.getBaseDomain(docURI, 0); - let linkURIDomain = Services.eTLD.getBaseDomain(linkURI, 0); - // External links from within app tabs should always open in new tabs - // instead of replacing the app tab's page (Bug 575561) - if (docURIDomain != linkURIDomain) - return "_blank"; - } catch(e) { - // If getBaseDomain fails, we return originalTarget below. - } - return originalTarget; - }, onLinkIconAvailable: function (aIconURL) { if (gProxyFavIcon && gBrowser.userTypedValue === null) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index fdb9bb62fc8..a11bde11f22 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -191,8 +191,6 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); - this.getBrowserForTab(aTab).docShell.isAppTab = true; - let event = document.createEvent("Events"); event.initEvent("TabPinned", true, false); aTab.dispatchEvent(event); @@ -212,8 +210,6 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); - this.getBrowserForTab(aTab).docShell.isAppTab = false; - let event = document.createEvent("Events"); event.initEvent("TabUnpinned", true, false); aTab.dispatchEvent(event); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 42ffaec9270..8257979f25d 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -159,7 +159,7 @@ #include "nsIController.h" #include "nsPICommandUpdater.h" #include "nsIDOMHTMLAnchorElement.h" -#include "nsIWebBrowserChrome3.h" +#include "nsIWebBrowserChrome2.h" #include "nsITabChild.h" #include "nsIStrictTransportSecurityService.h" @@ -711,7 +711,6 @@ nsDocShell::nsDocShell(): mAllowKeywordFixup(PR_FALSE), mIsOffScreenBrowser(PR_FALSE), mIsActive(PR_TRUE), - mIsAppTab(PR_FALSE), mFiredUnloadEvent(PR_FALSE), mEODForCurrentDocument(PR_FALSE), mURIResultedInDocument(PR_FALSE), @@ -4803,20 +4802,6 @@ nsDocShell::GetIsActive(PRBool *aIsActive) return NS_OK; } -NS_IMETHODIMP -nsDocShell::SetIsAppTab(PRBool aIsAppTab) -{ - mIsAppTab = aIsAppTab; - return NS_OK; -} - -NS_IMETHODIMP -nsDocShell::GetIsAppTab(PRBool *aIsAppTab) -{ - *aIsAppTab = mIsAppTab; - return NS_OK; -} - NS_IMETHODIMP nsDocShell::SetVisibility(PRBool aVisibility) { @@ -11326,22 +11311,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent, return NS_OK; } - nsresult rv = NS_ERROR_FAILURE; - nsAutoString target; - - nsCOMPtr browserChrome3 = do_GetInterface(mTreeOwner); - if (browserChrome3) { - nsCOMPtr linkNode = do_QueryInterface(aContent); - nsAutoString oldTarget(aTargetSpec); - rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI, - linkNode, mIsAppTab, target); - } - - if (NS_FAILED(rv)) - target = aTargetSpec; - nsCOMPtr ev = - new OnLinkClickEvent(this, aContent, aURI, target.get(), + new OnLinkClickEvent(this, aContent, aURI, aTargetSpec, aPostDataStream, aHeadersDataStream); return NS_DispatchToCurrentThread(ev); } diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 317f766a48a..a6c33f149c1 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -790,7 +790,6 @@ protected: PRPackedBool mAllowKeywordFixup; PRPackedBool mIsOffScreenBrowser; PRPackedBool mIsActive; - PRPackedBool mIsAppTab; // This boolean is set to true right before we fire pagehide and generally // unset when we embed a new content viewer. While it's true no navigation diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index e5a72e5813e..788be5c5ef2 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -71,7 +71,7 @@ interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; -[scriptable, uuid(98cdbcc4-2d81-4191-a63f-b6c52085edbc)] +[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)] interface nsIDocShell : nsISupports { /** @@ -529,17 +529,11 @@ interface nsIDocShell : nsISupports */ attribute boolean isActive; + /** * The ID of the docshell in the session history. */ readonly attribute unsigned long long historyID; - - /** - * Sets whether a docshell is an app tab. An app tab docshell may behave - * differently than a non-app tab docshell in some cases, such as when - * handling link clicks. Docshells are not app tabs unless told otherwise. - */ - attribute boolean isAppTab; }; [uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)] diff --git a/embedding/browser/webBrowser/Makefile.in b/embedding/browser/webBrowser/Makefile.in index 10a56f9671c..b068d4c210d 100644 --- a/embedding/browser/webBrowser/Makefile.in +++ b/embedding/browser/webBrowser/Makefile.in @@ -78,7 +78,6 @@ XPIDLSRCS = \ nsIEmbeddingSiteWindow2.idl \ nsIContextMenuListener2.idl \ nsIWebBrowserChrome2.idl \ - nsIWebBrowserChrome3.idl \ $(NULL) CPPSRCS = \ diff --git a/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl deleted file mode 100644 index b15bf12335e..00000000000 --- a/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl +++ /dev/null @@ -1,65 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Margaret Leibovic - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "nsIWebBrowserChrome2.idl" -#include "nsIURI.idl" -#include "nsIDOMNode.idl" - -/** - * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2. - */ -[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)] -interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 -{ - /** - * Determines the appropriate target for a link. - * - * @param originalTarget - * The original link target. - * @param linkURI - * Link destination URI. - * @param aDOMNode - * Link DOM node. - * @param isAppTab - * Whether or not the link is in an app tab. - * @returns A new link target, if appropriate. - * Otherwise returns originalTarget. - */ - AString onBeforeLinkTraversal(in AString originalTarget, - in nsIURI linkURI, - in nsIDOMNode linkNode, - in PRBool isAppTab); -}; diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js index 4a49bfb9b7c..f17403b17bd 100644 --- a/toolkit/components/help/content/help.js +++ b/toolkit/components/help/content/help.js @@ -562,8 +562,7 @@ nsHelpStatusHandler.prototype = { setJSStatus : function(status) {}, setJSDefaultStatus : function(status) {}, - setOverLink : function(link, context) {}, - onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {} + setOverLink : function(link, context) {} } function UpdateBackForwardButtons() { diff --git a/toolkit/content/Services.jsm b/toolkit/content/Services.jsm index 86ad255edd2..4d6a82866bf 100644 --- a/toolkit/content/Services.jsm +++ b/toolkit/content/Services.jsm @@ -130,7 +130,3 @@ XPCOMUtils.defineLazyServiceGetter(Services, "strings", XPCOMUtils.defineLazyServiceGetter(Services, "urlFormatter", "@mozilla.org/toolkit/URLFormatterService;1", "nsIURLFormatter"); - -XPCOMUtils.defineLazyServiceGetter(Services, "eTLD", - "@mozilla.org/network/effective-tld-service;1", - "nsIEffectiveTLDService"); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index 911b3e9cf85..33729245b7e 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -76,9 +76,7 @@ setOverLink: function(aStatusText, aLink) { gStatusText = aStatusText; - }, - - onBeforeLinkTraversal: function() { } + } }; function ok(condition, message) { diff --git a/xpfe/appshell/public/nsIXULBrowserWindow.idl b/xpfe/appshell/public/nsIXULBrowserWindow.idl index d787d9405a0..37a8676aa99 100644 --- a/xpfe/appshell/public/nsIXULBrowserWindow.idl +++ b/xpfe/appshell/public/nsIXULBrowserWindow.idl @@ -38,8 +38,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -#include "nsIURI.idl" -#include "nsIDOMNode.idl" interface nsIRequest; interface nsIDOMElement; @@ -67,13 +65,5 @@ interface nsIXULBrowserWindow : nsISupports * over. */ void setOverLink(in AString link, in nsIDOMElement element); - - /** - * Determines the appropriate target for a link. - */ - AString onBeforeLinkTraversal(in AString originalTarget, - in nsIURI linkURI, - in nsIDOMNode linkNode, - in PRBool isAppTab); }; diff --git a/xpfe/appshell/src/nsContentTreeOwner.cpp b/xpfe/appshell/src/nsContentTreeOwner.cpp index f6c21a0a86d..3794e06d4b9 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -124,7 +124,6 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) - NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) // NOTE: This is using aggregation because there are some properties and @@ -431,29 +430,6 @@ nsContentTreeOwner::GetPersistence(PRBool* aPersistPosition, return NS_OK; } -//***************************************************************************** -// nsContentTreeOwner::nsIWebBrowserChrome3 -//***************************************************************************** - -NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget, - nsIURI *linkURI, - nsIDOMNode *linkNode, - PRBool isAppTab, - nsAString &_retval) -{ - NS_ENSURE_STATE(mXULWindow); - - nsCOMPtr xulBrowserWindow; - mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); - - if (xulBrowserWindow) - return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI, - linkNode, isAppTab, _retval); - - _retval = originalTarget; - return NS_OK; -} - //***************************************************************************** // nsContentTreeOwner::nsIWebBrowserChrome2 //***************************************************************************** diff --git a/xpfe/appshell/src/nsContentTreeOwner.h b/xpfe/appshell/src/nsContentTreeOwner.h index 31d462a52e5..efc4e54b339 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.h +++ b/xpfe/appshell/src/nsContentTreeOwner.h @@ -49,7 +49,7 @@ #include "nsIDocShellTreeOwner.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsIWebBrowserChrome3.h" +#include "nsIWebBrowserChrome2.h" #include "nsIWindowProvider.h" class nsXULWindow; @@ -58,7 +58,7 @@ class nsSiteWindow2; class nsContentTreeOwner : public nsIDocShellTreeOwner, public nsIBaseWindow, public nsIInterfaceRequestor, - public nsIWebBrowserChrome3, + public nsIWebBrowserChrome2, public nsIWindowProvider { friend class nsXULWindow; @@ -72,7 +72,6 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 - NS_DECL_NSIWEBBROWSERCHROME3 NS_DECL_NSIWINDOWPROVIDER protected: From 3f29ca47ee6c63015965ec737b5a3052ce8214db Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Oct 2010 16:08:07 +1300 Subject: [PATCH 013/263] Bug 595842. When GetHDCWithClip fails, fall through to the fallback rendering path. r=vlad,a=blocking-beta7 --- gfx/thebes/gfxWindowsNativeDrawing.cpp | 39 ++++++++++--------- .../native-theme/border-radius-ref.html | 9 +++++ .../reftests/native-theme/border-radius.html | 9 +++++ layout/reftests/native-theme/reftest.list | 2 + 4 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 layout/reftests/native-theme/border-radius-ref.html create mode 100644 layout/reftests/native-theme/border-radius.html diff --git a/gfx/thebes/gfxWindowsNativeDrawing.cpp b/gfx/thebes/gfxWindowsNativeDrawing.cpp index 44dc6368664..cca132f0d40 100644 --- a/gfx/thebes/gfxWindowsNativeDrawing.cpp +++ b/gfx/thebes/gfxWindowsNativeDrawing.cpp @@ -90,25 +90,29 @@ gfxWindowsNativeDrawing::BeginNativeDrawing() (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA && (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA)))) { - if (mTransformType == TRANSLATION_ONLY) { - mRenderState = RENDER_STATE_NATIVE_DRAWING; + // grab the DC. This can fail if there is a complex clipping path, + // in which case we'll have to fall back. + mWinSurface = static_cast(static_cast(surf.get())); + mDC = mWinSurface->GetDCWithClip(mContext); - mTranslation = m.GetTranslation(); + if (mDC) { + if (mTransformType == TRANSLATION_ONLY) { + mRenderState = RENDER_STATE_NATIVE_DRAWING; - mWinSurface = static_cast(static_cast(surf.get())); - } else if (((mTransformType == AXIS_ALIGNED_SCALE) - && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) || - (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM)) - { - mWorldTransform.eM11 = (FLOAT) m.xx; - mWorldTransform.eM12 = (FLOAT) m.yx; - mWorldTransform.eM21 = (FLOAT) m.xy; - mWorldTransform.eM22 = (FLOAT) m.yy; - mWorldTransform.eDx = (FLOAT) m.x0; - mWorldTransform.eDy = (FLOAT) m.y0; + mTranslation = m.GetTranslation(); + } else if (((mTransformType == AXIS_ALIGNED_SCALE) + && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) || + (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM)) + { + mWorldTransform.eM11 = (FLOAT) m.xx; + mWorldTransform.eM12 = (FLOAT) m.yx; + mWorldTransform.eM21 = (FLOAT) m.xy; + mWorldTransform.eM22 = (FLOAT) m.yy; + mWorldTransform.eDx = (FLOAT) m.x0; + mWorldTransform.eDy = (FLOAT) m.y0; - mRenderState = RENDER_STATE_NATIVE_DRAWING; - mWinSurface = static_cast(static_cast(surf.get())); + mRenderState = RENDER_STATE_NATIVE_DRAWING; + } } } @@ -156,9 +160,6 @@ gfxWindowsNativeDrawing::BeginNativeDrawing() if (mRenderState == RENDER_STATE_NATIVE_DRAWING) { // we can just do native drawing directly to the context's surface - // grab the DC - mDC = mWinSurface->GetDCWithClip(mContext); - // do we need to use SetWorldTransform? if (mTransformType != TRANSLATION_ONLY) { SetGraphicsMode(mDC, GM_ADVANCED); diff --git a/layout/reftests/native-theme/border-radius-ref.html b/layout/reftests/native-theme/border-radius-ref.html new file mode 100644 index 00000000000..d6d4b16ccec --- /dev/null +++ b/layout/reftests/native-theme/border-radius-ref.html @@ -0,0 +1,9 @@ + + + +
+ + +
+ + diff --git a/layout/reftests/native-theme/border-radius.html b/layout/reftests/native-theme/border-radius.html new file mode 100644 index 00000000000..f9ced1d436e --- /dev/null +++ b/layout/reftests/native-theme/border-radius.html @@ -0,0 +1,9 @@ + + + +
+ + +
+ + diff --git a/layout/reftests/native-theme/reftest.list b/layout/reftests/native-theme/reftest.list index 151ecef2e9e..e500e06530c 100644 --- a/layout/reftests/native-theme/reftest.list +++ b/layout/reftests/native-theme/reftest.list @@ -61,4 +61,6 @@ skip-if(gtk2Widget) random-if(d2d) == resizer-bottomend-rtl.xul resizer-bottomen skip-if(!winWidget) == scroll-thumb-minimum-size-notheme.html scroll-thumb-minimum-size-notheme-ref.html # skip-if(!winWidget) == scroll-thumb-minimum-size-theme.html scroll-thumb-minimum-size-theme-ref.html # Bug 512206 +== border-radius.html border-radius-ref.html + == checkbox-dynamic-1.html checkbox-dynamic-1-ref.html From 35249f2ed6c629d247acb2c35942eabae5265ca3 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 27 Oct 2010 16:56:11 -0400 Subject: [PATCH 014/263] Bug 482175 - Rely on password manager notifications instead of timeouts in tests. r=dolske a=test-only --- .../passwordmgr/test/test_prompt.html | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/toolkit/components/passwordmgr/test/test_prompt.html b/toolkit/components/passwordmgr/test/test_prompt.html index cbbe750a261..5775866204a 100644 --- a/toolkit/components/passwordmgr/test/test_prompt.html +++ b/toolkit/components/passwordmgr/test/test_prompt.html @@ -124,6 +124,33 @@ ok(true, "whee, done!"); SimpleTest.finish(); } +function addNotificationCallback(cb) +{ + storageObserver.notificationCallbacks.push(cb); +} + +var storageObserver = { + notificationCallbacks: [], + + QueryInterface : function (iid) { + const interfaces = [Ci.nsIObserver, + Ci.nsISupports, Ci.nsISupportsWeakReference]; + + if (!interfaces.some( function(v) { return iid.equals(v) } )) + throw Components.results.NS_ERROR_NO_INTERFACE; + return this; + }, + + observe : function (subject, topic, data) { + if (this.notificationCallbacks.length) + this.notificationCallbacks.splice(0, 1)[0](); + } +}; + +var observerService = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); +observerService.addObserver(storageObserver, "passwordmgr-storage-changed", false); + /* * handleDialog * @@ -417,12 +444,6 @@ function handleLoad() { is(username, "mochiuser1", "Checking for echoed username"); is(password, "mochipass1-new", "Checking for echoed password"); - // Check for the popup notification, and change the password. - popup = getPopup(popupNotifications, "password-change"); - ok(popup, "got popup notification"); - clickPopupButton(popup, kChangeButton); - popup.remove(); - // Housekeeping: change it back function resetIt() { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); @@ -430,7 +451,13 @@ function handleLoad() { "mochiuser1", "mochipass1-new", "", ""); pwmgr.modifyLogin(tmpLogin, login3A); } - setTimeout(resetIt, 0); + addNotificationCallback(resetIt); + + // Check for the popup notification, and change the password. + popup = getPopup(popupNotifications, "password-change"); + ok(popup, "got popup notification"); + clickPopupButton(popup, kChangeButton); + popup.remove(); // Same as last test, but for a realm we haven't already authenticated // to (but have an existing saved login for, so that we'll trigger @@ -445,30 +472,30 @@ function handleLoad() { is(username, "mochiuser3", "Checking for echoed username"); is(password, "mochipass3-new", "Checking for echoed password"); + // Housekeeping: change it back to the original login4. Actually, + // just delete it and we'll re-add it as the next test. + function clearIt() { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + tmpLogin.init("http://mochi.test:8888", null, "mochitest3", + "mochiuser3", "mochipass3-new", "", ""); + pwmgr.removeLogin(tmpLogin); + + // Trigger a new prompt, so we can test adding a new login. + startCallbackTimer(); + iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3"; + } + addNotificationCallback(clearIt); + // Check for the popup notification, and change the password. popup = getPopup(popupNotifications, "password-change"); ok(popup, "got popup notification"); clickPopupButton(popup, kChangeButton); popup.remove(); - // Housekeeping: change it back to the original login4. Actually, - // just delete it and we'll re-add it as the next test. - function clearIt() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - tmpLogin.init("http://mochi.test:8888", null, "mochitest3", - "mochiuser3", "mochipass3-new", "", ""); - pwmgr.removeLogin(tmpLogin); - } - setTimeout(clearIt, 0); - // Clear cached auth from this subtest, and avoid leaking due to bug 459620. var authMgr = Cc['@mozilla.org/network/http-auth-manager;1']. getService(Ci.nsIHttpAuthManager); authMgr.clearAll(); - - // Trigger a new prompt, so we can test adding a new login. - startCallbackTimer(); - iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3"; break; case 1005: @@ -477,17 +504,17 @@ function handleLoad() { is(username, "mochiuser3", "Checking for echoed username"); is(password, "mochipass3-old", "Checking for echoed password"); + function finishIt() { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + finishTest(); + } + addNotificationCallback(finishIt); + // Check for the popup notification, and change the password. popup = getPopup(popupNotifications, "password-save"); ok(popup, "got popup notification"); clickPopupButton(popup, kRememberButton); popup.remove(); - - function finishIt() { - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - finishTest(); - } - setTimeout(finishIt, 0); break; default: From bb0cf0f8a4400a0d9826d2d663554125801c5bae Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Thu, 28 Oct 2010 23:45:46 -0700 Subject: [PATCH 015/263] Bug 607534 - Optimize custom dynamic loader to use less memory, r=cjones a=blocking-fennec --- ipc/glue/GeckoChildProcessHost.cpp | 22 ++++ ipc/glue/SharedMemoryBasic_android.cpp | 12 +-- other-licenses/android/APKOpen.cpp | 144 +++++++++++++++++++++++-- other-licenses/android/APKOpen.h | 12 ++- other-licenses/android/linker.c | 55 ++++++++-- toolkit/xre/nsAndroidStartup.cpp | 2 +- 6 files changed, 217 insertions(+), 30 deletions(-) diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 28f444a2141..7442c566bd4 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -69,6 +69,10 @@ #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" #endif +#ifdef ANDROID +#include "APKOpen.h" +#endif + using mozilla::MonitorAutoEnter; using mozilla::ipc::GeckoChildProcessHost; @@ -388,6 +392,20 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b #ifdef ANDROID // The java wrapper unpacks this for us but can't make it executable chmod(exePath.value().c_str(), 0700); + int cacheCount = 0; + const struct lib_cache_info * cache = getLibraryCache(); + nsCString cacheStr; + while (cache && + cacheCount++ < MAX_LIB_CACHE_ENTRIES && + strlen(cache->name)) { + mFileMap.push_back(std::pair(cache->fd, cache->fd)); + cacheStr.Append(cache->name); + cacheStr.AppendPrintf(":%d;", cache->fd); + cache++; + } + // fill the last arg with something if there's no cache + if (cacheStr.IsEmpty()) + cacheStr.AppendLiteral("-"); #endif // remap the IPC socket fd to a well-known int, as the OS does for @@ -451,6 +469,10 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b childArgv.push_back(childProcessType); +#ifdef ANDROID + childArgv.push_back(cacheStr.get()); +#endif + base::LaunchApp(childArgv, mFileMap, #if defined(OS_LINUX) || defined(OS_MACOSX) newEnvVars, diff --git a/ipc/glue/SharedMemoryBasic_android.cpp b/ipc/glue/SharedMemoryBasic_android.cpp index 6f457b107c4..34385c08995 100644 --- a/ipc/glue/SharedMemoryBasic_android.cpp +++ b/ipc/glue/SharedMemoryBasic_android.cpp @@ -56,15 +56,7 @@ // Temporarily go directly to the kernel interface until we can // interact better with libcutils. // -#define ASHMEM_DEVICE "/dev/ashmem" -#define ASHMEM_NAME_LEN 256 -#define __ASHMEMIOC 0x77 -#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) -#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) -#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) -#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) -#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long) -#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6) +#include namespace mozilla { namespace ipc { @@ -102,7 +94,7 @@ SharedMemoryBasic::Create(size_t aNbytes) NS_ABORT_IF_FALSE(-1 == mShmFd, "Already Create()d"); // Carve a new instance off of /dev/ashmem - int shmfd = open(ASHMEM_DEVICE, O_RDWR, 0600); + int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); if (-1 == shmfd) { LogError("ShmemAndroid::Create():open"); return false; diff --git a/other-licenses/android/APKOpen.cpp b/other-licenses/android/APKOpen.cpp index f8f9a85f1fd..7de334c6d63 100644 --- a/other-licenses/android/APKOpen.cpp +++ b/other-licenses/android/APKOpen.cpp @@ -34,19 +34,29 @@ * * ***** END LICENSE BLOCK ***** */ +/* + * This custom library loading code is only meant to be called + * during initialization. As a result, it takes no special + * precautions to be threadsafe. Any of the library loading functions + * like mozload should not be available to other code. + */ + #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include #include +#include #include "dlfcn.h" #include "APKOpen.h" @@ -109,7 +119,27 @@ struct cdir_end { static size_t zip_size; static int zip_fd; -NS_EXPORT struct mapping_info * lib_mapping; +static struct mapping_info * lib_mapping; + +NS_EXPORT const struct mapping_info * +getLibraryMapping() +{ + return lib_mapping; +} + +static int +createAshmem(size_t bytes) +{ + int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); + if (fd < 0) + return -1; + + if (!ioctl(fd, ASHMEM_SET_SIZE, bytes)) + return fd; + + close(fd); + return -1; +} static void * map_file (const char *file) { @@ -320,6 +350,80 @@ extractLib(const struct cdir_entry *entry, void * data, void * dest) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size)); } +static int cache_count = 0; +static struct lib_cache_info *cache_mapping = NULL; + +NS_EXPORT const struct lib_cache_info * +getLibraryCache() +{ + return cache_mapping; +} + +static void +ensureLibCache() +{ + if (!cache_mapping) + cache_mapping = (struct lib_cache_info *)calloc(MAX_LIB_CACHE_ENTRIES, + sizeof(*cache_mapping)); +} + +static void +fillLibCache(const char *buf) +{ + ensureLibCache(); + + char * str = strdup(buf); + if (!str) + return; + + char * saveptr; + char * nextstr = str; + do { + struct lib_cache_info *info = &cache_mapping[cache_count]; + + char * name = strtok_r(nextstr, ":", &saveptr); + if (!name) + break; + nextstr = NULL; + + char * fd_str = strtok_r(NULL, ";", &saveptr); + if (!fd_str) + break; + + long int fd = strtol(fd_str, NULL, 10); + if (fd == LONG_MIN || fd == LONG_MAX) + break; + strncpy(info->name, name, MAX_LIB_CACHE_NAME_LEN - 1); + info->fd = fd; + } while (cache_count++ < MAX_LIB_CACHE_ENTRIES); + free(str); +} + +static int +lookupLibCacheFd(const char *libName) +{ + if (!cache_mapping) + return -1; + + int count = cache_count; + while (count--) { + struct lib_cache_info *info = &cache_mapping[count]; + if (!strcmp(libName, info->name)) + return info->fd; + } + return -1; +} + +static void +addLibCacheFd(const char *libName, int fd) +{ + ensureLibCache(); + + struct lib_cache_info *info = &cache_mapping[cache_count++]; + strncpy(info->name, libName, MAX_LIB_CACHE_NAME_LEN - 1); + info->fd = fd; +} + static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { @@ -338,9 +442,7 @@ static void * mozload(const char * path, void *zip, snprintf(fullpath, 256, "/data/data/org.mozilla.fennec/%s", path + 4); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 1", fullpath); handle = __wrap_dlopen(fullpath, RTLD_LAZY); - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 2", fullpath); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG @@ -358,32 +460,48 @@ static void * mozload(const char * path, void *zip, int fd = zip_fd; void * buf = NULL; + uint32_t lib_size = letoh32(entry->uncompressed_size); if (letoh16(file->compression) == DEFLATE) { - fd = -1; - buf = mmap(NULL, letoh32(entry->uncompressed_size), - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + int cache_fd = lookupLibCacheFd(path + 4); + fd = cache_fd; + if (fd < 0) + fd = createAshmem(lib_size); +#ifdef DEBUG + else + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path + 4); +#endif + if (fd < 0) { + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get an ashmem buffer"); + return NULL; + } + buf = mmap(NULL, lib_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); + close(fd); return NULL; } offset = 0; - extractLib(entry, data, buf); + if (cache_fd < 0) { + extractLib(entry, data, buf); + addLibCacheFd(path + 4, fd); + } data = buf; } #ifdef DEBUG - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d and offset %d", path, letoh32(entry->uncompressed_size), offset); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, - letoh32(entry->uncompressed_size), offset); + lib_size, offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); if (buf) - munmap(buf, letoh32(entry->uncompressed_size)); + munmap(buf, lib_size); #ifdef DEBUG gettimeofday(&t1, 0); @@ -550,8 +668,12 @@ ChildProcessInit(int argc, char* argv[]) break; } + fillLibCache(argv[argc - 1]); loadLibs(argv[i]); + // don't pass the last arg - it's only recognized by the lib cache + argc--; + typedef GeckoProcessType (*XRE_StringToChildProcessType_t)(char*); typedef nsresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType); XRE_StringToChildProcessType_t fXRE_StringToChildProcessType = diff --git a/other-licenses/android/APKOpen.h b/other-licenses/android/APKOpen.h index 7d4fa4b16d1..c5425441b8b 100644 --- a/other-licenses/android/APKOpen.h +++ b/other-licenses/android/APKOpen.h @@ -45,6 +45,16 @@ struct mapping_info { size_t offset; }; -extern struct mapping_info * lib_mapping; +const struct mapping_info * getLibraryMapping(); + +#define MAX_LIB_CACHE_ENTRIES 32 +#define MAX_LIB_CACHE_NAME_LEN 32 + +struct lib_cache_info { + char name[MAX_LIB_CACHE_NAME_LEN]; + int fd; +}; + +const struct lib_cache_info * getLibraryCache(); #endif /* APKOpen_h */ diff --git a/other-licenses/android/linker.c b/other-licenses/android/linker.c index b33e6dcafd8..28636db11c1 100644 --- a/other-licenses/android/linker.c +++ b/other-licenses/android/linker.c @@ -930,18 +930,19 @@ load_segments(int fd, size_t offset, void *header, soinfo *si) TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); - if (fd == -1) { + if (fd == -1 || PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE) { pbase = mmap(tmp, len, PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, - 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (pbase != MAP_FAILED) { memcpy(pbase, header + ((phdr->p_offset) & (~PAGE_MASK)), len); mprotect(pbase, len, PFLAGS_TO_PROT(phdr->p_flags)); - } - } else + } else + DL_ERR("%s: Memcpy mapping of segment failed!", si->name); + } else { pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr->p_flags), - MAP_PRIVATE | MAP_FIXED, fd, + MAP_SHARED | MAP_FIXED, fd, offset + ((phdr->p_offset) & (~PAGE_MASK))); + } if (pbase == MAP_FAILED) { DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, @@ -1238,7 +1239,7 @@ load_mapped_library(const char * name, int fd, pid, name, (void *)si->base, (unsigned) ext_sz); /* Now actually load the library's segments into right places in memory */ - if (load_segments(offset ? fd : -1, offset, mem, si) < 0) { + if (load_segments(fd, offset, mem, si) < 0) { if (si->ba_index >= 0) { ba_free(&ba_nonprelink, si->ba_index); si->ba_index = -1; @@ -1394,6 +1395,28 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) Elf32_Rel *start = rel; unsigned idx; + /* crappy hack to ensure we don't write into the read-only region */ + + /* crappy hack part 1: find the read only region */ + int cnt; + void * ro_region_end = si->base; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)si->base; + Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)si->base + ehdr->e_phoff); + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { + if (phdr->p_type != PT_LOAD || + PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE || + phdr->p_vaddr != 0) + continue; + + ro_region_end = si->base + phdr->p_filesz; + break; + } + + void * remapped_page = NULL; + void * copy_page = mmap(NULL, PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + for (idx = 0; idx < count; ++idx) { unsigned type = ELF32_R_TYPE(rel->r_info); unsigned sym = ELF32_R_SYM(rel->r_info); @@ -1479,6 +1502,23 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) s = NULL; } + /* crappy hack part 2: make this page writable */ + void * reloc_page = reloc & ~PAGE_MASK; + if (reloc < ro_region_end && reloc_page != remapped_page) { + if (remapped_page != NULL) + mprotect(remapped_page, PAGE_SIZE, PROT_READ | PROT_EXEC); + memcpy(copy_page, reloc_page, PAGE_SIZE); + munmap(reloc_page, PAGE_SIZE); + if (mmap(reloc_page, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0) == MAP_FAILED) + DL_ERR("failed to map page for %s at 0x%08x! errno=%d", + si->name, reloc_page, errno); + + memcpy(reloc_page, copy_page, PAGE_SIZE); + remapped_page = reloc_page; + } + /* TODO: This is ugly. Split up the relocations by arch into * different files. */ @@ -1584,6 +1624,7 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) } rel++; } + munmap(copy_page, PAGE_SIZE); return 0; } diff --git a/toolkit/xre/nsAndroidStartup.cpp b/toolkit/xre/nsAndroidStartup.cpp index b8e36515b1f..5a8599bd241 100644 --- a/toolkit/xre/nsAndroidStartup.cpp +++ b/toolkit/xre/nsAndroidStartup.cpp @@ -75,7 +75,7 @@ static void* GeckoStart(void *data) { #ifdef MOZ_CRASHREPORTER - struct mapping_info *info = lib_mapping; + const struct mapping_info *info = getLibraryMapping(); while (info->name) { CrashReporter::AddLibraryMapping(info->name, info->file_id, info->base, info->len, info->offset); From 68b93068742bfac93644c16e61e3ce4f0b381c5d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Oct 2010 22:17:07 +1300 Subject: [PATCH 016/263] Try to fix failing test for bug 595842 by removing border whose antialiasing seems to be inconsistent, a=testonly --- layout/reftests/native-theme/border-radius-ref.html | 2 +- layout/reftests/native-theme/border-radius.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/reftests/native-theme/border-radius-ref.html b/layout/reftests/native-theme/border-radius-ref.html index d6d4b16ccec..908f9515d8a 100644 --- a/layout/reftests/native-theme/border-radius-ref.html +++ b/layout/reftests/native-theme/border-radius-ref.html @@ -1,7 +1,7 @@ -
+
diff --git a/layout/reftests/native-theme/border-radius.html b/layout/reftests/native-theme/border-radius.html index f9ced1d436e..43ed3964591 100644 --- a/layout/reftests/native-theme/border-radius.html +++ b/layout/reftests/native-theme/border-radius.html @@ -1,7 +1,7 @@ -
+
From c13d5f5238374701b3d3db5dc5db42e766620367 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Fri, 29 Oct 2010 10:07:54 -0400 Subject: [PATCH 017/263] Bug 608239: Backout changeset 99233ad2ff70 a=fennec-should-load-pages --- ipc/glue/GeckoChildProcessHost.cpp | 22 ---- ipc/glue/SharedMemoryBasic_android.cpp | 12 ++- other-licenses/android/APKOpen.cpp | 144 ++----------------------- other-licenses/android/APKOpen.h | 12 +-- other-licenses/android/linker.c | 55 ++-------- toolkit/xre/nsAndroidStartup.cpp | 2 +- 6 files changed, 30 insertions(+), 217 deletions(-) diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 7442c566bd4..28f444a2141 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -69,10 +69,6 @@ #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" #endif -#ifdef ANDROID -#include "APKOpen.h" -#endif - using mozilla::MonitorAutoEnter; using mozilla::ipc::GeckoChildProcessHost; @@ -392,20 +388,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b #ifdef ANDROID // The java wrapper unpacks this for us but can't make it executable chmod(exePath.value().c_str(), 0700); - int cacheCount = 0; - const struct lib_cache_info * cache = getLibraryCache(); - nsCString cacheStr; - while (cache && - cacheCount++ < MAX_LIB_CACHE_ENTRIES && - strlen(cache->name)) { - mFileMap.push_back(std::pair(cache->fd, cache->fd)); - cacheStr.Append(cache->name); - cacheStr.AppendPrintf(":%d;", cache->fd); - cache++; - } - // fill the last arg with something if there's no cache - if (cacheStr.IsEmpty()) - cacheStr.AppendLiteral("-"); #endif // remap the IPC socket fd to a well-known int, as the OS does for @@ -469,10 +451,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b childArgv.push_back(childProcessType); -#ifdef ANDROID - childArgv.push_back(cacheStr.get()); -#endif - base::LaunchApp(childArgv, mFileMap, #if defined(OS_LINUX) || defined(OS_MACOSX) newEnvVars, diff --git a/ipc/glue/SharedMemoryBasic_android.cpp b/ipc/glue/SharedMemoryBasic_android.cpp index 34385c08995..6f457b107c4 100644 --- a/ipc/glue/SharedMemoryBasic_android.cpp +++ b/ipc/glue/SharedMemoryBasic_android.cpp @@ -56,7 +56,15 @@ // Temporarily go directly to the kernel interface until we can // interact better with libcutils. // -#include +#define ASHMEM_DEVICE "/dev/ashmem" +#define ASHMEM_NAME_LEN 256 +#define __ASHMEMIOC 0x77 +#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) +#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) +#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) +#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) +#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long) +#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6) namespace mozilla { namespace ipc { @@ -94,7 +102,7 @@ SharedMemoryBasic::Create(size_t aNbytes) NS_ABORT_IF_FALSE(-1 == mShmFd, "Already Create()d"); // Carve a new instance off of /dev/ashmem - int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); + int shmfd = open(ASHMEM_DEVICE, O_RDWR, 0600); if (-1 == shmfd) { LogError("ShmemAndroid::Create():open"); return false; diff --git a/other-licenses/android/APKOpen.cpp b/other-licenses/android/APKOpen.cpp index 7de334c6d63..f8f9a85f1fd 100644 --- a/other-licenses/android/APKOpen.cpp +++ b/other-licenses/android/APKOpen.cpp @@ -34,29 +34,19 @@ * * ***** END LICENSE BLOCK ***** */ -/* - * This custom library loading code is only meant to be called - * during initialization. As a result, it takes no special - * precautions to be threadsafe. Any of the library loading functions - * like mozload should not be available to other code. - */ - #include #include #include #include #include #include -#include #include #include #include -#include #include #include #include #include -#include #include "dlfcn.h" #include "APKOpen.h" @@ -119,27 +109,7 @@ struct cdir_end { static size_t zip_size; static int zip_fd; -static struct mapping_info * lib_mapping; - -NS_EXPORT const struct mapping_info * -getLibraryMapping() -{ - return lib_mapping; -} - -static int -createAshmem(size_t bytes) -{ - int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); - if (fd < 0) - return -1; - - if (!ioctl(fd, ASHMEM_SET_SIZE, bytes)) - return fd; - - close(fd); - return -1; -} +NS_EXPORT struct mapping_info * lib_mapping; static void * map_file (const char *file) { @@ -350,80 +320,6 @@ extractLib(const struct cdir_entry *entry, void * data, void * dest) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size)); } -static int cache_count = 0; -static struct lib_cache_info *cache_mapping = NULL; - -NS_EXPORT const struct lib_cache_info * -getLibraryCache() -{ - return cache_mapping; -} - -static void -ensureLibCache() -{ - if (!cache_mapping) - cache_mapping = (struct lib_cache_info *)calloc(MAX_LIB_CACHE_ENTRIES, - sizeof(*cache_mapping)); -} - -static void -fillLibCache(const char *buf) -{ - ensureLibCache(); - - char * str = strdup(buf); - if (!str) - return; - - char * saveptr; - char * nextstr = str; - do { - struct lib_cache_info *info = &cache_mapping[cache_count]; - - char * name = strtok_r(nextstr, ":", &saveptr); - if (!name) - break; - nextstr = NULL; - - char * fd_str = strtok_r(NULL, ";", &saveptr); - if (!fd_str) - break; - - long int fd = strtol(fd_str, NULL, 10); - if (fd == LONG_MIN || fd == LONG_MAX) - break; - strncpy(info->name, name, MAX_LIB_CACHE_NAME_LEN - 1); - info->fd = fd; - } while (cache_count++ < MAX_LIB_CACHE_ENTRIES); - free(str); -} - -static int -lookupLibCacheFd(const char *libName) -{ - if (!cache_mapping) - return -1; - - int count = cache_count; - while (count--) { - struct lib_cache_info *info = &cache_mapping[count]; - if (!strcmp(libName, info->name)) - return info->fd; - } - return -1; -} - -static void -addLibCacheFd(const char *libName, int fd) -{ - ensureLibCache(); - - struct lib_cache_info *info = &cache_mapping[cache_count++]; - strncpy(info->name, libName, MAX_LIB_CACHE_NAME_LEN - 1); - info->fd = fd; -} - static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { @@ -442,7 +338,9 @@ static void * mozload(const char * path, void *zip, snprintf(fullpath, 256, "/data/data/org.mozilla.fennec/%s", path + 4); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 1", fullpath); handle = __wrap_dlopen(fullpath, RTLD_LAZY); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 2", fullpath); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG @@ -460,48 +358,32 @@ static void * mozload(const char * path, void *zip, int fd = zip_fd; void * buf = NULL; - uint32_t lib_size = letoh32(entry->uncompressed_size); if (letoh16(file->compression) == DEFLATE) { - int cache_fd = lookupLibCacheFd(path + 4); - fd = cache_fd; - if (fd < 0) - fd = createAshmem(lib_size); -#ifdef DEBUG - else - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path + 4); -#endif - if (fd < 0) { - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get an ashmem buffer"); - return NULL; - } - buf = mmap(NULL, lib_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); + fd = -1; + buf = mmap(NULL, letoh32(entry->uncompressed_size), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); - close(fd); return NULL; } offset = 0; - if (cache_fd < 0) { - extractLib(entry, data, buf); - addLibCacheFd(path + 4, fd); - } + extractLib(entry, data, buf); data = buf; } #ifdef DEBUG - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d and offset %d", path, letoh32(entry->uncompressed_size), offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, - lib_size, offset); + letoh32(entry->uncompressed_size), offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); if (buf) - munmap(buf, lib_size); + munmap(buf, letoh32(entry->uncompressed_size)); #ifdef DEBUG gettimeofday(&t1, 0); @@ -668,12 +550,8 @@ ChildProcessInit(int argc, char* argv[]) break; } - fillLibCache(argv[argc - 1]); loadLibs(argv[i]); - // don't pass the last arg - it's only recognized by the lib cache - argc--; - typedef GeckoProcessType (*XRE_StringToChildProcessType_t)(char*); typedef nsresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType); XRE_StringToChildProcessType_t fXRE_StringToChildProcessType = diff --git a/other-licenses/android/APKOpen.h b/other-licenses/android/APKOpen.h index c5425441b8b..7d4fa4b16d1 100644 --- a/other-licenses/android/APKOpen.h +++ b/other-licenses/android/APKOpen.h @@ -45,16 +45,6 @@ struct mapping_info { size_t offset; }; -const struct mapping_info * getLibraryMapping(); - -#define MAX_LIB_CACHE_ENTRIES 32 -#define MAX_LIB_CACHE_NAME_LEN 32 - -struct lib_cache_info { - char name[MAX_LIB_CACHE_NAME_LEN]; - int fd; -}; - -const struct lib_cache_info * getLibraryCache(); +extern struct mapping_info * lib_mapping; #endif /* APKOpen_h */ diff --git a/other-licenses/android/linker.c b/other-licenses/android/linker.c index 28636db11c1..b33e6dcafd8 100644 --- a/other-licenses/android/linker.c +++ b/other-licenses/android/linker.c @@ -930,19 +930,18 @@ load_segments(int fd, size_t offset, void *header, soinfo *si) TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); - if (fd == -1 || PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE) { + if (fd == -1) { pbase = mmap(tmp, len, PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, + 0); if (pbase != MAP_FAILED) { memcpy(pbase, header + ((phdr->p_offset) & (~PAGE_MASK)), len); mprotect(pbase, len, PFLAGS_TO_PROT(phdr->p_flags)); - } else - DL_ERR("%s: Memcpy mapping of segment failed!", si->name); - } else { + } + } else pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr->p_flags), - MAP_SHARED | MAP_FIXED, fd, + MAP_PRIVATE | MAP_FIXED, fd, offset + ((phdr->p_offset) & (~PAGE_MASK))); - } if (pbase == MAP_FAILED) { DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, @@ -1239,7 +1238,7 @@ load_mapped_library(const char * name, int fd, pid, name, (void *)si->base, (unsigned) ext_sz); /* Now actually load the library's segments into right places in memory */ - if (load_segments(fd, offset, mem, si) < 0) { + if (load_segments(offset ? fd : -1, offset, mem, si) < 0) { if (si->ba_index >= 0) { ba_free(&ba_nonprelink, si->ba_index); si->ba_index = -1; @@ -1395,28 +1394,6 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) Elf32_Rel *start = rel; unsigned idx; - /* crappy hack to ensure we don't write into the read-only region */ - - /* crappy hack part 1: find the read only region */ - int cnt; - void * ro_region_end = si->base; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)si->base; - Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)si->base + ehdr->e_phoff); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { - if (phdr->p_type != PT_LOAD || - PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE || - phdr->p_vaddr != 0) - continue; - - ro_region_end = si->base + phdr->p_filesz; - break; - } - - void * remapped_page = NULL; - void * copy_page = mmap(NULL, PAGE_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - for (idx = 0; idx < count; ++idx) { unsigned type = ELF32_R_TYPE(rel->r_info); unsigned sym = ELF32_R_SYM(rel->r_info); @@ -1502,23 +1479,6 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) s = NULL; } - /* crappy hack part 2: make this page writable */ - void * reloc_page = reloc & ~PAGE_MASK; - if (reloc < ro_region_end && reloc_page != remapped_page) { - if (remapped_page != NULL) - mprotect(remapped_page, PAGE_SIZE, PROT_READ | PROT_EXEC); - memcpy(copy_page, reloc_page, PAGE_SIZE); - munmap(reloc_page, PAGE_SIZE); - if (mmap(reloc_page, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, - -1, 0) == MAP_FAILED) - DL_ERR("failed to map page for %s at 0x%08x! errno=%d", - si->name, reloc_page, errno); - - memcpy(reloc_page, copy_page, PAGE_SIZE); - remapped_page = reloc_page; - } - /* TODO: This is ugly. Split up the relocations by arch into * different files. */ @@ -1624,7 +1584,6 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) } rel++; } - munmap(copy_page, PAGE_SIZE); return 0; } diff --git a/toolkit/xre/nsAndroidStartup.cpp b/toolkit/xre/nsAndroidStartup.cpp index 5a8599bd241..b8e36515b1f 100644 --- a/toolkit/xre/nsAndroidStartup.cpp +++ b/toolkit/xre/nsAndroidStartup.cpp @@ -75,7 +75,7 @@ static void* GeckoStart(void *data) { #ifdef MOZ_CRASHREPORTER - const struct mapping_info *info = getLibraryMapping(); + struct mapping_info *info = lib_mapping; while (info->name) { CrashReporter::AddLibraryMapping(info->name, info->file_id, info->base, info->len, info->offset); From 275d1802e2df3448460f9e683b0ec8094c2a0479 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Fri, 29 Oct 2010 11:38:26 -0400 Subject: [PATCH 018/263] Bug 608258 - Crash at visiting AMO [r=jdm a=blocking-fennecb2] --- netwerk/protocol/http/HttpChannelParentListener.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp index 74fe14c70e4..6f5e1afb6f3 100644 --- a/netwerk/protocol/http/HttpChannelParentListener.cpp +++ b/netwerk/protocol/http/HttpChannelParentListener.cpp @@ -144,7 +144,7 @@ HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result) } if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) { - if (!mActiveChannel && !mActiveChannel->mTabParent) + if (!mActiveChannel || !mActiveChannel->mTabParent) return NS_NOINTERFACE; return mActiveChannel->mTabParent->QueryInterface(aIID, result); } From 6a27d3fb589c9276d8e0a071fcd598a62a194ddc Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Thu, 28 Oct 2010 15:00:31 -0700 Subject: [PATCH 019/263] Bug 575561 - External links from within app tabs should always open in new tabs instead of replacing the app tab's page. r=gavin+bz, a=blocking-beta7 --- browser/base/content/browser.js | 21 ++++++ browser/base/content/tabbrowser.xml | 4 ++ docshell/base/nsDocShell.cpp | 33 +++++++++- docshell/base/nsDocShell.h | 1 + docshell/base/nsIDocShell.idl | 10 ++- embedding/browser/webBrowser/Makefile.in | 1 + .../webBrowser/nsIWebBrowserChrome3.idl | 65 +++++++++++++++++++ toolkit/components/help/content/help.js | 3 +- toolkit/content/Services.jsm | 4 ++ .../content/tests/chrome/findbar_window.xul | 4 +- xpfe/appshell/public/nsIXULBrowserWindow.idl | 10 +++ xpfe/appshell/src/nsContentTreeOwner.cpp | 24 +++++++ xpfe/appshell/src/nsContentTreeOwner.h | 5 +- 13 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 embedding/browser/webBrowser/nsIWebBrowserChrome3.idl diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 006eec5f90c..65310db8558 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3985,6 +3985,27 @@ var XULBrowserWindow = { encodeURIComponent); gURLBar.setOverLink(link); }, + + // Called before links are navigated to to allow us to retarget them if needed. + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { + // Don't modify non-default targets or targets that aren't in top-level app + // tab docshells (isAppTab will be false for app tab subframes). + if (originalTarget != "" || !isAppTab) + return originalTarget; + + let docURI = linkNode.ownerDocument.documentURIObject; + try { + let docURIDomain = Services.eTLD.getBaseDomain(docURI, 0); + let linkURIDomain = Services.eTLD.getBaseDomain(linkURI, 0); + // External links from within app tabs should always open in new tabs + // instead of replacing the app tab's page (Bug 575561) + if (docURIDomain != linkURIDomain) + return "_blank"; + } catch(e) { + // If getBaseDomain fails, we return originalTarget below. + } + return originalTarget; + }, onLinkIconAvailable: function (aIconURL) { if (gProxyFavIcon && gBrowser.userTypedValue === null) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index a11bde11f22..fdb9bb62fc8 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -191,6 +191,8 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = true; + let event = document.createEvent("Events"); event.initEvent("TabPinned", true, false); aTab.dispatchEvent(event); @@ -210,6 +212,8 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = false; + let event = document.createEvent("Events"); event.initEvent("TabUnpinned", true, false); aTab.dispatchEvent(event); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 8257979f25d..42ffaec9270 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -159,7 +159,7 @@ #include "nsIController.h" #include "nsPICommandUpdater.h" #include "nsIDOMHTMLAnchorElement.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsITabChild.h" #include "nsIStrictTransportSecurityService.h" @@ -711,6 +711,7 @@ nsDocShell::nsDocShell(): mAllowKeywordFixup(PR_FALSE), mIsOffScreenBrowser(PR_FALSE), mIsActive(PR_TRUE), + mIsAppTab(PR_FALSE), mFiredUnloadEvent(PR_FALSE), mEODForCurrentDocument(PR_FALSE), mURIResultedInDocument(PR_FALSE), @@ -4802,6 +4803,20 @@ nsDocShell::GetIsActive(PRBool *aIsActive) return NS_OK; } +NS_IMETHODIMP +nsDocShell::SetIsAppTab(PRBool aIsAppTab) +{ + mIsAppTab = aIsAppTab; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShell::GetIsAppTab(PRBool *aIsAppTab) +{ + *aIsAppTab = mIsAppTab; + return NS_OK; +} + NS_IMETHODIMP nsDocShell::SetVisibility(PRBool aVisibility) { @@ -11311,8 +11326,22 @@ nsDocShell::OnLinkClick(nsIContent* aContent, return NS_OK; } + nsresult rv = NS_ERROR_FAILURE; + nsAutoString target; + + nsCOMPtr browserChrome3 = do_GetInterface(mTreeOwner); + if (browserChrome3) { + nsCOMPtr linkNode = do_QueryInterface(aContent); + nsAutoString oldTarget(aTargetSpec); + rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI, + linkNode, mIsAppTab, target); + } + + if (NS_FAILED(rv)) + target = aTargetSpec; + nsCOMPtr ev = - new OnLinkClickEvent(this, aContent, aURI, aTargetSpec, + new OnLinkClickEvent(this, aContent, aURI, target.get(), aPostDataStream, aHeadersDataStream); return NS_DispatchToCurrentThread(ev); } diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index a6c33f149c1..317f766a48a 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -790,6 +790,7 @@ protected: PRPackedBool mAllowKeywordFixup; PRPackedBool mIsOffScreenBrowser; PRPackedBool mIsActive; + PRPackedBool mIsAppTab; // This boolean is set to true right before we fire pagehide and generally // unset when we embed a new content viewer. While it's true no navigation diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 788be5c5ef2..e5a72e5813e 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -71,7 +71,7 @@ interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; -[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)] +[scriptable, uuid(98cdbcc4-2d81-4191-a63f-b6c52085edbc)] interface nsIDocShell : nsISupports { /** @@ -529,11 +529,17 @@ interface nsIDocShell : nsISupports */ attribute boolean isActive; - /** * The ID of the docshell in the session history. */ readonly attribute unsigned long long historyID; + + /** + * Sets whether a docshell is an app tab. An app tab docshell may behave + * differently than a non-app tab docshell in some cases, such as when + * handling link clicks. Docshells are not app tabs unless told otherwise. + */ + attribute boolean isAppTab; }; [uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)] diff --git a/embedding/browser/webBrowser/Makefile.in b/embedding/browser/webBrowser/Makefile.in index b068d4c210d..10a56f9671c 100644 --- a/embedding/browser/webBrowser/Makefile.in +++ b/embedding/browser/webBrowser/Makefile.in @@ -78,6 +78,7 @@ XPIDLSRCS = \ nsIEmbeddingSiteWindow2.idl \ nsIContextMenuListener2.idl \ nsIWebBrowserChrome2.idl \ + nsIWebBrowserChrome3.idl \ $(NULL) CPPSRCS = \ diff --git a/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl new file mode 100644 index 00000000000..b15bf12335e --- /dev/null +++ b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl @@ -0,0 +1,65 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Margaret Leibovic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "nsIWebBrowserChrome2.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" + +/** + * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2. + */ +[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)] +interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 +{ + /** + * Determines the appropriate target for a link. + * + * @param originalTarget + * The original link target. + * @param linkURI + * Link destination URI. + * @param aDOMNode + * Link DOM node. + * @param isAppTab + * Whether or not the link is in an app tab. + * @returns A new link target, if appropriate. + * Otherwise returns originalTarget. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); +}; diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js index f17403b17bd..4a49bfb9b7c 100644 --- a/toolkit/components/help/content/help.js +++ b/toolkit/components/help/content/help.js @@ -562,7 +562,8 @@ nsHelpStatusHandler.prototype = { setJSStatus : function(status) {}, setJSDefaultStatus : function(status) {}, - setOverLink : function(link, context) {} + setOverLink : function(link, context) {}, + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {} } function UpdateBackForwardButtons() { diff --git a/toolkit/content/Services.jsm b/toolkit/content/Services.jsm index 4d6a82866bf..86ad255edd2 100644 --- a/toolkit/content/Services.jsm +++ b/toolkit/content/Services.jsm @@ -130,3 +130,7 @@ XPCOMUtils.defineLazyServiceGetter(Services, "strings", XPCOMUtils.defineLazyServiceGetter(Services, "urlFormatter", "@mozilla.org/toolkit/URLFormatterService;1", "nsIURLFormatter"); + +XPCOMUtils.defineLazyServiceGetter(Services, "eTLD", + "@mozilla.org/network/effective-tld-service;1", + "nsIEffectiveTLDService"); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index 33729245b7e..911b3e9cf85 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -76,7 +76,9 @@ setOverLink: function(aStatusText, aLink) { gStatusText = aStatusText; - } + }, + + onBeforeLinkTraversal: function() { } }; function ok(condition, message) { diff --git a/xpfe/appshell/public/nsIXULBrowserWindow.idl b/xpfe/appshell/public/nsIXULBrowserWindow.idl index 37a8676aa99..d787d9405a0 100644 --- a/xpfe/appshell/public/nsIXULBrowserWindow.idl +++ b/xpfe/appshell/public/nsIXULBrowserWindow.idl @@ -38,6 +38,8 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" interface nsIRequest; interface nsIDOMElement; @@ -65,5 +67,13 @@ interface nsIXULBrowserWindow : nsISupports * over. */ void setOverLink(in AString link, in nsIDOMElement element); + + /** + * Determines the appropriate target for a link. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); }; diff --git a/xpfe/appshell/src/nsContentTreeOwner.cpp b/xpfe/appshell/src/nsContentTreeOwner.cpp index 3794e06d4b9..f6c21a0a86d 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -124,6 +124,7 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) // NOTE: This is using aggregation because there are some properties and @@ -430,6 +431,29 @@ nsContentTreeOwner::GetPersistence(PRBool* aPersistPosition, return NS_OK; } +//***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome3 +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget, + nsIURI *linkURI, + nsIDOMNode *linkNode, + PRBool isAppTab, + nsAString &_retval) +{ + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI, + linkNode, isAppTab, _retval); + + _retval = originalTarget; + return NS_OK; +} + //***************************************************************************** // nsContentTreeOwner::nsIWebBrowserChrome2 //***************************************************************************** diff --git a/xpfe/appshell/src/nsContentTreeOwner.h b/xpfe/appshell/src/nsContentTreeOwner.h index efc4e54b339..31d462a52e5 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.h +++ b/xpfe/appshell/src/nsContentTreeOwner.h @@ -49,7 +49,7 @@ #include "nsIDocShellTreeOwner.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsIWindowProvider.h" class nsXULWindow; @@ -58,7 +58,7 @@ class nsSiteWindow2; class nsContentTreeOwner : public nsIDocShellTreeOwner, public nsIBaseWindow, public nsIInterfaceRequestor, - public nsIWebBrowserChrome2, + public nsIWebBrowserChrome3, public nsIWindowProvider { friend class nsXULWindow; @@ -72,6 +72,7 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 + NS_DECL_NSIWEBBROWSERCHROME3 NS_DECL_NSIWINDOWPROVIDER protected: From 0268cab922ee46abca23692f39926d91e100cc53 Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Thu, 28 Oct 2010 15:00:50 -0700 Subject: [PATCH 020/263] Bug 575561 - External links from within app tabs should always open in new tabs instead of replacing the app tab's page (Tests). r=gavin, a=blocking-beta7 --- browser/base/content/test/Makefile.in | 3 + browser/base/content/test/app_bug575561.html | 16 ++++ .../content/test/app_subframe_bug575561.html | 12 +++ .../base/content/test/browser_bug575561.js | 77 +++++++++++++++++++ .../content/tests/browser/browser_Services.js | 3 + 5 files changed, 111 insertions(+) create mode 100644 browser/base/content/test/app_bug575561.html create mode 100644 browser/base/content/test/app_subframe_bug575561.html create mode 100644 browser/base/content/test/browser_bug575561.js diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 6022529c7ac..3492d16576f 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -145,6 +145,7 @@ _BROWSER_FILES = \ browser_bug561636.js \ browser_bug562649.js \ browser_bug563588.js \ + browser_bug575561.js \ browser_bug577121.js \ browser_bug579872.js \ browser_bug580956.js \ @@ -218,6 +219,8 @@ _BROWSER_FILES = \ file_bug550565_favicon.ico \ browser_overLinkInLocationBar.js \ browser_aboutHome.js \ + app_bug575561.html \ + app_subframe_bug575561.html \ $(NULL) # compartment-disabled diff --git a/browser/base/content/test/app_bug575561.html b/browser/base/content/test/app_bug575561.html new file mode 100644 index 00000000000..60511f5dedd --- /dev/null +++ b/browser/base/content/test/app_bug575561.html @@ -0,0 +1,16 @@ + + + + + Test for links in app tabs + + + same domain + same domain (different subdomain) + different domain + different domain (with target) + + + diff --git a/browser/base/content/test/app_subframe_bug575561.html b/browser/base/content/test/app_subframe_bug575561.html new file mode 100644 index 00000000000..754f3806e15 --- /dev/null +++ b/browser/base/content/test/app_subframe_bug575561.html @@ -0,0 +1,12 @@ + + + + + Test for links in app tab subframes + + + different domain + + diff --git a/browser/base/content/test/browser_bug575561.js b/browser/base/content/test/browser_bug575561.js new file mode 100644 index 00000000000..b3a69105fbb --- /dev/null +++ b/browser/base/content/test/browser_bug575561.js @@ -0,0 +1,77 @@ +function test() { + waitForExplicitFinish(); + + // Pinned: Link to the same domain should not open a new tab + // Tests link to http://example.com/browser/browser/base/content/test/dummy_page.html + testLink(0, true, false, function() { + // Pinned: Link to the same domain should not open a new tab + // Tests link to http://test1.example.com/browser/browser/base/content/test/dummy_page.html + testLink(1, true, false, function() { + // Pinned: Link to a different domain should open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html + testLink(2, true, true, function() { + // Not Pinned: Link to a different domain should not open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html + testLink(2, false, false, function() { + // Pinned: Targetted link should open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html with target="foo" + testLink(3, true, true, function() { + // Pinned: Link in a subframe should not open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html in subframe + testLink(0, true, false, finish, true); + }); + }); + }); + }); + }); +} + +function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) { + let appTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/app_bug575561.html", {skipAnimation: true}); + if (pinTab) + gBrowser.pinTab(appTab); + gBrowser.selectedTab = appTab; + appTab.linkedBrowser.addEventListener("load", onLoad, true); + + let loadCount = 0; + function onLoad() { + loadCount++; + if (loadCount < 2) + return; + + appTab.linkedBrowser.removeEventListener("load", onLoad, true); + + let browser = gBrowser.getBrowserForTab(appTab); + if (testSubFrame) + browser = browser.contentDocument.getElementsByTagName("iframe")[0]; + + let links = browser.contentDocument.getElementsByTagName("a"); + + if (expectNewTab) + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true); + else + browser.addEventListener("load", onPageLoad, true); + + info("Clicking " + links[aLinkIndex].textContent); + EventUtils.sendMouseEvent({type:"click"}, links[aLinkIndex], browser.contentWindow); + + function onPageLoad() { + browser.removeEventListener("load", onPageLoad, true); + is(browser.contentDocument.location.href, links[aLinkIndex].href, "Link should not open in a new tab"); + executeSoon(function(){ + gBrowser.removeTab(appTab); + nextTest(); + }); + } + + function onTabOpen(event) { + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true); + ok(true, "Link should open a new tab"); + executeSoon(function(){ + gBrowser.removeTab(appTab); + gBrowser.removeCurrentTab(); + nextTest(); + }); + } + } +} diff --git a/toolkit/content/tests/browser/browser_Services.js b/toolkit/content/tests/browser/browser_Services.js index 311de6a2e5a..635e06d68aa 100644 --- a/toolkit/content/tests/browser/browser_Services.js +++ b/toolkit/content/tests/browser/browser_Services.js @@ -50,6 +50,7 @@ function checkServices() { checkService("prefs", Ci.nsIPrefService); checkService("contentPrefs", Ci.nsIContentPrefService); checkService("wm", Ci.nsIWindowMediator); + checkService("obs", Ci.nsIObserverService); checkService("perms", Ci.nsIPermissionManager); checkService("io", Ci.nsIIOService); checkService("io", Ci.nsIIOService2); @@ -66,6 +67,8 @@ function checkServices() { checkService("scriptloader", Ci.mozIJSSubScriptLoader); checkService("ww", Ci.nsIWindowWatcher); checkService("tm", Ci.nsIThreadManager); + checkService("droppedLinkHandler", Ci.nsIDroppedLinkHandler); checkService("strings", Ci.nsIStringBundleService); checkService("urlFormatter", Ci.nsIURLFormatter); + checkService("eTLD", Ci.nsIEffectiveTLDService); } From 3c024e757b6aa5393148c5389470a4e078ed7572 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 27 Oct 2010 02:14:45 -0400 Subject: [PATCH 021/263] Bug 593358 - Avoid use of setTimeout to check more geolocation results. r=dougt a=test-only --HG-- extra : rebase_source : e023865e5f432a87a981fe19c09dbab5fd603cd4 --- .../test_manyCurrentConcurrent.html | 21 +++++++++++++------ .../geolocation/test_manyWatchConcurrent.html | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/dom/tests/mochitest/geolocation/test_manyCurrentConcurrent.html b/dom/tests/mochitest/geolocation/test_manyCurrentConcurrent.html index d2ed31a4deb..3d77c971b5d 100644 --- a/dom/tests/mochitest/geolocation/test_manyCurrentConcurrent.html +++ b/dom/tests/mochitest/geolocation/test_manyCurrentConcurrent.html @@ -24,21 +24,30 @@ SimpleTest.waitForExplicitFinish(); resume_geolocationProvider(); force_prompt(true); -var successCallbackCalled = false; +var successCallbackCalled = 0; +var failureCallbackCalled = 0; +const totalResults = 100; function successCallback(position) { - successCallbackCalled = true; + successCallbackCalled++; + testPassed(); } -for (var x = 0; x < 100; x++) - navigator.geolocation.getCurrentPosition(successCallback); +function failureCallback(code) { + failureCallbackCalled++; + testPassed(); +} + +for (var x = 0; x < totalResults; x++) + navigator.geolocation.getCurrentPosition(successCallback, failureCallback); function testPassed() { - ok(successCallbackCalled, "if nothing crashed, all okay"); + if (successCallbackCalled + failureCallbackCalled != totalResults) + return; + is(failureCallbackCalled, 0, "no failure callbacks should have been received"); reset_prompt(); SimpleTest.finish(); } -setTimeout(testPassed, 1000); diff --git a/dom/tests/mochitest/geolocation/test_manyWatchConcurrent.html b/dom/tests/mochitest/geolocation/test_manyWatchConcurrent.html index a22ea9b350e..2dd547bb4d6 100644 --- a/dom/tests/mochitest/geolocation/test_manyWatchConcurrent.html +++ b/dom/tests/mochitest/geolocation/test_manyWatchConcurrent.html @@ -44,7 +44,7 @@ for (var x = 0; x < totalResults; x++) function testPassed() { if (successCallbackCalled + failureCallbackCalled != totalResults) return; - is(failureCallbackCalled, 0, "if nothing crashed, all okay"); + is(failureCallbackCalled, 0, "no failure callbacks should have been received"); reset_prompt(); SimpleTest.finish(); } From 77a2b2c775875848ecf25718681494b71aea03ef Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:04:20 -0700 Subject: [PATCH 022/263] Bug 608112 - undeclared variable formatted chrome://mozapps/content/extensions/extensions.js line: 2086. r=dtownsend, a=b7 --- toolkit/mozapps/extensions/content/extensions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index ba3c126f64c..7ec4b7390ef 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -2083,7 +2083,7 @@ var gDetailView = { var sizeRow = document.getElementById("detail-size"); if (aAddon.size && aIsRemote) { let [size, unit] = DownloadUtils.convertByteUnits(parseInt(aAddon.size)); - formatted = gStrings.dl.GetStringFromName("doneSize"); + let formatted = gStrings.dl.GetStringFromName("doneSize"); formatted = formatted.replace("#1", size).replace("#2", unit); sizeRow.value = formatted; } else { From 6c85ea837cec20d9596334c985acc88a9165cd3f Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:04:38 -0700 Subject: [PATCH 023/263] Bug 608115 - ReferenceError: strings is not defined in a couple of obvious places in update.js. r=dtownsend, a=b7 --- toolkit/mozapps/extensions/content/update.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toolkit/mozapps/extensions/content/update.js b/toolkit/mozapps/extensions/content/update.js index 831284dcd12..ed187335749 100644 --- a/toolkit/mozapps/extensions/content/update.js +++ b/toolkit/mozapps/extensions/content/update.js @@ -401,6 +401,7 @@ var gInstallingPage = { ///////////////////////////////////////////////////////////////////////////// // InstallListener onDownloadStarted: function(aInstall) { + var strings = document.getElementById("updateStrings"); var label = strings.getFormattedString("downloadingPrefix", [aInstall.name]); var actionItem = document.getElementById("actionItem"); actionItem.value = label; @@ -421,6 +422,7 @@ var gInstallingPage = { }, onInstallStarted: function(aInstall) { + var strings = document.getElementById("updateStrings"); var label = strings.getFormattedString("installingPrefix", [aInstall.name]); var actionItem = document.getElementById("actionItem"); actionItem.value = label; From d37c6a2c01e2123c33791073fd5519162ff8c769 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:04:52 -0700 Subject: [PATCH 024/263] Bug 608138 - Exclude plugins from the compatibility wizard checks. r=dtownsend, a=b7 --- toolkit/mozapps/extensions/content/update.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/toolkit/mozapps/extensions/content/update.js b/toolkit/mozapps/extensions/content/update.js index ed187335749..b3bc8c22560 100644 --- a/toolkit/mozapps/extensions/content/update.js +++ b/toolkit/mozapps/extensions/content/update.js @@ -158,11 +158,13 @@ var gVersionInfoPage = { // Retrieve all add-ons in order to sync their app compatibility information AddonManager.getAllAddons(function(aAddons) { - gUpdateWizard.addons = aAddons; + gUpdateWizard.addons = aAddons.filter(function(a) { + return a.type != "plugin"; + }); - gVersionInfoPage._totalCount = aAddons.length; + gVersionInfoPage._totalCount = gUpdateWizard.addons.length; - aAddons.forEach(function(aAddon) { + gUpdateWizard.addons.forEach(function(aAddon) { aAddon.findUpdates(gVersionInfoPage, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); }, this); }); From 2693ba366096dec1f3cc4b956a04eefed67ec942 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:05:08 -0700 Subject: [PATCH 025/263] Bug 608165 - Lots of 'reference to undefined property this.mAddon.applyBackgroundUpdates' warnings when running browser_bug562797.js in a debug build. r=dtownsend, a=b7 --- toolkit/mozapps/extensions/content/extensions.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml index c71db7a1523..2a2620fd3d5 100644 --- a/toolkit/mozapps/extensions/content/extensions.xml +++ b/toolkit/mozapps/extensions/content/extensions.xml @@ -1044,9 +1044,10 @@ else this._description.hidden = true; - if (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE || - (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT && - !AddonManager.autoUpdateDefault)) { + if (!("applyBackgroundUpdates" in this.mAddon) || + (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE || + (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT && + !AddonManager.autoUpdateDefault))) { var self = this; AddonManager.getAllInstalls(function(aInstallsList) { // This can return after the binding has been destroyed, From 47566b56c60f124396aa38d344957dd23fe990b1 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:05:26 -0700 Subject: [PATCH 026/263] Bug 607821 - intermittent timeout toolkit/mozapps/extensions/test/browser/browser_bug557956.js | Test timed out. r=dtownsend, a=b7 --- toolkit/mozapps/extensions/content/update.xul | 2 +- .../extensions/test/browser/browser_bug557956.js | 5 +++++ toolkit/mozapps/extensions/test/browser/head.js | 13 +++++++++++++ .../test/xpinstall/browser_multipackage.js | 2 +- .../extensions/test/xpinstall/browser_relative.js | 2 +- .../test/xpinstall/browser_signed_multiple.js | 2 +- .../mozapps/xpinstall/content/xpinstallConfirm.xul | 1 + 7 files changed, 23 insertions(+), 4 deletions(-) diff --git a/toolkit/mozapps/extensions/content/update.xul b/toolkit/mozapps/extensions/content/update.xul index 9432ae2e346..80fa58ed7e8 100644 --- a/toolkit/mozapps/extensions/content/update.xul +++ b/toolkit/mozapps/extensions/content/update.xul @@ -51,7 +51,7 @@ From 1f1ed9be70c66b179194273cba1c214e446b6eac Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 12:05:43 -0700 Subject: [PATCH 027/263] Bug 608210 - requestLongerTimeout for each test within a test in extensions/test/browser. r=dtownsend, a=test fix --- .../mozapps/extensions/test/browser/browser_bug562797.js | 4 +--- .../mozapps/extensions/test/browser/browser_details.js | 2 ++ toolkit/mozapps/extensions/test/browser/head.js | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js index e2f8f87f8ae..a54302445c5 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js @@ -7,9 +7,7 @@ */ function test() { - // Set the timeout to 300 seconds since this test can easily take 220 seconds - // to run on a Windows debug build when it runs in a tab. - requestLongerTimeout(10); + requestLongerTimeout(2); waitForExplicitFinish(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_details.js b/toolkit/mozapps/extensions/test/browser/browser_details.js index 36c59512d07..ac13656e4a5 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_details.js +++ b/toolkit/mozapps/extensions/test/browser/browser_details.js @@ -19,6 +19,8 @@ var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); var gDate = new Date(2010, 7, 1); function open_details(aId, aType, aCallback) { + requestLongerTimeout(2); + gCategoryUtilities.openType(aType, function() { var list = gManagerWindow.document.getElementById("addon-list"); var item = list.firstChild; diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index 06038f2ed99..a4405bda6e3 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -211,7 +211,9 @@ function wait_for_manager_load(aManagerWindow, aCallback) { }, false); } -function open_manager(aView, aCallback, aLoadCallback) { +function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) { + requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); + function setup_manager(aManagerWindow) { if (aLoadCallback) aLoadCallback(aManagerWindow); @@ -241,7 +243,9 @@ function open_manager(aView, aCallback, aLoadCallback) { }, true); } -function close_manager(aManagerWindow, aCallback) { +function close_manager(aManagerWindow, aCallback, aLongerTimeout) { + requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); + ok(aManagerWindow != null, "Should have an add-ons manager window to close"); is(aManagerWindow.location, MANAGER_URI, "Should be closing window with correct URI"); From 402efe298fea6e3f8dcd8ec4d91a6e0264f60ce7 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Fri, 29 Oct 2010 12:22:28 -0700 Subject: [PATCH 028/263] Bug 607534 - Optimize custom dynamic loader to use less memory, r=cjones a=blocking-fennec --- ipc/glue/GeckoChildProcessHost.cpp | 22 ++++ ipc/glue/SharedMemoryBasic_android.cpp | 12 +-- other-licenses/android/APKOpen.cpp | 144 +++++++++++++++++++++++-- other-licenses/android/APKOpen.h | 12 ++- other-licenses/android/linker.c | 55 ++++++++-- toolkit/xre/nsAndroidStartup.cpp | 2 +- 6 files changed, 217 insertions(+), 30 deletions(-) diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 28f444a2141..7442c566bd4 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -69,6 +69,10 @@ #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1" #endif +#ifdef ANDROID +#include "APKOpen.h" +#endif + using mozilla::MonitorAutoEnter; using mozilla::ipc::GeckoChildProcessHost; @@ -388,6 +392,20 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b #ifdef ANDROID // The java wrapper unpacks this for us but can't make it executable chmod(exePath.value().c_str(), 0700); + int cacheCount = 0; + const struct lib_cache_info * cache = getLibraryCache(); + nsCString cacheStr; + while (cache && + cacheCount++ < MAX_LIB_CACHE_ENTRIES && + strlen(cache->name)) { + mFileMap.push_back(std::pair(cache->fd, cache->fd)); + cacheStr.Append(cache->name); + cacheStr.AppendPrintf(":%d;", cache->fd); + cache++; + } + // fill the last arg with something if there's no cache + if (cacheStr.IsEmpty()) + cacheStr.AppendLiteral("-"); #endif // remap the IPC socket fd to a well-known int, as the OS does for @@ -451,6 +469,10 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b childArgv.push_back(childProcessType); +#ifdef ANDROID + childArgv.push_back(cacheStr.get()); +#endif + base::LaunchApp(childArgv, mFileMap, #if defined(OS_LINUX) || defined(OS_MACOSX) newEnvVars, diff --git a/ipc/glue/SharedMemoryBasic_android.cpp b/ipc/glue/SharedMemoryBasic_android.cpp index 6f457b107c4..34385c08995 100644 --- a/ipc/glue/SharedMemoryBasic_android.cpp +++ b/ipc/glue/SharedMemoryBasic_android.cpp @@ -56,15 +56,7 @@ // Temporarily go directly to the kernel interface until we can // interact better with libcutils. // -#define ASHMEM_DEVICE "/dev/ashmem" -#define ASHMEM_NAME_LEN 256 -#define __ASHMEMIOC 0x77 -#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN]) -#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN]) -#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t) -#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4) -#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long) -#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6) +#include namespace mozilla { namespace ipc { @@ -102,7 +94,7 @@ SharedMemoryBasic::Create(size_t aNbytes) NS_ABORT_IF_FALSE(-1 == mShmFd, "Already Create()d"); // Carve a new instance off of /dev/ashmem - int shmfd = open(ASHMEM_DEVICE, O_RDWR, 0600); + int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); if (-1 == shmfd) { LogError("ShmemAndroid::Create():open"); return false; diff --git a/other-licenses/android/APKOpen.cpp b/other-licenses/android/APKOpen.cpp index f8f9a85f1fd..7de334c6d63 100644 --- a/other-licenses/android/APKOpen.cpp +++ b/other-licenses/android/APKOpen.cpp @@ -34,19 +34,29 @@ * * ***** END LICENSE BLOCK ***** */ +/* + * This custom library loading code is only meant to be called + * during initialization. As a result, it takes no special + * precautions to be threadsafe. Any of the library loading functions + * like mozload should not be available to other code. + */ + #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include #include +#include #include "dlfcn.h" #include "APKOpen.h" @@ -109,7 +119,27 @@ struct cdir_end { static size_t zip_size; static int zip_fd; -NS_EXPORT struct mapping_info * lib_mapping; +static struct mapping_info * lib_mapping; + +NS_EXPORT const struct mapping_info * +getLibraryMapping() +{ + return lib_mapping; +} + +static int +createAshmem(size_t bytes) +{ + int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); + if (fd < 0) + return -1; + + if (!ioctl(fd, ASHMEM_SET_SIZE, bytes)) + return fd; + + close(fd); + return -1; +} static void * map_file (const char *file) { @@ -320,6 +350,80 @@ extractLib(const struct cdir_entry *entry, void * data, void * dest) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "File not fully uncompressed! %d / %d", strm.total_out, letoh32(entry->uncompressed_size)); } +static int cache_count = 0; +static struct lib_cache_info *cache_mapping = NULL; + +NS_EXPORT const struct lib_cache_info * +getLibraryCache() +{ + return cache_mapping; +} + +static void +ensureLibCache() +{ + if (!cache_mapping) + cache_mapping = (struct lib_cache_info *)calloc(MAX_LIB_CACHE_ENTRIES, + sizeof(*cache_mapping)); +} + +static void +fillLibCache(const char *buf) +{ + ensureLibCache(); + + char * str = strdup(buf); + if (!str) + return; + + char * saveptr; + char * nextstr = str; + do { + struct lib_cache_info *info = &cache_mapping[cache_count]; + + char * name = strtok_r(nextstr, ":", &saveptr); + if (!name) + break; + nextstr = NULL; + + char * fd_str = strtok_r(NULL, ";", &saveptr); + if (!fd_str) + break; + + long int fd = strtol(fd_str, NULL, 10); + if (fd == LONG_MIN || fd == LONG_MAX) + break; + strncpy(info->name, name, MAX_LIB_CACHE_NAME_LEN - 1); + info->fd = fd; + } while (cache_count++ < MAX_LIB_CACHE_ENTRIES); + free(str); +} + +static int +lookupLibCacheFd(const char *libName) +{ + if (!cache_mapping) + return -1; + + int count = cache_count; + while (count--) { + struct lib_cache_info *info = &cache_mapping[count]; + if (!strcmp(libName, info->name)) + return info->fd; + } + return -1; +} + +static void +addLibCacheFd(const char *libName, int fd) +{ + ensureLibCache(); + + struct lib_cache_info *info = &cache_mapping[cache_count++]; + strncpy(info->name, libName, MAX_LIB_CACHE_NAME_LEN - 1); + info->fd = fd; +} + static void * mozload(const char * path, void *zip, struct cdir_entry *cdir_start, uint16_t cdir_entries) { @@ -338,9 +442,7 @@ static void * mozload(const char * path, void *zip, snprintf(fullpath, 256, "/data/data/org.mozilla.fennec/%s", path + 4); __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath); extractFile(fullpath, entry, data); - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 1", fullpath); handle = __wrap_dlopen(fullpath, RTLD_LAZY); - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: 2", fullpath); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror()); #ifdef DEBUG @@ -358,32 +460,48 @@ static void * mozload(const char * path, void *zip, int fd = zip_fd; void * buf = NULL; + uint32_t lib_size = letoh32(entry->uncompressed_size); if (letoh16(file->compression) == DEFLATE) { - fd = -1; - buf = mmap(NULL, letoh32(entry->uncompressed_size), - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + int cache_fd = lookupLibCacheFd(path + 4); + fd = cache_fd; + if (fd < 0) + fd = createAshmem(lib_size); +#ifdef DEBUG + else + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s from cache", path + 4); +#endif + if (fd < 0) { + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get an ashmem buffer"); + return NULL; + } + buf = mmap(NULL, lib_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); + close(fd); return NULL; } offset = 0; - extractLib(entry, data, buf); + if (cache_fd < 0) { + extractLib(entry, data, buf); + addLibCacheFd(path + 4, fd); + } data = buf; } #ifdef DEBUG - __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d and offset %d", path, letoh32(entry->uncompressed_size), offset); + __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loading %s with len %d (0x%08x) and offset %d (0x%08x)", path, lib_size, lib_size, offset, offset); #endif handle = moz_mapped_dlopen(path, RTLD_LAZY, fd, data, - letoh32(entry->uncompressed_size), offset); + lib_size, offset); if (!handle) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror()); if (buf) - munmap(buf, letoh32(entry->uncompressed_size)); + munmap(buf, lib_size); #ifdef DEBUG gettimeofday(&t1, 0); @@ -550,8 +668,12 @@ ChildProcessInit(int argc, char* argv[]) break; } + fillLibCache(argv[argc - 1]); loadLibs(argv[i]); + // don't pass the last arg - it's only recognized by the lib cache + argc--; + typedef GeckoProcessType (*XRE_StringToChildProcessType_t)(char*); typedef nsresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType); XRE_StringToChildProcessType_t fXRE_StringToChildProcessType = diff --git a/other-licenses/android/APKOpen.h b/other-licenses/android/APKOpen.h index 7d4fa4b16d1..c5425441b8b 100644 --- a/other-licenses/android/APKOpen.h +++ b/other-licenses/android/APKOpen.h @@ -45,6 +45,16 @@ struct mapping_info { size_t offset; }; -extern struct mapping_info * lib_mapping; +const struct mapping_info * getLibraryMapping(); + +#define MAX_LIB_CACHE_ENTRIES 32 +#define MAX_LIB_CACHE_NAME_LEN 32 + +struct lib_cache_info { + char name[MAX_LIB_CACHE_NAME_LEN]; + int fd; +}; + +const struct lib_cache_info * getLibraryCache(); #endif /* APKOpen_h */ diff --git a/other-licenses/android/linker.c b/other-licenses/android/linker.c index b33e6dcafd8..28636db11c1 100644 --- a/other-licenses/android/linker.c +++ b/other-licenses/android/linker.c @@ -930,18 +930,19 @@ load_segments(int fd, size_t offset, void *header, soinfo *si) TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); - if (fd == -1) { + if (fd == -1 || PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE) { pbase = mmap(tmp, len, PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, - 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); if (pbase != MAP_FAILED) { memcpy(pbase, header + ((phdr->p_offset) & (~PAGE_MASK)), len); mprotect(pbase, len, PFLAGS_TO_PROT(phdr->p_flags)); - } - } else + } else + DL_ERR("%s: Memcpy mapping of segment failed!", si->name); + } else { pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr->p_flags), - MAP_PRIVATE | MAP_FIXED, fd, + MAP_SHARED | MAP_FIXED, fd, offset + ((phdr->p_offset) & (~PAGE_MASK))); + } if (pbase == MAP_FAILED) { DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, @@ -1238,7 +1239,7 @@ load_mapped_library(const char * name, int fd, pid, name, (void *)si->base, (unsigned) ext_sz); /* Now actually load the library's segments into right places in memory */ - if (load_segments(offset ? fd : -1, offset, mem, si) < 0) { + if (load_segments(fd, offset, mem, si) < 0) { if (si->ba_index >= 0) { ba_free(&ba_nonprelink, si->ba_index); si->ba_index = -1; @@ -1394,6 +1395,28 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) Elf32_Rel *start = rel; unsigned idx; + /* crappy hack to ensure we don't write into the read-only region */ + + /* crappy hack part 1: find the read only region */ + int cnt; + void * ro_region_end = si->base; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)si->base; + Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)si->base + ehdr->e_phoff); + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { + if (phdr->p_type != PT_LOAD || + PFLAGS_TO_PROT(phdr->p_flags) & PROT_WRITE || + phdr->p_vaddr != 0) + continue; + + ro_region_end = si->base + phdr->p_filesz; + break; + } + + void * remapped_page = NULL; + void * copy_page = mmap(NULL, PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + for (idx = 0; idx < count; ++idx) { unsigned type = ELF32_R_TYPE(rel->r_info); unsigned sym = ELF32_R_SYM(rel->r_info); @@ -1479,6 +1502,23 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) s = NULL; } + /* crappy hack part 2: make this page writable */ + void * reloc_page = reloc & ~PAGE_MASK; + if (reloc < ro_region_end && reloc_page != remapped_page) { + if (remapped_page != NULL) + mprotect(remapped_page, PAGE_SIZE, PROT_READ | PROT_EXEC); + memcpy(copy_page, reloc_page, PAGE_SIZE); + munmap(reloc_page, PAGE_SIZE); + if (mmap(reloc_page, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0) == MAP_FAILED) + DL_ERR("failed to map page for %s at 0x%08x! errno=%d", + si->name, reloc_page, errno); + + memcpy(reloc_page, copy_page, PAGE_SIZE); + remapped_page = reloc_page; + } + /* TODO: This is ugly. Split up the relocations by arch into * different files. */ @@ -1584,6 +1624,7 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) } rel++; } + munmap(copy_page, PAGE_SIZE); return 0; } diff --git a/toolkit/xre/nsAndroidStartup.cpp b/toolkit/xre/nsAndroidStartup.cpp index b8e36515b1f..5a8599bd241 100644 --- a/toolkit/xre/nsAndroidStartup.cpp +++ b/toolkit/xre/nsAndroidStartup.cpp @@ -75,7 +75,7 @@ static void* GeckoStart(void *data) { #ifdef MOZ_CRASHREPORTER - struct mapping_info *info = lib_mapping; + const struct mapping_info *info = getLibraryMapping(); while (info->name) { CrashReporter::AddLibraryMapping(info->name, info->file_id, info->base, info->len, info->offset); From 26ef32dbd53f06da3fcd69a557335eab0ead8bd9 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 29 Oct 2010 14:20:43 -0500 Subject: [PATCH 029/263] Bug 607534: Avoid fd remap collisions. r=mwu a=blocking-fennec --- toolkit/crashreporter/nsExceptionHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp index 380e4033238..7e0ac09d05d 100644 --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -208,7 +208,7 @@ static char* childCrashNotifyPipe; # elif defined(XP_LINUX) static int serverSocketFd = -1; static int clientSocketFd = -1; -static const int kMagicChildCrashReportFd = 42; +static const int kMagicChildCrashReportFd = 4; # endif From 9d78bf153f853df99e2483085d584a9470d8b86a Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 29 Oct 2010 21:49:42 +0200 Subject: [PATCH 030/263] Bug 607145 - form.action, button.formAction and input.formAction should be reflected as URL. r=bz a=blocking-b7 --- .../html/content/src/nsGenericHTMLElement.h | 21 +++++ .../html/content/src/nsHTMLButtonElement.cpp | 2 +- .../html/content/src/nsHTMLFormElement.cpp | 45 ++++++----- .../html/content/src/nsHTMLInputElement.cpp | 2 +- content/html/content/test/Makefile.in | 1 + content/html/content/test/test_bug392567.html | 26 +++---- content/html/content/test/test_bug566160.html | 33 -------- content/html/content/test/test_bug607145.html | 78 +++++++++++++++++++ dom/interfaces/html/nsIDOMHTMLFormElement.idl | 5 +- .../dom-level2-html/test_button03.html | 2 +- .../passwordmgr/src/nsLoginManager.js | 4 +- 11 files changed, 141 insertions(+), 78 deletions(-) create mode 100644 content/html/content/test/test_bug607145.html diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index ec04135b323..f30eb4341dd 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -1186,6 +1186,27 @@ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ return SetAttrHelper(nsGkAtoms::_atom, aValue); \ } +/** + * A macro to implement getter and setter for action and form action content + * attributes. It's very similar to NS_IMPL_URI_ATTR expected that if the + * content attribute is the empty string, the empty string is returned. + */ +#define NS_IMPL_ACTION_ATTR(_class, _method, _atom) \ + NS_IMETHODIMP \ + _class::Get##_method(nsAString& aValue) \ + { \ + GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue); \ + if (aValue.IsEmpty()) { \ + return NS_OK; \ + } \ + return GetURIAttr(nsGkAtoms::_atom, nsnull, aValue); \ + } \ + NS_IMETHODIMP \ + _class::Set##_method(const nsAString& aValue) \ + { \ + return SetAttrHelper(nsGkAtoms::_atom, aValue); \ + } + /** * A macro to implement the getter and setter for a given content * property that needs to set a non-negative integer. The method diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index 2420d21242a..a7a705ce107 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -218,7 +218,7 @@ nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Autofocus, autofocus) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled) -NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormAction, formaction) +NS_IMPL_ACTION_ATTR(nsHTMLButtonElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormMethod, formmethod, diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index bb62ab3ac2c..22fbb02bed4 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -83,6 +83,8 @@ #include "nsIConstraintValidation.h" #include "nsIEventStateManager.h" +#include "nsIDOMHTMLButtonElement.h" + static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16; static const PRUint8 NS_FORM_AUTOCOMPLETE_ON = 1; @@ -375,7 +377,7 @@ nsHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, } NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset) -NS_IMPL_STRING_ATTR(nsHTMLFormElement, Action, action) +NS_IMPL_ACTION_ATTR(nsHTMLFormElement, Action, action) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Autocomplete, autocomplete, kFormDefaultAutocomplete->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Enctype, enctype, @@ -386,17 +388,6 @@ NS_IMPL_BOOL_ATTR(nsHTMLFormElement, NoValidate, novalidate) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Name, name) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target) -NS_IMETHODIMP -nsHTMLFormElement::GetMozActionUri(nsAString& aValue) -{ - GetAttr(kNameSpaceID_None, nsGkAtoms::action, aValue); - if (aValue.IsEmpty()) { - // Avoid resolving action="" to the base uri, bug 297761. - return NS_OK; - } - return GetURIAttr(nsGkAtoms::action, nsnull, aValue); -} - NS_IMETHODIMP nsHTMLFormElement::Submit() { @@ -1431,17 +1422,29 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL, // from the form element should be used. // nsAutoString action; - nsCOMPtr formControl = do_QueryInterface(aOriginatingElement); - if (formControl && formControl->IsSubmitControl() && - aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formaction, - action)) { - // Avoid resolving action="" to the base uri, bug 297761. - if (!action.IsEmpty()) { - static_cast(aOriginatingElement)-> - GetURIAttr(nsGkAtoms::formaction, nsnull, action); + + if (aOriginatingElement && + aOriginatingElement->HasAttr(kNameSpaceID_None, nsGkAtoms::formaction)) { +#ifdef DEBUG + nsCOMPtr formControl = do_QueryInterface(aOriginatingElement); + NS_ASSERTION(formControl && formControl->IsSubmitControl(), + "The originating element must be a submit form control!"); +#endif // DEBUG + + nsCOMPtr inputElement = do_QueryInterface(aOriginatingElement); + if (inputElement) { + inputElement->GetFormAction(action); + } else { + nsCOMPtr buttonElement = do_QueryInterface(aOriginatingElement); + if (buttonElement) { + buttonElement->GetFormAction(action); + } else { + NS_ERROR("Originating element must be an input or button element!"); + return NS_ERROR_UNEXPECTED; + } } } else { - GetMozActionUri(action); + GetAction(action); } // diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index f56251136a4..a88c13def26 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -962,7 +962,7 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete, NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus) //NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked) NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled) -NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormAction, formaction) +NS_IMPL_ACTION_ATTR(nsHTMLInputElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod, diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index 7170818b06c..e84f741f722 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -238,6 +238,7 @@ _TEST_FILES = \ test_bug606817.html \ test_bug297761.html \ file_bug297761.html \ + test_bug607145.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/test_bug392567.html b/content/html/content/test/test_bug392567.html index e7e76d8d081..766c8e7b870 100644 --- a/content/html/content/test/test_bug392567.html +++ b/content/html/content/test/test_bug392567.html @@ -42,17 +42,17 @@ function runTests() // List of tests to run, each test consists of form action URL and expected result URL var tests = [ - [jarUrl, jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null], - ["data:text/html,", "data:text/html,?$PARAMS", null], - ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS", null], - [httpUrl, httpUrl + "?$PARAMS", null], - [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ], - [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null], - ["", documentURL + "?$PARAMS", null], - [" ", documentURL + "?$PARAMS", document.location], - ["../", previousDir + "?$PARAMS", previousDir], + [jarUrl, jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"], + ["data:text/html,", "data:text/html,?$PARAMS"], + ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS"], + [httpUrl, httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"], + ["", documentURL + "?$PARAMS"], + [" ", documentURL + "?$PARAMS"], + ["../", previousDir + "?$PARAMS"], ]; var currentTest = -1; @@ -67,10 +67,6 @@ function runTests() } form.setAttribute("action", tests[currentTest][0]); - is(form.action, tests[currentTest][0], - "action IDL attribute should reflect the action content attribute"); - is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0], - "mozActionUri IDL attribute should resolve the action URI"); form.key.value = "value" + currentTest; form.submit(); } diff --git a/content/html/content/test/test_bug566160.html b/content/html/content/test/test_bug566160.html index cd258ce0b14..c11faaef65d 100644 --- a/content/html/content/test/test_bug566160.html +++ b/content/html/content/test/test_bug566160.html @@ -83,41 +83,8 @@ var gTestResults = { var gPendingLoad = 0; // Has to be set after depending on the frames number. -function checkFormActionAttribute(aElement) -{ - ok("formAction" in aElement, "formAction IDL attribute should be available in " - + aElement); - - is(aElement.formAction, "", "formAction IDL attribute should be " + - "undefined by default"); - is(aElement.getAttribute('formaction'), null, "formaction content attribute " + - "should be the empty string by default"); - - aElement.formAction = "foo"; - is(aElement.getAttribute('formaction'), "foo", "formaction content attribute " + - "should be 'foo'."); - is(aElement.formAction, "foo", "formAction IDL attribute should reflect " + - "the content attribute"); - - aElement.setAttribute('formaction', 'bar'); - is(aElement.getAttribute('formaction'), "bar", "formaction content attribute " + - "should be 'foo'."); - is(aElement.formAction, "bar", "formAction IDL attribute should reflect " + - "the content attribute"); - - aElement.removeAttribute('formaction'); - is(aElement.formAction, "", "formAction IDL attribute should be " + - "undefined by default"); - is(aElement.getAttribute('formaction'), null, "formaction content attribute " + - "should be the empty string by default"); -} - function runTests() { - // First of all, let's check if .formAction and @formaction work correctly. - checkFormActionAttribute(document.createElement('input')); - checkFormActionAttribute(document.createElement('button')); - // We add a load event for the frames which will be called when the forms // will be submitted. var frames = [ document.getElementById('frame1'), diff --git a/content/html/content/test/test_bug607145.html b/content/html/content/test/test_bug607145.html new file mode 100644 index 00000000000..752b03b2aa4 --- /dev/null +++ b/content/html/content/test/test_bug607145.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 607145 + + + + + +Mozilla Bug 607145 +

+
+
+
+ + diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index 96da5649277..7d78a2d0035 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -47,7 +47,7 @@ * http://www.w3.org/TR/DOM-Level-2-HTML/ */ -[scriptable, uuid(653dc482-d6db-4e85-bdd9-151fd110e7b1)] +[scriptable, uuid(0884ce23-e069-499e-a13c-a91c8ae0fc98)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString name; @@ -65,7 +65,4 @@ interface nsIDOMHTMLFormElement : nsIDOMHTMLElement void submit(); void reset(); - - // This property returns the resolved action URI. - readonly attribute DOMString mozActionUri; }; diff --git a/dom/tests/mochitest/dom-level2-html/test_button03.html b/dom/tests/mochitest/dom-level2-html/test_button03.html index 3aa230f795b..54cb2ac7e10 100644 --- a/dom/tests/mochitest/dom-level2-html/test_button03.html +++ b/dom/tests/mochitest/dom-level2-html/test_button03.html @@ -99,7 +99,7 @@ testNode = nodeList.item(0); // its not clear that this test is valid // mozilla returns a fully expanded uri - is(vfaction, "...", "formLink"); + is(vfaction, formNode.ownerDocument.location.href.replace(/button\.html/, "..."), "formLink"); } diff --git a/toolkit/components/passwordmgr/src/nsLoginManager.js b/toolkit/components/passwordmgr/src/nsLoginManager.js index 25140729414..592d9d08741 100644 --- a/toolkit/components/passwordmgr/src/nsLoginManager.js +++ b/toolkit/components/passwordmgr/src/nsLoginManager.js @@ -978,9 +978,9 @@ LoginManager.prototype = { }, _getActionOrigin : function (form) { - var uriString = form.mozActionUri; + var uriString = form.action; - // A blank or mission action submits to where it came from. + // A blank or missing action submits to where it came from. if (uriString == "") uriString = form.baseURI; // ala bug 297761 From 69515390a1842948a3e688c6235800959b7518e5 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 29 Oct 2010 21:50:27 +0200 Subject: [PATCH 031/263] Bug 595062 - Fix Intermittent mochitest-ipcplugins failures in test_cocoa_focus.html. r=jst a=tests --- .../test/mochitest/cocoa_window_focus.html | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/modules/plugin/test/mochitest/cocoa_window_focus.html b/modules/plugin/test/mochitest/cocoa_window_focus.html index b44bdd3a3e5..ddb2f1de2c7 100644 --- a/modules/plugin/test/mochitest/cocoa_window_focus.html +++ b/modules/plugin/test/mochitest/cocoa_window_focus.html @@ -45,32 +45,39 @@ ok(false, "Plugin does not know its initial top-level window activation state!"); } - // Send our window to the back and make sure plugins were properly notified. - // Calling window.blur() is not allowed. netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var fm = Components.classes["@mozilla.org/focus-manager;1"]. getService(Components.interfaces.nsIFocusManager); + + window.opener.addEventListener("focus", function() { + window.opener.removeEventListener("focus", arguments.callee, false); + + expectedEventCount++; + + is(plugin1.getTopLevelWindowActivationState(), false, "Activation state should be: deactivated"); + is(plugin1.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); + + is(plugin2.getTopLevelWindowActivationState(), false, "Activation state should be: deactivated"); + is(plugin2.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); + + // Bring our window back to the front and make sure plugins were properly notified. + window.focus(); + + expectedEventCount++; + + is(plugin1.getTopLevelWindowActivationState(), true, "Activation state should be: activated"); + is(plugin1.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); + + is(plugin2.getTopLevelWindowActivationState(), true, "Activation state should be: activated"); + is(plugin2.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); + + window.opener.testsFinished(); + }, false); + + // Send our window to the back and make sure plugins were properly notified. + // Calling window.blur() is not allowed. + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); fm.focusedWindow = window.opener; - - expectedEventCount++; - - is(plugin1.getTopLevelWindowActivationState(), false, "Activation state should be: deactivated"); - is(plugin1.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); - - is(plugin2.getTopLevelWindowActivationState(), false, "Activation state should be: deactivated"); - is(plugin2.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); - - // Bring our window back to the front and make sure plugins were properly notified. - window.focus(); - expectedEventCount++; - - is(plugin1.getTopLevelWindowActivationState(), true, "Activation state should be: activated"); - is(plugin1.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); - - is(plugin2.getTopLevelWindowActivationState(), true, "Activation state should be: activated"); - is(plugin2.getTopLevelWindowActivationEventCount(), expectedEventCount, "Window focus event count should be " + expectedEventCount); - - window.opener.testsFinished(); } From d27fe90d81b1a4544cbaaae9010c81f9c6d58df4 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Fri, 29 Oct 2010 21:52:42 +0200 Subject: [PATCH 032/263] Fix comment. a=typo --- content/html/content/src/nsGenericHTMLElement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index f30eb4341dd..e4f8599d153 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -1188,7 +1188,7 @@ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ /** * A macro to implement getter and setter for action and form action content - * attributes. It's very similar to NS_IMPL_URI_ATTR expected that if the + * attributes. It's very similar to NS_IMPL_URI_ATTR excepted that if the * content attribute is the empty string, the empty string is returned. */ #define NS_IMPL_ACTION_ATTR(_class, _method, _atom) \ From 69de583083ca0dea9db885ac71e933d34fcb10e8 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Fri, 29 Oct 2010 14:41:11 -0700 Subject: [PATCH 033/263] Bug 584944 - Intermittent browser_uninstalling.js | Timed out. r=dtownsend, a=test fix --- toolkit/mozapps/extensions/test/browser/head.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index a4405bda6e3..663496083c7 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -186,7 +186,9 @@ function get_addon_element(aManager, aId) { return null; } -function wait_for_view_load(aManagerWindow, aCallback, aForceWait) { +function wait_for_view_load(aManagerWindow, aCallback, aForceWait, aLongerTimeout) { + requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); + if (!aForceWait && !aManagerWindow.gViewController.isLoading) { aCallback(aManagerWindow); return; @@ -212,8 +214,6 @@ function wait_for_manager_load(aManagerWindow, aCallback) { } function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) { - requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2); - function setup_manager(aManagerWindow) { if (aLoadCallback) aLoadCallback(aManagerWindow); @@ -225,7 +225,7 @@ function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) { is(aManagerWindow.location, MANAGER_URI, "Should be displaying the correct UI"); wait_for_manager_load(aManagerWindow, function() { - wait_for_view_load(aManagerWindow, aCallback); + wait_for_view_load(aManagerWindow, aCallback, null, aLongerTimeout); }); } From 0947251bf8822e2f73ffa89ce6c0002002ba9879 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 26 Oct 2010 23:57:31 -0700 Subject: [PATCH 034/263] Bug 606585 - Make the compartment map use principals properly. r=peterv/bz, a=beta7+ --- .../base/src/nsInProcessTabChildGlobal.cpp | 2 +- content/xbl/src/nsXBLDocumentInfo.cpp | 4 +- .../document/src/nsXULPrototypeDocument.cpp | 4 +- dom/base/nsJSEnvironment.cpp | 2 +- dom/ipc/TabChild.cpp | 2 +- dom/src/threads/nsDOMWorker.cpp | 7 +- extensions/jssh/nsJSSh.cpp | 2 +- ipc/testshell/XPCShellEnvironment.cpp | 2 +- js/src/xpconnect/idl/nsIXPConnect.idl | 14 +- .../xpconnect/loader/mozJSComponentLoader.cpp | 2 +- js/src/xpconnect/shell/xpcshell.cpp | 2 +- js/src/xpconnect/src/XPCWrapper.h | 4 +- js/src/xpconnect/src/nsXPConnect.cpp | 159 +++++++++++------- js/src/xpconnect/src/xpccomponents.cpp | 26 ++- js/src/xpconnect/src/xpcinlines.h | 13 ++ js/src/xpconnect/src/xpcjsruntime.cpp | 36 ++-- js/src/xpconnect/src/xpcprivate.h | 95 ++++++++++- js/src/xpconnect/src/xpcpublic.h | 12 +- js/src/xpconnect/src/xpcthreadcontext.cpp | 12 +- 19 files changed, 269 insertions(+), 131 deletions(-) diff --git a/content/base/src/nsInProcessTabChildGlobal.cpp b/content/base/src/nsInProcessTabChildGlobal.cpp index ac4b590b471..608799bb364 100644 --- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -315,7 +315,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal() nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports, NS_GET_IID(nsISupports), - GetPrincipal(), EmptyCString(), + GetPrincipal(), nsnull, flags, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index 846a061b4bd..84f3af36008 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -327,11 +327,9 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID) JS_SetErrorReporter(cx, XBL_ProtoErrorReporter); nsIPrincipal *principal = GetPrincipal(); - nsCString origin; JSCompartment *compartment; - principal->GetOrigin(getter_Copies(origin)); - rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal, + rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull, false, &mJSObject, &compartment); NS_ENSURE_SUCCESS(rv, nsnull); diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 6ddcfe5f32e..5981d819a5a 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -732,12 +732,10 @@ nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id) JSAutoRequest ar(cx); nsIPrincipal *principal = GetPrincipal(); - nsCString origin; JSObject *newGlob; JSCompartment *compartment; - principal->GetOrigin(getter_Copies(origin)); - rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal, + rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull, false, &newGlob, &compartment); NS_ENSURE_SUCCESS(rv, nsnull); diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 62ccbf1ab12..84ccd622096 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2534,7 +2534,7 @@ nsJSContext::CreateNativeGlobalForInner( InitClassesWithNewWrappedGlobal(mContext, aNewInner, NS_GET_IID(nsISupports), aIsChrome ? systemPrincipal.get() : aPrincipal, - EmptyCString(), flags, + nsnull, flags, getter_AddRefs(jsholder)); if (NS_FAILED(rv)) return rv; diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index c28a5e6a72f..ec4874668df 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -850,7 +850,7 @@ TabChild::InitTabChildGlobal() nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports, NS_GET_IID(nsISupports), - scope->GetPrincipal(), EmptyCString(), + scope->GetPrincipal(), nsnull, flags, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/dom/src/threads/nsDOMWorker.cpp b/dom/src/threads/nsDOMWorker.cpp index ec1a5b5e6c8..21fcc03a1e4 100644 --- a/dom/src/threads/nsDOMWorker.cpp +++ b/dom/src/threads/nsDOMWorker.cpp @@ -1641,15 +1641,12 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES | nsIXPConnect::OMIT_COMPONENTS_OBJECT; - nsCAutoString origin("DOM worker: "); - origin.AppendInt((PRUint64)this); - nsCOMPtr globalWrapper; nsresult rv = xpc->InitClassesWithNewWrappedGlobal(aCx, scopeSupports, NS_GET_IID(nsISupports), nsnull, - origin, flags, - getter_AddRefs(globalWrapper)); + NS_ISUPPORTS_CAST(nsIWorker*, this), + flags, getter_AddRefs(globalWrapper)); NS_ENSURE_SUCCESS(rv, PR_FALSE); JSObject* global; diff --git a/extensions/jssh/nsJSSh.cpp b/extensions/jssh/nsJSSh.cpp index 3170f93ea65..3614b0c87a3 100644 --- a/extensions/jssh/nsJSSh.cpp +++ b/extensions/jssh/nsJSSh.cpp @@ -618,7 +618,7 @@ NS_IMETHODIMP nsJSSh::Init() nsCOMPtr holder; xpc->InitClassesWithNewWrappedGlobal(mJSContext, (nsIJSSh*)this, NS_GET_IID(nsISupports), - PR_TRUE, + mPrincipal, nsnull, PR_TRUE, getter_AddRefs(holder)); if (!holder) { NS_ERROR("global initialization failed"); diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 716c0fce70b..57774cd31bc 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -1164,7 +1164,7 @@ XPCShellEnvironment::Init() rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), principal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index 31e2323d98a..eb44d356091 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(74b5811e-92d1-468a-a59a-47760200370f)] +[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)] interface nsIXPConnect : nsISupports { %{ C++ @@ -424,12 +424,10 @@ interface nsIXPConnect : nsISupports * @param aCOMObj the native object that represents the global object. * @param aIID the IID used to wrap the global object. * @param aPrincipal the principal of the code that will run in this - * compartment. Can be null. If no specific origin is - * passed, will be used to compute the origin. - * @param aOrigin must be passed if aPrincipal is null. If non-empty, - * overrides aPrincipal's origin. (can be used to separate - * code from the same principals into different - * comartments, like sandboxes). + * compartment. Can be null if not on the main thread. + * @param aExtraPtr must be passed if aPrincipal is null. Used to separate + * code from the same principal into different + * compartments, as for sandboxes. * @param aFlags one of the flags below specifying what options this * global object wants. */ @@ -439,7 +437,7 @@ interface nsIXPConnect : nsISupports in nsISupports aCOMObj, in nsIIDRef aIID, in nsIPrincipal aPrincipal, - in ACString aOrigin, + in nsISupports aExtraPtr, in PRUint32 aFlags); const PRUint32 INIT_JS_STANDARD_CLASSES = 1 << 0; diff --git a/js/src/xpconnect/loader/mozJSComponentLoader.cpp b/js/src/xpconnect/loader/mozJSComponentLoader.cpp index 2f1bc6f188e..3e99f247ae1 100644 --- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp @@ -976,7 +976,7 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), mSystemPrincipal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/shell/xpcshell.cpp b/js/src/xpconnect/shell/xpcshell.cpp index 49e06b0a2fa..fc85b25c881 100644 --- a/js/src/xpconnect/shell/xpcshell.cpp +++ b/js/src/xpconnect/shell/xpcshell.cpp @@ -1957,7 +1957,7 @@ main(int argc, char **argv) rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), systemprincipal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/src/XPCWrapper.h b/js/src/xpconnect/src/XPCWrapper.h index 834e436c0c8..29dce8124b5 100644 --- a/js/src/xpconnect/src/XPCWrapper.h +++ b/js/src/xpconnect/src/XPCWrapper.h @@ -60,8 +60,6 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject); } // namespace XPCNativeWrapper -extern nsIScriptSecurityManager *gScriptSecurityManager; - // This namespace wraps some common functionality between the three existing // wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both // as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to @@ -75,7 +73,7 @@ namespace XPCWrapper { inline nsIScriptSecurityManager * GetSecurityManager() { - return ::gScriptSecurityManager; + return nsXPConnect::gScriptSecurityManager; } inline JSBool diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 28c443c404e..1711f54c8d0 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -75,7 +75,7 @@ PRUint32 nsXPConnect::gReportAllJSExceptions = 0; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) -nsIScriptSecurityManager *gScriptSecurityManager = nsnull; +nsIScriptSecurityManager *nsXPConnect::gScriptSecurityManager = nsnull; const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1"; const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1"; @@ -939,69 +939,105 @@ static JSClass xpcTempGlobalClass = { JSCLASS_NO_OPTIONAL_MEMBERS }; +static bool +CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, + xpc::CompartmentPrivate *priv, JSObject **global, + JSCompartment **compartment) +{ + // We take ownership of |priv|. Ensure that either we free it in the case + // of failure or give ownership to the compartment in case of success (in + // that case it will be free'd in CompartmentCallback during GC). + nsAutoPtr priv_holder(priv); + JSPrincipals *principals = nsnull; + if(principal) + principal->GetJSPrincipals(cx, &principals); + JSObject *tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals); + if(principals) + JSPRINCIPALS_DROP(cx, principals); + + if(!tempGlobal) + return false; + + *global = tempGlobal; + *compartment = tempGlobal->getCompartment(); + + js::SwitchToCompartment sc(cx, *compartment); + JS_SetCompartmentPrivate(cx, *compartment, priv_holder.forget()); + return true; +} + nsresult xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, - const nsACString &origin, nsIPrincipal *principal, + nsIPrincipal *principal, nsISupports *ptr, bool wantXrays, JSObject **global, JSCompartment **compartment) { + NS_ABORT_IF_FALSE(NS_IsMainThread(), "using a principal off the main thread?"); + NS_ABORT_IF_FALSE(principal, "bad key"); + + nsCOMPtr uri; + nsresult rv = principal->GetURI(getter_AddRefs(uri)); + if(NS_FAILED(rv)) + return UnexpectedFailure(rv); + XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap(); - nsCAutoString local_origin(origin); - if(local_origin.EqualsLiteral("file://") && principal) + xpc::PtrAndPrincipalHashKey key(ptr, uri); + if(!map.Get(&key, compartment)) { - nsCOMPtr uri; - principal->GetURI(getter_AddRefs(uri)); - uri->GetSpec(local_origin); - } - - JSObject *tempGlobal; - if(!map.Get(local_origin, compartment)) - { - JSPrincipals *principals = nsnull; - if(principal) - principal->GetJSPrincipals(cx, &principals); - tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals); - if(principals) - JSPRINCIPALS_DROP(cx, principals); - - if(!tempGlobal) - return UnexpectedFailure(NS_ERROR_FAILURE); - - *global = tempGlobal; - *compartment = tempGlobal->getCompartment(); - - js::SwitchToCompartment sc(cx, *compartment); - + xpc::PtrAndPrincipalHashKey *priv_key = + new xpc::PtrAndPrincipalHashKey(ptr, uri); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(ToNewCString(local_origin), wantXrays); - JS_SetCompartmentPrivate(cx, *compartment, priv); - map.Put(local_origin, *compartment); + new xpc::CompartmentPrivate(priv_key, wantXrays); + if(!CreateNewCompartment(cx, clasp, principal, priv, + global, compartment)) + { + return UnexpectedFailure(NS_ERROR_FAILURE); + } + + map.Put(&key, *compartment); } else { js::SwitchToCompartment sc(cx, *compartment); -#ifdef DEBUG - if(principal) - { - nsIPrincipal *cprincipal = xpc::AccessCheck::getPrincipal(*compartment); - PRBool equals; - nsresult rv = cprincipal->Equals(principal, &equals); - NS_ASSERTION(NS_SUCCEEDED(rv), "bad Equals implementation"); - if(!equals) - { - nsCOMPtr domain; - cprincipal->GetDomain(getter_AddRefs(domain)); - if(!domain) - { - principal->GetDomain(getter_AddRefs(domain)); - NS_ASSERTION(!domain, "bad mixing"); - } - } - } -#endif - - tempGlobal = JS_NewGlobalObject(cx, clasp); + JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp); + if(!tempGlobal) + return UnexpectedFailure(NS_ERROR_FAILURE); + *global = tempGlobal; + } + + return NS_OK; +} + +nsresult +xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, + nsISupports *ptr, JSObject **global, + JSCompartment **compartment) +{ + // NB: We can be either on or off the main thread here. + XPCMTCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetMTCompartmentMap(); + if(!map.Get(ptr, compartment)) + { + // We allow the pointer to be a principal, in which case it becomes + // the principal for the newly created compartment. The caller is + // responsible for ensuring that doing this doesn't violate + // threadsafety assumptions. + nsCOMPtr principal(do_QueryInterface(ptr)); + xpc::CompartmentPrivate *priv = + new xpc::CompartmentPrivate(ptr, false); + if(!CreateNewCompartment(cx, clasp, principal, priv, global, + compartment)) + { + return UnexpectedFailure(NS_ERROR_UNEXPECTED); + } + + map.Put(ptr, *compartment); + } + else + { + js::SwitchToCompartment sc(cx, *compartment); + + JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp); if(!tempGlobal) return UnexpectedFailure(NS_ERROR_FAILURE); *global = tempGlobal; @@ -1010,20 +1046,19 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, return NS_OK; } -/* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */ NS_IMETHODIMP nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsISupports *aCOMObj, const nsIID & aIID, nsIPrincipal * aPrincipal, - const nsACString & aOrigin, + nsISupports * aExtraPtr, PRUint32 aFlags, nsIXPConnectJSObjectHolder **_retval) { NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aCOMObj, "bad param"); NS_ASSERTION(_retval, "bad param"); - NS_ASSERTION(!aOrigin.IsEmpty() || aPrincipal, "must be able to assign an origin"); + NS_ASSERTION(aExtraPtr || aPrincipal, "must be able to find a compartment"); // XXX This is not pretty. We make a temporary global object and // init it with all the Components object junk just so we have a @@ -1032,18 +1067,16 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, XPCCallContext ccx(NATIVE_CALLER, aJSContext); - nsCString origin; - if(aOrigin.IsEmpty()) - aPrincipal->GetOrigin(getter_Copies(origin)); - else - origin = aOrigin; - JSCompartment* compartment; JSObject* tempGlobal; - nsresult rv = xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, origin, - aPrincipal, false, &tempGlobal, - &compartment); + nsresult rv = aPrincipal + ? xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, aPrincipal, + aExtraPtr, false, &tempGlobal, + &compartment) + : xpc_CreateMTGlobalObject(ccx, &xpcTempGlobalClass, + aExtraPtr, &tempGlobal, + &compartment); NS_ENSURE_SUCCESS(rv, rv); JSAutoEnterCompartment ac; diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index bbf3c76d43c..b7237eb82c9 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -3174,6 +3174,15 @@ WrapForSandbox(JSContext *cx, bool wantXrays, jsval *vp) : xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp); } +// Needed to distinguish multiple compartments with the same origin from each +// other. The only thing we need out of identity objects are unique addresses. +class Identity : public nsISupports +{ + NS_DECL_ISUPPORTS +}; + +NS_IMPL_ISUPPORTS0(Identity) + nsresult xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto, bool wantXrays) @@ -3209,25 +3218,12 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSOb } nsIPrincipal *principal = sop->GetPrincipal(); - nsAdoptingCString principalorigin; - principal->GetOrigin(getter_Copies(principalorigin)); - - nsCAutoString origin("sandbox:"); - origin.Append(principalorigin); - - nsRefPtr nullPrincipal = new nsNullPrincipal(); - rv = nullPrincipal->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = nullPrincipal->GetOrigin(getter_Copies(principalorigin)); - NS_ENSURE_SUCCESS(rv, rv); - - origin.Append(principalorigin); JSCompartment *compartment; JSObject *sandbox; - rv = xpc_CreateGlobalObject(cx, &SandboxClass, origin, principal, + nsRefPtr identity = new Identity(); + rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identity, wantXrays, &sandbox, &compartment); NS_ENSURE_SUCCESS(rv, rv); diff --git a/js/src/xpconnect/src/xpcinlines.h b/js/src/xpconnect/src/xpcinlines.h index f55c05be478..d146e326720 100644 --- a/js/src/xpconnect/src/xpcinlines.h +++ b/js/src/xpconnect/src/xpcinlines.h @@ -44,6 +44,19 @@ #define xpcinlines_h___ /***************************************************************************/ +PRBool +xpc::PtrAndPrincipalHashKey::KeyEquals(const PtrAndPrincipalHashKey* aKey) const +{ + if(aKey->mPtr != mPtr) + return PR_FALSE; + + if(!mURI || !aKey->mURI) + return mURI == aKey->mURI; + + nsIScriptSecurityManager *ssm = nsXPConnect::gScriptSecurityManager; + return !ssm || NS_SUCCEEDED(ssm->CheckSameOriginURI(mURI, aKey->mURI, PR_FALSE)); +} + inline void XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant) { diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index e780a383916..e745826f8d0 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -246,24 +246,37 @@ CompartmentCallback(JSContext *cx, JSCompartment *compartment, uintN op) if(!self) return JS_TRUE; - XPCCompartmentMap& map = self->GetCompartmentMap(); nsAutoPtr priv( static_cast(JS_SetCompartmentPrivate(cx, compartment, nsnull))); - if (!priv) + if(!priv) return JS_TRUE; - nsAdoptingCString origin; - origin.Adopt(static_cast(priv->origin)); - -#ifdef DEBUG + if(xpc::PtrAndPrincipalHashKey *key = priv->key) { - JSCompartment *current; - NS_ASSERTION(map.Get(origin, ¤t), "no compartment?"); - NS_ASSERTION(current == compartment, "compartment mismatch"); - } + XPCCompartmentMap &map = self->GetCompartmentMap(); +#ifdef DEBUG + { + JSCompartment *current; + NS_ASSERTION(map.Get(key, ¤t), "no compartment?"); + NS_ASSERTION(current == compartment, "compartment mismatch"); + } #endif + map.Remove(key); + } + else + { + nsISupports *ptr = priv->ptr; + XPCMTCompartmentMap &map = self->GetMTCompartmentMap(); +#ifdef DEBUG + { + JSCompartment *current; + NS_ASSERTION(map.Get(ptr, ¤t), "no compartment?"); + NS_ASSERTION(current == compartment, "compartment mismatch"); + } +#endif + map.Remove(ptr); + } - map.Remove(origin); return JS_TRUE; } @@ -1168,6 +1181,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) mJSHolders.ops = nsnull; mCompartmentMap.Init(); + mMTCompartmentMap.Init(); // Install a JavaScript 'debugger' keyword handler in debug builds only #ifdef DEBUG diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index daa14be8756..e749c7de227 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -117,6 +117,9 @@ #include "nsWrapperCache.h" #include "nsStringBuffer.h" +#include "nsIScriptSecurityManager.h" +#include "nsNetUtil.h" + #include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated #ifndef XPCONNECT_STANDALONE @@ -242,7 +245,75 @@ extern const char XPC_SCRIPT_ERROR_CONTRACTID[]; extern const char XPC_ID_CONTRACTID[]; extern const char XPC_XPCONNECT_CONTRACTID[]; -typedef nsDataHashtableMT XPCCompartmentMap; +namespace xpc { + +class PtrAndPrincipalHashKey : public PLDHashEntryHdr +{ + public: + typedef PtrAndPrincipalHashKey *KeyType; + typedef const PtrAndPrincipalHashKey *KeyTypePointer; + + PtrAndPrincipalHashKey(const PtrAndPrincipalHashKey *aKey) + : mPtr(aKey->mPtr), mURI(aKey->mURI), mSavedHash(aKey->mSavedHash) + { + MOZ_COUNT_CTOR(PtrAndPrincipalHashKey); + } + + PtrAndPrincipalHashKey(nsISupports *aPtr, nsIURI *aURI) + : mPtr(aPtr), mURI(aURI) + { + MOZ_COUNT_CTOR(PtrAndPrincipalHashKey); + mSavedHash = mURI + ? NS_SecurityHashURI(mURI) + : (NS_PTR_TO_UINT32(mPtr.get()) >> 2); + } + + ~PtrAndPrincipalHashKey() + { + MOZ_COUNT_DTOR(PtrAndPrincipalHashKey); + } + + PtrAndPrincipalHashKey* GetKey() const + { + return const_cast(this); + } + const PtrAndPrincipalHashKey* GetKeyPointer() const { return this; } + + inline PRBool KeyEquals(const PtrAndPrincipalHashKey* aKey) const; + + static const PtrAndPrincipalHashKey* + KeyToPointer(PtrAndPrincipalHashKey* aKey) { return aKey; } + static PLDHashNumber HashKey(const PtrAndPrincipalHashKey* aKey) + { + return aKey->mSavedHash; + } + + enum { ALLOW_MEMMOVE = PR_TRUE }; + + protected: + nsCOMPtr mPtr; + nsCOMPtr mURI; + + // During shutdown, when we GC, we need to remove these keys from the hash + // table. However, computing the saved hash, NS_SecurityHashURI calls back + // into XPCOM (which is illegal during shutdown). In order to avoid this, + // we compute the hash up front, so when we're in GC during shutdown, we + // don't have to call into XPCOM. + PLDHashNumber mSavedHash; +}; + +} + +// NB: nsDataHashtableMT is usually not very useful as all it does is lock +// around each individual operation performed on it. That would imply, that +// the pattern: if(!map.Get(key)) map.Put(key, value); is not safe as another +// thread could race to insert key into map. However, in our case, only one +// thread at any time could attempt to insert |key| into |map|, so it works +// well enough for our uses. +typedef nsDataHashtableMT XPCMTCompartmentMap; + +// This map is only used on the main thread. +typedef nsDataHashtable XPCCompartmentMap; /***************************************************************************/ // useful macros... @@ -555,6 +626,9 @@ private: nsCOMPtr mBackstagePass; static PRUint32 gReportAllJSExceptions; + +public: + static nsIScriptSecurityManager *gScriptSecurityManager; }; /***************************************************************************/ @@ -631,6 +705,8 @@ public: XPCCompartmentMap& GetCompartmentMap() {return mCompartmentMap;} + XPCMTCompartmentMap& GetMTCompartmentMap() + {return mMTCompartmentMap;} XPCLock* GetMapLock() const {return mMapLock;} @@ -754,6 +830,7 @@ private: XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap; XPCNativeWrapperMap* mExplicitNativeWrapperMap; XPCCompartmentMap mCompartmentMap; + XPCMTCompartmentMap mMTCompartmentMap; XPCLock* mMapLock; PRThread* mThreadRunningGC; nsTArray mWrappedJSToReleaseArray; @@ -4431,12 +4508,22 @@ namespace xpc { struct CompartmentPrivate { - CompartmentPrivate(char *origin, bool wantXrays) - : origin(origin), + CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays) + : key(key), + ptr(nsnull), wantXrays(wantXrays) { } - char *origin; + CompartmentPrivate(nsISupports *ptr, bool wantXrays) + : key(nsnull), + ptr(ptr), + wantXrays(wantXrays) + { + } + + // NB: key and ptr are mutually exclusive. + nsAutoPtr key; + nsCOMPtr ptr; bool wantXrays; }; diff --git a/js/src/xpconnect/src/xpcpublic.h b/js/src/xpconnect/src/xpcpublic.h index 2f9d40f046c..3be157907f0 100644 --- a/js/src/xpconnect/src/xpcpublic.h +++ b/js/src/xpconnect/src/xpcpublic.h @@ -41,13 +41,19 @@ #define xpcpublic_h #include "jsapi.h" -#include "nsAString.h" -#include "nsIPrincipal.h" +#include "nsISupports.h" + +class nsIPrincipal; nsresult xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, - const nsACString &origin, nsIPrincipal *principal, + nsIPrincipal *principal, nsISupports *ptr, bool wantXrays, JSObject **global, JSCompartment **compartment); +nsresult +xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, + nsISupports *ptr, JSObject **global, + JSCompartment **compartment); + #endif diff --git a/js/src/xpconnect/src/xpcthreadcontext.cpp b/js/src/xpconnect/src/xpcthreadcontext.cpp index ec4e40c8e8c..9c2805b65e0 100644 --- a/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -259,16 +259,16 @@ XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext) mSafeJSContext = JS_NewContext(rt, 8192); if(mSafeJSContext) { - nsCString origin; - principal->GetOrigin(getter_Copies(origin)); - // scoped JS Request JSAutoRequest req(mSafeJSContext); + // Because we can run off the main thread, we create an MT + // global object. Our principal is the unique key. JSCompartment *compartment; - nsresult rv = xpc_CreateGlobalObject(mSafeJSContext, &global_class, - origin, principal, false, &glob, - &compartment); + nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext, + &global_class, + principal, &glob, + &compartment); if(NS_FAILED(rv)) glob = nsnull; From 4cc16a6dd2a4a60fb96d6f62f018abf08d42f038 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 26 Oct 2010 19:48:51 -0700 Subject: [PATCH 035/263] Bug 607174 - Add assertions to jsdbgapi.cpp and enter compartments where it isn't possible for the caller to do so. landing with r=gal, a=beta7+ --- js/jsd/jsd_xpc.cpp | 6 ++++++ js/src/jsapi.h | 4 ++-- js/src/jscntxtinlines.h | 4 ++++ js/src/jsdbgapi.cpp | 21 +++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 582852fb0fe..d044f1eafde 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2316,7 +2316,13 @@ jsdValue::GetWrappedValue() if (result) { + JSContext *cx; + rv = cc->GetJSContext(&cx); + if (NS_FAILED(rv)) + return rv; *result = JSD_GetValueWrappedJSVal (mCx, mValue); + if (!JS_WrapValue(cx, result)) + return NS_ERROR_FAILURE; cc->SetReturnValueWasSet(PR_TRUE); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 48aae27c6a1..11e095bc160 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2633,10 +2633,10 @@ Call(JSContext *cx, jsval thisv, JSObject *funObj, uintN argc, jsval *argv, jsva return Call(cx, thisv, OBJECT_TO_JSVAL(funObj), argc, argv, rval); } -} // namespace JS +} /* namespace JS */ JS_BEGIN_EXTERN_C -#endif // __cplusplus +#endif /* __cplusplus */ /* * These functions allow setting an operation callback that will be called diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 4e02ffe5255..9697cd43815 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -570,6 +570,10 @@ class CompartmentChecker } } + void check(JSStackFrame *fp) { + check(&fp->scopeChain()); + } + void check(JSString *) { /* nothing for now */ } }; diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index b4b9deb1321..25d993e5743 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,6 +62,7 @@ #include "jsscript.h" #include "jsstaticcheck.h" #include "jsstr.h" +#include "jswrapper.h" #include "jsatominlines.h" #include "jsinterpinlines.h" @@ -1180,6 +1181,10 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp) { JS_ASSERT(cx->stack().contains(fp)); + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return NULL; + /* Force creation of argument and call objects if not yet created */ (void) JS_GetFrameCallObject(cx, fp); return js_GetScopeChain(cx, fp); @@ -1193,6 +1198,10 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp) if (!fp->isFunctionFrame()) return NULL; + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return NULL; + /* Force creation of argument object if not yet created */ (void) js_GetArgsObject(cx, fp); @@ -1208,6 +1217,11 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv) { if (fp->isDummyFrame()) return false; + + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return false; + if (!fp->computeThis(cx)) return false; *thisv = Jsvalify(fp->thisValue()); @@ -1269,6 +1283,7 @@ JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp) JS_PUBLIC_API(void) JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval) { + assertSameCompartment(cx, fp, rval); fp->setReturnValue(Valueify(rval)); } @@ -1332,6 +1347,10 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp, if (!scobj) return false; + js::AutoCompartment ac(cx, scobj); + if (!ac.enter()) + return NULL; + /* * NB: This function breaks the assumption that the compiler can see all * calls and properly compute a static level. In order to get around this, @@ -1404,6 +1423,7 @@ JS_PUBLIC_API(JSBool) JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JSPropertyDesc *pd) { + assertSameCompartment(cx, obj); Shape *shape = (Shape *) sprop; pd->id = IdToJsval(shape->id); @@ -1457,6 +1477,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JS_PUBLIC_API(JSBool) JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) { + assertSameCompartment(cx, obj); Class *clasp = obj->getClass(); if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, From 5df760df9ecca035e79bd15c2f2c74d5d76fb0e1 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Wed, 27 Oct 2010 18:02:28 -0700 Subject: [PATCH 036/263] Bug 607799 - Make typeof wrapper(regexp) be function. --HG-- extra : rebase_source : 36598f7a268721eb569215d0ccd6859c3cd88701 --- js/src/jsproxy.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ac1bacf1763..3d2deb0b2ef 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1041,7 +1041,9 @@ proxy_Construct(JSContext *cx, uintN argc, Value *vp) static JSType proxy_TypeOf_fun(JSContext *cx, JSObject *obj) { - return JSTYPE_FUNCTION; + return obj->unwrap()->isRegExp() + ? JSTYPE_OBJECT + : JSTYPE_FUNCTION; } JS_FRIEND_API(Class) FunctionProxyClass = { From 7416dcca8419b160843a8de1a70d9143f441ab6b Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 29 Oct 2010 10:42:35 -0700 Subject: [PATCH 037/263] Bug 596031 - 'this' is wrong in getters and setters when a proxy object is on the prototype chain. r=brendan --- js/src/jsarray.cpp | 10 +-- js/src/jsinterp.cpp | 4 +- js/src/jsobj.cpp | 61 +++++++++++-------- js/src/jsobj.h | 43 ++++++++++--- js/src/jsobjinlines.h | 2 +- js/src/jsproxy.cpp | 23 +++---- js/src/jstracer.cpp | 5 +- js/src/jstypedarray.cpp | 7 ++- js/src/jsvalue.h | 9 ++- js/src/jswrapper.cpp | 5 +- js/src/jsxml.cpp | 4 +- js/src/methodjit/StubCalls.cpp | 4 +- js/src/tests/js1_8_5/regress/jstests.list | 3 +- .../tests/js1_8_5/regress/regress-607863.js | 13 ++++ 14 files changed, 124 insertions(+), 69 deletions(-) create mode 100644 js/src/tests/js1_8_5/regress/regress-607863.js diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index cd21b609143..fff6a339666 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -688,7 +688,7 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp) } static JSBool -array_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +array_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { uint32 i; @@ -754,7 +754,8 @@ array_typeOf(JSContext *cx, JSObject *obj) } static JSBool -array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +array_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict) { uint32 i; @@ -781,7 +782,8 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool stric } static JSBool -slowarray_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +slowarray_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict) { JS_ASSERT(obj->isSlowArray()); @@ -849,7 +851,7 @@ array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, } Value tmp = *value; - return array_setProperty(cx, obj, id, &tmp, false); + return array_setProperty(cx, obj, obj, id, &tmp, false); } static JSBool diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b283cf1b7ad..ae0ba892d73 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -4422,7 +4422,7 @@ BEGIN_CASE(JSOP_SETMETHOD) defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED; else defineHow = JSDNP_CACHE_RESULT; - if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)) + if (!js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, script->strictModeCode)) goto error; } else { if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) @@ -5980,7 +5980,7 @@ BEGIN_CASE(JSOP_INITMETHOD) ? JSDNP_CACHE_RESULT | JSDNP_SET_METHOD : JSDNP_CACHE_RESULT; if (!(JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom) - ? js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode) + ? js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, script->strictModeCode) : js_DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, NULL, defineHow))) { diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c21d73ec623..e31973508c1 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3021,13 +3021,14 @@ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, } static JSBool -with_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { return obj->getProto()->getProperty(cx, id, vp); } static JSBool -with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +with_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict) { return obj->getProto()->setProperty(cx, id, vp, strict); } @@ -4931,7 +4932,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value } static JS_ALWAYS_INLINE bool -js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, +js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { @@ -5017,8 +5018,11 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, return JS_TRUE; } - if (!obj2->isNative()) - return obj2->getProperty(cx, id, vp); + if (!obj2->isNative()) { + return obj2->isProxy() + ? JSProxy::get(cx, obj2, receiver, id, vp) + : obj2->getProperty(cx, id, vp); + } shape = (Shape *) prop; *shapeOut = shape; @@ -5029,39 +5033,41 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, } /* This call site is hot -- use the always-inlined variant of js_NativeGet(). */ - if (!js_NativeGetInline(cx, obj, obj2, shape, getHow, vp)) + if (!js_NativeGetInline(cx, receiver, obj2, shape, getHow, vp)) return JS_FALSE; return JS_TRUE; } -extern bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, +bool +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uint32 getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { - return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, shapeOut, holderOut); + return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, + shapeOut, holderOut); } static JS_ALWAYS_INLINE JSBool -js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) +js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, + uint32 getHow, Value *vp) { const Shape *shape; JSObject *holder; - return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, &shape, &holder); -} - -extern JSBool -js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) -{ - return js_GetPropertyHelperInline(cx, obj, id, getHow, vp); + return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, &shape, &holder); } JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) +{ + return js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp); +} + +JSBool +js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */ - return js_GetPropertyHelperInline(cx, obj, id, JSGET_METHOD_BARRIER, vp); + return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp); } JSBool @@ -5097,7 +5103,7 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp) if (obj->isXML()) return js_GetXMLMethod(cx, obj, id, vp); #endif - return op(cx, obj, id, vp); + return op(cx, obj, obj, id, vp); } JS_FRIEND_API(bool) @@ -5152,7 +5158,7 @@ JSObject::reportNotExtensible(JSContext *cx, uintN report) * (defineHow & JSDNP_CACHE_RESULT). */ JSBool -js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, +js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN defineHow, Value *vp, JSBool strict) { int protoIndex; @@ -5178,8 +5184,11 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, if (protoIndex < 0) return JS_FALSE; if (prop) { - if (!pobj->isNative()) + if (!pobj->isNative()) { + if (pobj->isProxy()) + return JSProxy::set(cx, pobj, receiver, id, vp); prop = NULL; + } } else { /* We should never add properties to lexical blocks. */ JS_ASSERT(!obj->isBlock()); @@ -5236,7 +5245,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, } attrs = shape->attributes(); - if (pobj != obj) { + if (pobj != receiver) { /* * We found id in a prototype object: prepare to share or shadow. * @@ -5255,7 +5264,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, if (shape->hasDefaultSetter() && !shape->hasGetterValue()) return JS_TRUE; - return shape->set(cx, obj, vp); + return shape->set(cx, receiver, vp); } /* Restore attrs to the ECMA default for new properties. */ @@ -5377,9 +5386,9 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, } JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +js_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, JSBool strict) { - return js_SetPropertyHelper(cx, obj, id, 0, vp, strict); + return js_SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict); } JSBool diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2db2a05d0cd..7454afd30e3 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -209,7 +209,13 @@ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value, js::PropertyOp getter, js::PropertyOp setter, uintN attrs); extern JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); +js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp); + +inline JSBool +js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp) +{ + return js_GetProperty(cx, obj, obj, id, vp); +} namespace js { @@ -219,7 +225,14 @@ GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, Value def, Value *vp); } /* namespace js */ extern JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp, JSBool strict); +js_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp, + JSBool strict); + +inline JSBool +js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp, JSBool strict) +{ + return js_SetProperty(cx, obj, obj, id, vp, strict); +} extern JSBool js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); @@ -1064,14 +1077,23 @@ struct JSObject : js::gc::Cell { return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); } - JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { + JSBool getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp) { js::PropertyIdOp op = getOps()->getProperty; - return (op ? op : js_GetProperty)(cx, this, id, vp); + return (op ? op : (js::PropertyIdOp)js_GetProperty)(cx, this, receiver, id, vp); + } + + JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { + return getProperty(cx, this, id, vp); + } + + JSBool setProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp, JSBool strict) { + js::StrictPropertyIdOp op = getOps()->setProperty; + return (op ? op : (js::StrictPropertyIdOp)js_SetProperty)(cx, this, receiver, id, + vp, strict); } JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) { - js::StrictPropertyIdOp op = getOps()->setProperty; - return (op ? op : js_SetProperty)(cx, this, id, vp, strict); + return setProperty(cx, this, id, vp, strict); } JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) { @@ -1085,7 +1107,7 @@ struct JSObject : js::gc::Cell { } JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict) { - js::StrictPropertyIdOp op = getOps()->deleteProperty; + js::DeleteIdOp op = getOps()->deleteProperty; return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict); } @@ -1569,8 +1591,9 @@ extern JSBool js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, js::Value *vp); extern bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, - js::Value *vp, const js::Shape **shapeOut, JSObject **holderOut); +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, + uint32 getHow, js::Value *vp, + const js::Shape **shapeOut, JSObject **holderOut); extern JSBool js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); @@ -1588,7 +1611,7 @@ extern JS_FRIEND_API(bool) js_CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname); extern JSBool -js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, +js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN defineHow, js::Value *vp, JSBool strict); /* diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 3ccc2809167..5d27261d118 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -153,7 +153,7 @@ JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp funobj->setMethodObj(*this); vp->setObject(*funobj); - if (!js_SetPropertyHelper(cx, this, shape.id, 0, vp, false)) + if (!js_SetPropertyHelper(cx, this, this, shape.id, 0, vp, false)) return false; #ifdef DEBUG diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 3d2deb0b2ef..1654d3b7582 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -127,7 +127,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, return true; } if (desc.attrs & JSPROP_GETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.getter), + return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.getter), JSACC_READ, 0, NULL, vp); } if (!(desc.attrs & JSPROP_SHARED)) @@ -136,7 +136,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, vp->setUndefined(); if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOp(cx, desc.getter, proxy, id, vp); + return CallJSPropertyOp(cx, desc.getter, receiver, id, vp); } bool @@ -150,12 +150,12 @@ JSProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, if (desc.obj) { if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), + return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.setter), JSACC_WRITE, 1, vp, vp); } if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); + return CallJSPropertyOpSetter(cx, desc.setter, receiver, id, vp); } if (desc.attrs & JSPROP_READONLY) return true; @@ -167,12 +167,12 @@ JSProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, if (desc.obj) { if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), + return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.setter), JSACC_WRITE, 1, vp, vp); } if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); + return CallJSPropertyOpSetter(cx, desc.setter, receiver, id, vp); } if (desc.attrs & JSPROP_READONLY) return true; @@ -862,16 +862,17 @@ proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, } static JSBool -proxy_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { - return JSProxy::get(cx, obj, obj, id, vp); + return JSProxy::get(cx, obj, receiver, id, vp); } static JSBool -proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +proxy_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict) { - // TODO: throwing away strict - return JSProxy::set(cx, obj, obj, id, vp); + // FIXME (bug 596351): throwing away strict. + return JSProxy::set(cx, obj, receiver, id, vp); } static JSBool diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 7b516112f2a..1d674ac734b 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -12032,7 +12032,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC /* Delegate to the op, if present. */ PropertyIdOp op = obj->getOps()->getProperty; if (op) { - bool result = op(cx, obj, id, vp); + bool result = op(cx, obj, obj, id, vp); if (!result) SetBuiltinError(cx); return cx->tracerState->builtinStatus == 0; @@ -12047,7 +12047,8 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC const Shape *shape; JSObject *holder; - if (!js_GetPropertyHelperWithShape(cx, obj, id, JSGET_METHOD_BARRIER, vp, &shape, &holder)) { + if (!js_GetPropertyHelperWithShape(cx, obj, obj, id, JSGET_METHOD_BARRIER, vp, &shape, + &holder)) { SetBuiltinError(cx); return false; } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 6ffdc14764f..799e8daaa27 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -493,7 +493,7 @@ class TypedArrayTemplate } static JSBool - obj_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) + obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); @@ -535,7 +535,8 @@ class TypedArrayTemplate } static JSBool - obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) + obj_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict) { ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); @@ -620,7 +621,7 @@ class TypedArrayTemplate return true; Value tmp = *v; - return obj_setProperty(cx, obj, id, &tmp, false); + return obj_setProperty(cx, obj, obj, id, &tmp, false); } static JSBool diff --git a/js/src/jsvalue.h b/js/src/jsvalue.h index a1fad41ab0d..36e2b2723df 100644 --- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -898,9 +898,12 @@ typedef JSBool (* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, PropertyOp getter, PropertyOp setter, uintN attrs); typedef JSBool -(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp); +(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); typedef JSBool -(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, + JSBool strict); +typedef JSBool +(* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); typedef JSBool (* CallOp)(JSContext *cx, uintN argc, Value *vp); typedef JSBool @@ -999,7 +1002,7 @@ struct ObjectOps { js::StrictPropertyIdOp setProperty; js::AttributesOp getAttributes; js::AttributesOp setAttributes; - js::StrictPropertyIdOp deleteProperty; + js::DeleteIdOp deleteProperty; js::NewEnumerateOp enumerate; js::TypeOfOp typeOf; js::TraceOp trace; diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index b3f4da8cfdf..68784676a78 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -204,13 +204,14 @@ JSWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) bool JSWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - GET(JS_GetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); + GET(wrappedObject(wrapper)->getProperty(cx, receiver, id, vp)); } bool JSWrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - SET(JS_SetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); + // FIXME (bug 596351): Need deal with strict mode. + SET(wrappedObject(wrapper)->setProperty(cx, receiver, id, vp, false)); } bool diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index f61320e2ec9..7eb680a5e8a 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -4743,7 +4743,7 @@ xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, } static JSBool -xml_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) { vp->setUndefined(); @@ -4754,7 +4754,7 @@ xml_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) } static JSBool -xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +xml_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, JSBool strict) { return PutProperty(cx, obj, id, Jsvalify(vp)); } diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 659c76b76b0..b1006719fc5 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -257,7 +257,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED; else defineHow = JSDNP_CACHE_RESULT; - if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, strict)) + if (!js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, strict)) THROW(); } else { if (!obj->setProperty(cx, id, &rval, strict)) @@ -2209,7 +2209,7 @@ InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op) ? JSDNP_CACHE_RESULT | JSDNP_SET_METHOD : JSDNP_CACHE_RESULT; if (!(JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom) - ? js_SetPropertyHelper(cx, obj, id, defineHow, &rval, false) + ? js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, false) : js_DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, NULL, defineHow))) { diff --git a/js/src/tests/js1_8_5/regress/jstests.list b/js/src/tests/js1_8_5/regress/jstests.list index 6c757e175a5..d577160082b 100644 --- a/js/src/tests/js1_8_5/regress/jstests.list +++ b/js/src/tests/js1_8_5/regress/jstests.list @@ -12,7 +12,7 @@ script regress-551763-0.js script regress-551763-1.js script regress-551763-2.js script regress-555246-0.js -fails-if(xulRuntime.shell) script regress-555246-1.js +script regress-555246-1.js script regress-559438.js script regress-560101.js script regress-560998-1.js @@ -48,3 +48,4 @@ script regress-598176.js script regress-600067.js script regress-600137.js script regress-602621.js +fails-if(!xulRuntime.shell) script regress-607863.js diff --git a/js/src/tests/js1_8_5/regress/regress-607863.js b/js/src/tests/js1_8_5/regress/regress-607863.js new file mode 100644 index 00000000000..2eb463df890 --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-607863.js @@ -0,0 +1,13 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var sandbox = evalcx(''); +var foreign = evalcx('({ get f() this, set x(v) { result = this } })', sandbox); +var local = Object.create(foreign); + +reportCompare(local, local.f, "this should be set correctly in getters"); +local.x = 42; +reportCompare(local, sandbox.result, "this should be set correctly in setters"); From ea9d8bbc178043d210321834aed7d77f4cf334da Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 29 Oct 2010 10:48:09 -0700 Subject: [PATCH 038/263] Backed out changeset f76fd418024c. This was never meant to be checked in. --- js/src/jsproxy.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 3d2deb0b2ef..ac1bacf1763 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1041,9 +1041,7 @@ proxy_Construct(JSContext *cx, uintN argc, Value *vp) static JSType proxy_TypeOf_fun(JSContext *cx, JSObject *obj) { - return obj->unwrap()->isRegExp() - ? JSTYPE_OBJECT - : JSTYPE_FUNCTION; + return JSTYPE_FUNCTION; } JS_FRIEND_API(Class) FunctionProxyClass = { From 8d23c3e1c435699cef10ec808948698ec275ccec Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 29 Oct 2010 12:55:23 -0700 Subject: [PATCH 039/263] Backed out changeset fcd3fcf8a35c. It broke deep wrapping. --- js/src/jsarray.cpp | 10 ++-- js/src/jsinterp.cpp | 4 +- js/src/jsobj.cpp | 53 ++++++++----------- js/src/jsobj.h | 43 ++++----------- js/src/jsobjinlines.h | 2 +- js/src/jsproxy.cpp | 23 ++++---- js/src/jstracer.cpp | 5 +- js/src/jstypedarray.cpp | 7 ++- js/src/jsvalue.h | 9 ++-- js/src/jswrapper.cpp | 5 +- js/src/jsxml.cpp | 4 +- js/src/methodjit/StubCalls.cpp | 4 +- js/src/tests/js1_8_5/regress/jstests.list | 3 +- .../tests/js1_8_5/regress/regress-607863.js | 13 ----- 14 files changed, 65 insertions(+), 120 deletions(-) delete mode 100644 js/src/tests/js1_8_5/regress/regress-607863.js diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index fff6a339666..cd21b609143 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -688,7 +688,7 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp) } static JSBool -array_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) +array_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { uint32 i; @@ -754,8 +754,7 @@ array_typeOf(JSContext *cx, JSObject *obj) } static JSBool -array_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict) +array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { uint32 i; @@ -782,8 +781,7 @@ array_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Val } static JSBool -slowarray_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict) +slowarray_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { JS_ASSERT(obj->isSlowArray()); @@ -851,7 +849,7 @@ array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, } Value tmp = *value; - return array_setProperty(cx, obj, obj, id, &tmp, false); + return array_setProperty(cx, obj, id, &tmp, false); } static JSBool diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index ae0ba892d73..b283cf1b7ad 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -4422,7 +4422,7 @@ BEGIN_CASE(JSOP_SETMETHOD) defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED; else defineHow = JSDNP_CACHE_RESULT; - if (!js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, script->strictModeCode)) + if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)) goto error; } else { if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) @@ -5980,7 +5980,7 @@ BEGIN_CASE(JSOP_INITMETHOD) ? JSDNP_CACHE_RESULT | JSDNP_SET_METHOD : JSDNP_CACHE_RESULT; if (!(JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom) - ? js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, script->strictModeCode) + ? js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode) : js_DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, NULL, defineHow))) { diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index e31973508c1..c21d73ec623 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3021,14 +3021,13 @@ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, } static JSBool -with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) +with_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { return obj->getProto()->getProperty(cx, id, vp); } static JSBool -with_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict) +with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { return obj->getProto()->setProperty(cx, id, vp, strict); } @@ -4932,7 +4931,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value } static JS_ALWAYS_INLINE bool -js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, +js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { @@ -5018,11 +5017,8 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, JSObject *rece return JS_TRUE; } - if (!obj2->isNative()) { - return obj2->isProxy() - ? JSProxy::get(cx, obj2, receiver, id, vp) - : obj2->getProperty(cx, id, vp); - } + if (!obj2->isNative()) + return obj2->getProperty(cx, id, vp); shape = (Shape *) prop; *shapeOut = shape; @@ -5033,41 +5029,39 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, JSObject *rece } /* This call site is hot -- use the always-inlined variant of js_NativeGet(). */ - if (!js_NativeGetInline(cx, receiver, obj2, shape, getHow, vp)) + if (!js_NativeGetInline(cx, obj, obj2, shape, getHow, vp)) return JS_FALSE; return JS_TRUE; } -bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, +extern bool +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { - return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, - shapeOut, holderOut); + return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, shapeOut, holderOut); } static JS_ALWAYS_INLINE JSBool -js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, - uint32 getHow, Value *vp) +js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) { const Shape *shape; JSObject *holder; - return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, &shape, &holder); + return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, &shape, &holder); } -JSBool +extern JSBool js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) { - return js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp); + return js_GetPropertyHelperInline(cx, obj, id, getHow, vp); } JSBool -js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) +js_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */ - return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp); + return js_GetPropertyHelperInline(cx, obj, id, JSGET_METHOD_BARRIER, vp); } JSBool @@ -5103,7 +5097,7 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp) if (obj->isXML()) return js_GetXMLMethod(cx, obj, id, vp); #endif - return op(cx, obj, obj, id, vp); + return op(cx, obj, id, vp); } JS_FRIEND_API(bool) @@ -5158,7 +5152,7 @@ JSObject::reportNotExtensible(JSContext *cx, uintN report) * (defineHow & JSDNP_CACHE_RESULT). */ JSBool -js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN defineHow, +js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, Value *vp, JSBool strict) { int protoIndex; @@ -5184,11 +5178,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, if (protoIndex < 0) return JS_FALSE; if (prop) { - if (!pobj->isNative()) { - if (pobj->isProxy()) - return JSProxy::set(cx, pobj, receiver, id, vp); + if (!pobj->isNative()) prop = NULL; - } } else { /* We should never add properties to lexical blocks. */ JS_ASSERT(!obj->isBlock()); @@ -5245,7 +5236,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, } attrs = shape->attributes(); - if (pobj != receiver) { + if (pobj != obj) { /* * We found id in a prototype object: prepare to share or shadow. * @@ -5264,7 +5255,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, if (shape->hasDefaultSetter() && !shape->hasGetterValue()) return JS_TRUE; - return shape->set(cx, receiver, vp); + return shape->set(cx, obj, vp); } /* Restore attrs to the ECMA default for new properties. */ @@ -5386,9 +5377,9 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, } JSBool -js_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, JSBool strict) +js_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { - return js_SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict); + return js_SetPropertyHelper(cx, obj, id, 0, vp, strict); } JSBool diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 7454afd30e3..2db2a05d0cd 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -209,13 +209,7 @@ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value, js::PropertyOp getter, js::PropertyOp setter, uintN attrs); extern JSBool -js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp); - -inline JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp) -{ - return js_GetProperty(cx, obj, obj, id, vp); -} +js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); namespace js { @@ -225,14 +219,7 @@ GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, Value def, Value *vp); } /* namespace js */ extern JSBool -js_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp, - JSBool strict); - -inline JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp, JSBool strict) -{ - return js_SetProperty(cx, obj, obj, id, vp, strict); -} +js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp, JSBool strict); extern JSBool js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); @@ -1077,23 +1064,14 @@ struct JSObject : js::gc::Cell { return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); } - JSBool getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp) { - js::PropertyIdOp op = getOps()->getProperty; - return (op ? op : (js::PropertyIdOp)js_GetProperty)(cx, this, receiver, id, vp); - } - JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { - return getProperty(cx, this, id, vp); - } - - JSBool setProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp, JSBool strict) { - js::StrictPropertyIdOp op = getOps()->setProperty; - return (op ? op : (js::StrictPropertyIdOp)js_SetProperty)(cx, this, receiver, id, - vp, strict); + js::PropertyIdOp op = getOps()->getProperty; + return (op ? op : js_GetProperty)(cx, this, id, vp); } JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) { - return setProperty(cx, this, id, vp, strict); + js::StrictPropertyIdOp op = getOps()->setProperty; + return (op ? op : js_SetProperty)(cx, this, id, vp, strict); } JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) { @@ -1107,7 +1085,7 @@ struct JSObject : js::gc::Cell { } JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict) { - js::DeleteIdOp op = getOps()->deleteProperty; + js::StrictPropertyIdOp op = getOps()->deleteProperty; return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict); } @@ -1591,9 +1569,8 @@ extern JSBool js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, js::Value *vp); extern bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, - uint32 getHow, js::Value *vp, - const js::Shape **shapeOut, JSObject **holderOut); +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, + js::Value *vp, const js::Shape **shapeOut, JSObject **holderOut); extern JSBool js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); @@ -1611,7 +1588,7 @@ extern JS_FRIEND_API(bool) js_CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname); extern JSBool -js_SetPropertyHelper(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN defineHow, +js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, js::Value *vp, JSBool strict); /* diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 5d27261d118..3ccc2809167 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -153,7 +153,7 @@ JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp funobj->setMethodObj(*this); vp->setObject(*funobj); - if (!js_SetPropertyHelper(cx, this, this, shape.id, 0, vp, false)) + if (!js_SetPropertyHelper(cx, this, shape.id, 0, vp, false)) return false; #ifdef DEBUG diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 1654d3b7582..3d2deb0b2ef 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -127,7 +127,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, return true; } if (desc.attrs & JSPROP_GETTER) { - return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.getter), + return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.getter), JSACC_READ, 0, NULL, vp); } if (!(desc.attrs & JSPROP_SHARED)) @@ -136,7 +136,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, vp->setUndefined(); if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOp(cx, desc.getter, receiver, id, vp); + return CallJSPropertyOp(cx, desc.getter, proxy, id, vp); } bool @@ -150,12 +150,12 @@ JSProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, if (desc.obj) { if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.setter), + return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), JSACC_WRITE, 1, vp, vp); } if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, receiver, id, vp); + return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); } if (desc.attrs & JSPROP_READONLY) return true; @@ -167,12 +167,12 @@ JSProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, if (desc.obj) { if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.setter), + return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), JSACC_WRITE, 1, vp, vp); } if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, receiver, id, vp); + return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); } if (desc.attrs & JSPROP_READONLY) return true; @@ -862,17 +862,16 @@ proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, } static JSBool -proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) +proxy_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return JSProxy::get(cx, obj, receiver, id, vp); + return JSProxy::get(cx, obj, obj, id, vp); } static JSBool -proxy_SetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict) +proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { - // FIXME (bug 596351): throwing away strict. - return JSProxy::set(cx, obj, receiver, id, vp); + // TODO: throwing away strict + return JSProxy::set(cx, obj, obj, id, vp); } static JSBool diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 1d674ac734b..7b516112f2a 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -12032,7 +12032,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC /* Delegate to the op, if present. */ PropertyIdOp op = obj->getOps()->getProperty; if (op) { - bool result = op(cx, obj, obj, id, vp); + bool result = op(cx, obj, id, vp); if (!result) SetBuiltinError(cx); return cx->tracerState->builtinStatus == 0; @@ -12047,8 +12047,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC const Shape *shape; JSObject *holder; - if (!js_GetPropertyHelperWithShape(cx, obj, obj, id, JSGET_METHOD_BARRIER, vp, &shape, - &holder)) { + if (!js_GetPropertyHelperWithShape(cx, obj, id, JSGET_METHOD_BARRIER, vp, &shape, &holder)) { SetBuiltinError(cx); return false; } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 799e8daaa27..6ffdc14764f 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -493,7 +493,7 @@ class TypedArrayTemplate } static JSBool - obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) + obj_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); @@ -535,8 +535,7 @@ class TypedArrayTemplate } static JSBool - obj_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict) + obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); @@ -621,7 +620,7 @@ class TypedArrayTemplate return true; Value tmp = *v; - return obj_setProperty(cx, obj, obj, id, &tmp, false); + return obj_setProperty(cx, obj, id, &tmp, false); } static JSBool diff --git a/js/src/jsvalue.h b/js/src/jsvalue.h index 36e2b2723df..a1fad41ab0d 100644 --- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -898,12 +898,9 @@ typedef JSBool (* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, PropertyOp getter, PropertyOp setter, uintN attrs); typedef JSBool -(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); +(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp); typedef JSBool -(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, - JSBool strict); -typedef JSBool -(* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); typedef JSBool (* CallOp)(JSContext *cx, uintN argc, Value *vp); typedef JSBool @@ -1002,7 +999,7 @@ struct ObjectOps { js::StrictPropertyIdOp setProperty; js::AttributesOp getAttributes; js::AttributesOp setAttributes; - js::DeleteIdOp deleteProperty; + js::StrictPropertyIdOp deleteProperty; js::NewEnumerateOp enumerate; js::TypeOfOp typeOf; js::TraceOp trace; diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 68784676a78..b3f4da8cfdf 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -204,14 +204,13 @@ JSWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) bool JSWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - GET(wrappedObject(wrapper)->getProperty(cx, receiver, id, vp)); + GET(JS_GetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); } bool JSWrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - // FIXME (bug 596351): Need deal with strict mode. - SET(wrappedObject(wrapper)->setProperty(cx, receiver, id, vp, false)); + SET(JS_SetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); } bool diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 7eb680a5e8a..f61320e2ec9 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -4743,7 +4743,7 @@ xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, } static JSBool -xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) +xml_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) { vp->setUndefined(); @@ -4754,7 +4754,7 @@ xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value } static JSBool -xml_setProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp, JSBool strict) +xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { return PutProperty(cx, obj, id, Jsvalify(vp)); } diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index b1006719fc5..659c76b76b0 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -257,7 +257,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) defineHow = JSDNP_CACHE_RESULT | JSDNP_UNQUALIFIED; else defineHow = JSDNP_CACHE_RESULT; - if (!js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, strict)) + if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, strict)) THROW(); } else { if (!obj->setProperty(cx, id, &rval, strict)) @@ -2209,7 +2209,7 @@ InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op) ? JSDNP_CACHE_RESULT | JSDNP_SET_METHOD : JSDNP_CACHE_RESULT; if (!(JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom) - ? js_SetPropertyHelper(cx, obj, obj, id, defineHow, &rval, false) + ? js_SetPropertyHelper(cx, obj, id, defineHow, &rval, false) : js_DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, NULL, defineHow))) { diff --git a/js/src/tests/js1_8_5/regress/jstests.list b/js/src/tests/js1_8_5/regress/jstests.list index d577160082b..6c757e175a5 100644 --- a/js/src/tests/js1_8_5/regress/jstests.list +++ b/js/src/tests/js1_8_5/regress/jstests.list @@ -12,7 +12,7 @@ script regress-551763-0.js script regress-551763-1.js script regress-551763-2.js script regress-555246-0.js -script regress-555246-1.js +fails-if(xulRuntime.shell) script regress-555246-1.js script regress-559438.js script regress-560101.js script regress-560998-1.js @@ -48,4 +48,3 @@ script regress-598176.js script regress-600067.js script regress-600137.js script regress-602621.js -fails-if(!xulRuntime.shell) script regress-607863.js diff --git a/js/src/tests/js1_8_5/regress/regress-607863.js b/js/src/tests/js1_8_5/regress/regress-607863.js deleted file mode 100644 index 2eb463df890..00000000000 --- a/js/src/tests/js1_8_5/regress/regress-607863.js +++ /dev/null @@ -1,13 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -var sandbox = evalcx(''); -var foreign = evalcx('({ get f() this, set x(v) { result = this } })', sandbox); -var local = Object.create(foreign); - -reportCompare(local, local.f, "this should be set correctly in getters"); -local.x = 42; -reportCompare(local, sandbox.result, "this should be set correctly in setters"); From e80289fa8a7e1457e9ddacf52605ca22567fee13 Mon Sep 17 00:00:00 2001 From: Walter Meinl Date: Fri, 29 Oct 2010 13:57:41 -0700 Subject: [PATCH 040/263] Bug 606834 - Fix int32/int32_t on OS/2 (r=daveryeo,wmccloskey) --- js/src/jsotypes.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/js/src/jsotypes.h b/js/src/jsotypes.h index 4bc8af5d225..a79044f29aa 100644 --- a/js/src/jsotypes.h +++ b/js/src/jsotypes.h @@ -75,11 +75,7 @@ typedef JSUintn uint; typedef JSUintn uintn; typedef JSUint64 uint64; -#if !defined(XP_OS2) typedef JSUint32 uint32; -#else -typedef unsigned long uint32; -#endif typedef JSUint16 uint16; typedef JSUint8 uint8; @@ -99,11 +95,7 @@ typedef JSIntn intn; typedef JSInt64 int64; /* /usr/include/model.h on HP-UX defines int8, int16, and int32 */ -#if !defined(XP_OS2) typedef JSInt32 int32; -#else -typedef long int32; -#endif typedef JSInt16 int16; typedef JSInt8 int8; #endif /* AIX && HAVE_SYS_INTTYPES_H */ From b2f34aa0365a548a338dfea92f851c8ca4274cae Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Sat, 30 Oct 2010 22:32:45 -0400 Subject: [PATCH 041/263] bug 608422 - cookies.sqlite-wal takes too much space for Fennec r=sdwilsh a=blocking-fennec --- netwerk/cookie/nsCookieService.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index d219e6637c5..27bab495011 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -956,8 +956,11 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB) // make operations on the table asynchronous, for performance mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF")); - // Use write-ahead-logging for performance. + // Use write-ahead-logging for performance. We cap the autocheckpoint limit at + // 16 pages (around 500KB). mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA journal_mode = WAL")); + mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "PRAGMA wal_autocheckpoint = 16")); // cache frequently used statements (for insertion, deletion, and updating) rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING( From 18ce84349191603a97c62954ed01ac7fc723eb1f Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Fri, 29 Oct 2010 14:43:02 -0700 Subject: [PATCH 042/263] Fix for bug 606705 (Browser crash when using many web workers [@ GCGraphBuilder::NoteXPCOMChild ] or beyond). r=jst, a=beta7+ --- js/src/xpconnect/src/nsXPConnect.cpp | 4 +- js/src/xpconnect/src/xpcjsruntime.cpp | 78 ++++++++++++++++--- js/src/xpconnect/src/xpcprivate.h | 27 ++++++- .../xpconnect/src/xpcwrappednativescope.cpp | 15 ++-- 4 files changed, 104 insertions(+), 20 deletions(-) diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 1711f54c8d0..fdaafc86ed3 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -987,7 +987,7 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, xpc::PtrAndPrincipalHashKey *priv_key = new xpc::PtrAndPrincipalHashKey(ptr, uri); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(priv_key, wantXrays); + new xpc::CompartmentPrivate(priv_key, wantXrays, NS_IsMainThread()); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { @@ -1024,7 +1024,7 @@ xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, // threadsafety assumptions. nsCOMPtr principal(do_QueryInterface(ptr)); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(ptr, false); + new xpc::CompartmentPrivate(ptr, false, NS_IsMainThread()); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index e745826f8d0..bdaa1988afc 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -408,23 +408,67 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); } +struct Closure +{ + JSContext *cx; + bool cycleCollectionEnabled; + nsCycleCollectionTraversalCallback *cb; +#ifdef DEBUG + JSCompartment *compartment; +#endif +}; + +static void +CheckParticipatesInCycleCollection(PRUint32 aLangID, void *aThing, void *aClosure) +{ + Closure *closure = static_cast(aClosure); + +#ifdef DEBUG + if(aLangID == nsIProgrammingLanguage::JAVASCRIPT && + js_GetGCThingTraceKind(aThing) == JSTRACE_OBJECT) + { + JSCompartment *c = static_cast(aThing)->compartment(); + JS_ASSERT(!closure->compartment || closure->compartment == c); + closure->compartment = c; + } +#endif + + if(!closure->cycleCollectionEnabled && + aLangID == nsIProgrammingLanguage::JAVASCRIPT && + js_GetGCThingTraceKind(aThing) == JSTRACE_OBJECT) + { + closure->cycleCollectionEnabled = + xpc::ParticipatesInCycleCollection(closure->cx, + static_cast(aThing)); + } +} + static JSDHashOperator NoteJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { ObjectHolder* entry = reinterpret_cast(hdr); + Closure *closure = static_cast(arg); - nsCycleCollectionTraversalCallback* cb = - static_cast(arg); - cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, - entry->tracer); + closure->cycleCollectionEnabled = PR_FALSE; +#ifdef DEBUG + closure->compartment = nsnull; +#endif + entry->tracer->Trace(entry->holder, CheckParticipatesInCycleCollection, + closure); + if(!closure->cycleCollectionEnabled) + return JS_DHASH_NEXT; + + closure->cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, + entry->tracer); return JS_DHASH_NEXT; } -void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, - nsCycleCollectionTraversalCallback &cb) +void +XPCJSRuntime::AddXPConnectRoots(JSContext* cx, + nsCycleCollectionTraversalCallback &cb) { // For all JS objects that are held by native objects but aren't held // through rooting or locking, we need to add all the native objects that @@ -447,6 +491,8 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, nsXPConnect::JSContextParticipant()); } + XPCAutoLock lock(mMapLock); + XPCWrappedNativeScope::SuspectAllWrappers(this, cx, cb); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) @@ -454,12 +500,26 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) { - nsIXPConnectWrappedJS *wrappedJS = static_cast(e); - cb.NoteXPCOMRoot(wrappedJS); + nsXPCWrappedJS *wrappedJS = static_cast(e); + JSObject *obj = wrappedJS->GetJSObject(); + + // Only suspect wrappedJSObjects that are in a compartment that + // participates in cycle collection. + if(!xpc::ParticipatesInCycleCollection(cx, obj)) + continue; + + cb.NoteXPCOMRoot(static_cast(wrappedJS)); } if(mJSHolders.ops) - JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &cb); + { + Closure closure = { cx, PR_TRUE, &cb +#if DEBUG + , nsnull +#endif + }; + JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &closure); + } } void diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e749c7de227..bfe595244b1 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -4508,16 +4508,18 @@ namespace xpc { struct CompartmentPrivate { - CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays) + CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays, bool cycleCollectionEnabled) : key(key), ptr(nsnull), - wantXrays(wantXrays) + wantXrays(wantXrays), + cycleCollectionEnabled(cycleCollectionEnabled) { } - CompartmentPrivate(nsISupports *ptr, bool wantXrays) + CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled) : key(nsnull), ptr(ptr), - wantXrays(wantXrays) + wantXrays(wantXrays), + cycleCollectionEnabled(cycleCollectionEnabled) { } @@ -4525,8 +4527,25 @@ struct CompartmentPrivate nsAutoPtr key; nsCOMPtr ptr; bool wantXrays; + bool cycleCollectionEnabled; }; +inline bool +CompartmentParticipatesInCycleCollection(JSContext *cx, JSCompartment *compartment) +{ + CompartmentPrivate *priv = + static_cast(JS_GetCompartmentPrivate(cx, compartment)); + NS_ASSERTION(priv, "This should never be null!"); + + return priv->cycleCollectionEnabled; +} + +inline bool +ParticipatesInCycleCollection(JSContext *cx, js::gc::Cell *cell) +{ + return CompartmentParticipatesInCycleCollection(cx, cell->compartment()); +} + } #ifdef XPC_IDISPATCH_SUPPORT diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index b08cb6a40db..541e3aadb62 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -415,17 +415,22 @@ WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, { NS_ASSERTION(NS_IsMainThread(), "Suspecting wrapped natives from non-main thread"); - NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject()), + + // Only suspect wrappedJSObjects that are in a compartment that + // participates in cycle collection. + JSObject* obj = wrapper->GetFlatJSObject(); + if(!xpc::ParticipatesInCycleCollection(closure->cx, obj)) + return JS_DHASH_NEXT; + + NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, obj), "WrappedNativeSuspecter attempting to touch dead object"); // Only record objects that might be part of a cycle as roots, unless // the callback wants all traces (a debug feature). - if(!(closure->cb.WantAllTraces()) && - !nsXPConnect::IsGray(wrapper->GetFlatJSObject())) + if(!(closure->cb.WantAllTraces()) && !nsXPConnect::IsGray(obj)) return JS_DHASH_NEXT; - closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, - wrapper->GetFlatJSObject(), + closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, obj, nsXPConnect::GetXPConnect()); } From 42793743d18292544690490f7652d497db2c8919 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Fri, 29 Oct 2010 14:43:02 -0700 Subject: [PATCH 043/263] Fix for bug 606705 (Browser crash when using many web workers [@ GCGraphBuilder::NoteXPCOMChild ] or beyond). r=jst, a=beta7+ --- js/src/xpconnect/src/nsXPConnect.cpp | 4 +- js/src/xpconnect/src/xpcjsruntime.cpp | 69 +++++++++++++------ js/src/xpconnect/src/xpcprivate.h | 42 +++++++++-- .../xpconnect/src/xpcwrappednativescope.cpp | 15 ++-- 4 files changed, 98 insertions(+), 32 deletions(-) diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 1711f54c8d0..fdaafc86ed3 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -987,7 +987,7 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, xpc::PtrAndPrincipalHashKey *priv_key = new xpc::PtrAndPrincipalHashKey(ptr, uri); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(priv_key, wantXrays); + new xpc::CompartmentPrivate(priv_key, wantXrays, NS_IsMainThread()); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { @@ -1024,7 +1024,7 @@ xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, // threadsafety assumptions. nsCOMPtr principal(do_QueryInterface(ptr)); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(ptr, false); + new xpc::CompartmentPrivate(ptr, false, NS_IsMainThread()); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index e745826f8d0..7cc68d555b4 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -408,16 +408,45 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); } +struct Closure +{ + JSContext *cx; + bool cycleCollectionEnabled; + nsCycleCollectionTraversalCallback *cb; +}; + +static void +CheckParticipatesInCycleCollection(PRUint32 aLangID, void *aThing, void *aClosure) +{ + Closure *closure = static_cast(aClosure); + + if(aLangID == nsIProgrammingLanguage::JAVASCRIPT && closure->cycleCollectionEnabled) + { + uint32 kind = js_GetGCThingTraceKind(aThing); + if(kind == JSTRACE_OBJECT) + closure->cycleCollectionEnabled = + xpc::ParticipatesInCycleCollection(closure->cx, static_cast(aThing)); + else if(kind == JSTRACE_STRING) + closure->cycleCollectionEnabled = + xpc::ParticipatesInCycleCollection(closure->cx, + static_cast(aThing)->asCell()); + } +} + static JSDHashOperator NoteJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { ObjectHolder* entry = reinterpret_cast(hdr); + Closure *closure = static_cast(arg); - nsCycleCollectionTraversalCallback* cb = - static_cast(arg); - cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, - entry->tracer); + closure->cycleCollectionEnabled = PR_TRUE; + entry->tracer->Trace(entry->holder, CheckParticipatesInCycleCollection, closure); + if(!closure->cycleCollectionEnabled) + return JS_DHASH_NEXT; + + closure->cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, + entry->tracer); return JS_DHASH_NEXT; } @@ -447,6 +476,8 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, nsXPConnect::JSContextParticipant()); } + AutoLockJSGC lock(cx->runtime); + XPCWrappedNativeScope::SuspectAllWrappers(this, cx, cb); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) @@ -454,12 +485,22 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) { - nsIXPConnectWrappedJS *wrappedJS = static_cast(e); - cb.NoteXPCOMRoot(wrappedJS); + nsXPCWrappedJS *wrappedJS = static_cast(e); + JSObject *obj = wrappedJS->GetJSObject(); + + // Only suspect wrappedJSObjects that are in a compartment that + // participates in cycle collection. + if(!xpc::ParticipatesInCycleCollection(cx, obj)) + continue; + + cb.NoteXPCOMRoot(static_cast(wrappedJS)); } if(mJSHolders.ops) - JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &cb); + { + Closure closure = { cx, PR_TRUE, &cb }; + JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &closure); + } } void @@ -781,20 +822,6 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status) return JS_TRUE; } -// Auto JS GC lock helper. -class AutoLockJSGC -{ -public: - AutoLockJSGC(JSRuntime* rt) : mJSRuntime(rt) { JS_LOCK_GC(mJSRuntime); } - ~AutoLockJSGC() { JS_UNLOCK_GC(mJSRuntime); } -private: - JSRuntime* mJSRuntime; - - // Disable copy or assignment semantics. - AutoLockJSGC(const AutoLockJSGC&); - void operator=(const AutoLockJSGC&); -}; - //static void XPCJSRuntime::WatchdogMain(void *arg) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e749c7de227..70120a08b96 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -472,6 +472,21 @@ private: static void operator delete(void* /*memory*/) {} }; +/************************************************/ + +class AutoLockJSGC +{ +public: + AutoLockJSGC(JSRuntime* rt) : mJSRuntime(rt) { JS_LOCK_GC(mJSRuntime); } + ~AutoLockJSGC() { JS_UNLOCK_GC(mJSRuntime); } +private: + JSRuntime* mJSRuntime; + + // Disable copy or assignment semantics. + AutoLockJSGC(const AutoLockJSGC&); + void operator=(const AutoLockJSGC&); +}; + /*************************************************************************** **************************************************************************** * @@ -4508,16 +4523,18 @@ namespace xpc { struct CompartmentPrivate { - CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays) + CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays, bool cycleCollectionEnabled) : key(key), ptr(nsnull), - wantXrays(wantXrays) + wantXrays(wantXrays), + cycleCollectionEnabled(cycleCollectionEnabled) { } - CompartmentPrivate(nsISupports *ptr, bool wantXrays) + CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled) : key(nsnull), ptr(ptr), - wantXrays(wantXrays) + wantXrays(wantXrays), + cycleCollectionEnabled(cycleCollectionEnabled) { } @@ -4525,8 +4542,25 @@ struct CompartmentPrivate nsAutoPtr key; nsCOMPtr ptr; bool wantXrays; + bool cycleCollectionEnabled; }; +inline bool +CompartmentParticipatesInCycleCollection(JSContext *cx, JSCompartment *compartment) +{ + CompartmentPrivate *priv = + static_cast(JS_GetCompartmentPrivate(cx, compartment)); + NS_ASSERTION(priv, "This should never be null!"); + + return priv->cycleCollectionEnabled; +} + +inline bool +ParticipatesInCycleCollection(JSContext *cx, js::gc::Cell *cell) +{ + return CompartmentParticipatesInCycleCollection(cx, cell->compartment()); +} + } #ifdef XPC_IDISPATCH_SUPPORT diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index b08cb6a40db..541e3aadb62 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -415,17 +415,22 @@ WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, { NS_ASSERTION(NS_IsMainThread(), "Suspecting wrapped natives from non-main thread"); - NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject()), + + // Only suspect wrappedJSObjects that are in a compartment that + // participates in cycle collection. + JSObject* obj = wrapper->GetFlatJSObject(); + if(!xpc::ParticipatesInCycleCollection(closure->cx, obj)) + return JS_DHASH_NEXT; + + NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, obj), "WrappedNativeSuspecter attempting to touch dead object"); // Only record objects that might be part of a cycle as roots, unless // the callback wants all traces (a debug feature). - if(!(closure->cb.WantAllTraces()) && - !nsXPConnect::IsGray(wrapper->GetFlatJSObject())) + if(!(closure->cb.WantAllTraces()) && !nsXPConnect::IsGray(obj)) return JS_DHASH_NEXT; - closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, - wrapper->GetFlatJSObject(), + closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, obj, nsXPConnect::GetXPConnect()); } From 01cf037eee77c2cb1d0e90e525bea3128242a227 Mon Sep 17 00:00:00 2001 From: Paul Biggar Date: Fri, 29 Oct 2010 14:52:28 -0700 Subject: [PATCH 044/263] Backed out changeset 66f4a212edeb (bug 605133). Configure broke shell and unclobbered-build with js-config problem. --- configure.in | 20 +- js/src/configure.in | 858 +++++++++----------------------------------- 2 files changed, 182 insertions(+), 696 deletions(-) diff --git a/configure.in b/configure.in index fd013fd3c74..af629d52aa6 100644 --- a/configure.in +++ b/configure.in @@ -622,9 +622,6 @@ case "$target" in # Make sure compilers are valid CFLAGS="$CFLAGS -TC -nologo" CXXFLAGS="$CXXFLAGS -TP -nologo" - # MSVC warning C4345 warns of newly conformant behavior as of VS2003. - # MSVC warning C4800 is ubiquitous, useless, and annoying. - CXXFLAGS="$CXXFLAGS -wd4345 -wd4800" AC_LANG_SAVE AC_LANG_C AC_TRY_COMPILE([#include ], @@ -2743,11 +2740,6 @@ alpha*-*-osf*) *-solaris*) AC_DEFINE(SOLARIS) TARGET_NSPR_MDCPUCFG='\"md/_solaris.cfg\"' - if test -z "$CROSS_COMPILE" && pkginfo -q SUNWpr && pkginfo -q SUNWprd; then - NO_NSPR_CONFIG_SYSTEM_LDFLAGS="-L/usr/lib/mps -R/usr/lib/mps -lnspr4" - NO_NSPR_CONFIG_SYSTEM_CFLAGS="-I/usr/include/mps" - NO_NSPR_CONFIG_SYSTEM_VERSION=["`pkgparam SUNWpr SUNW_PRODVERS | sed -e 's/^[1-9][0-9]*\.[0-9][0-9]*$/&.0/'`"] - fi SYSTEM_MAKEDEPEND= MOZ_FIX_LINK_PATHS= # $ORIGIN/.. is for shared libraries under components/ to locate shared @@ -3806,9 +3798,9 @@ dnl Checks for library functions. dnl ======================================================== AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP -AC_CHECK_FUNCS([fchmod flockfile getc_unlocked _getc_nolock getpagesize \ - lchown localtime_r lstat64 memmove random rint sbrk snprintf \ - stat64 statvfs statvfs64 strerror strtok_r truncate64]) +AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat64 lstat64 truncate64 statvfs64 setbuf isatty) +AC_CHECK_FUNCS(flockfile getpagesize) +AC_CHECK_FUNCS(localtime_r strtok_r) dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt _SAVE_LDFLAGS=$LDFLAGS @@ -5268,6 +5260,7 @@ cairo-cocoa) MOZ_WIDGET_TOOLKIT=cocoa AC_DEFINE(MOZ_WIDGET_COCOA) MOZ_USER_DIR="Mozilla" + AC_DEFINE(XP_MACOSX) TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL' TK_CFLAGS="-DNO_X11" LDFLAGS="$LDFLAGS -framework Cocoa -lobjc" @@ -7068,7 +7061,6 @@ if test -n "$MOZ_THUMB2"; then case "$target_cpu" in arm*) if test "$GNU_CC"; then - AC_DEFINE(MOZ_THUMB2) CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" @@ -8026,6 +8018,7 @@ dnl ======================================================== dnl C++ rtti dnl Should be smarter and check that the compiler does indeed have rtti dnl ======================================================== + MOZ_ARG_ENABLE_BOOL(cpp-rtti, [ --enable-cpp-rtti Enable C++ RTTI ], [ _MOZ_USE_RTTI=1 ], @@ -9096,7 +9089,7 @@ if test "$USING_HCC"; then AC_SUBST(CXX) fi -AC_MSG_CHECKING([for posix_fallocate]) +AC_MSG_CHECKING([for posix_fallocate]) AC_TRY_LINK([#define _XOPEN_SOURCE 600 #include ], [posix_fallocate(0, 0, 0);], @@ -9167,7 +9160,6 @@ dnl ======================================================== if test "$OS_ARCH" = "BeOS"; then AC_DEFINE(XP_BEOS) elif test "$OS_ARCH" = "Darwin"; then - AC_DEFINE(XP_MACOSX) AC_DEFINE(XP_UNIX) AC_DEFINE(UNIX_ASYNC_DNS) elif test "$OS_ARCH" = "OpenVMS"; then diff --git a/js/src/configure.in b/js/src/configure.in index 46d491d77bb..619fd104123 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -42,8 +42,6 @@ dnl Mac OS X 10.4 support dnl Giorgio Maone dnl MSVC l10n compatible version check dnl Ben Turner -dnl Windows x64 support -dnl Makoto Kato dnl dnl Alternatively, the contents of this file may be used under the terms of dnl either the GNU General Public License Version 2 or later (the "GPL"), or @@ -110,7 +108,6 @@ NSPR_VERSION=4 dnl Set the minimum version of toolkit libs used by mozilla dnl ======================================================== PERL_VERSION=5.006 -PYTHON_VERSION=2.5 WINDRES_VERSION=2.14.90 W32API_VERSION=3.8 @@ -203,17 +200,11 @@ esac fi COMPILE_ENVIRONMENT=1 -MOZ_ARG_DISABLE_BOOL(compile-environment, +MOZ_ARG_ENABLE_BOOL(compile-environment, [ --disable-compile-environment Disable compiler/library checks.], + COMPILE_ENVIRONMENT=1, COMPILE_ENVIRONMENT= ) -AC_SUBST(COMPILE_ENVIRONMENT) - -dnl Check for Perl first -- needed for win32 SDK checks -MOZ_PATH_PROGS(PERL, $PERL perl5 perl ) -if test -z "$PERL" -o "$PERL" = ":"; then - AC_MSG_ERROR([perl not found in \$PATH]) -fi MOZ_ARG_ENABLE_BOOL(shared-js, [ --disable-shared-js @@ -234,8 +225,7 @@ dnl = here, so that the compiler checks can succeed dnl ======================================================== MOZ_ARG_WITH_STRING(android-ndk, -[ --with-android-ndk=DIR - location where the Android NDK can be found], +[ --with-android-ndk=DIR location where the Android NDK can be found], android_ndk=$withval) MOZ_ARG_WITH_STRING(android-toolchain, @@ -250,29 +240,11 @@ MOZ_ARG_WITH_STRING(android-version, android_version=$withval, android_version=5) -MOZ_ARG_WITH_STRING(android-sdk, -[ --with-android-sdk=DIR - location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)], - android_sdk=$withval) - -MOZ_ARG_WITH_STRING(android-tools, -[ --with-android-tools=DIR - location where the Android Tools can be found (base directory, e.g. .../android/tools)], - android_tools=$withval) - if test "$target" = "arm-android-eabi" ; then if test -z "$android_ndk" ; then AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.]) fi - if test -z "$android_sdk" ; then - AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.]) - fi - - if test -z "$android_tools" ; then - AC_MSG_ERROR([You must specify --with-android-tools=/path/to/sdk/tools when targeting Android.]) - fi - if test -z "$android_toolchain" ; then android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0 fi @@ -280,7 +252,6 @@ if test "$target" = "arm-android-eabi" ; then if test -z "$android_platform" ; then android_platform="$android_ndk"/build/platforms/android-"$android_version"/arch-"$target_cpu" fi - dnl set up compilers AS="$android_toolchain"/bin/arm-eabi-as CC="$android_toolchain"/bin/arm-eabi-gcc @@ -292,14 +263,9 @@ if test "$target" = "arm-android-eabi" ; then STRIP="$android_toolchain"/bin/arm-eabi-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" - CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CFLAGS" - CXXFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CXXFLAGS" - - dnl Add -llog by default, since we use it all over the place. - dnl Add --allow-shlib-undefined, because libGLESv2 links to an - dnl undefined symbol (present on the hardware, just not in the - dnl NDK.) - LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS" + CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CFLAGS" + CXXFLAGS="-mandroid -std=gnu++0x -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CXXFLAGS" + LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" dnl prevent cross compile section from using these flags as host flags if test -z "$HOST_CPPFLAGS" ; then @@ -315,13 +281,6 @@ if test "$target" = "arm-android-eabi" ; then HOST_LDFLAGS=" " fi - ANDROID_NDK="${android_ndk}" - ANDROID_TOOLCHAIN="{android_toolchain}" - ANDROID_PLATFORM="{android_platform}" - ANDROID_SDK="${android_sdk}" - ANDROID_TOOLS="${android_tools}" - ANDROID_VERSION="${android_version}" - # save these for libffi's subconfigure, # which doesn't know how to figure this stuff out on its own ANDROID_CFLAGS="$CFLAGS" @@ -330,23 +289,12 @@ if test "$target" = "arm-android-eabi" ; then AC_DEFINE(ANDROID) AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version) - AC_SUBST(ANDROID_VERSION) - CROSS_COMPILE=1 - MOZ_CHROME_FILE_FORMAT=omni + AC_DEFINE(FORCE_LITTLE_ENDIAN) fi -AC_SUBST(ANDROID_NDK) -AC_SUBST(ANDROID_TOOLCHAIN) -AC_SUBST(ANDROID_PLATFORM) -AC_SUBST(ANDROID_SDK) -AC_SUBST(ANDROID_TOOLS) - dnl ======================================================== dnl Checks for compilers. dnl ======================================================== -dnl Set CROSS_COMPILE in the environment when running configure -dnl to use the cross-compile setup for now -dnl ======================================================== dnl AR_FLAGS set here so HOST_AR_FLAGS can be set correctly (see bug 538269) AR_FLAGS='cr $@' @@ -355,7 +303,6 @@ if test "$COMPILE_ENVIRONMENT"; then if test "$target" != "$host"; then echo "cross compiling from $host to $target" - cross_compiling=yes _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" @@ -418,8 +365,8 @@ if test "$target" != "$host"; then dnl checks will fail. Fake a working SDK in that case. _SAVE_CFLAGS=$CFLAGS _SAVE_CXXFLAGS=$CXXLAGS - CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk $CFLAGS" - CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk $CXXFLAGS" + CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" + CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" ;; esac @@ -481,6 +428,12 @@ if test "$target" != "$host"; then AC_CHECK_PROGS(STRIP, $STRIP "${target_alias}-strip" "${target}-strip", :) AC_CHECK_PROGS(WINDRES, $WINDRES "${target_alias}-windres" "${target}-windres", :) AC_DEFINE(CROSS_COMPILE) + + dnl If we cross compile for ppc on Mac OS X x86, cross_compiling will + dnl have erroneously been set to "no", because the x86 build host is + dnl able to run ppc code in a translated environment, making a cross + dnl compiler appear native. So we override that here. + cross_compiling=yes else AC_PROG_CC AC_PROG_CXX @@ -561,34 +514,16 @@ dnl ======================================================== case "$target" in *-wince|*-winmo) WINVER=500 - WINSDK_TARGETVER=502 ;; *) - WINVER=502 - dnl Target the Windows 7 SDK by default - WINSDK_TARGETVER=601 + if test -n "$GNU_CC"; then + WINVER=501 + else + WINVER=500 + fi ;; esac -MOZ_ARG_WITH_STRING(windows-version, -[ --with-windows-version=WINSDK_TARGETVER - Highest Windows version to target using this SDK - 502: Windows Server 2003 - 600: Windows Vista - 601: Windows 7], - WINSDK_TARGETVER=$withval) - -case "$WINSDK_TARGETVER" in -502|600|601) - MOZ_WINSDK_TARGETVER=0${WINSDK_TARGETVER}0000 - ;; - -*) - AC_MSG_ERROR([Invalid value for --with-windows-version ($WINSDK_TARGETVER), must be 502, 600 or 601]); - ;; - -esac - case "$target" in *-cygwin*|*-mingw*|*-msvc*|*-mks*|*-wince|*-winmo) if test "$GCC" != "yes"; then @@ -699,112 +634,8 @@ case "$target" in fi INCREMENTAL_LINKER=1 - # Identify which version of the SDK we're building with - # Windows Server 2008 and newer SDKs have WinSDKVer.h, get the version - # from there - AC_CHECK_HEADERS([winsdkver.h]) - if test "$ac_cv_header_winsdkver_h" = "yes"; then - # Get the highest _WIN32_WINNT and NTDDI versions supported - # Take the higher of the two - # This is done because the Windows 7 beta SDK reports its - # NTDDI_MAXVER to be 0x06000100 instead of 0x06010000, as it should - AC_CACHE_CHECK(for highest Windows version supported by this SDK, - ac_cv_winsdk_maxver, - [cat > conftest.h < -#include - -#if (NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) > NTDDI_MAXVER) -#define WINSDK_MAXVER NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) -#else -#define WINSDK_MAXVER NTDDI_MAXVER -#endif - -WINSDK_MAXVER -EOF - ac_cv_winsdk_maxver=`$CPP conftest.h 2>/dev/null | tail -n1` - rm -f conftest.h - ]) - MOZ_WINSDK_MAXVER=${ac_cv_winsdk_maxver} - else - # The Vista SDK is the only one to have sdkddkver.h but not - # WinSDKVer.h - AC_CHECK_HEADERS([sdkddkver.h]) - if test "$ac_cv_header_sdkddkver_h" = "yes"; then - MOZ_WINSDK_MAXVER=0x06000000 - else - # Assume the Server 2003 Platform SDK - MOZ_WINSDK_MAXVER=0x05020000 - fi - fi - unset _MSVC_VER_FILTER - AC_CACHE_CHECK(for std::_Throw, ac_cv_have_std__Throw, - [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - _SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" - AC_TRY_COMPILE([#include ], - [std::_Throw(std::exception()); return 0;], - ac_cv_have_std__Throw="yes", - ac_cv_have_std__Throw="no") - CXXFLAGS="$_SAVE_CXXFLAGS" - AC_LANG_RESTORE - ]) - - if test "$ac_cv_have_std__Throw" == "yes"; then - AC_CACHE_CHECK(for |class __declspec(dllimport) exception| bug, - ac_cv_have_dllimport_exception_bug, - [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - _SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" - AC_TRY_LINK([#include ], - [std::vector v; return v.at(1);], - ac_cv_have_dllimport_exception_bug="no", - ac_cv_have_dllimport_exception_bug="yes") - CXXFLAGS="$_SAVE_CXXFLAGS" - AC_LANG_RESTORE - ]) - if test "$ac_cv_have_dllimport_exception_bug" = "no"; then - WRAP_STL_INCLUDES=1 - MOZ_MSVC_STL_WRAP__Throw=1 - AC_DEFINE(MOZ_MSVC_STL_WRAP__Throw) - fi - else - AC_CACHE_CHECK(for overridable _RAISE, - ac_cv_have__RAISE, - [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - _SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" - AC_TRY_COMPILE([#include - #undef _RAISE - #define _RAISE(x) externallyDefinedFunction((x).what()) - #include - ], - [std::vector v; return v.at(1);], - ac_cv_have__RAISE="no", - ac_cv_have__RAISE="yes") - CXXFLAGS="$_SAVE_CXXFLAGS" - AC_LANG_RESTORE - ]) - if test "$ac_cv_have__RAISE" = "yes"; then - WRAP_STL_INCLUDES=1 - MOZ_MSVC_STL_WRAP__RAISE=1 - AC_DEFINE(MOZ_MSVC_STL_WRAP__RAISE) - else - AC_MSG_ERROR([Gecko exception wrapping doesn't understand your your MSVC/SDK. Please file a bug describing this error and your build configuration.]) - fi - fi - - if test "$WRAP_STL_INCLUDES" = "1"; then - STL_FLAGS='-D_HAS_EXCEPTIONS=0 -I$(DIST)/stl_wrappers' - fi else # Check w32api version _W32API_MAJOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $1 }'` @@ -840,31 +671,12 @@ EOF then AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.]) fi - - # Server 2003 is the highest version supported - MOZ_WINSDK_MAXVER=0x05020000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) AC_DEFINE_UNQUOTED(_WIN32_WINNT,0x$WINVER) # Require OS features provided by IE 5.0 AC_DEFINE_UNQUOTED(_WIN32_IE,0x0500) - - # If the maximum version supported by this SDK is lower than the target - # version, error out - AC_MSG_CHECKING([for Windows SDK being recent enough]) - if $PERL -e "exit(0x$MOZ_WINSDK_TARGETVER > $MOZ_WINSDK_MAXVER)"; then - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") - AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. Alternatively, try running the Windows SDK Configuration Tool and selecting a newer SDK. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.]) - fi - - AC_DEFINE_UNQUOTED(MOZ_WINSDK_TARGETVER,0x$MOZ_WINSDK_TARGETVER) - # Definitions matching sdkddkver.h - AC_DEFINE_UNQUOTED(MOZ_NTDDI_WS03, 0x05020000) - AC_DEFINE_UNQUOTED(MOZ_NTDDI_LONGHORN, 0x06000000) - AC_DEFINE_UNQUOTED(MOZ_NTDDI_WIN7, 0x06010000) ;; esac @@ -914,6 +726,12 @@ fi fi # COMPILE_ENVIRONMENT +if test "$cross_compiling" = "yes"; then + CROSS_COMPILE=1 +else + CROSS_COMPILE= +fi + # Check to see if we are running in a broken QEMU scratchbox. # We know that anything below 1.0.16 is broken. AC_CHECK_PROGS(SBCONF, sb-conf ve, "") @@ -937,16 +755,15 @@ AC_SUBST(GNU_CXX) AC_SUBST(INTEL_CC) AC_SUBST(INTEL_CXX) -AC_SUBST(STL_FLAGS) -AC_SUBST(WRAP_STL_INCLUDES) -AC_SUBST(MOZ_MSVC_STL_WRAP__Throw) -AC_SUBST(MOZ_MSVC_STL_WRAP__RAISE) - dnl ======================================================== dnl Checks for programs. dnl ======================================================== AC_PROG_INSTALL AC_PROG_LN_S +MOZ_PATH_PROGS(PERL, $PERL perl5 perl ) +if test -z "$PERL" -o "$PERL" = ":"; then + AC_MSG_ERROR([perl not found in \$PATH]) +fi if test -z "$TINDERBOX_SKIP_PERL_VERSION_CHECK"; then AC_MSG_CHECKING([for minimum required perl version >= $PERL_VERSION]) @@ -969,7 +786,7 @@ else AC_MSG_RESULT([yes]) fi -MOZ_PATH_PROGS(PYTHON, $PYTHON python2.6 python2.5 python2.4 python) +MOZ_PATH_PROGS(PYTHON, $PYTHON python) if test -z "$PYTHON"; then AC_MSG_ERROR([python was not found in \$PATH]) fi @@ -1056,7 +873,7 @@ dnl Check for MacOS deployment target version dnl ======================================================== MOZ_ARG_ENABLE_STRING(macos-target, - [ --enable-macos-target=VER (default=10.5) + [ --enable-macos-target=VER (default=10.4) Set the minimum MacOS version needed at runtime], [_MACOSX_DEPLOYMENT_TARGET=$enableval]) @@ -1066,20 +883,11 @@ case "$target" in dnl Use the specified value export MACOSX_DEPLOYMENT_TARGET=$_MACOSX_DEPLOYMENT_TARGET AC_DEFINE_UNQUOTED(__ENVIRONMENT_MAC_OS_X_VERION_MIN_REQUIRED__,$_MACOSX_DEPLOYMENT_TARGET) - else + elif test -z "$MACOSX_DEPLOYMENT_TARGET" ; then dnl No value specified on the command line or in the environment, - dnl use architecture minimum. - case "${target_cpu}" in - ppc*) - export MACOSX_DEPLOYMENT_TARGET=10.5 - ;; - i*86) - export MACOSX_DEPLOYMENT_TARGET=10.5 - ;; - x86_64) - export MACOSX_DEPLOYMENT_TARGET=10.6 - ;; - esac + dnl use the lesser of the application's minimum or the architecture's + dnl minimum. + export MACOSX_DEPLOYMENT_TARGET=10.4 fi ;; esac @@ -1149,25 +957,17 @@ fi fi # COMPILE_ENVIRONMENT -if test -n "$MAKE"; then - if test `echo $MAKE | grep -c make.py` != 1; then - NOT_PYMAKE=$MAKE - fi +if test -z "$MAKE"; then + case "$host_os" in + cygwin*|mingw*|mks*|msvc*) + MOZ_PATH_PROGS(MAKE, $MAKE make gmake, :) + ;; + *) + MOZ_PATH_PROGS(MAKE, $MAKE gmake make, :) + ;; + esac fi -case "$host_os" in -cygwin*|mingw*|mks*|msvc*) - MOZ_PATH_PROGS(GMAKE, $GMAKE $NOT_PYMAKE make gmake, :) - ;; -*) - MOZ_PATH_PROGS(GMAKE, $GMAKE $NOT_PYMAKE gmake make, :) - ;; -esac -if test "$GMAKE" = ":"; then - AC_MSG_ERROR([GNU make not found]) -fi -AC_SUBST(GMAKE) - if test "$COMPILE_ENVIRONMENT"; then AC_PATH_XTRA @@ -1199,7 +999,7 @@ WIN_TOP_SRC= MOZ_USER_DIR=".mozilla" MOZ_JS_LIBS='-L$(libdir) -lmozjs' -MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib' +MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(PREFIX)/lib' MOZ_COMPONENT_NSPR_LIBS='-L$(LIBXUL_DIST)/bin $(NSPR_LIBS)' @@ -1207,6 +1007,8 @@ USE_DEPENDENT_LIBS=1 _PLATFORM_DEFAULT_TOOLKIT=cairo-gtk2 +MOZ_THUMB2= + if test -n "$CROSS_COMPILE"; then OS_TARGET="${target_os}" OS_ARCH=`echo $target_os | sed -e 's|/|_|g'` @@ -1221,9 +1023,6 @@ if test -n "$CROSS_COMPILE"; then winmo*) OS_ARCH=WINCE ;; darwin*) OS_ARCH=Darwin OS_TARGET=Darwin ;; esac - case "${target}" in - arm-android-eabi) OS_ARCH=Linux OS_TARGET=Android ;; - esac else OS_TARGET=`uname -s` OS_ARCH=`uname -s | sed -e 's|/|_|g'` @@ -1261,9 +1060,6 @@ case "$HOST_OS_ARCH" in cygwin*|mingw*|mks*|msvc*) HOST_OS_ARCH=WINNT ;; -darwin*) - HOST_OS_ARCH=Darwin - ;; linux*) HOST_OS_ARCH=Linux ;; @@ -1330,9 +1126,7 @@ esac case "$OS_ARCH" in WINNT) - if test -z "$CROSS_COMPILE" ; then - OS_TEST=`uname -p` - fi + OS_TEST=`uname -p` ;; Windows_NT) # @@ -1436,17 +1230,13 @@ UnixWare) OS_RELEASE=`uname -v` ;; WINCE) + WINCE=1 OS_ARCH=WINCE - case "${target_os}" in - *winmo) + if test "$WINCE_WINDOWS_MOBILE"; then OS_TARGET=WINMO - WINCE_WINDOWS_MOBILE=1 - AC_DEFINE(WINCE_WINDOWS_MOBILE) - ;; - *) + else OS_TARGET=WINCE - ;; - esac + fi ;; Darwin) case "${target_cpu}" in @@ -1481,11 +1271,7 @@ case "$OS_TEST" in CPU_ARCH=x86 ;; -powerpc64 | ppc64) - CPU_ARCH=ppc64 - ;; - -powerpc | ppc | rs6000) +powerpc* | ppc | rs6000) CPU_ARCH=ppc ;; @@ -1493,14 +1279,6 @@ Alpha | alpha | ALPHA) CPU_ARCH=Alpha ;; -s390) - CPU_ARCH=s390 - ;; - -s390x) - CPU_ARCH=s390x - ;; - hppa* | parisc) CPU_ARCH=hppa ;; @@ -1556,7 +1334,7 @@ if test "$GNU_CC"; then if test -z "$INTEL_CC"; then # Don't use -Wcast-align with ICC case "$CPU_ARCH" in - # And don't use it on hppa, ia64, sparc, arm, since it's noisy there + # And don't use it on hppa, ia64, sparc, or arm since it's noisy there hppa | ia64 | sparc | arm) ;; *) @@ -1606,7 +1384,7 @@ if test "$GNU_CXX"; then if test -z "$INTEL_CC"; then # Don't use -Wcast-align with ICC case "$CPU_ARCH" in - # And don't use it on hppa, ia64, sparc, arm, since it's noisy there + # And don't use it on hppa, ia64, sparc, or arm since it's noisy there hppa | ia64 | sparc | arm) ;; *) @@ -1653,25 +1431,6 @@ if test "$GNU_CXX"; then if test "$ac_has_wno_variadic_macros" = "yes"; then _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-variadic-macros" fi - - AC_CACHE_CHECK(whether the compiler supports -Werror=return-type, - ac_has_werror_return_type, - [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - _SAVE_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -Werror=return-type" - AC_TRY_COMPILE([], - [return(0);], - ac_has_werror_return_type="yes", - ac_has_werror_return_type="no") - CXXFLAGS="$_SAVE_CXXFLAGS" - AC_LANG_RESTORE - ]) - if test "$ac_has_werror_return_type" = "yes"; then - _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type" - fi - else _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_JS_CONFDEFS_H_ $(ACDEFINES)' fi @@ -1806,8 +1565,6 @@ case "$host" in ;; *cygwin*|*mingw*|*mks*|*msvc*|*wince|*winmo) - # we need Python 2.5 on Windows - PYTHON_VERSION=2.5 if test -n "$_WIN32_MSVC"; then HOST_AR=lib HOST_AR_FLAGS='-NOLOGO -OUT:"$@"' @@ -1823,7 +1580,6 @@ case "$host" in case "$host" in *mingw*) dnl MinGW/MSYS does not need CYGWIN_WRAPPER - PERL="/bin/sh ${_topsrcdir}/build/msys-perl-wrapper" ;; *) CYGWIN_WRAPPER="${srcdir}/build/cygwin-wrapper" @@ -1841,12 +1597,6 @@ case "$host" in fi ;; esac - - case "${host_cpu}" in - x86_64) - HOST_CFLAGS="$HOST_CFLAGS -D_AMD64_" - ;; - esac ;; *-darwin*) @@ -1881,18 +1631,6 @@ case "$host" in ;; esac -dnl We require version 2.4 or newer of Python to build, -dnl and 2.5 or newer on Windows. -AC_MSG_CHECKING([for minimum required Python version >= $PYTHON_VERSION]) -changequote(,) -$PYTHON -c "import sys; sys.exit(sys.version[:3] < sys.argv[1])" $PYTHON_VERSION -_python_res=$? -changequote([,]) -if test "$_python_res" != 0; then - AC_MSG_ERROR([Python $PYTHON_VERSION or higher is required.]) -fi -AC_MSG_RESULT([yes]) - dnl ======================================================== dnl System overrides of the defaults for target dnl ======================================================== @@ -2065,7 +1803,6 @@ ia64*-hpux*) MOZ_FIX_LINK_PATHS= SYSTEM_MAKEDEPEND= AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES) - AC_DEFINE(_LARGEFILE64_SOURCE) ;; *-hpux*) @@ -2147,15 +1884,14 @@ ia64*-hpux*) ;; *-*linux*) - # Note: both GNU_CC and INTEL_CC are set when using Intel's C compiler. - # Similarly for GNU_CXX and INTEL_CXX. - if test "$INTEL_CC" -o "$INTEL_CXX"; then + # Note: both GNU_CXX and INTEL_CXX are set when using Intel's C compiler. + if test "$INTEL_CXX"; then # -Os has been broken on Intel's C/C++ compilers for quite a # while; Intel recommends against using it. MOZ_OPTIMIZE_FLAGS="-O2" MOZ_DEBUG_FLAGS="-g" - elif test "$GNU_CC" -o "$GNU_CXX"; then - GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'` + elif test "$GNU_CXX"; then + GCC_VERSION=`$CXX -v 2>&1 | awk '/^gcc version/ { print $3 }'` case $GCC_VERSION in 4.1.*|4.2.*|4.5.*) # -Os is broken on gcc 4.1.x 4.2.x, 4.5.x we need to tweak it to get good results. @@ -2163,9 +1899,9 @@ ia64*-hpux*) esac # If we're building with --enable-profiling, we need a frame pointer. if test -z "$MOZ_PROFILING"; then - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" else - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-omit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" fi MOZ_DEBUG_FLAGS="-g" fi @@ -2212,7 +1948,7 @@ ia64*-hpux*) WARNINGS_AS_ERRORS='-WX' - MOZ_OPTIMIZE_FLAGS='-Ox' + MOZ_OPTIMIZE_FLAGS='-O1' AR_FLAGS='-NOLOGO -OUT:"$@"' ASM_SUFFIX=asm CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)" @@ -2220,12 +1956,11 @@ ia64*-hpux*) DLL_PREFIX= DOXYGEN=: DSO_LDOPTS=-SUBSYSTEM:WINDOWSCE - DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib' GARBAGE= IMPORT_LIB_SUFFIX=lib - dnl Need to force-link against mozalloc because it's used in the shunt - LIBS="$LIBS \$(LIBXUL_DIST)/lib/mozalloc.lib" - LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + LIBS="$LIBS" + LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib' LIB_PREFIX= LIB_SUFFIX=lib MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ $(DSO_LDOPTS)' @@ -2244,9 +1979,10 @@ ia64*-hpux*) TARGET_NSPR_MDCPUCFG='\"md/_wince.cfg\"' UNZIP=unzip XARGS=xargs - XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib' ZIP=zip + AC_DEFINE(WINCE) AC_DEFINE(HAVE_SNPRINTF) AC_DEFINE(_WINDOWS) AC_DEFINE(WIN32) @@ -2256,10 +1992,9 @@ ia64*-hpux*) AC_DEFINE(STDC_HEADERS) AC_DEFINE(NEW_H, ) AC_DEFINE(WIN32_LEAN_AND_MEAN) - AC_DEFINE(HAVE_LOCALTIME_R) TARGET_MD_ARCH=win32 - _PLATFORM_DEFAULT_TOOLKIT='cairo-windows' + _PLATFORM_DEFAULT_TOOLKIT='windows' BIN_SUFFIX='.exe' MOZ_USER_DIR="Mozilla" @@ -2330,8 +2065,8 @@ ia64*-hpux*) LIBS="$LIBS -lgdi32 -lwinmm -lwsock32" MOZ_JS_LIBS='-L$(libdir) -lmozjs' MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc' - XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc' + DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core' + XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom' DLL_PREFIX= IMPORT_LIB_SUFFIX=dll.a GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'` @@ -2341,7 +2076,7 @@ ia64*-hpux*) HOST_CXX='$(CXX)' HOST_LD='$(LD)' if test "$AS_BIN"; then - AS="$(basename "$AS_BIN")" + AS="$(basename "$AS_BIN")" fi AR='lib -NOLOGO -OUT:"$@"' AR_FLAGS= @@ -2382,9 +2117,9 @@ ia64*-hpux*) fi MOZ_JS_LIBS='$(libdir)/mozjs.lib' MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' - XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib' - LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib' + LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib' MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)' if test $_MSC_VER -ge 1400; then LDFLAGS="$LDFLAGS -NXCOMPAT" @@ -2448,12 +2183,11 @@ ia64*-hpux*) AC_MSG_ERROR([MOZ_TOOLS is not set]) fi - MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd -W` + MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd` if test "$?" != "0" -o -z "$MOZ_TOOLS_DIR"; then AC_MSG_ERROR([cd \$MOZ_TOOLS failed. MOZ_TOOLS ==? $MOZ_TOOLS]) fi - MOZ_TOOLS_BIN_DIR="$(cd "$MOZ_TOOLS_DIR/bin" && pwd)" - if test `echo ${PATH}: | grep -ic "$MOZ_TOOLS_BINDIR:"` = 0; then + if test `echo ${PATH}: | grep -ic "$MOZ_TOOLS_DIR/bin:"` = 0; then AC_MSG_ERROR([\$MOZ_TOOLS\\bin must be in your path.]) fi MOZ_TOOLS_DIR=`$CYGPATH_W $MOZ_TOOLS_DIR | $CYGPATH_S` @@ -2486,8 +2220,8 @@ ia64*-hpux*) AC_DEFINE(_MIPS_) ;; x86_64-*) - AC_DEFINE(_AMD64_) - ;; + AC_DEFINE(_AMD64_) + ;; *) AC_DEFINE(_CPU_ARCH_NOT_DEFINED) ;; @@ -2802,21 +2536,6 @@ alpha*-*-osf*) HOST_NSPR_MDCPUCFG='\"md/_os2.cfg\"' ;; -*-android*) - AC_DEFINE(NO_PW_GECOS) - no_x=yes - _PLATFORM_DEFAULT_TOOLKIT=cairo-android - TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' - - MOZ_GFX_OPTIMIZE_MOBILE=1 - # If we're building with --enable-profiling, we need a frame pointer. - if test -z "$MOZ_PROFILING"; then - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer" - else - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer" - fi - ;; - esac dnl Only one oddball right now (QNX), but this gives us flexibility @@ -3021,28 +2740,13 @@ AC_SUBST(NANOJIT_ARCH) if test -z "$SKIP_COMPILER_CHECKS"; then dnl Checks for typedefs, structures, and compiler characteristics. dnl ======================================================== +AC_LANG_C AC_HEADER_STDC AC_C_CONST AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T -AC_LANG_CPLUSPLUS -AC_MSG_CHECKING(for __stdcall) -AC_CACHE_VAL(ac_cv___stdcall, - [AC_TRY_COMPILE([template struct foo; - template <> struct foo {}; - template <> struct foo {};], - [], - [ac_cv___stdcall=true], - [ac_cv___stdcall=false])]) -if test "$ac_cv___stdcall" = true ; then - AC_DEFINE(HAVE_STDCALL) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi -AC_LANG_C AC_MSG_CHECKING(for ssize_t) AC_CACHE_VAL(ac_cv_type_ssize_t, [AC_TRY_COMPILE([#include @@ -3340,8 +3044,6 @@ EOF "$ac_cv_have_visibility_class_bug" = "no"; then VISIBILITY_FLAGS='-I$(DIST)/system_wrappers_js -include $(topsrcdir)/config/gcc_hidden.h' WRAP_SYSTEM_INCLUDES=1 - STL_FLAGS='-I$(DIST)/stl_wrappers' - WRAP_STL_INCLUDES=1 else VISIBILITY_FLAGS='-fvisibility=hidden' fi # have visibility pragma bug @@ -3358,26 +3060,6 @@ fi # Sun Studio on Solaris AC_SUBST(WRAP_SYSTEM_INCLUDES) AC_SUBST(VISIBILITY_FLAGS) -dnl Check for __force_align_arg_pointer__ for SSE2 on gcc -dnl ======================================================== -if test "$GNU_CC"; then - CFLAGS_save="${CFLAGS}" - CFLAGS="${CFLAGS} -Werror" - AC_CACHE_CHECK(for __force_align_arg_pointer__ attribute, - ac_cv_force_align_arg_pointer, - [AC_TRY_COMPILE([__attribute__ ((__force_align_arg_pointer__)) void test() {}], - [], - ac_cv_force_align_arg_pointer="yes", - ac_cv_force_align_arg_pointer="no")]) - CFLAGS="${CFLAGS_save}" - if test "$ac_cv_force_align_arg_pointer" = "yes"; then - HAVE_GCC_ALIGN_ARG_POINTER=1 - else - HAVE_GCC_ALIGN_ARG_POINTER= - fi -fi -AC_SUBST(HAVE_GCC_ALIGN_ARG_POINTER) - dnl Checks for header files. dnl ======================================================== AC_HEADER_DIRENT @@ -3392,15 +3074,10 @@ AC_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h) AC_CHECK_HEADERS(gnu/libc-version.h nl_types.h) AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(X11/XKBlib.h) -AC_CHECK_HEADERS(io.h) dnl These are all the places some variant of statfs can be hiding. AC_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h) -dnl Quota support -AC_CHECK_HEADERS(sys/quota.h) -AC_CHECK_HEADERS(linux/quota.h) - dnl Try for MMX support dnl NB - later gcc versions require -mmmx for this header to be successfully dnl included (or another option which implies it, such as -march=pentium-mmx) @@ -3496,34 +3173,6 @@ case $target in AC_CHECK_LIB(socket, socket) esac -AC_MSG_CHECKING(for ARM SIMD support in compiler) -AC_TRY_COMPILE([], - [asm("uqadd8 r1, r1, r2");], - result="yes", result="no") -AC_MSG_RESULT("$result") -if test "$result" = "yes"; then - AC_DEFINE(HAVE_ARM_SIMD) - HAVE_ARM_SIMD=1 -fi -AC_SUBST(HAVE_ARM_SIMD) - -AC_MSG_CHECKING(for ARM NEON support in compiler) -_SAVE_CFLAGS="$CFLAGS" -if test "$GNU_CC"; then - # gcc needs -mfpu=neon to recognize NEON instructions - CFLAGS="$CFLAGS -mfpu=neon -mfloat-abi=softfp" -fi -AC_TRY_COMPILE([], - [asm("vadd.i8 d0, d0, d0");], - result="yes", result="no") -AC_MSG_RESULT("$result") -if test "$result" = "yes"; then - AC_DEFINE(HAVE_ARM_NEON) - HAVE_ARM_NEON=1 -fi -CFLAGS="$_SAVE_CFLAGS" -AC_SUBST(HAVE_ARM_NEON) - dnl ======================================================== dnl = pthread support dnl = Start by checking whether the system support pthreads @@ -3574,7 +3223,7 @@ then echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then - if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then + if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthread=yes case "$target_os" in freebsd*) @@ -3599,7 +3248,7 @@ then echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then - if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then + if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthreads=yes CFLAGS="$CFLAGS -pthreads" CXXFLAGS="$CXXFLAGS -pthreads" @@ -3713,29 +3362,11 @@ dnl Checks for library functions. dnl ======================================================== AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP + AC_CHECK_FUNCS([fchmod flockfile getc_unlocked _getc_nolock getpagesize \ lchown localtime_r lstat64 memmove random rint sbrk snprintf \ stat64 statvfs statvfs64 strerror strtok_r truncate64]) -dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt -_SAVE_LDFLAGS=$LDFLAGS -LDFLAGS="$LDFLAGS -lrt" -AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC) and -lrt, - ac_cv_have_clock_monotonic, - [AC_TRY_LINK([#include ], - [ struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); ], - ac_cv_have_clock_monotonic=yes, - ac_cv_have_clock_monotonic=no)]) -LDFLAGS=$_SAVE_LDFLAGS -if test "$ac_cv_have_clock_monotonic" = "yes"; then - HAVE_CLOCK_MONOTONIC=1 - REALTIME_LIBS=-lrt - AC_DEFINE(HAVE_CLOCK_MONOTONIC) - AC_SUBST(HAVE_CLOCK_MONOTONIC) - AC_SUBST(REALTIME_LIBS) -fi - dnl Windows functions, for mingw. AC_TRY_LINK([#include ], [SYSTEMTIME st;FILETIME ft;SystemTimeToFileTime(&st,&ft);], @@ -4032,7 +3663,6 @@ if test "$GNU_CC"; then ac_cv_gcc_arm_eabi="yes", ac_cv_gcc_arm_eabi="no")]) if test "$ac_cv_gcc_arm_eabi" = "yes"; then - HAVE_ARM_EABI=1 ARM_ABI_PREFIX=eabi- else ARM_ABI_PREFIX=oabi- @@ -4347,79 +3977,8 @@ if test "$ac_cv_trouble_comparing_to_zero" = yes ; then AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) fi -# try harder, when checking for __thread support, see bug 521750 comment #33 and below -_SAVE_LDFLAGS=$LDFLAGS -LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS $DSO_LDOPTS" -AC_CACHE_CHECK(for __thread keyword for TLS variables, - ac_cv_thread_keyword, - [AC_TRY_LINK([__thread bool tlsIsMainThread = false;], - [return tlsIsMainThread;], - ac_cv_thread_keyword=yes, - ac_cv_thread_keyword=no)]) -LDFLAGS=$_SAVE_LDFLAGS -if test "$ac_cv_thread_keyword" = yes; then - # mips builds fail with TLS variables because of a binutils bug. - # See bug 528687 - case "${target}" in - mips*-*) - : - ;; - *-android*) - : - ;; - *) - AC_DEFINE(HAVE_THREAD_TLS_KEYWORD) - ;; - esac -fi -dnl Check for the existence of various allocation headers/functions -MALLOC_H= -AC_CHECK_HEADER(malloc.h, [MALLOC_H=malloc.h]) -if test "$MALLOC_H" = ""; then - AC_CHECK_HEADER(malloc/malloc.h, [MALLOC_H=malloc/malloc.h]) - if test "$MALLOC_H" = ""; then - AC_CHECK_HEADER(sys/malloc.h, [MALLOC_H=sys/malloc.h]) - fi -fi -if test "$MALLOC_H" != ""; then - AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) -fi - -MOZ_ALLOCATING_FUNCS="strndup posix_memalign memalign valloc" -AC_CHECK_FUNCS(strndup posix_memalign memalign valloc) - -dnl See if compiler supports some gcc-style attributes - -AC_CACHE_CHECK(for __attribute__((always_inline)), - ac_cv_attribute_always_inline, - [AC_TRY_COMPILE([], - [inline void f(void) __attribute__((always_inline));], - ac_cv_attribute_always_inline=yes, - ac_cv_attribute_always_inline=no)]) - -AC_CACHE_CHECK(for __attribute__((malloc)), - ac_cv_attribute_malloc, - [AC_TRY_COMPILE([], - [void* f(int) __attribute__((malloc));], - ac_cv_attribute_malloc=yes, - ac_cv_attribute_malloc=no)]) - -AC_CACHE_CHECK(for __attribute__((warn_unused_result)), - ac_cv_attribute_warn_unused, - [AC_TRY_COMPILE([], - [int f(void) __attribute__((warn_unused_result));], - ac_cv_attribute_warn_unused=yes, - ac_cv_attribute_warn_unused=no)]) - -AC_CACHE_CHECK(for __attribute__((noreturn)), - ac_cv_attribute_noreturn, - [AC_TRY_COMPILE([], - [void f(void) __attribute__((noreturn));], - ac_cv_attribute_noreturn=yes, - ac_cv_attribute_noreturn=no)]) - dnl End of C++ language/feature checks AC_LANG_C @@ -4440,9 +3999,7 @@ AC_CACHE_CHECK(for LC_MESSAGES, ac_cv_i18n_lc_messages=no)]) if test "$ac_cv_i18n_lc_messages" = yes; then AC_DEFINE(HAVE_I18N_LC_MESSAGES) -fi - -AC_HAVE_FUNCS(localeconv) +fi fi # SKIP_COMPILER_CHECKS @@ -4456,41 +4013,6 @@ dnl ======================================================== dnl The macros used for command line options dnl are defined in build/autoconf/altoptions.m4. -dnl If the compiler supports these attributes, define them as -dnl convenience macros. -if test "$ac_cv_attribute_always_inline" = yes ; then - AC_DEFINE(NS_ALWAYS_INLINE, [__attribute__((always_inline))]) -else - AC_DEFINE(NS_ALWAYS_INLINE,) -fi - -if test "$ac_cv_attribute_malloc" = yes ; then - AC_DEFINE(NS_ATTR_MALLOC, [__attribute__((malloc))]) -else - AC_DEFINE(NS_ATTR_MALLOC,) -fi - -if test "$ac_cv_attribute_warn_unused" = yes ; then - AC_DEFINE(NS_WARN_UNUSED_RESULT, [__attribute__((warn_unused_result))]) -else - AC_DEFINE(NS_WARN_UNUSED_RESULT,) -fi - -if test "$ac_cv_attribute_noreturn" = yes ; then - AC_DEFINE(NS_NORETURN, [__attribute__((noreturn))]) -else - AC_DEFINE(NS_NORETURN,) -fi - -dnl We can't run TRY_COMPILE tests on Windows, so hard-code some -dnl features that Windows actually does support. - -if test -n "$SKIP_COMPILER_CHECKS"; then - dnl Windows has malloc.h - AC_DEFINE(MALLOC_H, []) - AC_DEFINE(HAVE_FORCEINLINE) - AC_DEFINE(HAVE_LOCALECONV) -fi # SKIP_COMPILER_CHECKS dnl ======================================================== dnl = @@ -4534,7 +4056,6 @@ if test "$_USE_SYSTEM_NSPR" && (test "$NSPR_CFLAGS" -o "$NSPR_LIBS"); then See 'configure --help'.]) fi -dnl Top-level Mozilla switched to requiring NSPR 4.8.6 (bug 560582), but we don't need it in JS. if test -n "$_USE_SYSTEM_NSPR"; then MOZ_NATIVE_NSPR= AM_PATH_NSPR(4.7.0, [MOZ_NATIVE_NSPR=1]) @@ -4557,6 +4078,18 @@ if test -n "$MOZ_NATIVE_NSPR"; then CFLAGS=$_SAVE_CFLAGS fi +dnl ======================================================== +dnl Use ARM userspace kernel helpers; tell NSPR to enable +dnl their usage and use them in spidermonkey. +dnl ======================================================== +MOZ_ARG_WITH_BOOL(arm-kuser, +[ --with-arm-kuser Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)], + USE_ARM_KUSER=1, + USE_ARM_KUSER=) +if test -n "$USE_ARM_KUSER"; then + AC_DEFINE(USE_ARM_KUSER) +fi + dnl ======================================================== dnl = dnl = Application @@ -4568,27 +4101,6 @@ MOZ_ARG_HEADER(Application) BUILD_STATIC_LIBS= ENABLE_TESTS=1 -MOZ_THUMB2= -USE_ARM_KUSER= - -case "${target}" in - arm-android-eabi) - USE_ARM_KUSER=1 - MOZ_THUMB2=1 - ;; -esac - -dnl ======================================================== -dnl Use ARM userspace kernel helpers; tell NSPR to enable -dnl their usage and use them in spidermonkey. -dnl ======================================================== -MOZ_ARG_WITH_BOOL(arm-kuser, -[ --with-arm-kuser Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)], - USE_ARM_KUSER=1,) -if test -n "$USE_ARM_KUSER"; then - AC_DEFINE(USE_ARM_KUSER) -fi - dnl ======================================================== dnl = dnl = Components & Features @@ -4596,6 +4108,33 @@ dnl = dnl ======================================================== MOZ_ARG_HEADER(Components and Features) +dnl ======================================================== + +dnl ======================================================== +dnl = Enable building the Thumb2 instruction set +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(thumb2, + [ --enable-thumb2 Enable Thumb2 instruction set], + MOZ_THUMB2=1,) + +if test -n "$MOZ_THUMB2"; then + case "$target_cpu" in + arm*) + if test "$GNU_CC"; then + AC_DEFINE(MOZ_THUMB2) + CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" + CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" + ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" + else + AC_MSG_ERROR([--enable-thumb2 is not supported for non-GNU toolchains]) + fi + ;; + *) + AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures]) + ;; + esac +fi + dnl ======================================================== dnl = Localization dnl ======================================================== @@ -4620,34 +4159,6 @@ dnl = dnl ======================================================== MOZ_ARG_HEADER(Individual module options) -dnl ======================================================== -dnl = Enable building the Thumb2 instruction set -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(thumb2, - [ --enable-thumb2 Enable Thumb2 instruction set], - MOZ_THUMB2=1, - MOZ_THUMB2=) - -if test -n "$MOZ_THUMB2"; then - case "$target_cpu" in - arm*) - if test "$GNU_CC"; then - AC_DEFINE(MOZ_THUMB2) - CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" - CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" - ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" - else - AC_MSG_ERROR([--enable-thumb2 is not supported for non-GNU toolchains]) - fi - ;; - *) - AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures]) - ;; - esac -fi - -AC_SUBST(MOZ_THUMB2) - dnl ======================================================== dnl = dnl = Debugging Options @@ -4659,13 +4170,33 @@ dnl ======================================================== dnl = Disable building with debug info. dnl = Debugging is OFF by default dnl ======================================================== -if test -z "$MOZ_DEBUG_FLAGS"; then - MOZ_DEBUG_FLAGS="-g" +if test -z "$MOZ_DEBUG_FLAGS" +then + case "$target" in + *-irix*) + if test "$GNU_CC"; then + GCC_VERSION=`$CC -v 2>&1 | awk '/version/ { print $3 }'` + case "$GCC_VERSION" in + 2.95.*) + MOZ_DEBUG_FLAGS="" + ;; + *) + MOZ_DEBUG_FLAGS="-g" + ;; + esac + else + MOZ_DEBUG_FLAGS="-g" + fi + ;; + *) + MOZ_DEBUG_FLAGS="-g" + ;; + esac fi MOZ_ARG_ENABLE_STRING(debug, [ --enable-debug[=DBG] Enable building with developer debug info - (using compiler flags DBG)], + (Using compiler flags DBG)], [ if test "$enableval" != "no"; then MOZ_DEBUG=1 if test -n "$enableval" -a "$enableval" != "yes"; then @@ -4680,12 +4211,13 @@ MOZ_ARG_ENABLE_STRING(debug, MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG -DTRACING" MOZ_ARG_WITH_STRING(debug-label, [ --with-debug-label=LABELS - Define DEBUG_ for each comma-separated - value given.], + Enabled the use of DEBUG_label ifdefs + (comma separated)], [ for option in `echo $withval | sed 's/,/ /g'`; do MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${option}" done]) + MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED" if test -n "$MOZ_DEBUG"; then @@ -4779,17 +4311,6 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then fi dnl ======================================================== -dnl = Disable any treating of compile warnings as errors -dnl ======================================================== -MOZ_ARG_DISABLE_BOOL(warnings-as-errors, -[ --disable-warnings-as-errors - Disable treating of warnings as errors], - MOZ_DISABLE_WARNINGS_AS_ERRORS=1, - MOZ_DISABLE_WARNINGS_AS_ERRORS= ) -if test "$MOZ_DISABLE_WARNINGS_AS_ERRORS"; then - WARNINGS_AS_ERRORS='' -fi - dnl = Enable trace malloc dnl ======================================================== NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC} @@ -4867,14 +4388,7 @@ if test "$MOZ_MEMORY"; then AC_DEFINE(MOZ_MEMORY_WINDOWS) # the interesting bits will get passed down in MOZ_MEMORY_LDFLAGS ;; - *-*wince) - AC_DEFINE(MOZ_MEMORY_WINCE) - AC_DEFINE(MOZ_MEMORY_WINDOWS) - if test -z "$WINCE_WINDOWS_MOBILE"; then - AC_DEFINE(MOZ_MEMORY_WINCE6) - fi - ;; - *-*winmo) + *-*wince|*-*winmo) AC_DEFINE(MOZ_MEMORY_WINCE) AC_DEFINE(MOZ_MEMORY_WINDOWS) ;; @@ -4886,13 +4400,6 @@ if test "$MOZ_MEMORY"; then AC_MSG_ERROR([--enable-jemalloc not supported on ${target}]) ;; esac - - if test "$OS_ARCH" != "Darwin"; then - dnl NB: this must be kept in sync with jemalloc.h - AC_DEFINE(HAVE_JEMALLOC_VALLOC) - AC_DEFINE(HAVE_JEMALLOC_POSIX_MEMALIGN) - AC_DEFINE(HAVE_JEMALLOC_MEMALIGN) - fi fi AC_SUBST(MOZ_MEMORY) AC_SUBST(MOZ_MEMORY_LDFLAGS) @@ -4919,6 +4426,22 @@ MOZ_ARG_WITH_STRING(wrap-malloc, [ --with-wrap-malloc=DIR Location of malloc wrapper library], WRAP_MALLOC_LIB=$withval) +dnl ======================================================== +dnl = Build jsctypes if it's enabled +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(ctypes, +[ --enable-ctypes Enable js-ctypes (default=no)], + JS_HAS_CTYPES=1, + JS_HAS_CTYPES= ) +AC_SUBST(JS_HAS_CTYPES) +if test "$JS_HAS_CTYPES"; then + if test "$_MSC_VER" -a -z $AS; then + # Error out if we're on MSVC and MASM is unavailable. + AC_MSG_ERROR([No suitable assembler found. An assembler is required to build js-ctypes. If you are building with MS Visual Studio 8 Express, you may download the MASM 8.0 package, upgrade to Visual Studio 9 Express, or install the Vista SDK.]) + fi + AC_DEFINE(JS_HAS_CTYPES) +fi + dnl ======================================================== dnl = Use JS Call tracing dnl ======================================================== @@ -5017,7 +4540,7 @@ if test -n "$MOZ_VTUNE"; then fi dnl ======================================================== -dnl Zealous JavaScript GC +dnl Zealous GC dnl ======================================================== MOZ_ARG_ENABLE_BOOL(gczeal, [ --enable-gczeal Enable zealous GCing], @@ -5036,11 +4559,13 @@ MOZ_ARG_WITH_STRING(ccache, CCACHE=$withval, CCACHE="no") if test "$CCACHE" != "no"; then - if test -z "$CCACHE" -o "$CCACHE" = "yes"; then - CCACHE= - else - if test ! -e "$CCACHE"; then - AC_MSG_ERROR([$CCACHE not found]) + if test -n "$CCACHE"; then + if test "$CCACHE" = "yes"; then + CCACHE= + else + if test ! -e "$CCACHE"; then + AC_MSG_ERROR([$CCACHE not found]) + fi fi fi MOZ_PATH_PROGS(CCACHE, $CCACHE ccache) @@ -5551,21 +5076,6 @@ dnl ======================================================== MOZ_ARG_HEADER(Standalone module options (Not for building Mozilla)) dnl ======================================================== -dnl = Build jsctypes if it's enabled -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(ctypes, -[ --enable-ctypes Enable js-ctypes (default=no)], - JS_HAS_CTYPES=1, - JS_HAS_CTYPES= ) -AC_SUBST(JS_HAS_CTYPES) -if test "$JS_HAS_CTYPES"; then - if test "$_MSC_VER" -a -z $AS; then - # Error out if we're on MSVC and MASM is unavailable. - AC_MSG_ERROR([No suitable assembler found. An assembler is required to build js-ctypes. If you are building with MS Visual Studio 8 Express, you may download the MASM 8.0 package, upgrade to Visual Studio 9 Express, or install the Vista SDK.]) - fi - AC_DEFINE(JS_HAS_CTYPES) -fi - if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi @@ -5640,6 +5150,8 @@ AC_SUBST(MOZ_OS2_USE_DECLSPEC) AC_SUBST(MOZ_POST_DSO_LIB_COMMAND) AC_SUBST(MOZ_POST_PROGRAM_COMMAND) AC_SUBST(MOZ_TIMELINE) +AC_SUBST(WINCE) +AC_SUBST(WINCE_WINDOWS_MOBILE) AC_SUBST(MOZ_APP_NAME) AC_SUBST(MOZ_APP_DISPLAYNAME) @@ -5661,10 +5173,6 @@ AC_SUBST(AS_PERL) AC_SUBST(WIN32_REDIST_DIR) AC_SUBST(PYTHON) -AC_SUBST(WINCE) -AC_SUBST(WINCE_SDK_DIR) -AC_SUBST(WINCE_WINDOWS_MOBILE) - dnl Echo the CFLAGS to remove extra whitespace. CFLAGS=`echo \ $_WARNINGS_CFLAGS \ @@ -5757,20 +5265,6 @@ if test "$USING_HCC"; then AC_SUBST(CXX) fi -AC_MSG_CHECKING([for posix_fallocate]) -AC_TRY_LINK([#define _XOPEN_SOURCE 600 - #include ], - [posix_fallocate(0, 0, 0);], - [ac_cv___posix_fallocate=true], - [ac_cv___posix_fallocate=false]) - -if test "$ac_cv___posix_fallocate" = true ; then - AC_DEFINE(HAVE_POSIX_FALLOCATE) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi - dnl Check for missing components if test "$COMPILE_ENVIRONMENT"; then if test "$MOZ_X11"; then From 4f2e656d403e4e6d4b21f7ae6b437d360690217e Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 29 Oct 2010 15:03:44 -0700 Subject: [PATCH 045/263] Disallow sending JS functions to a different thread (608142, r=jst). --- js/src/xpconnect/src/xpc.msg | 1 + js/src/xpconnect/src/xpcprivate.h | 1 + js/src/xpconnect/src/xpcwrappedjs.cpp | 7 ++- js/src/xpconnect/tests/unit/test_bug608142.js | 51 +++++++++++++++++++ xpcom/base/nsError.h | 4 ++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 js/src/xpconnect/tests/unit/test_bug608142.js diff --git a/js/src/xpconnect/src/xpc.msg b/js/src/xpconnect/src/xpc.msg index 489e4c39d1d..784fb403933 100644 --- a/js/src/xpconnect/src/xpc.msg +++ b/js/src/xpconnect/src/xpc.msg @@ -215,6 +215,7 @@ XPC_MSG_DEF(NS_ERROR_CACHE_IN_USE , "Cache is currently in use XPC_MSG_DEF(NS_ERROR_DOCUMENT_NOT_CACHED , "Document does not exist in cache") XPC_MSG_DEF(NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS , "The requested number of domain levels exceeds those present in the host string") XPC_MSG_DEF(NS_ERROR_HOST_IS_IP_ADDRESS , "The host string is an IP address") +XPC_MSG_DEF(NS_ERROR_NOT_SAME_THREAD , "Can't access a wrapped JS object from a different thread") /* storage related codes (from mozStorage.h) */ XPC_MSG_DEF(NS_ERROR_STORAGE_BUSY , "SQLite database connection is busy") diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e749c7de227..24c17bad9cc 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,6 +3071,7 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root + nsCOMPtr mThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index 9eff0818e45..abdc7b43b75 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -43,6 +43,7 @@ #include "xpcprivate.h" #include "nsAtomicRefcnt.h" +#include "nsThreadUtils.h" // NOTE: much of the fancy footwork is done in xpcstubs.cpp @@ -290,6 +291,7 @@ nsXPCWrappedJS::GetJSObject(JSObject** aJSObj) { NS_PRECONDITION(aJSObj, "bad param"); NS_PRECONDITION(mJSObj, "bad wrapper"); + if(!(*aJSObj = mJSObj)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -433,7 +435,8 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mClass(aClass), mRoot(root ? root : this), mNext(nsnull), - mOuter(root ? nsnull : aOuter) + mOuter(root ? nsnull : aOuter), + mThread(do_GetCurrentThread()) { #ifdef DEBUG_stats_jband static int count = 0; @@ -568,6 +571,8 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; + if (NS_GetCurrentThread() != mThread) + return NS_ERROR_NOT_SAME_THREAD; return GetClass()->CallMethod(this, methodIndex, info, params); } diff --git a/js/src/xpconnect/tests/unit/test_bug608142.js b/js/src/xpconnect/tests/unit/test_bug608142.js new file mode 100644 index 00000000000..ab1cd93d120 --- /dev/null +++ b/js/src/xpconnect/tests/unit/test_bug608142.js @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 sts=4 et + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Necko Test Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +function run_test() { + var tm = Components.classes["@mozilla.org/thread-manager;1"].getService(); + var thr = tm.newThread(0); + + thr.dispatch({ + run: function() { + do_check_true(false); + } + }, Components.interfaces.nsIThread.DISPATCH_NORMAL); + + thr.shutdown(); +} + diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index d79e0bfafe9..b1f39e208ca 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -307,6 +307,10 @@ inline int NS_SUCCEEDED(nsresult _nsresult) { #define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) +/* Result codes used by nsIThreadManager */ + +#define NS_ERROR_NOT_SAME_THREAD NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 4) + /** * Various operations are not permitted during XPCOM shutdown and will fail * with this exception. From 837f283c028838bcc1630d0df4a126e4406d9bfa Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 29 Oct 2010 15:03:44 -0700 Subject: [PATCH 046/263] Disallow sending JS functions to a different thread (608142, r=jst). a=beta7+ --- js/src/xpconnect/src/xpc.msg | 1 + js/src/xpconnect/src/xpcprivate.h | 1 + js/src/xpconnect/src/xpcwrappedjs.cpp | 7 ++- js/src/xpconnect/tests/unit/test_bug608142.js | 51 +++++++++++++++++++ xpcom/base/nsError.h | 4 ++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 js/src/xpconnect/tests/unit/test_bug608142.js diff --git a/js/src/xpconnect/src/xpc.msg b/js/src/xpconnect/src/xpc.msg index 489e4c39d1d..784fb403933 100644 --- a/js/src/xpconnect/src/xpc.msg +++ b/js/src/xpconnect/src/xpc.msg @@ -215,6 +215,7 @@ XPC_MSG_DEF(NS_ERROR_CACHE_IN_USE , "Cache is currently in use XPC_MSG_DEF(NS_ERROR_DOCUMENT_NOT_CACHED , "Document does not exist in cache") XPC_MSG_DEF(NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS , "The requested number of domain levels exceeds those present in the host string") XPC_MSG_DEF(NS_ERROR_HOST_IS_IP_ADDRESS , "The host string is an IP address") +XPC_MSG_DEF(NS_ERROR_NOT_SAME_THREAD , "Can't access a wrapped JS object from a different thread") /* storage related codes (from mozStorage.h) */ XPC_MSG_DEF(NS_ERROR_STORAGE_BUSY , "SQLite database connection is busy") diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index bfe595244b1..06ff14a3e13 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,6 +3071,7 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root + nsCOMPtr mThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index 9eff0818e45..abdc7b43b75 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -43,6 +43,7 @@ #include "xpcprivate.h" #include "nsAtomicRefcnt.h" +#include "nsThreadUtils.h" // NOTE: much of the fancy footwork is done in xpcstubs.cpp @@ -290,6 +291,7 @@ nsXPCWrappedJS::GetJSObject(JSObject** aJSObj) { NS_PRECONDITION(aJSObj, "bad param"); NS_PRECONDITION(mJSObj, "bad wrapper"); + if(!(*aJSObj = mJSObj)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -433,7 +435,8 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mClass(aClass), mRoot(root ? root : this), mNext(nsnull), - mOuter(root ? nsnull : aOuter) + mOuter(root ? nsnull : aOuter), + mThread(do_GetCurrentThread()) { #ifdef DEBUG_stats_jband static int count = 0; @@ -568,6 +571,8 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; + if (NS_GetCurrentThread() != mThread) + return NS_ERROR_NOT_SAME_THREAD; return GetClass()->CallMethod(this, methodIndex, info, params); } diff --git a/js/src/xpconnect/tests/unit/test_bug608142.js b/js/src/xpconnect/tests/unit/test_bug608142.js new file mode 100644 index 00000000000..ab1cd93d120 --- /dev/null +++ b/js/src/xpconnect/tests/unit/test_bug608142.js @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 sts=4 et + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Necko Test Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +function run_test() { + var tm = Components.classes["@mozilla.org/thread-manager;1"].getService(); + var thr = tm.newThread(0); + + thr.dispatch({ + run: function() { + do_check_true(false); + } + }, Components.interfaces.nsIThread.DISPATCH_NORMAL); + + thr.shutdown(); +} + diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index d79e0bfafe9..b1f39e208ca 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -307,6 +307,10 @@ inline int NS_SUCCEEDED(nsresult _nsresult) { #define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) +/* Result codes used by nsIThreadManager */ + +#define NS_ERROR_NOT_SAME_THREAD NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 4) + /** * Various operations are not permitted during XPCOM shutdown and will fail * with this exception. From 19cc79ccf398f1ee201fdc0d529be05606202878 Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Fri, 29 Oct 2010 18:35:07 -0400 Subject: [PATCH 047/263] Bug 595243 - Expose debugMode to JSD. r=gal --- dom/base/nsJSEnvironment.cpp | 4 -- js/jsd/idl/jsdIDebuggerService.idl | 41 ++++++++++++++++---- js/jsd/jsd_scpt.c | 7 +--- js/jsd/jsd_xpc.cpp | 55 +++++++++++++++++++++------ js/jsd/jsd_xpc.h | 2 +- js/src/jsapi.cpp | 3 ++ js/src/jscntxt.h | 5 +++ js/src/jscompartment.cpp | 2 +- js/src/jsdbgapi.cpp | 6 +++ js/src/jsdbgapi.h | 7 ++++ js/src/xpconnect/idl/nsIXPConnect.idl | 11 +++++- js/src/xpconnect/src/nsXPConnect.cpp | 44 +++++++++++++++++++++ js/src/xpconnect/src/xpcprivate.h | 3 ++ 13 files changed, 157 insertions(+), 33 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 84ccd622096..96c689ec994 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -993,10 +993,6 @@ nsJSContext::DOMOperationCallback(JSContext *cx) if (NS_SUCCEEDED(rv)) { jsds->GetDebuggerHook(getter_AddRefs(jsdHook)); jsds->GetIsOn(&jsds_IsOn); - if (jsds_IsOn) { // If this is not true, the next call would start jsd... - rv = jsds->OnForRuntime(cx->runtime); - jsds_IsOn = NS_SUCCEEDED(rv); - } } // If there is a debug handler registered for this runtime AND diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index ea250cf525f..c9c2c3b03f9 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -72,12 +72,13 @@ interface jsdIScript; interface jsdIValue; interface jsdIObject; interface jsdIProperty; +interface jsdIActivationCallback; /** * Debugger service. It's not a good idea to have more than one active client of * the debugger service. */ -[scriptable, uuid(dc0a24db-f8ac-4889-80d0-6016545a2dda)] +[scriptable, uuid(01769775-c77c-47f9-8848-0abbab404215)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -216,19 +217,34 @@ interface jsdIDebuggerService : nsISupports */ readonly attribute boolean isOn; + + /** + * Synchronous activation of the debugger is no longer supported, + * and will throw an exception. + */ + void on (); + /** * Turn on the debugger. This function should only be called from JavaScript * code. The debugger will be enabled on the runtime the call is made on, * as determined by nsIXPCNativeCallContext. - */ - void on (); - /** - * Turn on the debugger for a given runtime. * - * @param rt The runtime you want to debug. You cannot turn the debugger - * on for multiple runtimes. + * The debugger will be activated asynchronously, because there can be no JS + * on the stack when code is to be re-compiled for debug mode. */ - [noscript] void onForRuntime (in JSRuntime rt); + void asyncOn (in jsdIActivationCallback callback); + + /** + * Called by nsIXPConnect after it's had a chance to recompile for + * debug mode. + */ + [noscript] void activateDebugger(in JSRuntime rt); + + /** + * Recompile all active scripts in the runtime for debugMode. + */ + [noscript] void recompileForDebugMode(in JSRuntime rt, in PRBool mode); + /** * Turn the debugger off. This will invalidate all of your jsdIEphemeral * derived objects, and clear all of your breakpoints. In theory you @@ -457,6 +473,15 @@ interface jsdIFilter : nsISupports attribute unsigned long endLine; }; +/** + * Notify client code that debugMode has been activated. + */ +[scriptable, uuid(6da7f5fb-3a84-4abe-9e23-8b2045960732)] +interface jsdIActivationCallback : nsISupports +{ + void onDebuggerActivated (); +}; + /** * Pass an instance of one of these to jsdIDebuggerService::enterNestedEventLoop. */ diff --git a/js/jsd/jsd_scpt.c b/js/jsd/jsd_scpt.c index 01e96c0668f..37e08b0aa2d 100644 --- a/js/jsd/jsd_scpt.c +++ b/js/jsd/jsd_scpt.c @@ -585,11 +585,6 @@ jsd_NewScriptHookProc( if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; -#ifdef LIVEWIRE - if( 1 == lineno ) - jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE ); -#endif - JSD_LOCK_SCRIPTS(jsdc); jsdscript = _newJSDScript(jsdc, cx, script, fun); JSD_UNLOCK_SCRIPTS(jsdc); @@ -611,7 +606,7 @@ jsd_NewScriptHookProc( if( hook ) hook(jsdc, jsdscript, JS_TRUE, hookData); -} +} void jsd_DestroyScriptHookProc( diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index d044f1eafde..dfba4dbf557 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2396,6 +2396,12 @@ jsdService::GetIsOn (PRBool *_rval) NS_IMETHODIMP jsdService::On (void) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +jsdService::AsyncOn (jsdIActivationCallback *activationCallback) { nsresult rv; @@ -2410,18 +2416,32 @@ jsdService::On (void) JSContext *cx; rv = cc->GetJSContext (&cx); if (NS_FAILED(rv)) return rv; + + mActivationCallback = activationCallback; - return OnForRuntime(JS_GetRuntime (cx)); - + return xpc->SetDebugModeWhenPossible(PR_TRUE); } NS_IMETHODIMP -jsdService::OnForRuntime (JSRuntime *rt) +jsdService::RecompileForDebugMode (JSRuntime *rt, JSBool mode) { + JSContext *cx; + JSContext *iter = NULL; + + while ((cx = JS_ContextIterator (rt, &iter))) { + JS_SetDebugMode(cx, mode); + } + + return NS_OK; +} + +NS_IMETHODIMP +jsdService::ActivateDebugger (JSRuntime *rt) { if (mOn) return (rt == mRuntime) ? NS_OK : NS_ERROR_ALREADY_INITIALIZED; mRuntime = rt; + RecompileForDebugMode(rt, JS_TRUE); if (gLastGCProc == jsds_GCCallbackProc) /* condition indicates that the callback proc has not been set yet */ @@ -2471,6 +2491,10 @@ jsdService::OnForRuntime (JSRuntime *rt) #ifdef DEBUG printf ("+++ JavaScript debugging hooks installed.\n"); #endif + + if (mActivationCallback) + return mActivationCallback->OnDebuggerActivated(); + return NS_OK; } @@ -2521,6 +2545,13 @@ jsdService::Off (void) printf ("+++ JavaScript debugging hooks removed.\n"); #endif + nsresult rv; + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); + if (NS_FAILED(rv)) + return rv; + + xpc->SetDebugModeWhenPossible(PR_FALSE); + return NS_OK; } @@ -2969,7 +3000,7 @@ jsdService::SetErrorHook (jsdIErrorHook *aHook) mErrorHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3013,7 +3044,7 @@ jsdService::SetDebugHook (jsdIExecutionHook *aHook) mDebugHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3041,7 +3072,7 @@ jsdService::SetDebuggerHook (jsdIExecutionHook *aHook) mDebuggerHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3069,7 +3100,7 @@ jsdService::SetInterruptHook (jsdIExecutionHook *aHook) mInterruptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3097,7 +3128,7 @@ jsdService::SetScriptHook (jsdIScriptHook *aHook) mScriptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3125,7 +3156,7 @@ jsdService::SetThrowHook (jsdIExecutionHook *aHook) mThrowHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3153,7 +3184,7 @@ jsdService::SetTopLevelHook (jsdICallHook *aHook) mTopLevelHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3181,7 +3212,7 @@ jsdService::SetFunctionHook (jsdICallHook *aHook) mFunctionHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3274,7 +3305,7 @@ jsdASObserver::Observe (nsISupports *aSubject, const char *aTopic, if (NS_FAILED(rv)) return rv; - rv = jsds->OnForRuntime(rt); + rv = jsds->ActivateDebugger(rt); if (NS_FAILED(rv)) return rv; diff --git a/js/jsd/jsd_xpc.h b/js/jsd/jsd_xpc.h index 92f08799242..06e5c2aeab8 100644 --- a/js/jsd/jsd_xpc.h +++ b/js/jsd/jsd_xpc.h @@ -305,7 +305,7 @@ class jsdService : public jsdIDebuggerService nsCOMPtr mThrowHook; nsCOMPtr mTopLevelHook; nsCOMPtr mFunctionHook; - + nsCOMPtr mActivationCallback; }; #endif /* JSDSERVICE_H___ */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3d4807861e0..07fa8728ee0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -653,6 +653,9 @@ JSRuntime::init(uint32 maxbytes) if (!debuggerLock) return false; #endif + + debugMode = JS_FALSE; + return propertyTree.init() && js_InitThreads(this); } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 8a90708ea7c..f598696023c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1416,6 +1416,11 @@ struct JSRuntime { /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */ JSDebugHooks globalDebugHooks; + /* + * Right now, we only support runtime-wide debugging. + */ + JSBool debugMode; + #ifdef JS_TRACER /* True if any debug hooks not supported by the JIT are enabled. */ bool debuggerInhibitsJIT() const { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d523ec261e4..70593387089 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -53,7 +53,7 @@ using namespace js; using namespace js::gc; JSCompartment::JSCompartment(JSRuntime *rt) - : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false), + : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(rt->debugMode), anynameObject(NULL), functionNamespaceObject(NULL) { JS_INIT_CLIST(&scripts); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 21e3bf5212a..05d03e5eab4 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -108,6 +108,12 @@ IsScriptLive(JSContext *cx, JSScript *script) } #endif +JS_PUBLIC_API(void) +JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug) +{ + rt->debugMode = debug; +} + JS_FRIEND_API(JSBool) js_SetDebugMode(JSContext *cx, JSBool debug) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index 7bc7a4aaa0a..7b16c5e7994 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -49,6 +49,13 @@ JS_BEGIN_EXTERN_C +/* + * Currently, we only support runtime-wide debugging. In the future, we should + * be able to support compartment-wide debugging. + */ +extern JS_PUBLIC_API(void) +JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug); + /* * Debug mode is a compartment-wide mode that enables a debugger to attach * to and interact with running methodjit-ed frames. In particular, it causes diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index eb44d356091..5a483ea2e7c 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)] +[uuid(c825b64b-d537-4e53-822e-547049aae9c9)] interface nsIXPConnect : nsISupports { %{ C++ @@ -827,4 +827,13 @@ interface nsIXPConnect : nsISupports */ [noscript,notxpcom] void getCaller(out JSContextPtr aJSContext, out JSObjectPtr aObject); + + /** + * When we place the browser in JS debug mode, there can't be any + * JS on the stack. This is because we currently activate debugMode + * on all scripts in the JSRuntime when the debugger is activated. + * This method will turn debug mode on or off when the context + * stack reaches zero length. + */ + [noscript] void setDebugModeWhenPossible(in PRBool mode); }; diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 1711f54c8d0..71ec35efbfa 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -61,6 +61,8 @@ #include "WrapperFactory.h" #include "AccessCheck.h" +#include "jsdIDebuggerService.h" + NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsIXPConnect, nsISupportsWeakReference, @@ -72,6 +74,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsXPConnect* nsXPConnect::gSelf = nsnull; JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE; PRUint32 nsXPConnect::gReportAllJSExceptions = 0; +JSBool nsXPConnect::gDebugMode = JS_FALSE; +JSBool nsXPConnect::gDesiredDebugMode = JS_FALSE; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) @@ -2407,6 +2411,30 @@ nsXPConnect::Peek(JSContext * *_retval) return data->GetJSContextStack()->Peek(_retval); } +void +nsXPConnect::CheckForDebugMode(JSRuntime *rt) { + if (gDebugMode != gDesiredDebugMode) { + nsresult rv; + const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1"; + nsCOMPtr jsds = do_GetService(jsdServiceCtrID, &rv); + if (NS_SUCCEEDED(rv)) { + if (gDesiredDebugMode == PR_FALSE) { + rv = jsds->RecompileForDebugMode(rt, PR_FALSE); + } else { + rv = jsds->ActivateDebugger(rt); + } + } + + if (NS_SUCCEEDED(rv)) { + JS_SetRuntimeDebugMode(rt, gDesiredDebugMode); + gDebugMode = gDesiredDebugMode; + } else { + // if the attempt failed, cancel the debugMode request + gDesiredDebugMode = gDebugMode; + } + } +} + /* JSContext Pop (); */ NS_IMETHODIMP nsXPConnect::Pop(JSContext * *_retval) @@ -2432,6 +2460,15 @@ nsXPConnect::Push(JSContext * cx) if(!data) return NS_ERROR_FAILURE; + PRInt32 count; + nsresult rv; + rv = data->GetJSContextStack()->GetCount(&count); + if (NS_FAILED(rv)) + return rv; + + if (count == 0) + CheckForDebugMode(mRuntime->GetJSRuntime()); + return data->GetJSContextStack()->Push(cx); } @@ -2539,6 +2576,13 @@ nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj) *aObj = ccx->GetFlattenedJSObject(); } +NS_IMETHODIMP +nsXPConnect::SetDebugModeWhenPossible(PRBool mode) +{ + gDesiredDebugMode = mode; + return NS_OK; +} + /* These are here to be callable from a debugger */ JS_BEGIN_EXTERN_C JS_EXPORT_API(void) DumpJSStack() diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e749c7de227..aaed5d80712 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -626,6 +626,9 @@ private: nsCOMPtr mBackstagePass; static PRUint32 gReportAllJSExceptions; + static JSBool gDebugMode; + static JSBool gDesiredDebugMode; + static inline void CheckForDebugMode(JSRuntime *rt); public: static nsIScriptSecurityManager *gScriptSecurityManager; From 03e709926a477bcf80fece3d4144c881642c7888 Mon Sep 17 00:00:00 2001 From: Johnny Stenback Date: Fri, 29 Oct 2010 17:33:29 -0700 Subject: [PATCH 048/263] Backed out changeset e7436725f170 due to crashes in mochitest and elsewhere. a=backout --- js/src/xpconnect/src/nsXPConnect.cpp | 4 +- js/src/xpconnect/src/xpcjsruntime.cpp | 69 ++++++------------- js/src/xpconnect/src/xpcprivate.h | 42 ++--------- .../xpconnect/src/xpcwrappednativescope.cpp | 15 ++-- 4 files changed, 32 insertions(+), 98 deletions(-) diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index fdaafc86ed3..1711f54c8d0 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -987,7 +987,7 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, xpc::PtrAndPrincipalHashKey *priv_key = new xpc::PtrAndPrincipalHashKey(ptr, uri); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(priv_key, wantXrays, NS_IsMainThread()); + new xpc::CompartmentPrivate(priv_key, wantXrays); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { @@ -1024,7 +1024,7 @@ xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, // threadsafety assumptions. nsCOMPtr principal(do_QueryInterface(ptr)); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(ptr, false, NS_IsMainThread()); + new xpc::CompartmentPrivate(ptr, false); if(!CreateNewCompartment(cx, clasp, principal, priv, global, compartment)) { diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 7cc68d555b4..e745826f8d0 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -408,45 +408,16 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); } -struct Closure -{ - JSContext *cx; - bool cycleCollectionEnabled; - nsCycleCollectionTraversalCallback *cb; -}; - -static void -CheckParticipatesInCycleCollection(PRUint32 aLangID, void *aThing, void *aClosure) -{ - Closure *closure = static_cast(aClosure); - - if(aLangID == nsIProgrammingLanguage::JAVASCRIPT && closure->cycleCollectionEnabled) - { - uint32 kind = js_GetGCThingTraceKind(aThing); - if(kind == JSTRACE_OBJECT) - closure->cycleCollectionEnabled = - xpc::ParticipatesInCycleCollection(closure->cx, static_cast(aThing)); - else if(kind == JSTRACE_STRING) - closure->cycleCollectionEnabled = - xpc::ParticipatesInCycleCollection(closure->cx, - static_cast(aThing)->asCell()); - } -} - static JSDHashOperator NoteJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { ObjectHolder* entry = reinterpret_cast(hdr); - Closure *closure = static_cast(arg); - closure->cycleCollectionEnabled = PR_TRUE; - entry->tracer->Trace(entry->holder, CheckParticipatesInCycleCollection, closure); - if(!closure->cycleCollectionEnabled) - return JS_DHASH_NEXT; - - closure->cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, - entry->tracer); + nsCycleCollectionTraversalCallback* cb = + static_cast(arg); + cb->NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, entry->holder, + entry->tracer); return JS_DHASH_NEXT; } @@ -476,8 +447,6 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, nsXPConnect::JSContextParticipant()); } - AutoLockJSGC lock(cx->runtime); - XPCWrappedNativeScope::SuspectAllWrappers(this, cx, cb); for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) @@ -485,22 +454,12 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx, for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) { - nsXPCWrappedJS *wrappedJS = static_cast(e); - JSObject *obj = wrappedJS->GetJSObject(); - - // Only suspect wrappedJSObjects that are in a compartment that - // participates in cycle collection. - if(!xpc::ParticipatesInCycleCollection(cx, obj)) - continue; - - cb.NoteXPCOMRoot(static_cast(wrappedJS)); + nsIXPConnectWrappedJS *wrappedJS = static_cast(e); + cb.NoteXPCOMRoot(wrappedJS); } if(mJSHolders.ops) - { - Closure closure = { cx, PR_TRUE, &cb }; - JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &closure); - } + JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &cb); } void @@ -822,6 +781,20 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status) return JS_TRUE; } +// Auto JS GC lock helper. +class AutoLockJSGC +{ +public: + AutoLockJSGC(JSRuntime* rt) : mJSRuntime(rt) { JS_LOCK_GC(mJSRuntime); } + ~AutoLockJSGC() { JS_UNLOCK_GC(mJSRuntime); } +private: + JSRuntime* mJSRuntime; + + // Disable copy or assignment semantics. + AutoLockJSGC(const AutoLockJSGC&); + void operator=(const AutoLockJSGC&); +}; + //static void XPCJSRuntime::WatchdogMain(void *arg) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 70120a08b96..e749c7de227 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -472,21 +472,6 @@ private: static void operator delete(void* /*memory*/) {} }; -/************************************************/ - -class AutoLockJSGC -{ -public: - AutoLockJSGC(JSRuntime* rt) : mJSRuntime(rt) { JS_LOCK_GC(mJSRuntime); } - ~AutoLockJSGC() { JS_UNLOCK_GC(mJSRuntime); } -private: - JSRuntime* mJSRuntime; - - // Disable copy or assignment semantics. - AutoLockJSGC(const AutoLockJSGC&); - void operator=(const AutoLockJSGC&); -}; - /*************************************************************************** **************************************************************************** * @@ -4523,18 +4508,16 @@ namespace xpc { struct CompartmentPrivate { - CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays, bool cycleCollectionEnabled) + CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays) : key(key), ptr(nsnull), - wantXrays(wantXrays), - cycleCollectionEnabled(cycleCollectionEnabled) + wantXrays(wantXrays) { } - CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled) + CompartmentPrivate(nsISupports *ptr, bool wantXrays) : key(nsnull), ptr(ptr), - wantXrays(wantXrays), - cycleCollectionEnabled(cycleCollectionEnabled) + wantXrays(wantXrays) { } @@ -4542,25 +4525,8 @@ struct CompartmentPrivate nsAutoPtr key; nsCOMPtr ptr; bool wantXrays; - bool cycleCollectionEnabled; }; -inline bool -CompartmentParticipatesInCycleCollection(JSContext *cx, JSCompartment *compartment) -{ - CompartmentPrivate *priv = - static_cast(JS_GetCompartmentPrivate(cx, compartment)); - NS_ASSERTION(priv, "This should never be null!"); - - return priv->cycleCollectionEnabled; -} - -inline bool -ParticipatesInCycleCollection(JSContext *cx, js::gc::Cell *cell) -{ - return CompartmentParticipatesInCycleCollection(cx, cell->compartment()); -} - } #ifdef XPC_IDISPATCH_SUPPORT diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index 541e3aadb62..b08cb6a40db 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -415,22 +415,17 @@ WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr, { NS_ASSERTION(NS_IsMainThread(), "Suspecting wrapped natives from non-main thread"); - - // Only suspect wrappedJSObjects that are in a compartment that - // participates in cycle collection. - JSObject* obj = wrapper->GetFlatJSObject(); - if(!xpc::ParticipatesInCycleCollection(closure->cx, obj)) - return JS_DHASH_NEXT; - - NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, obj), + NS_ASSERTION(!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject()), "WrappedNativeSuspecter attempting to touch dead object"); // Only record objects that might be part of a cycle as roots, unless // the callback wants all traces (a debug feature). - if(!(closure->cb.WantAllTraces()) && !nsXPConnect::IsGray(obj)) + if(!(closure->cb.WantAllTraces()) && + !nsXPConnect::IsGray(wrapper->GetFlatJSObject())) return JS_DHASH_NEXT; - closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, obj, + closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, + wrapper->GetFlatJSObject(), nsXPConnect::GetXPConnect()); } From ff603e73f43b8ce077203bdd101af8ddb563a1cd Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Fri, 29 Oct 2010 22:31:12 -0700 Subject: [PATCH 049/263] Backed out changeset 85feecf161fe (Career Limiting Move? ), seems to have turned mochitest-plain-4 orange. --- dom/base/nsJSEnvironment.cpp | 4 ++ js/jsd/idl/jsdIDebuggerService.idl | 41 ++++---------------- js/jsd/jsd_scpt.c | 7 +++- js/jsd/jsd_xpc.cpp | 55 ++++++--------------------- js/jsd/jsd_xpc.h | 2 +- js/src/jsapi.cpp | 3 -- js/src/jscntxt.h | 5 --- js/src/jscompartment.cpp | 2 +- js/src/jsdbgapi.cpp | 6 --- js/src/jsdbgapi.h | 7 ---- js/src/xpconnect/idl/nsIXPConnect.idl | 11 +----- js/src/xpconnect/src/nsXPConnect.cpp | 44 --------------------- js/src/xpconnect/src/xpcprivate.h | 3 -- 13 files changed, 33 insertions(+), 157 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 96c689ec994..84ccd622096 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -993,6 +993,10 @@ nsJSContext::DOMOperationCallback(JSContext *cx) if (NS_SUCCEEDED(rv)) { jsds->GetDebuggerHook(getter_AddRefs(jsdHook)); jsds->GetIsOn(&jsds_IsOn); + if (jsds_IsOn) { // If this is not true, the next call would start jsd... + rv = jsds->OnForRuntime(cx->runtime); + jsds_IsOn = NS_SUCCEEDED(rv); + } } // If there is a debug handler registered for this runtime AND diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index c9c2c3b03f9..ea250cf525f 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -72,13 +72,12 @@ interface jsdIScript; interface jsdIValue; interface jsdIObject; interface jsdIProperty; -interface jsdIActivationCallback; /** * Debugger service. It's not a good idea to have more than one active client of * the debugger service. */ -[scriptable, uuid(01769775-c77c-47f9-8848-0abbab404215)] +[scriptable, uuid(dc0a24db-f8ac-4889-80d0-6016545a2dda)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -217,34 +216,19 @@ interface jsdIDebuggerService : nsISupports */ readonly attribute boolean isOn; - - /** - * Synchronous activation of the debugger is no longer supported, - * and will throw an exception. - */ - void on (); - /** * Turn on the debugger. This function should only be called from JavaScript * code. The debugger will be enabled on the runtime the call is made on, * as determined by nsIXPCNativeCallContext. + */ + void on (); + /** + * Turn on the debugger for a given runtime. * - * The debugger will be activated asynchronously, because there can be no JS - * on the stack when code is to be re-compiled for debug mode. + * @param rt The runtime you want to debug. You cannot turn the debugger + * on for multiple runtimes. */ - void asyncOn (in jsdIActivationCallback callback); - - /** - * Called by nsIXPConnect after it's had a chance to recompile for - * debug mode. - */ - [noscript] void activateDebugger(in JSRuntime rt); - - /** - * Recompile all active scripts in the runtime for debugMode. - */ - [noscript] void recompileForDebugMode(in JSRuntime rt, in PRBool mode); - + [noscript] void onForRuntime (in JSRuntime rt); /** * Turn the debugger off. This will invalidate all of your jsdIEphemeral * derived objects, and clear all of your breakpoints. In theory you @@ -473,15 +457,6 @@ interface jsdIFilter : nsISupports attribute unsigned long endLine; }; -/** - * Notify client code that debugMode has been activated. - */ -[scriptable, uuid(6da7f5fb-3a84-4abe-9e23-8b2045960732)] -interface jsdIActivationCallback : nsISupports -{ - void onDebuggerActivated (); -}; - /** * Pass an instance of one of these to jsdIDebuggerService::enterNestedEventLoop. */ diff --git a/js/jsd/jsd_scpt.c b/js/jsd/jsd_scpt.c index 37e08b0aa2d..01e96c0668f 100644 --- a/js/jsd/jsd_scpt.c +++ b/js/jsd/jsd_scpt.c @@ -585,6 +585,11 @@ jsd_NewScriptHookProc( if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; +#ifdef LIVEWIRE + if( 1 == lineno ) + jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE ); +#endif + JSD_LOCK_SCRIPTS(jsdc); jsdscript = _newJSDScript(jsdc, cx, script, fun); JSD_UNLOCK_SCRIPTS(jsdc); @@ -606,7 +611,7 @@ jsd_NewScriptHookProc( if( hook ) hook(jsdc, jsdscript, JS_TRUE, hookData); -} +} void jsd_DestroyScriptHookProc( diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index dfba4dbf557..d044f1eafde 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2396,12 +2396,6 @@ jsdService::GetIsOn (PRBool *_rval) NS_IMETHODIMP jsdService::On (void) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -jsdService::AsyncOn (jsdIActivationCallback *activationCallback) { nsresult rv; @@ -2416,32 +2410,18 @@ jsdService::AsyncOn (jsdIActivationCallback *activationCallback) JSContext *cx; rv = cc->GetJSContext (&cx); if (NS_FAILED(rv)) return rv; - - mActivationCallback = activationCallback; - return xpc->SetDebugModeWhenPossible(PR_TRUE); + return OnForRuntime(JS_GetRuntime (cx)); + } NS_IMETHODIMP -jsdService::RecompileForDebugMode (JSRuntime *rt, JSBool mode) { - JSContext *cx; - JSContext *iter = NULL; - - while ((cx = JS_ContextIterator (rt, &iter))) { - JS_SetDebugMode(cx, mode); - } - - return NS_OK; -} - -NS_IMETHODIMP -jsdService::ActivateDebugger (JSRuntime *rt) +jsdService::OnForRuntime (JSRuntime *rt) { if (mOn) return (rt == mRuntime) ? NS_OK : NS_ERROR_ALREADY_INITIALIZED; mRuntime = rt; - RecompileForDebugMode(rt, JS_TRUE); if (gLastGCProc == jsds_GCCallbackProc) /* condition indicates that the callback proc has not been set yet */ @@ -2491,10 +2471,6 @@ jsdService::ActivateDebugger (JSRuntime *rt) #ifdef DEBUG printf ("+++ JavaScript debugging hooks installed.\n"); #endif - - if (mActivationCallback) - return mActivationCallback->OnDebuggerActivated(); - return NS_OK; } @@ -2545,13 +2521,6 @@ jsdService::Off (void) printf ("+++ JavaScript debugging hooks removed.\n"); #endif - nsresult rv; - nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); - if (NS_FAILED(rv)) - return rv; - - xpc->SetDebugModeWhenPossible(PR_FALSE); - return NS_OK; } @@ -3000,7 +2969,7 @@ jsdService::SetErrorHook (jsdIErrorHook *aHook) mErrorHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3044,7 +3013,7 @@ jsdService::SetDebugHook (jsdIExecutionHook *aHook) mDebugHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3072,7 +3041,7 @@ jsdService::SetDebuggerHook (jsdIExecutionHook *aHook) mDebuggerHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3100,7 +3069,7 @@ jsdService::SetInterruptHook (jsdIExecutionHook *aHook) mInterruptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3128,7 +3097,7 @@ jsdService::SetScriptHook (jsdIScriptHook *aHook) mScriptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3156,7 +3125,7 @@ jsdService::SetThrowHook (jsdIExecutionHook *aHook) mThrowHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3184,7 +3153,7 @@ jsdService::SetTopLevelHook (jsdICallHook *aHook) mTopLevelHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3212,7 +3181,7 @@ jsdService::SetFunctionHook (jsdICallHook *aHook) mFunctionHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * ActivateDebugger() method will do the rest when the coast is clear. + * OnForRuntime() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3305,7 +3274,7 @@ jsdASObserver::Observe (nsISupports *aSubject, const char *aTopic, if (NS_FAILED(rv)) return rv; - rv = jsds->ActivateDebugger(rt); + rv = jsds->OnForRuntime(rt); if (NS_FAILED(rv)) return rv; diff --git a/js/jsd/jsd_xpc.h b/js/jsd/jsd_xpc.h index 06e5c2aeab8..92f08799242 100644 --- a/js/jsd/jsd_xpc.h +++ b/js/jsd/jsd_xpc.h @@ -305,7 +305,7 @@ class jsdService : public jsdIDebuggerService nsCOMPtr mThrowHook; nsCOMPtr mTopLevelHook; nsCOMPtr mFunctionHook; - nsCOMPtr mActivationCallback; + }; #endif /* JSDSERVICE_H___ */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 07fa8728ee0..3d4807861e0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -653,9 +653,6 @@ JSRuntime::init(uint32 maxbytes) if (!debuggerLock) return false; #endif - - debugMode = JS_FALSE; - return propertyTree.init() && js_InitThreads(this); } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index f598696023c..8a90708ea7c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1416,11 +1416,6 @@ struct JSRuntime { /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */ JSDebugHooks globalDebugHooks; - /* - * Right now, we only support runtime-wide debugging. - */ - JSBool debugMode; - #ifdef JS_TRACER /* True if any debug hooks not supported by the JIT are enabled. */ bool debuggerInhibitsJIT() const { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 70593387089..d523ec261e4 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -53,7 +53,7 @@ using namespace js; using namespace js::gc; JSCompartment::JSCompartment(JSRuntime *rt) - : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(rt->debugMode), + : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false), anynameObject(NULL), functionNamespaceObject(NULL) { JS_INIT_CLIST(&scripts); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 05d03e5eab4..21e3bf5212a 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -108,12 +108,6 @@ IsScriptLive(JSContext *cx, JSScript *script) } #endif -JS_PUBLIC_API(void) -JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug) -{ - rt->debugMode = debug; -} - JS_FRIEND_API(JSBool) js_SetDebugMode(JSContext *cx, JSBool debug) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index 7b16c5e7994..7bc7a4aaa0a 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -49,13 +49,6 @@ JS_BEGIN_EXTERN_C -/* - * Currently, we only support runtime-wide debugging. In the future, we should - * be able to support compartment-wide debugging. - */ -extern JS_PUBLIC_API(void) -JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug); - /* * Debug mode is a compartment-wide mode that enables a debugger to attach * to and interact with running methodjit-ed frames. In particular, it causes diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index 5a483ea2e7c..eb44d356091 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(c825b64b-d537-4e53-822e-547049aae9c9)] +[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)] interface nsIXPConnect : nsISupports { %{ C++ @@ -827,13 +827,4 @@ interface nsIXPConnect : nsISupports */ [noscript,notxpcom] void getCaller(out JSContextPtr aJSContext, out JSObjectPtr aObject); - - /** - * When we place the browser in JS debug mode, there can't be any - * JS on the stack. This is because we currently activate debugMode - * on all scripts in the JSRuntime when the debugger is activated. - * This method will turn debug mode on or off when the context - * stack reaches zero length. - */ - [noscript] void setDebugModeWhenPossible(in PRBool mode); }; diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 71ec35efbfa..1711f54c8d0 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -61,8 +61,6 @@ #include "WrapperFactory.h" #include "AccessCheck.h" -#include "jsdIDebuggerService.h" - NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsIXPConnect, nsISupportsWeakReference, @@ -74,8 +72,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsXPConnect* nsXPConnect::gSelf = nsnull; JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE; PRUint32 nsXPConnect::gReportAllJSExceptions = 0; -JSBool nsXPConnect::gDebugMode = JS_FALSE; -JSBool nsXPConnect::gDesiredDebugMode = JS_FALSE; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) @@ -2411,30 +2407,6 @@ nsXPConnect::Peek(JSContext * *_retval) return data->GetJSContextStack()->Peek(_retval); } -void -nsXPConnect::CheckForDebugMode(JSRuntime *rt) { - if (gDebugMode != gDesiredDebugMode) { - nsresult rv; - const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1"; - nsCOMPtr jsds = do_GetService(jsdServiceCtrID, &rv); - if (NS_SUCCEEDED(rv)) { - if (gDesiredDebugMode == PR_FALSE) { - rv = jsds->RecompileForDebugMode(rt, PR_FALSE); - } else { - rv = jsds->ActivateDebugger(rt); - } - } - - if (NS_SUCCEEDED(rv)) { - JS_SetRuntimeDebugMode(rt, gDesiredDebugMode); - gDebugMode = gDesiredDebugMode; - } else { - // if the attempt failed, cancel the debugMode request - gDesiredDebugMode = gDebugMode; - } - } -} - /* JSContext Pop (); */ NS_IMETHODIMP nsXPConnect::Pop(JSContext * *_retval) @@ -2460,15 +2432,6 @@ nsXPConnect::Push(JSContext * cx) if(!data) return NS_ERROR_FAILURE; - PRInt32 count; - nsresult rv; - rv = data->GetJSContextStack()->GetCount(&count); - if (NS_FAILED(rv)) - return rv; - - if (count == 0) - CheckForDebugMode(mRuntime->GetJSRuntime()); - return data->GetJSContextStack()->Push(cx); } @@ -2576,13 +2539,6 @@ nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj) *aObj = ccx->GetFlattenedJSObject(); } -NS_IMETHODIMP -nsXPConnect::SetDebugModeWhenPossible(PRBool mode) -{ - gDesiredDebugMode = mode; - return NS_OK; -} - /* These are here to be callable from a debugger */ JS_BEGIN_EXTERN_C JS_EXPORT_API(void) DumpJSStack() diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index aaed5d80712..e749c7de227 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -626,9 +626,6 @@ private: nsCOMPtr mBackstagePass; static PRUint32 gReportAllJSExceptions; - static JSBool gDebugMode; - static JSBool gDesiredDebugMode; - static inline void CheckForDebugMode(JSRuntime *rt); public: static nsIScriptSecurityManager *gScriptSecurityManager; From 27484886a8789bdfa9b259307a08f8f74ba2225f Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Fri, 29 Oct 2010 22:39:19 -0700 Subject: [PATCH 050/263] Backed out changeset 71728ff7002c, seems to have turned mochitest-plain-2 orange. --- js/src/xpconnect/src/xpc.msg | 1 - js/src/xpconnect/src/xpcprivate.h | 1 - js/src/xpconnect/src/xpcwrappedjs.cpp | 7 +-- js/src/xpconnect/tests/unit/test_bug608142.js | 51 ------------------- xpcom/base/nsError.h | 4 -- 5 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 js/src/xpconnect/tests/unit/test_bug608142.js diff --git a/js/src/xpconnect/src/xpc.msg b/js/src/xpconnect/src/xpc.msg index 784fb403933..489e4c39d1d 100644 --- a/js/src/xpconnect/src/xpc.msg +++ b/js/src/xpconnect/src/xpc.msg @@ -215,7 +215,6 @@ XPC_MSG_DEF(NS_ERROR_CACHE_IN_USE , "Cache is currently in use XPC_MSG_DEF(NS_ERROR_DOCUMENT_NOT_CACHED , "Document does not exist in cache") XPC_MSG_DEF(NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS , "The requested number of domain levels exceeds those present in the host string") XPC_MSG_DEF(NS_ERROR_HOST_IS_IP_ADDRESS , "The host string is an IP address") -XPC_MSG_DEF(NS_ERROR_NOT_SAME_THREAD , "Can't access a wrapped JS object from a different thread") /* storage related codes (from mozStorage.h) */ XPC_MSG_DEF(NS_ERROR_STORAGE_BUSY , "SQLite database connection is busy") diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 24c17bad9cc..e749c7de227 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,7 +3071,6 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root - nsCOMPtr mThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index abdc7b43b75..9eff0818e45 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -43,7 +43,6 @@ #include "xpcprivate.h" #include "nsAtomicRefcnt.h" -#include "nsThreadUtils.h" // NOTE: much of the fancy footwork is done in xpcstubs.cpp @@ -291,7 +290,6 @@ nsXPCWrappedJS::GetJSObject(JSObject** aJSObj) { NS_PRECONDITION(aJSObj, "bad param"); NS_PRECONDITION(mJSObj, "bad wrapper"); - if(!(*aJSObj = mJSObj)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -435,8 +433,7 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mClass(aClass), mRoot(root ? root : this), mNext(nsnull), - mOuter(root ? nsnull : aOuter), - mThread(do_GetCurrentThread()) + mOuter(root ? nsnull : aOuter) { #ifdef DEBUG_stats_jband static int count = 0; @@ -571,8 +568,6 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; - if (NS_GetCurrentThread() != mThread) - return NS_ERROR_NOT_SAME_THREAD; return GetClass()->CallMethod(this, methodIndex, info, params); } diff --git a/js/src/xpconnect/tests/unit/test_bug608142.js b/js/src/xpconnect/tests/unit/test_bug608142.js deleted file mode 100644 index ab1cd93d120..00000000000 --- a/js/src/xpconnect/tests/unit/test_bug608142.js +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 sts=4 et - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Necko Test Code. - * - * The Initial Developer of the Original Code is the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -function run_test() { - var tm = Components.classes["@mozilla.org/thread-manager;1"].getService(); - var thr = tm.newThread(0); - - thr.dispatch({ - run: function() { - do_check_true(false); - } - }, Components.interfaces.nsIThread.DISPATCH_NORMAL); - - thr.shutdown(); -} - diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index b1f39e208ca..d79e0bfafe9 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -307,10 +307,6 @@ inline int NS_SUCCEEDED(nsresult _nsresult) { #define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) -/* Result codes used by nsIThreadManager */ - -#define NS_ERROR_NOT_SAME_THREAD NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 4) - /** * Various operations are not permitted during XPCOM shutdown and will fail * with this exception. From 682ce67f2d353025d7574e025547ae255595a13f Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sat, 30 Oct 2010 06:01:25 -0700 Subject: [PATCH 051/263] Re-land bug 608142. --- js/src/xpconnect/src/xpc.msg | 1 + js/src/xpconnect/src/xpcprivate.h | 1 + js/src/xpconnect/src/xpcwrappedjs.cpp | 7 ++- js/src/xpconnect/tests/unit/test_bug608142.js | 51 +++++++++++++++++++ xpcom/base/nsError.h | 4 ++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 js/src/xpconnect/tests/unit/test_bug608142.js diff --git a/js/src/xpconnect/src/xpc.msg b/js/src/xpconnect/src/xpc.msg index 489e4c39d1d..784fb403933 100644 --- a/js/src/xpconnect/src/xpc.msg +++ b/js/src/xpconnect/src/xpc.msg @@ -215,6 +215,7 @@ XPC_MSG_DEF(NS_ERROR_CACHE_IN_USE , "Cache is currently in use XPC_MSG_DEF(NS_ERROR_DOCUMENT_NOT_CACHED , "Document does not exist in cache") XPC_MSG_DEF(NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS , "The requested number of domain levels exceeds those present in the host string") XPC_MSG_DEF(NS_ERROR_HOST_IS_IP_ADDRESS , "The host string is an IP address") +XPC_MSG_DEF(NS_ERROR_NOT_SAME_THREAD , "Can't access a wrapped JS object from a different thread") /* storage related codes (from mozStorage.h) */ XPC_MSG_DEF(NS_ERROR_STORAGE_BUSY , "SQLite database connection is busy") diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index e749c7de227..24c17bad9cc 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,6 +3071,7 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root + nsCOMPtr mThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index 9eff0818e45..abdc7b43b75 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -43,6 +43,7 @@ #include "xpcprivate.h" #include "nsAtomicRefcnt.h" +#include "nsThreadUtils.h" // NOTE: much of the fancy footwork is done in xpcstubs.cpp @@ -290,6 +291,7 @@ nsXPCWrappedJS::GetJSObject(JSObject** aJSObj) { NS_PRECONDITION(aJSObj, "bad param"); NS_PRECONDITION(mJSObj, "bad wrapper"); + if(!(*aJSObj = mJSObj)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -433,7 +435,8 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mClass(aClass), mRoot(root ? root : this), mNext(nsnull), - mOuter(root ? nsnull : aOuter) + mOuter(root ? nsnull : aOuter), + mThread(do_GetCurrentThread()) { #ifdef DEBUG_stats_jband static int count = 0; @@ -568,6 +571,8 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; + if (NS_GetCurrentThread() != mThread) + return NS_ERROR_NOT_SAME_THREAD; return GetClass()->CallMethod(this, methodIndex, info, params); } diff --git a/js/src/xpconnect/tests/unit/test_bug608142.js b/js/src/xpconnect/tests/unit/test_bug608142.js new file mode 100644 index 00000000000..ab1cd93d120 --- /dev/null +++ b/js/src/xpconnect/tests/unit/test_bug608142.js @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 sts=4 et + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Necko Test Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +function run_test() { + var tm = Components.classes["@mozilla.org/thread-manager;1"].getService(); + var thr = tm.newThread(0); + + thr.dispatch({ + run: function() { + do_check_true(false); + } + }, Components.interfaces.nsIThread.DISPATCH_NORMAL); + + thr.shutdown(); +} + diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index d79e0bfafe9..b1f39e208ca 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -307,6 +307,10 @@ inline int NS_SUCCEEDED(nsresult _nsresult) { #define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) +/* Result codes used by nsIThreadManager */ + +#define NS_ERROR_NOT_SAME_THREAD NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 4) + /** * Various operations are not permitted during XPCOM shutdown and will fail * with this exception. From 142e029c979b591461a653eb0b4023db2a6af4a2 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sat, 30 Oct 2010 08:39:53 -0700 Subject: [PATCH 052/263] Follow-up for bug 608142: disallow sending between main and non-main thread only (r=orange). --- js/src/xpconnect/src/xpcprivate.h | 2 +- js/src/xpconnect/src/xpcwrappedjs.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 24c17bad9cc..36b5cc381ef 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,7 +3071,7 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root - nsCOMPtr mThread; + bool mMainThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index abdc7b43b75..59bc773215b 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -436,7 +436,7 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mRoot(root ? root : this), mNext(nsnull), mOuter(root ? nsnull : aOuter), - mThread(do_GetCurrentThread()) + mMainThread(NS_IsMainThread()) { #ifdef DEBUG_stats_jband static int count = 0; @@ -571,8 +571,9 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; - if (NS_GetCurrentThread() != mThread) + if (NS_IsMainThread() != mMainThread) { return NS_ERROR_NOT_SAME_THREAD; + } return GetClass()->CallMethod(this, methodIndex, info, params); } From ed107b01531e5221b4b2b14cda007ed1f79d4d83 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sat, 30 Oct 2010 08:39:53 -0700 Subject: [PATCH 053/263] Follow-up for bug 608142: disallow sending between main and non-main thread only (r=orange). a=beta7+ --- js/src/xpconnect/src/xpcprivate.h | 2 +- js/src/xpconnect/src/xpcwrappedjs.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 06ff14a3e13..8da42f24353 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -3071,7 +3071,7 @@ private: nsXPCWrappedJS* mRoot; nsXPCWrappedJS* mNext; nsISupports* mOuter; // only set in root - nsCOMPtr mThread; + bool mMainThread; }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcwrappedjs.cpp b/js/src/xpconnect/src/xpcwrappedjs.cpp index abdc7b43b75..59bc773215b 100644 --- a/js/src/xpconnect/src/xpcwrappedjs.cpp +++ b/js/src/xpconnect/src/xpcwrappedjs.cpp @@ -436,7 +436,7 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx, mRoot(root ? root : this), mNext(nsnull), mOuter(root ? nsnull : aOuter), - mThread(do_GetCurrentThread()) + mMainThread(NS_IsMainThread()) { #ifdef DEBUG_stats_jband static int count = 0; @@ -571,8 +571,9 @@ nsXPCWrappedJS::CallMethod(PRUint16 methodIndex, { if(!IsValid()) return NS_ERROR_UNEXPECTED; - if (NS_GetCurrentThread() != mThread) + if (NS_IsMainThread() != mMainThread) { return NS_ERROR_NOT_SAME_THREAD; + } return GetClass()->CallMethod(this, methodIndex, info, params); } From 03513401daaa80ec9ef5a51c1c88e327f957fb1d Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Sat, 30 Oct 2010 12:13:02 -0400 Subject: [PATCH 054/263] Bug 595243 - Expose debugMode to JSD. Relanding test bustage fixed up. r=gal. --- dom/base/nsJSEnvironment.cpp | 4 -- js/jsd/idl/jsdIDebuggerService.idl | 41 ++++++++++++--- js/jsd/jsd_scpt.c | 7 +-- js/jsd/jsd_xpc.cpp | 55 +++++++++++++++----- js/jsd/jsd_xpc.h | 2 +- js/jsd/test/test_bug507448.html | 72 ++++++++++++++++----------- js/src/jsapi.cpp | 3 ++ js/src/jscntxt.h | 5 ++ js/src/jscompartment.cpp | 2 +- js/src/jsdbgapi.cpp | 6 +++ js/src/jsdbgapi.h | 7 +++ js/src/xpconnect/idl/nsIXPConnect.idl | 11 +++- js/src/xpconnect/src/nsXPConnect.cpp | 44 ++++++++++++++++ js/src/xpconnect/src/xpcprivate.h | 3 ++ 14 files changed, 201 insertions(+), 61 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 84ccd622096..96c689ec994 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -993,10 +993,6 @@ nsJSContext::DOMOperationCallback(JSContext *cx) if (NS_SUCCEEDED(rv)) { jsds->GetDebuggerHook(getter_AddRefs(jsdHook)); jsds->GetIsOn(&jsds_IsOn); - if (jsds_IsOn) { // If this is not true, the next call would start jsd... - rv = jsds->OnForRuntime(cx->runtime); - jsds_IsOn = NS_SUCCEEDED(rv); - } } // If there is a debug handler registered for this runtime AND diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index ea250cf525f..c9c2c3b03f9 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -72,12 +72,13 @@ interface jsdIScript; interface jsdIValue; interface jsdIObject; interface jsdIProperty; +interface jsdIActivationCallback; /** * Debugger service. It's not a good idea to have more than one active client of * the debugger service. */ -[scriptable, uuid(dc0a24db-f8ac-4889-80d0-6016545a2dda)] +[scriptable, uuid(01769775-c77c-47f9-8848-0abbab404215)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -216,19 +217,34 @@ interface jsdIDebuggerService : nsISupports */ readonly attribute boolean isOn; + + /** + * Synchronous activation of the debugger is no longer supported, + * and will throw an exception. + */ + void on (); + /** * Turn on the debugger. This function should only be called from JavaScript * code. The debugger will be enabled on the runtime the call is made on, * as determined by nsIXPCNativeCallContext. - */ - void on (); - /** - * Turn on the debugger for a given runtime. * - * @param rt The runtime you want to debug. You cannot turn the debugger - * on for multiple runtimes. + * The debugger will be activated asynchronously, because there can be no JS + * on the stack when code is to be re-compiled for debug mode. */ - [noscript] void onForRuntime (in JSRuntime rt); + void asyncOn (in jsdIActivationCallback callback); + + /** + * Called by nsIXPConnect after it's had a chance to recompile for + * debug mode. + */ + [noscript] void activateDebugger(in JSRuntime rt); + + /** + * Recompile all active scripts in the runtime for debugMode. + */ + [noscript] void recompileForDebugMode(in JSRuntime rt, in PRBool mode); + /** * Turn the debugger off. This will invalidate all of your jsdIEphemeral * derived objects, and clear all of your breakpoints. In theory you @@ -457,6 +473,15 @@ interface jsdIFilter : nsISupports attribute unsigned long endLine; }; +/** + * Notify client code that debugMode has been activated. + */ +[scriptable, uuid(6da7f5fb-3a84-4abe-9e23-8b2045960732)] +interface jsdIActivationCallback : nsISupports +{ + void onDebuggerActivated (); +}; + /** * Pass an instance of one of these to jsdIDebuggerService::enterNestedEventLoop. */ diff --git a/js/jsd/jsd_scpt.c b/js/jsd/jsd_scpt.c index 01e96c0668f..37e08b0aa2d 100644 --- a/js/jsd/jsd_scpt.c +++ b/js/jsd/jsd_scpt.c @@ -585,11 +585,6 @@ jsd_NewScriptHookProc( if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; -#ifdef LIVEWIRE - if( 1 == lineno ) - jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE ); -#endif - JSD_LOCK_SCRIPTS(jsdc); jsdscript = _newJSDScript(jsdc, cx, script, fun); JSD_UNLOCK_SCRIPTS(jsdc); @@ -611,7 +606,7 @@ jsd_NewScriptHookProc( if( hook ) hook(jsdc, jsdscript, JS_TRUE, hookData); -} +} void jsd_DestroyScriptHookProc( diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index d044f1eafde..dfba4dbf557 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2396,6 +2396,12 @@ jsdService::GetIsOn (PRBool *_rval) NS_IMETHODIMP jsdService::On (void) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +jsdService::AsyncOn (jsdIActivationCallback *activationCallback) { nsresult rv; @@ -2410,18 +2416,32 @@ jsdService::On (void) JSContext *cx; rv = cc->GetJSContext (&cx); if (NS_FAILED(rv)) return rv; + + mActivationCallback = activationCallback; - return OnForRuntime(JS_GetRuntime (cx)); - + return xpc->SetDebugModeWhenPossible(PR_TRUE); } NS_IMETHODIMP -jsdService::OnForRuntime (JSRuntime *rt) +jsdService::RecompileForDebugMode (JSRuntime *rt, JSBool mode) { + JSContext *cx; + JSContext *iter = NULL; + + while ((cx = JS_ContextIterator (rt, &iter))) { + JS_SetDebugMode(cx, mode); + } + + return NS_OK; +} + +NS_IMETHODIMP +jsdService::ActivateDebugger (JSRuntime *rt) { if (mOn) return (rt == mRuntime) ? NS_OK : NS_ERROR_ALREADY_INITIALIZED; mRuntime = rt; + RecompileForDebugMode(rt, JS_TRUE); if (gLastGCProc == jsds_GCCallbackProc) /* condition indicates that the callback proc has not been set yet */ @@ -2471,6 +2491,10 @@ jsdService::OnForRuntime (JSRuntime *rt) #ifdef DEBUG printf ("+++ JavaScript debugging hooks installed.\n"); #endif + + if (mActivationCallback) + return mActivationCallback->OnDebuggerActivated(); + return NS_OK; } @@ -2521,6 +2545,13 @@ jsdService::Off (void) printf ("+++ JavaScript debugging hooks removed.\n"); #endif + nsresult rv; + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); + if (NS_FAILED(rv)) + return rv; + + xpc->SetDebugModeWhenPossible(PR_FALSE); + return NS_OK; } @@ -2969,7 +3000,7 @@ jsdService::SetErrorHook (jsdIErrorHook *aHook) mErrorHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3013,7 +3044,7 @@ jsdService::SetDebugHook (jsdIExecutionHook *aHook) mDebugHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3041,7 +3072,7 @@ jsdService::SetDebuggerHook (jsdIExecutionHook *aHook) mDebuggerHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3069,7 +3100,7 @@ jsdService::SetInterruptHook (jsdIExecutionHook *aHook) mInterruptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3097,7 +3128,7 @@ jsdService::SetScriptHook (jsdIScriptHook *aHook) mScriptHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3125,7 +3156,7 @@ jsdService::SetThrowHook (jsdIExecutionHook *aHook) mThrowHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3153,7 +3184,7 @@ jsdService::SetTopLevelHook (jsdICallHook *aHook) mTopLevelHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3181,7 +3212,7 @@ jsdService::SetFunctionHook (jsdICallHook *aHook) mFunctionHook = aHook; /* if the debugger isn't initialized, that's all we can do for now. The - * OnForRuntime() method will do the rest when the coast is clear. + * ActivateDebugger() method will do the rest when the coast is clear. */ if (!mCx || mPauseLevel) return NS_OK; @@ -3274,7 +3305,7 @@ jsdASObserver::Observe (nsISupports *aSubject, const char *aTopic, if (NS_FAILED(rv)) return rv; - rv = jsds->OnForRuntime(rt); + rv = jsds->ActivateDebugger(rt); if (NS_FAILED(rv)) return rv; diff --git a/js/jsd/jsd_xpc.h b/js/jsd/jsd_xpc.h index 92f08799242..06e5c2aeab8 100644 --- a/js/jsd/jsd_xpc.h +++ b/js/jsd/jsd_xpc.h @@ -305,7 +305,7 @@ class jsdService : public jsdIDebuggerService nsCOMPtr mThrowHook; nsCOMPtr mTopLevelHook; nsCOMPtr mFunctionHook; - + nsCOMPtr mActivationCallback; }; #endif /* JSDSERVICE_H___ */ diff --git a/js/jsd/test/test_bug507448.html b/js/jsd/test/test_bug507448.html index 8180658e420..49f7fde8289 100644 --- a/js/jsd/test/test_bug507448.html +++ b/js/jsd/test/test_bug507448.html @@ -16,8 +16,39 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=507448
+
+
 
-
-
 
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3d4807861e0..07fa8728ee0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -653,6 +653,9 @@ JSRuntime::init(uint32 maxbytes) if (!debuggerLock) return false; #endif + + debugMode = JS_FALSE; + return propertyTree.init() && js_InitThreads(this); } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 890bd9cb737..38f71028276 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1380,6 +1380,11 @@ struct JSRuntime { /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */ JSDebugHooks globalDebugHooks; + /* + * Right now, we only support runtime-wide debugging. + */ + JSBool debugMode; + #ifdef JS_TRACER /* True if any debug hooks not supported by the JIT are enabled. */ bool debuggerInhibitsJIT() const { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index af333d9c18a..d75088c2ba5 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -54,7 +54,7 @@ using namespace js; using namespace js::gc; JSCompartment::JSCompartment(JSRuntime *rt) - : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false), + : rt(rt), principals(NULL), data(NULL), marked(false), debugMode(rt->debugMode), anynameObject(NULL), functionNamespaceObject(NULL) { JS_INIT_CLIST(&scripts); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 5ad7ceda80a..99a17bb6312 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -108,6 +108,12 @@ IsScriptLive(JSContext *cx, JSScript *script) } #endif +JS_PUBLIC_API(void) +JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug) +{ + rt->debugMode = debug; +} + JS_FRIEND_API(JSBool) js_SetDebugMode(JSContext *cx, JSBool debug) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index 7bc7a4aaa0a..7b16c5e7994 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -49,6 +49,13 @@ JS_BEGIN_EXTERN_C +/* + * Currently, we only support runtime-wide debugging. In the future, we should + * be able to support compartment-wide debugging. + */ +extern JS_PUBLIC_API(void) +JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug); + /* * Debug mode is a compartment-wide mode that enables a debugger to attach * to and interact with running methodjit-ed frames. In particular, it causes diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index eb44d356091..5a483ea2e7c 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)] +[uuid(c825b64b-d537-4e53-822e-547049aae9c9)] interface nsIXPConnect : nsISupports { %{ C++ @@ -827,4 +827,13 @@ interface nsIXPConnect : nsISupports */ [noscript,notxpcom] void getCaller(out JSContextPtr aJSContext, out JSObjectPtr aObject); + + /** + * When we place the browser in JS debug mode, there can't be any + * JS on the stack. This is because we currently activate debugMode + * on all scripts in the JSRuntime when the debugger is activated. + * This method will turn debug mode on or off when the context + * stack reaches zero length. + */ + [noscript] void setDebugModeWhenPossible(in PRBool mode); }; diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 1711f54c8d0..71ec35efbfa 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -61,6 +61,8 @@ #include "WrapperFactory.h" #include "AccessCheck.h" +#include "jsdIDebuggerService.h" + NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsIXPConnect, nsISupportsWeakReference, @@ -72,6 +74,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect, nsXPConnect* nsXPConnect::gSelf = nsnull; JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE; PRUint32 nsXPConnect::gReportAllJSExceptions = 0; +JSBool nsXPConnect::gDebugMode = JS_FALSE; +JSBool nsXPConnect::gDesiredDebugMode = JS_FALSE; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) @@ -2407,6 +2411,30 @@ nsXPConnect::Peek(JSContext * *_retval) return data->GetJSContextStack()->Peek(_retval); } +void +nsXPConnect::CheckForDebugMode(JSRuntime *rt) { + if (gDebugMode != gDesiredDebugMode) { + nsresult rv; + const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1"; + nsCOMPtr jsds = do_GetService(jsdServiceCtrID, &rv); + if (NS_SUCCEEDED(rv)) { + if (gDesiredDebugMode == PR_FALSE) { + rv = jsds->RecompileForDebugMode(rt, PR_FALSE); + } else { + rv = jsds->ActivateDebugger(rt); + } + } + + if (NS_SUCCEEDED(rv)) { + JS_SetRuntimeDebugMode(rt, gDesiredDebugMode); + gDebugMode = gDesiredDebugMode; + } else { + // if the attempt failed, cancel the debugMode request + gDesiredDebugMode = gDebugMode; + } + } +} + /* JSContext Pop (); */ NS_IMETHODIMP nsXPConnect::Pop(JSContext * *_retval) @@ -2432,6 +2460,15 @@ nsXPConnect::Push(JSContext * cx) if(!data) return NS_ERROR_FAILURE; + PRInt32 count; + nsresult rv; + rv = data->GetJSContextStack()->GetCount(&count); + if (NS_FAILED(rv)) + return rv; + + if (count == 0) + CheckForDebugMode(mRuntime->GetJSRuntime()); + return data->GetJSContextStack()->Push(cx); } @@ -2539,6 +2576,13 @@ nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj) *aObj = ccx->GetFlattenedJSObject(); } +NS_IMETHODIMP +nsXPConnect::SetDebugModeWhenPossible(PRBool mode) +{ + gDesiredDebugMode = mode; + return NS_OK; +} + /* These are here to be callable from a debugger */ JS_BEGIN_EXTERN_C JS_EXPORT_API(void) DumpJSStack() diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 36b5cc381ef..b217146a383 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -626,6 +626,9 @@ private: nsCOMPtr mBackstagePass; static PRUint32 gReportAllJSExceptions; + static JSBool gDebugMode; + static JSBool gDesiredDebugMode; + static inline void CheckForDebugMode(JSRuntime *rt); public: static nsIScriptSecurityManager *gScriptSecurityManager; From 2ea8fdd74f1c1ee932fa4ba35fe3a0e171c44037 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Sat, 30 Oct 2010 11:59:18 -0700 Subject: [PATCH 055/263] Bug 608416: Stop exceptions from cleanup functions from breaking the harness. r=gavin, a=tests --- testing/mochitest/browser-test.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testing/mochitest/browser-test.js b/testing/mochitest/browser-test.js index da7a3f34d44..15276e7259f 100644 --- a/testing/mochitest/browser-test.js +++ b/testing/mochitest/browser-test.js @@ -161,7 +161,12 @@ Tester.prototype = { let testScope = this.currentTest.scope; while (testScope.__cleanupFunctions.length > 0) { let func = testScope.__cleanupFunctions.shift(); - func.apply(testScope); + try { + func.apply(testScope); + } + catch (ex) { + this.currentTest.addResult(new testResult(false, "Cleanup function threw an exception", ex, false)); + } }; // Note the test run time From aecb00a9790a2bdf56789842ff0fa3d9e8ce6472 Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Sat, 30 Oct 2010 15:07:46 -0400 Subject: [PATCH 056/263] Follow-up fix for bug 595243. Don't try to place non-main thread scripts in debug mode, and don't attempt to set debug mode from a non-main thread. r=gal --- js/jsd/jsd_val.c | 1 + js/jsd/jsd_xpc.cpp | 7 ++ js/jsd/test/Makefile.in | 1 + js/jsd/test/bug507448.js | 25 ++++++ js/jsd/test/test_bug507448.html | 109 ++++++++++++++++----------- js/src/xpconnect/src/nsXPConnect.cpp | 6 ++ 6 files changed, 107 insertions(+), 42 deletions(-) create mode 100644 js/jsd/test/bug507448.js diff --git a/js/jsd/jsd_val.c b/js/jsd/jsd_val.c index c2a3bd0ac50..75ef2d5bc71 100644 --- a/js/jsd/jsd_val.c +++ b/js/jsd/jsd_val.c @@ -789,6 +789,7 @@ jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval) return NULL; } + exceptionState = JS_SaveExceptionState(cx); fun = JS_ValueToFunction(cx, val); JS_RestoreExceptionState(cx, exceptionState); diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index dfba4dbf557..82a6dc329e2 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -38,6 +38,7 @@ * ***** END LICENSE BLOCK ***** */ #include "jsdbgapi.h" +#include "jslock.h" #include "jsd_xpc.h" #include "nsIXPConnect.h" @@ -2424,11 +2425,17 @@ jsdService::AsyncOn (jsdIActivationCallback *activationCallback) NS_IMETHODIMP jsdService::RecompileForDebugMode (JSRuntime *rt, JSBool mode) { + NS_ASSERTION(NS_IsMainThread(), "wrong thread"); + JSContext *cx; JSContext *iter = NULL; + jsword currentThreadId = reinterpret_cast(js_CurrentThreadId()); + while ((cx = JS_ContextIterator (rt, &iter))) { + if (JS_GetContextThread(cx) == currentThreadId) { JS_SetDebugMode(cx, mode); + } } return NS_OK; diff --git a/js/jsd/test/Makefile.in b/js/jsd/test/Makefile.in index d4d75a26b14..7da163dd97f 100644 --- a/js/jsd/test/Makefile.in +++ b/js/jsd/test/Makefile.in @@ -48,6 +48,7 @@ MODULE = jsdebug include $(topsrcdir)/config/rules.mk _TEST_FILES = test_bug507448.html \ + bug507448.js \ $(NULL) libs:: $(_TEST_FILES) diff --git a/js/jsd/test/bug507448.js b/js/jsd/test/bug507448.js new file mode 100644 index 00000000000..9ef2241dc6f --- /dev/null +++ b/js/jsd/test/bug507448.js @@ -0,0 +1,25 @@ +netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + +function f() {} +function g(a,b) {} +function h(me, too, here) { var x = 1; } +function annoying(a, b, a, b, b, a) {} +function manyLocals(a, b, c, d, e, f, g, h, i, j, k, l, m) { + var n, o, p, q, r, s, t, u, v, w, x, y, z; +} + +assertArraysEqual(jsd.wrapValue(f).script.getParameterNames(), []); +assertArraysEqual(jsd.wrapValue(g).script.getParameterNames(), ["a", "b"]); +assertArraysEqual(jsd.wrapValue(h).script.getParameterNames(), ["me", "too", "here"]); +assertArraysEqual(jsd.wrapValue(annoying).script.getParameterNames(), + ["a", "b", "a", "b", "b", "a"]); +assertArraysEqual(jsd.wrapValue(manyLocals).script.getParameterNames(), + "abcdefghijklm".split("")); + +if (!jsdOnAtStart) { + // turn JSD off if it wasn't on when this test started + jsd.off(); + ok(!jsd.isOn, "JSD shouldn't be running at the end of this test."); +} + +SimpleTest.finish(); \ No newline at end of file diff --git a/js/jsd/test/test_bug507448.html b/js/jsd/test/test_bug507448.html index 49f7fde8289..54f87cc74c1 100644 --- a/js/jsd/test/test_bug507448.html +++ b/js/jsd/test/test_bug507448.html @@ -16,39 +16,48 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=507448
-
-
 
+
 
diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 71ec35efbfa..c62bdf5ad0f 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -2414,6 +2414,12 @@ nsXPConnect::Peek(JSContext * *_retval) void nsXPConnect::CheckForDebugMode(JSRuntime *rt) { if (gDebugMode != gDesiredDebugMode) { + // This can happen if a Worker is running, but we don't have the ability + // to debug workers right now, so just return. + if (!NS_IsMainThread()) { + return; + } + nsresult rv; const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1"; nsCOMPtr jsds = do_GetService(jsdServiceCtrID, &rv); From f23170426826d75d1f393f466c4bc8577967fb66 Mon Sep 17 00:00:00 2001 From: Johnny Stenback Date: Sat, 30 Oct 2010 22:51:35 -0700 Subject: [PATCH 057/263] Remove new JS_ASSERT() that triggers during browser-chrome runs. Will investigate further. r=orange, a=orange --- js/src/xpconnect/src/xpcjsruntime.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index bdaa1988afc..202f7f98527 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -413,9 +413,6 @@ struct Closure JSContext *cx; bool cycleCollectionEnabled; nsCycleCollectionTraversalCallback *cb; -#ifdef DEBUG - JSCompartment *compartment; -#endif }; static void @@ -423,16 +420,6 @@ CheckParticipatesInCycleCollection(PRUint32 aLangID, void *aThing, void *aClosur { Closure *closure = static_cast(aClosure); -#ifdef DEBUG - if(aLangID == nsIProgrammingLanguage::JAVASCRIPT && - js_GetGCThingTraceKind(aThing) == JSTRACE_OBJECT) - { - JSCompartment *c = static_cast(aThing)->compartment(); - JS_ASSERT(!closure->compartment || closure->compartment == c); - closure->compartment = c; - } -#endif - if(!closure->cycleCollectionEnabled && aLangID == nsIProgrammingLanguage::JAVASCRIPT && js_GetGCThingTraceKind(aThing) == JSTRACE_OBJECT) @@ -451,9 +438,6 @@ NoteJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, Closure *closure = static_cast(arg); closure->cycleCollectionEnabled = PR_FALSE; -#ifdef DEBUG - closure->compartment = nsnull; -#endif entry->tracer->Trace(entry->holder, CheckParticipatesInCycleCollection, closure); if(!closure->cycleCollectionEnabled) @@ -513,11 +497,7 @@ XPCJSRuntime::AddXPConnectRoots(JSContext* cx, if(mJSHolders.ops) { - Closure closure = { cx, PR_TRUE, &cb -#if DEBUG - , nsnull -#endif - }; + Closure closure = { cx, PR_TRUE, &cb }; JS_DHashTableEnumerate(&mJSHolders, NoteJSHolder, &closure); } } From 91827b88c7c7491d1db86eb0adf9311872f4a0af Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 18 Oct 2010 16:29:37 +0300 Subject: [PATCH 058/263] Bug 604924 - Make preloaded parser-inserted external scripts wait for style sheets. r=sicking, a=b --- content/base/src/nsScriptLoader.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index a1315db6cb0..3a0915c8bb2 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -591,10 +591,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) } return NS_OK; } - if (!request->mLoading) { - // The request has already been loaded. If the script comes from the - // network stream, cheat for performance reasons and avoid a trip - // through the event loop. + if (!request->mLoading && ReadyToExecuteScripts()) { + // The request has already been loaded and there are no pending style + // sheets. If the script comes from the network stream, cheat for + // performance reasons and avoid a trip through the event loop. if (aElement->GetParserCreated() == NS_FROM_PARSER_NETWORK) { return ProcessRequest(request); } @@ -607,8 +607,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) ProcessPendingRequestsAsync(); return NS_ERROR_HTMLPARSER_BLOCK; } - // The script hasn't loaded yet and is parser-inserted and non-async. - // It'll be executed when it has loaded. + // The script hasn't loaded yet or there's a style sheet blocking it. + // The script will be run when it loads or the style sheet loads. NS_ASSERTION(!mParserBlockingRequest, "There can be only one parser-blocking script at a time"); mParserBlockingRequest = request; From 7f5dd43f9b8c4413e7c017bcb2219e0dfdecd6ea Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Tue, 19 Oct 2010 00:10:22 +0200 Subject: [PATCH 059/263] Bug 604565 - Attempt to make tests hang less on OS X. [r=mconnor] Reduce amount of pointless network calls by not registering any engines for tests that provide their own fake engine implementations anyway. --- .../sync/tests/unit/test_service_sync_checkServerError.js | 4 +++- .../tests/unit/test_service_sync_updateEnabledEngines.js | 6 +++++- services/sync/tests/unit/test_service_wipeClient.js | 5 ++++- services/sync/tests/unit/test_service_wipeServer.js | 4 +++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/services/sync/tests/unit/test_service_sync_checkServerError.js b/services/sync/tests/unit/test_service_sync_checkServerError.js index dc1459380f6..f05e7b97824 100644 --- a/services/sync/tests/unit/test_service_sync_checkServerError.js +++ b/services/sync/tests/unit/test_service_sync_checkServerError.js @@ -1,9 +1,11 @@ -Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/engines.js"); Cu.import("resource://services-sync/status.js"); Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/util.js"); +Svc.DefaultPrefs.set("registerEngines", ""); +Cu.import("resource://services-sync/service.js"); + initTestLogging(); function CatapultEngine() { diff --git a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js index 92f960f1d09..50b506f2a27 100644 --- a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js @@ -1,4 +1,3 @@ -Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/engines.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/constants.js"); @@ -6,6 +5,11 @@ Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/keys.js"); Cu.import("resource://services-sync/base_records/wbo.js"); +Svc.DefaultPrefs.set("registerEngines", ""); +Cu.import("resource://services-sync/service.js"); + +initTestLogging(); + function SteamEngine() { SyncEngine.call(this, "Steam"); } diff --git a/services/sync/tests/unit/test_service_wipeClient.js b/services/sync/tests/unit/test_service_wipeClient.js index 0859f380ebf..1f4af871883 100644 --- a/services/sync/tests/unit/test_service_wipeClient.js +++ b/services/sync/tests/unit/test_service_wipeClient.js @@ -1,5 +1,8 @@ -Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/engines.js"); +Cu.import("resource://services-sync/util.js"); + +Svc.DefaultPrefs.set("registerEngines", ""); +Cu.import("resource://services-sync/service.js"); function CanDecryptEngine() { diff --git a/services/sync/tests/unit/test_service_wipeServer.js b/services/sync/tests/unit/test_service_wipeServer.js index 906560f6226..9d65409c549 100644 --- a/services/sync/tests/unit/test_service_wipeServer.js +++ b/services/sync/tests/unit/test_service_wipeServer.js @@ -1,9 +1,11 @@ Cu.import("resource://services-sync/util.js"); -Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/keys.js"); Cu.import("resource://services-sync/resource.js"); +Svc.DefaultPrefs.set("registerEngines", ""); +Cu.import("resource://services-sync/service.js"); + function FakeCollection() { this.deleted = false; } From 1588afd2db7cd06b27e3584e14f9355212ab6cad Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 21 Oct 2010 13:47:47 +0200 Subject: [PATCH 060/263] Bug 604565 - Disable intermittently failing xpcshell tests on OSX debug builds. [r=mconnor] --HG-- rename : services/sync/tests/unit/head_appinfo.js => services/sync/tests/unit/head_appinfo.js.in --- .../tests/unit/{head_appinfo.js => head_appinfo.js.in} | 9 +++++++++ .../tests/unit/test_service_sync_checkServerError.js | 3 +++ .../tests/unit/test_service_sync_updateEnabledEngines.js | 3 +++ services/sync/tests/unit/test_syncengine_sync.js | 3 +++ 4 files changed, 18 insertions(+) rename services/sync/tests/unit/{head_appinfo.js => head_appinfo.js.in} (91%) diff --git a/services/sync/tests/unit/head_appinfo.js b/services/sync/tests/unit/head_appinfo.js.in similarity index 91% rename from services/sync/tests/unit/head_appinfo.js rename to services/sync/tests/unit/head_appinfo.js.in index 278ee6dc0a1..8fa133ae0e8 100644 --- a/services/sync/tests/unit/head_appinfo.js +++ b/services/sync/tests/unit/head_appinfo.js.in @@ -62,3 +62,12 @@ registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}" // Provide resource://services-sync if it isn't already available let weaveService = Cc["@mozilla.org/weave/service;1"].getService(); weaveService.wrappedJSObject.addResourceAlias(); + + +// Some tests hang on OSX debug builds. See bug 604565. +let DISABLE_TESTS_BUG_604565 = false; +#ifdef XP_MACOSX +#ifdef MOZ_DEBUG_SYMBOLS +DISABLE_TESTS_BUG_604565 = true; +#endif +#endif diff --git a/services/sync/tests/unit/test_service_sync_checkServerError.js b/services/sync/tests/unit/test_service_sync_checkServerError.js index f05e7b97824..5f69a1a9134 100644 --- a/services/sync/tests/unit/test_service_sync_checkServerError.js +++ b/services/sync/tests/unit/test_service_sync_checkServerError.js @@ -132,6 +132,9 @@ function test_overQuota() { } function run_test() { + if (DISABLE_TESTS_BUG_604565) + return; + test_backoff500(); test_backoff503(); test_overQuota(); diff --git a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js index 50b506f2a27..b6e7b89f220 100644 --- a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js @@ -342,6 +342,9 @@ function test_dependentEnginesDisabledLocally() { } function run_test() { + if (DISABLE_TESTS_BUG_604565) + return; + test_newAccount(); test_enabledLocally(); test_disabledLocally(); diff --git a/services/sync/tests/unit/test_syncengine_sync.js b/services/sync/tests/unit/test_syncengine_sync.js index 257ddee3772..6aeb566311c 100644 --- a/services/sync/tests/unit/test_syncengine_sync.js +++ b/services/sync/tests/unit/test_syncengine_sync.js @@ -1150,6 +1150,9 @@ function test_canDecrypt_true() { function run_test() { + if (DISABLE_TESTS_BUG_604565) + return; + test_syncStartup_emptyOrOutdatedGlobalsResetsSync(); test_syncStartup_metaGet404(); test_syncStartup_failedMetaGet(); From d71e4fe2da9c1971c1590fb411d62c32acd48b1a Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 26 Oct 2010 16:20:21 -0700 Subject: [PATCH 061/263] Bug 605186 - js_NewStringFromCharBuffer should create short strings if it can (r=waldo) --- js/src/jsstr.cpp | 87 +++++++++++++++++++++++++---------------------- js/src/jsvector.h | 2 ++ 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 2281c5f3512..721bdb3bf4a 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3418,6 +3418,47 @@ js_NewString(JSContext *cx, jschar *chars, size_t length) return str; } +static JS_ALWAYS_INLINE JSString * +NewShortString(JSContext *cx, const jschar *chars, size_t length) +{ + JS_ASSERT(JSShortString::fitsIntoShortString(length)); + JSShortString *str = js_NewGCShortString(cx); + if (!str) + return NULL; + jschar *storage = str->init(length); + js_short_strncpy(storage, chars, length); + storage[length] = 0; + return str->header(); +} + +static JSString * +NewShortString(JSContext *cx, const char *chars, size_t length) +{ + JS_ASSERT(JSShortString::fitsIntoShortString(length)); + JSShortString *str = js_NewGCShortString(cx); + if (!str) + return NULL; + jschar *storage = str->init(length); + + if (js_CStringsAreUTF8) { +#ifdef DEBUG + size_t oldLength = length; +#endif + if (!js_InflateStringToBuffer(cx, chars, length, storage, &length)) + return NULL; + JS_ASSERT(length <= oldLength); + storage[length] = 0; + str->resetLength(length); + } else { + size_t n = length; + jschar *p = storage; + while (n--) + *p++ = jschar(*chars++); + *p = 0; + } + return str->header(); +} + static const size_t sMinWasteSize = 16; JSString * @@ -3427,6 +3468,11 @@ js_NewStringFromCharBuffer(JSContext *cx, JSCharBuffer &cb) return ATOM_TO_STRING(cx->runtime->atomState.emptyAtom); size_t length = cb.length(); + + JS_STATIC_ASSERT(JSShortString::MAX_SHORT_STRING_LENGTH < JSCharBuffer::InlineLength); + if (JSShortString::fitsIntoShortString(length)) + return NewShortString(cx, cb.begin(), length); + if (!cb.append('\0')) return NULL; @@ -3520,47 +3566,6 @@ void printJSStringStats(JSRuntime *rt) } #endif -JSString * -NewShortString(JSContext *cx, const jschar *chars, size_t length) -{ - JS_ASSERT(JSShortString::fitsIntoShortString(length)); - JSShortString *str = js_NewGCShortString(cx); - if (!str) - return NULL; - jschar *storage = str->init(length); - js_short_strncpy(storage, chars, length); - storage[length] = 0; - return str->header(); -} - -JSString * -NewShortString(JSContext *cx, const char *chars, size_t length) -{ - JS_ASSERT(JSShortString::fitsIntoShortString(length)); - JSShortString *str = js_NewGCShortString(cx); - if (!str) - return NULL; - jschar *storage = str->init(length); - - if (js_CStringsAreUTF8) { -#ifdef DEBUG - size_t oldLength = length; -#endif - if (!js_InflateStringToBuffer(cx, chars, length, storage, &length)) - return NULL; - JS_ASSERT(length <= oldLength); - storage[length] = 0; - str->resetLength(length); - } else { - size_t n = length; - jschar *p = storage; - while (n--) - *p++ = jschar(*chars++); - *p = 0; - } - return str->header(); -} - JSString * js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n) { diff --git a/js/src/jsvector.h b/js/src/jsvector.h index 90917f8a582..ee974faf603 100644 --- a/js/src/jsvector.h +++ b/js/src/jsvector.h @@ -314,6 +314,8 @@ class Vector : AllocPolicy /* accessors */ + enum { InlineLength = N }; + size_t length() const { return usingInlineStorage() ? inlineLength() : heapLength(); } From 3e1a9e035e7ef680ed8fa66cf852e38cc44e1e61 Mon Sep 17 00:00:00 2001 From: Tero Koskinen Date: Mon, 25 Oct 2010 09:51:59 +0100 Subject: [PATCH 062/263] Add support for ARM's 'hard' EABI variant. (FP arguments go in VFP registers.) [Bug 602834] [r=jbramley,rreitmai] --HG-- extra : convert_revision : 113a2e56c62fca5adc557906dd729a4ec632d994 --- js/src/nanojit/NativeARM.cpp | 160 ++++++++++++++++++++++------------- js/src/nanojit/NativeARM.h | 99 ++++++++++++++-------- 2 files changed, 163 insertions(+), 96 deletions(-) diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index 280c8d6045e..fe180fd1d2d 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -24,6 +24,7 @@ * Adobe AS3 Team * Vladimir Vukicevic * Jacob Bramley + * Tero Koskinen * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -52,7 +53,7 @@ namespace nanojit #ifdef NJ_VERBOSE const char* regNames[] = {"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","fp","ip","sp","lr","pc", - "d0","d1","d2","d3","d4","d5","d6","d7","s14"}; + "d0","d1","d2","d3","d4","d5","d6","d7","s0"}; const char* condNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc","hi","ls","ge","lt","gt","le",""/*al*/,"nv"}; const char* shiftNames[] = { "lsl", "lsl", "lsr", "lsr", "asr", "asr", "ror", "ror" }; #endif @@ -613,6 +614,9 @@ Assembler::genEpilogue() * - 32-bit arguments are placed in registers and 32-bit aligned * on the stack. * + * Under EABI with hardware floating-point procedure-call variant: + * - Same as EABI, but doubles are passed in D0..D7 registers. + * * Under legacy ABI: * - doubles are placed in subsequent arg registers; if the next * available register is r3, the low order word goes into r3 @@ -622,23 +626,23 @@ Assembler::genEpilogue() * alignment. */ void -Assembler::asm_arg(ArgType ty, LIns* arg, Register& r, int& stkd) +Assembler::asm_arg(ArgType ty, LIns* arg, ParameterRegisters& params) { // The stack pointer must always be at least aligned to 4 bytes. - NanoAssert((stkd & 3) == 0); + NanoAssert((params.stkd & 3) == 0); if (ty == ARGTYPE_D) { // This task is fairly complex and so is delegated to asm_arg_64. - asm_arg_64(arg, r, stkd); + asm_arg_64(arg, params); } else { NanoAssert(ty == ARGTYPE_I || ty == ARGTYPE_UI); // pre-assign registers R0-R3 for arguments (if they fit) - if (r < R4) { - asm_regarg(ty, arg, r); - r = Register(r + 1); + if (params.r < R4) { + asm_regarg(ty, arg, params.r); + params.r = Register(params.r + 1); } else { - asm_stkarg(arg, stkd); - stkd += 4; + asm_stkarg(arg, params.stkd); + params.stkd += 4; } } } @@ -646,11 +650,26 @@ Assembler::asm_arg(ArgType ty, LIns* arg, Register& r, int& stkd) // Encode a 64-bit floating-point argument using the appropriate ABI. // This function operates in the same way as asm_arg, except that it will only // handle arguments where (ArgType)ty == ARGTYPE_D. + +#ifdef NJ_ARM_EABI_HARD_FLOAT void -Assembler::asm_arg_64(LIns* arg, Register& r, int& stkd) +Assembler::asm_arg_64(LIns* arg, ParameterRegisters& params) +{ + NanoAssert(IsFpReg(params.float_r)); + if (params.float_r <= D7) { + findSpecificRegFor(arg, params.float_r); + params.float_r = Register(params.float_r + 1); + } else { + NanoAssertMsg(0, "Only 8 floating point arguments supported"); + } +} + +#else +void +Assembler::asm_arg_64(LIns* arg, ParameterRegisters& params) { // The stack pointer must always be at least aligned to 4 bytes. - NanoAssert((stkd & 3) == 0); + NanoAssert((params.stkd & 3) == 0); // The only use for this function when we are using soft floating-point // is for LIR_ii2d. NanoAssert(ARM_VFP || arg->isop(LIR_ii2d)); @@ -661,15 +680,15 @@ Assembler::asm_arg_64(LIns* arg, Register& r, int& stkd) // odd-numbered register, advance it. Note that this will push r past // R3 if r is R3 to start with, and will force the argument to go on // the stack. - if ((r == R1) || (r == R3)) { - r = Register(r + 1); + if ((params.r == R1) || (params.r == R3)) { + params.r = Register(params.r + 1); } #endif - if (r < R3) { - Register ra = r; - Register rb = Register(r + 1); - r = Register(rb + 1); + if (params.r < R3) { + Register ra = params.r; + Register rb = Register(params.r + 1); + params.r = Register(rb + 1); #ifdef NJ_ARM_EABI // EABI requires that 64-bit arguments are aligned on even-numbered @@ -693,12 +712,12 @@ Assembler::asm_arg_64(LIns* arg, Register& r, int& stkd) // We only have one register left, but the legacy ABI requires that we // put 32 bits of the argument in the register (R3) and the remaining // 32 bits on the stack. - Register ra = r; // R3 - r = R4; + Register ra = params.r; // R3 + params.r = R4; // We're splitting the argument between registers and the stack. This // must be the first time that the stack is used, so stkd must be at 0. - NanoAssert(stkd == 0); + NanoAssert(params.stkd == 0); if (ARM_VFP) { Register dm = findRegFor(arg, FpRegs); @@ -717,27 +736,28 @@ Assembler::asm_arg_64(LIns* arg, Register& r, int& stkd) asm_regarg(ARGTYPE_I, arg->oprnd1(), ra); asm_stkarg(arg->oprnd2(), 0); } - stkd += 4; + params.stkd += 4; #endif } else { // The argument won't fit in registers, so pass on to asm_stkarg. #ifdef NJ_ARM_EABI // EABI requires that 64-bit arguments are 64-bit aligned. - if ((stkd & 7) != 0) { + if ((params.stkd & 7) != 0) { // stkd will always be aligned to at least 4 bytes; this was // asserted on entry to this function. - stkd += 4; + params.stkd += 4; } #endif if (ARM_VFP) { - asm_stkarg(arg, stkd); + asm_stkarg(arg, params.stkd); } else { - asm_stkarg(arg->oprnd1(), stkd); - asm_stkarg(arg->oprnd2(), stkd+4); + asm_stkarg(arg->oprnd1(), params.stkd); + asm_stkarg(arg->oprnd2(), params.stkd+4); } - stkd += 8; + params.stkd += 8; } } +#endif // NJ_ARM_EABI_HARD_FLOAT void Assembler::asm_regarg(ArgType ty, LIns* p, Register rd) @@ -818,6 +838,14 @@ Assembler::asm_call(LIns* ins) * used here with the ultimate VFP register, and not R0/R1, which * potentially allows for R0/R1 to get corrupted as described. */ +#ifdef NJ_ARM_EABI_HARD_FLOAT + /* With ARM hardware floating point ABI, D0 is used to return the double + * from the function. We need to prepare it like we do for R0 in the else + * branch. + */ + prepareResultReg(ins, rmask(D0)); + freeResourcesOf(ins); +#endif } else if (!ins->isop(LIR_callv)) { prepareResultReg(ins, rmask(retRegs[0])); // Immediately free the resources as we need to re-use the register for @@ -839,11 +867,12 @@ Assembler::asm_call(LIns* ins) // function call. NanoAssert(ARM_VFP || ins->isop(LIR_callv) || ins->isop(LIR_calli)); - // If we're using VFP, and the return type is a double, it'll come back in - // R0/R1. We need to either place it in the result fp reg, or store it. + // If we're using VFP, but not hardware floating point ABI, and + // the return type is a double, it'll come back in R0/R1. + // We need to either place it in the result fp reg, or store it. // See comments above for more details as to why this is necessary here // for floating point calls, but not for integer calls. - if (ARM_VFP && ins->isExtant()) { + if (!ARM_EABI_HARD && ARM_VFP && ins->isExtant()) { // If the result size is a floating-point value, treat the result // specially, as described previously. if (ci->returnType() == ARGTYPE_D) { @@ -894,9 +923,9 @@ Assembler::asm_call(LIns* ins) asm_regarg(ARGTYPE_I, ins->arg(--argc), LR); } - // Encode the arguments, starting at R0 and with an empty argument stack. - Register r = R0; - int stkd = 0; + // Encode the arguments, starting at R0 and with an empty argument stack (0). + // With hardware fp ABI, floating point arguments start from D0. + ParameterRegisters params = init_params(0, R0, D0); // Iterate through the argument list and encode each argument according to // the ABI. @@ -904,11 +933,11 @@ Assembler::asm_call(LIns* ins) // in reverse order. uint32_t i = argc; while(i--) { - asm_arg(argTypes[i], ins->arg(i), r, stkd); + asm_arg(argTypes[i], ins->arg(i), params); } - if (stkd > max_out_args) { - max_out_args = stkd; + if (params.stkd > max_out_args) { + max_out_args = params.stkd; } } @@ -941,7 +970,7 @@ Assembler::nRegisterResetAll(RegAlloc& a) if (ARM_VFP) { a.free |= rmask(D0) | rmask(D1) | rmask(D2) | rmask(D3) | - rmask(D4) | rmask(D5) | rmask(D6); + rmask(D4) | rmask(D5) | rmask(D6) | rmask(D7); } } @@ -1329,13 +1358,14 @@ Assembler::asm_load64(LIns* ins) int offset = ins->disp(); if (ins->isInReg()) { - dd = prepareResultReg(ins, FpRegs); + dd = prepareResultReg(ins, FpRegs & ~rmask(D0)); } else { // If the result isn't already in a register, use the VFP scratch // register for the result and store it directly into memory. NanoAssert(ins->isInAr()); int d = arDisp(ins); - dd = D7; + evictIfActive(D0); + dd = D0; // VFP can only do loads and stores with a range of ±1020, so we // might need to do some arithmetic to extend its range. if (isU8(d/4) || isU8(-d/4)) { @@ -1356,11 +1386,12 @@ Assembler::asm_load64(LIns* ins) } break; case LIR_ldf2d: - FCVTDS(dd, S14); + evictIfActive(D0); + FCVTDS(dd, S0); if (isU8(offset/4) || isU8(-offset/4)) { - FLDS(S14, rn, offset); + FLDS(S0, rn, offset); } else { - FLDS(S14, IP, offset%1024); + FLDS(S0, IP, offset%1024); asm_add_imm(IP, rn, offset-(offset%1024)); } break; @@ -1398,7 +1429,7 @@ Assembler::asm_store64(LOpcode op, LIns* value, int dr, LIns* base) NanoAssert(value->isD()); if (ARM_VFP) { - Register dd = findRegFor(value, FpRegs); + Register dd = findRegFor(value, FpRegs & ~rmask(D0)); Register rn = findRegFor(base, GpRegs); switch (op) { @@ -1416,14 +1447,15 @@ Assembler::asm_store64(LOpcode op, LIns* value, int dr, LIns* base) case LIR_std2f: // VFP can only do stores with a range of ±1020, so we might // need to do some arithmetic to extend its range. + evictIfActive(D0); if (isU8(dr/4) || isU8(-dr/4)) { - FSTS(S14, rn, dr); + FSTS(S0, rn, dr); } else { - FSTS(S14, IP, dr%1024); + FSTS(S0, IP, dr%1024); asm_add_imm(IP, rn, dr-(dr%1024)); } - FCVTSD(S14, dd); + FCVTSD(S0, dd); break; default: @@ -2123,11 +2155,12 @@ Assembler::B_cond_chk(ConditionCode _c, NIns* _t, bool _chk) void Assembler::asm_i2d(LIns* ins) { - Register dd = prepareResultReg(ins, FpRegs); + Register dd = prepareResultReg(ins, FpRegs & ~rmask(D0)); Register rt = findRegFor(ins->oprnd1(), GpRegs); - FSITOD(dd, S14); - FMSR(S14, rt); + evictIfActive(D0); + FSITOD(dd, S0); + FMSR(S0, rt); freeResourcesOf(ins); } @@ -2135,20 +2168,22 @@ Assembler::asm_i2d(LIns* ins) void Assembler::asm_ui2d(LIns* ins) { - Register dd = prepareResultReg(ins, FpRegs); + Register dd = prepareResultReg(ins, FpRegs & ~rmask(D0)); Register rt = findRegFor(ins->oprnd1(), GpRegs); - FUITOD(dd, S14); - FMSR(S14, rt); + evictIfActive(D0); + FUITOD(dd, S0); + FMSR(S0, rt); freeResourcesOf(ins); } void Assembler::asm_d2i(LIns* ins) { + evictIfActive(D0); if (ins->isInReg()) { Register rt = ins->getReg(); - FMRS(rt, S14); + FMRS(rt, S0); } else { // There's no active result register, so store the result directly into // memory to avoid the FP->GP transfer cost on Cortex-A8. @@ -2156,16 +2191,16 @@ void Assembler::asm_d2i(LIns* ins) // VFP can only do stores with a range of ±1020, so we might need to do // some arithmetic to extend its range. if (isU8(d/4) || isU8(-d/4)) { - FSTS(S14, FP, d); + FSTS(S0, FP, d); } else { - FSTS(S14, IP, d%1024); + FSTS(S0, IP, d%1024); asm_add_imm(IP, FP, d-(d%1024)); } } - Register dm = findRegFor(ins->oprnd1(), FpRegs); + Register dm = findRegFor(ins->oprnd1(), FpRegs & ~rmask(D0)); - FTOSID(S14, dm); + FTOSID(S0, dm); freeResourcesOf(ins); } @@ -2832,8 +2867,11 @@ Assembler::asm_ret(LIns *ins) // we are intending for R0 is currently IP, not R0. This has to do with // the strange dual-nature of the patchable jump in a side-exit. See // nPatchBranch. - - MOV(IP, R0); + // + // With hardware floating point ABI we can skip this for retd. + if (!(ARM_EABI_HARD && ins->isop(LIR_retd))) { + MOV(IP, R0); + } // Pop the stack frame. MOV(SP,FP); @@ -2847,8 +2885,12 @@ Assembler::asm_ret(LIns *ins) else { NanoAssert(ins->isop(LIR_retd)); if (ARM_VFP) { +#ifdef NJ_ARM_EABI_HARD_FLOAT + findSpecificRegFor(value, D0); +#else Register reg = findRegFor(value, FpRegs); FMRRD(R0, R1, reg); +#endif } else { NanoAssert(value->isop(LIR_ii2d)); findSpecificRegFor(value->oprnd1(), R0); // lo diff --git a/js/src/nanojit/NativeARM.h b/js/src/nanojit/NativeARM.h index 973e4362cca..e68f97976c4 100644 --- a/js/src/nanojit/NativeARM.h +++ b/js/src/nanojit/NativeARM.h @@ -75,7 +75,19 @@ namespace nanojit # define NJ_ARM_EABI 1 #endif -// only d0-d6 are actually used; we'll use d7 as s14-s15 for i2d/u2f/etc. +// GCC defines __ARM_PCS_VFP if it uses hardware floating point ABI +// See http://gcc.gnu.org/viewcvs?view=revision&revision=162637 +#ifdef __ARM_PCS_VFP +# define NJ_ARM_EABI_HARD_FLOAT 1 +#endif + +#ifdef NJ_ARM_EABI_HARD_FLOAT +# define ARM_EABI_HARD true +#else +# define ARM_EABI_HARD false +#endif + +// only d0-d7 are used; in addition, we'll use d0 as s0-s1 for i2d/u2f/etc. #define NJ_VFP_MAX_REGISTERS 8 #define NJ_MAX_REGISTERS (11 + NJ_VFP_MAX_REGISTERS) #define NJ_MAX_STACK_ENTRY 4096 @@ -118,7 +130,7 @@ static const Register LR = { 14 }, PC = { 15 }, - // VFP regs (we currently only use D0-D6 and S14) + // VFP regs (we currently only use D0-D7 and S0) D0 = { 16 }, D1 = { 17 }, D2 = { 18 }, @@ -126,23 +138,22 @@ static const Register D4 = { 20 }, D5 = { 21 }, D6 = { 22 }, - // S14 overlaps with D7 and is hard-coded into i2d and u2f operations, but - // D7 is still listed here for completeness and to facilitate assertions. D7 = { 23 }, // D8-D15 are caller-saved registers that we don't currently handle. FirstFloatReg = D0, - LastFloatReg = D6, + LastFloatReg = D7, deprecated_UnknownReg = { 32 }, // XXX: remove eventually, see bug 538924 - S14 = { 24 }, + // S0 overlaps with D0 and is hard-coded into i2d and u2f operations + S0 = { 24 }, SBZ = { 0 } ; // Used for 'should-be-zero' fields in instructions with // unused register fields. static const uint32_t FirstRegNum = R0; -static const uint32_t LastRegNum = D6; +static const uint32_t LastRegNum = D7; } #define NJ_USE_UINT32_REGISTER 1 @@ -189,6 +200,20 @@ typedef struct _FragInfo { NIns* epilogue; } FragInfo; +typedef struct _ParameterRegisters { + int stkd; + Register r; +#ifdef NJ_ARM_EABI_HARD_FLOAT + Register float_r; +#endif +} ParameterRegisters; + +#ifdef NJ_ARM_EABI_HARD_FLOAT +#define init_params(a,b,c) { (a), (b), (c) } +#else +#define init_params(a,b,c) { (a), (b) } +#endif + // D0-D7 are not saved; D8-D15 are, but we don't use those, // so we don't have to worry about saving/restoring them static const RegisterMask SavedFpRegs = 0; @@ -253,8 +278,8 @@ verbose_only( extern const char* shiftNames[]; ) void asm_cmp(LIns *cond); \ void asm_cmpd(LIns *cond); \ void asm_ld_imm(Register d, int32_t imm, bool chk = true); \ - void asm_arg(ArgType ty, LIns* arg, Register& r, int& stkd); \ - void asm_arg_64(LIns* arg, Register& r, int& stkd); \ + void asm_arg(ArgType ty, LIns* arg, ParameterRegisters& params); \ + void asm_arg_64(LIns* arg, ParameterRegisters& params); \ void asm_add_imm(Register rd, Register rn, int32_t imm, int stat = 0); \ void asm_sub_imm(Register rd, Register rn, int32_t imm, int stat = 0); \ void asm_and_imm(Register rd, Register rn, int32_t imm, int stat = 0); \ @@ -910,8 +935,8 @@ enum { #define FUITOD(_Dd,_Sm) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(IsFpReg(_Dd) && ((_Sm) == S14)); \ - *(--_nIns) = (NIns)( COND_AL | (0xEB8<<16) | (FpRegNum(_Dd)<<12) | (0x2D<<6) | (0<<5) | (0x7) ); \ + NanoAssert(IsFpReg(_Dd) && ((_Sm) == S0)); \ + *(--_nIns) = (NIns)( COND_AL | (0xEB8<<16) | (FpRegNum(_Dd)<<12) | (0x2D<<6) | (0<<5) | (0x0) ); \ asm_output("fuitod %s,%s", gpn(_Dd), gpn(_Sm)); \ } while (0) @@ -984,13 +1009,13 @@ enum { #define FMRS(_Rd,_Sn) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sn) == S14) && IsGpReg(_Rd)); \ - *(--_nIns) = (NIns)( COND_AL | (0xE1<<20) | (0x7<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ + NanoAssert(((_Sn) == S0) && IsGpReg(_Rd)); \ + *(--_nIns) = (NIns)( COND_AL | (0xE1<<20) | (0x0<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ asm_output("fmrs %s,%s", gpn(_Rd), gpn(_Sn)); \ } while (0) /* - * The following instructions can only be used with S14 as the + * The following instructions can only be used with S0 as the * single-precision register; that limitation can be removed if * needed, but we'd have to teach NJ about all the single precision * regs, and their encoding is strange (top 4 bits usually in a block, @@ -1000,55 +1025,55 @@ enum { #define FSITOD(_Dd,_Sm) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(IsFpReg(_Dd) && ((_Sm) == S14)); \ - *(--_nIns) = (NIns)( COND_AL | (0xEB8<<16) | (FpRegNum(_Dd)<<12) | (0x2F<<6) | (0<<5) | (0x7) ); \ + NanoAssert(IsFpReg(_Dd) && ((_Sm) == S0)); \ + *(--_nIns) = (NIns)( COND_AL | (0xEB8<<16) | (FpRegNum(_Dd)<<12) | (0x2F<<6) | (0<<5) | (0x0) ); \ asm_output("fsitod %s,%s", gpn(_Dd), gpn(_Sm)); \ } while (0) #define FMSR(_Sn,_Rd) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sn) == S14) && IsGpReg(_Rd)); \ - *(--_nIns) = (NIns)( COND_AL | (0xE0<<20) | (0x7<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ + NanoAssert(((_Sn) == S0) && IsGpReg(_Rd)); \ + *(--_nIns) = (NIns)( COND_AL | (0xE0<<20) | (0x0<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ asm_output("fmsr %s,%s", gpn(_Sn), gpn(_Rd)); \ } while (0) #define FMRS(_Rd,_Sn) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sn) == S14) && IsGpReg(_Rd)); \ - *(--_nIns) = (NIns)( COND_AL | (0xE1<<20) | (0x7<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ + NanoAssert(((_Sn) == S0) && IsGpReg(_Rd)); \ + *(--_nIns) = (NIns)( COND_AL | (0xE1<<20) | (0x0<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ asm_output("fmrs %s,%s", gpn(_Rd), gpn(_Sn)); \ } while (0) #define FMSR(_Sn,_Rd) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sn) == S14) && IsGpReg(_Rd)); \ - *(--_nIns) = (NIns)( COND_AL | (0xE0<<20) | (0x7<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ + NanoAssert(((_Sn) == S0) && IsGpReg(_Rd)); \ + *(--_nIns) = (NIns)( COND_AL | (0xE0<<20) | (0x0<<16) | ((_Rd)<<12) | (0xA<<8) | (0<<7) | (0x1<<4) ); \ asm_output("fmsr %s,%s", gpn(_Sn), gpn(_Rd)); \ } while (0) #define FCVTSD(_Sd,_Dm) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sd) == S14) && IsFpReg(_Dm)); \ - *(--_nIns) = (NIns)( COND_AL | (0xEB7<<16) | (0x7<<12) | (0xBC<<4) | (FpRegNum(_Dm)) ); \ - asm_output("[0x%08x] fcvtsd s14,%s", *_nIns, gpn(_Dm)); \ + NanoAssert(((_Sd) == S0) && IsFpReg(_Dm)); \ + *(--_nIns) = (NIns)( COND_AL | (0xEB7<<16) | (0x0<<12) | (0xBC<<4) | (FpRegNum(_Dm)) ); \ + asm_output("[0x%08x] fcvtsd s0,%s", *_nIns, gpn(_Dm)); \ } while (0) #define FCVTDS(_Dd,_Sm) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sm) == S14) && IsFpReg(_Dd)); \ - *(--_nIns) = (NIns)( COND_AL | (0xEB7<<16) | (FpRegNum(_Dd)<<12) | (0xAC<<4) | (0x7) ); \ - asm_output("fcvtds %s,s14", gpn(_Dd)); \ + NanoAssert(((_Sm) == S0) && IsFpReg(_Dd)); \ + *(--_nIns) = (NIns)( COND_AL | (0xEB7<<16) | (FpRegNum(_Dd)<<12) | (0xAC<<4) | (0x0) ); \ + asm_output("fcvtds %s,s0", gpn(_Dd)); \ } while(0) #define FLDS(_Sd,_Rn,_offs) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sd) == S14) && !IsFpReg(_Rn)); \ + NanoAssert(((_Sd) == S0) && !IsFpReg(_Rn)); \ NanoAssert(((_offs)%4) == 0); \ NanoAssert((isU8((_offs)/4)) || isU8(-(_offs)/4)); \ int addflag = 1<<23; \ @@ -1057,14 +1082,14 @@ enum { addflag = 0; \ offs = -offs; \ } \ - *(--_nIns) = (NIns)( COND_AL | (0xD1<<20) | ((_Rn)<<16) | (0x7<<12) | (0xA << 8) | addflag | ((offs>>2)&0xff) ); \ - asm_output("flds s14, [%s, #%d]", gpn(_Rn), (_offs)); \ + *(--_nIns) = (NIns)( COND_AL | (0xD1<<20) | ((_Rn)<<16) | (0x0<<12) | (0xA << 8) | addflag | ((offs>>2)&0xff) ); \ + asm_output("flds s0, [%s, #%d]", gpn(_Rn), (_offs)); \ } while (0) #define FSTS(_Sd,_Rn,_offs) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sd) == S14) && !IsFpReg(_Rn)); \ + NanoAssert(((_Sd) == S0) && !IsFpReg(_Rn)); \ NanoAssert(((_offs)%4) == 0); \ NanoAssert((isU8((_offs)/4)) || isU8(-(_offs)/4)); \ int addflag = 1<<23; \ @@ -1073,16 +1098,16 @@ enum { addflag = 0; \ offs = -offs; \ } \ - *(--_nIns) = (NIns)( COND_AL | (0xD0<<20) | ((_Rn)<<16) | (0x7<<12) | (0xA << 8) | addflag | ((offs>>2)&0xff) ); \ - asm_output("fsts s14, [%s, #%d]", gpn(_Rn), (_offs)); \ + *(--_nIns) = (NIns)( COND_AL | (0xD0<<20) | ((_Rn)<<16) | (0x0<<12) | (0xA << 8) | addflag | ((offs>>2)&0xff) ); \ + asm_output("fsts s0, [%s, #%d]", gpn(_Rn), (_offs)); \ } while (0) #define FTOSID(_Sd,_Dm) do { \ underrunProtect(4); \ NanoAssert(ARM_VFP); \ - NanoAssert(((_Sd) == S14) && IsFpReg(_Dm)); \ - *(--_nIns) = (NIns)( COND_AL | (0xEBD<<16) | (0x7<<12) | (0xB4<<4) | FpRegNum(_Dm) ); \ - asm_output("ftosid s14, %s", gpn(_Dm)); \ + NanoAssert(((_Sd) == S0) && IsFpReg(_Dm)); \ + *(--_nIns) = (NIns)( COND_AL | (0xEBD<<16) | (0x0<<12) | (0xB4<<4) | FpRegNum(_Dm) ); \ + asm_output("ftosid s0, %s", gpn(_Dm)); \ } while (0) } // namespace nanojit From 2bdb2f941b562d0b2d8ebde55845701ac6d00682 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sun, 31 Oct 2010 10:32:46 -0400 Subject: [PATCH 063/263] Bug 604395 - OpenGL contexts use uninitialized format, often resulting in failure to create - r+sr=vladimir, a=bjacob:trust me, we want this in beta7. Note: pushed by bjacob -- so complain to me if you're not happy about that. --- gfx/thebes/GLContext.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/GLContext.h b/gfx/thebes/GLContext.h index 9353cb8993c..9a6f31cf7a7 100644 --- a/gfx/thebes/GLContext.h +++ b/gfx/thebes/GLContext.h @@ -295,10 +295,11 @@ struct THEBES_API ContextFormat }; ContextFormat() { - memset(this, 0, sizeof(this)); + memset(this, 0, sizeof(*this)); } ContextFormat(const StandardContextFormat cf) { + memset(this, 0, sizeof(*this)); switch (cf) { case BasicRGBA32: red = green = blue = alpha = 8; From 40a819f1e319240d62be36b4040fea3580a48910 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Sun, 31 Oct 2010 11:07:33 -0700 Subject: [PATCH 064/263] Bug 607767 - Don't let XPConnect objetcs pretend to have an inner object hook, since that confuses us. r=peterv, a=beta7+ --- dom/base/nsDOMClassInfo.cpp | 9 ---- js/src/xpconnect/idl/nsIXPCScriptable.idl | 6 +-- js/src/xpconnect/public/xpc_map_end.h | 9 ---- js/src/xpconnect/src/xpcprivate.h | 1 - .../xpconnect/src/xpcwrappednativejsops.cpp | 48 ++----------------- 5 files changed, 4 insertions(+), 69 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index da7107f6a1e..52e1c10b64c 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4582,15 +4582,6 @@ nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, return NS_ERROR_UNEXPECTED; } -NS_IMETHODIMP -nsDOMClassInfo::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, - JSObject * obj, JSObject * *_retval) -{ - NS_WARNING("nsDOMClassInfo::InnerObject Don't call me!"); - - return NS_ERROR_UNEXPECTED; -} - static nsresult GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager, const nsString &aName, diff --git a/js/src/xpconnect/idl/nsIXPCScriptable.idl b/js/src/xpconnect/idl/nsIXPCScriptable.idl index 575749ac0c6..55ef7cb6fa3 100644 --- a/js/src/xpconnect/idl/nsIXPCScriptable.idl +++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl @@ -80,7 +80,7 @@ * to *_retval unless they want to return PR_FALSE. */ -[uuid(5d309b93-e9b4-4374-bcd5-44245c83408f)] +[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)] interface nsIXPCScriptable : nsISupports { /* bitflags used for 'flags' (only 32 bits available!) */ @@ -115,7 +115,6 @@ interface nsIXPCScriptable : nsISupports const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27; const PRUint32 WANT_EQUALITY = 1 << 28; const PRUint32 WANT_OUTER_OBJECT = 1 << 29; - const PRUint32 WANT_INNER_OBJECT = 1 << 30; // The high order bit is RESERVED for consumers of these flags. // No implementor of this interface should ever return flags @@ -197,9 +196,6 @@ interface nsIXPCScriptable : nsISupports JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); - JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper, - in JSContextPtr cx, in JSObjectPtr obj); - void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto); }; diff --git a/js/src/xpconnect/public/xpc_map_end.h b/js/src/xpconnect/public/xpc_map_end.h index 5d4e65792aa..e0d317041b8 100644 --- a/js/src/xpconnect/public/xpc_map_end.h +++ b/js/src/xpconnect/public/xpc_map_end.h @@ -118,10 +118,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags) #ifdef XPC_MAP_WANT_OUTER_OBJECT nsIXPCScriptable::WANT_OUTER_OBJECT | #endif -#ifdef XPC_MAP_WANT_INNER_OBJECT - nsIXPCScriptable::WANT_INNER_OBJECT | -#endif - #ifdef XPC_MAP_FLAGS XPC_MAP_FLAGS | #endif @@ -227,11 +223,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::OuterObject(nsIXPConnectWrappedNative *wrapper, {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} #endif -#ifndef XPC_MAP_WANT_INNER_OBJECT -NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval) - {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} -#endif - #ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *proto) {return NS_OK;} diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 79759815e37..98bb64864dd 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2004,7 +2004,6 @@ public: JSBool WantTrace() GET_IT(WANT_TRACE) JSBool WantEquality() GET_IT(WANT_EQUALITY) JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) - JSBool WantInnerObject() GET_IT(WANT_INNER_OBJECT) JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY) JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY) diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 3a0d49c89f0..6173a19ce91 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -857,45 +857,6 @@ XPC_WN_OuterObject(JSContext *cx, JSObject *obj) return obj; } -static JSObject * -XPC_WN_InnerObject(JSContext *cx, JSObject *obj) -{ - XPCWrappedNative *wrapper = - static_cast(obj->getPrivate()); - if(!wrapper) - { - Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); - - return nsnull; - } - - if(!wrapper->IsValid()) - { - Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); - - return nsnull; - } - - XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); - if(si && si->GetFlags().WantInnerObject()) - { - JSObject *newThis; - nsresult rv = - si->GetCallback()->InnerObject(wrapper, cx, obj, &newThis); - - if(NS_FAILED(rv)) - { - Throw(rv, cx); - - return nsnull; - } - - obj = newThis; - } - - return obj; -} - js::Class XPC_WN_NoHelper_JSClass = { "XPCWrappedNative_NoHelper", // name; WRAPPER_SLOTS | @@ -925,8 +886,8 @@ js::Class XPC_WN_NoHelper_JSClass = { // ClassExtension { JS_VALUEIFY(js::EqualityOp, XPC_WN_Equality), - XPC_WN_OuterObject, - XPC_WN_InnerObject, + nsnull, // outerObject + nsnull, // innerObject nsnull, // iteratorObject nsnull, // wrappedObject }, @@ -1589,11 +1550,8 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) if(mFlags.WantOuterObject()) mJSClass.base.ext.outerObject = XPC_WN_OuterObject; - if(mFlags.WantInnerObject()) - mJSClass.base.ext.innerObject = XPC_WN_InnerObject; - if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT | - nsIXPCScriptable::WANT_INNER_OBJECT))) + if(!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT)) mCanBeSlim = JS_TRUE; } From 131f4e4cc05dc79366a671f1f741963c10e15706 Mon Sep 17 00:00:00 2001 From: Johnny Stenback Date: Sun, 31 Oct 2010 12:20:04 -0700 Subject: [PATCH 065/263] Backed out changeset 1c265164a571 due to orange. a=backout --- dom/base/nsDOMClassInfo.cpp | 9 ++++ js/src/xpconnect/idl/nsIXPCScriptable.idl | 6 ++- js/src/xpconnect/public/xpc_map_end.h | 9 ++++ js/src/xpconnect/src/xpcprivate.h | 1 + .../xpconnect/src/xpcwrappednativejsops.cpp | 48 +++++++++++++++++-- 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 52e1c10b64c..da7107f6a1e 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4582,6 +4582,15 @@ nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, return NS_ERROR_UNEXPECTED; } +NS_IMETHODIMP +nsDOMClassInfo::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, JSObject * *_retval) +{ + NS_WARNING("nsDOMClassInfo::InnerObject Don't call me!"); + + return NS_ERROR_UNEXPECTED; +} + static nsresult GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager, const nsString &aName, diff --git a/js/src/xpconnect/idl/nsIXPCScriptable.idl b/js/src/xpconnect/idl/nsIXPCScriptable.idl index 55ef7cb6fa3..575749ac0c6 100644 --- a/js/src/xpconnect/idl/nsIXPCScriptable.idl +++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl @@ -80,7 +80,7 @@ * to *_retval unless they want to return PR_FALSE. */ -[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)] +[uuid(5d309b93-e9b4-4374-bcd5-44245c83408f)] interface nsIXPCScriptable : nsISupports { /* bitflags used for 'flags' (only 32 bits available!) */ @@ -115,6 +115,7 @@ interface nsIXPCScriptable : nsISupports const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27; const PRUint32 WANT_EQUALITY = 1 << 28; const PRUint32 WANT_OUTER_OBJECT = 1 << 29; + const PRUint32 WANT_INNER_OBJECT = 1 << 30; // The high order bit is RESERVED for consumers of these flags. // No implementor of this interface should ever return flags @@ -196,6 +197,9 @@ interface nsIXPCScriptable : nsISupports JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); + JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper, + in JSContextPtr cx, in JSObjectPtr obj); + void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto); }; diff --git a/js/src/xpconnect/public/xpc_map_end.h b/js/src/xpconnect/public/xpc_map_end.h index e0d317041b8..5d4e65792aa 100644 --- a/js/src/xpconnect/public/xpc_map_end.h +++ b/js/src/xpconnect/public/xpc_map_end.h @@ -118,6 +118,10 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags) #ifdef XPC_MAP_WANT_OUTER_OBJECT nsIXPCScriptable::WANT_OUTER_OBJECT | #endif +#ifdef XPC_MAP_WANT_INNER_OBJECT + nsIXPCScriptable::WANT_INNER_OBJECT | +#endif + #ifdef XPC_MAP_FLAGS XPC_MAP_FLAGS | #endif @@ -223,6 +227,11 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::OuterObject(nsIXPConnectWrappedNative *wrapper, {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} #endif +#ifndef XPC_MAP_WANT_INNER_OBJECT +NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval) + {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} +#endif + #ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *proto) {return NS_OK;} diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 98bb64864dd..79759815e37 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2004,6 +2004,7 @@ public: JSBool WantTrace() GET_IT(WANT_TRACE) JSBool WantEquality() GET_IT(WANT_EQUALITY) JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) + JSBool WantInnerObject() GET_IT(WANT_INNER_OBJECT) JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY) JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY) diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 6173a19ce91..3a0d49c89f0 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -857,6 +857,45 @@ XPC_WN_OuterObject(JSContext *cx, JSObject *obj) return obj; } +static JSObject * +XPC_WN_InnerObject(JSContext *cx, JSObject *obj) +{ + XPCWrappedNative *wrapper = + static_cast(obj->getPrivate()); + if(!wrapper) + { + Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); + + return nsnull; + } + + if(!wrapper->IsValid()) + { + Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); + + return nsnull; + } + + XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); + if(si && si->GetFlags().WantInnerObject()) + { + JSObject *newThis; + nsresult rv = + si->GetCallback()->InnerObject(wrapper, cx, obj, &newThis); + + if(NS_FAILED(rv)) + { + Throw(rv, cx); + + return nsnull; + } + + obj = newThis; + } + + return obj; +} + js::Class XPC_WN_NoHelper_JSClass = { "XPCWrappedNative_NoHelper", // name; WRAPPER_SLOTS | @@ -886,8 +925,8 @@ js::Class XPC_WN_NoHelper_JSClass = { // ClassExtension { JS_VALUEIFY(js::EqualityOp, XPC_WN_Equality), - nsnull, // outerObject - nsnull, // innerObject + XPC_WN_OuterObject, + XPC_WN_InnerObject, nsnull, // iteratorObject nsnull, // wrappedObject }, @@ -1550,8 +1589,11 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) if(mFlags.WantOuterObject()) mJSClass.base.ext.outerObject = XPC_WN_OuterObject; + if(mFlags.WantInnerObject()) + mJSClass.base.ext.innerObject = XPC_WN_InnerObject; - if(!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT)) + if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT | + nsIXPCScriptable::WANT_INNER_OBJECT))) mCanBeSlim = JS_TRUE; } From 7224f2d38d669cbad679f1ac2919294b6f3586f2 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 30 Oct 2010 01:31:45 +0200 Subject: [PATCH 066/263] Bug 573524 - Try to run the test on load to see if it fixes the intermittent orange; r=ehsan a=test-only --- content/html/document/test/test_bug404320.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/content/html/document/test/test_bug404320.html b/content/html/document/test/test_bug404320.html index 1d30a2e699b..47ffaada494 100644 --- a/content/html/document/test/test_bug404320.html +++ b/content/html/document/test/test_bug404320.html @@ -20,6 +20,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=404320 /** Test for Bug 404320 **/ +SimpleTest.waitForExplicitFinish(); + var win = document.getElementById("testIframe").contentWindow; var doc = document.getElementById("testIframe").contentDocument; @@ -76,8 +78,13 @@ var badTags = [ "b", "span", "foo" ]; -formatBlockTests(goodTags, true); -formatBlockTests(badTags, false); +function runTests() { + formatBlockTests(goodTags, true); + formatBlockTests(badTags, false); + SimpleTest.finish(); +} + +addLoadEvent(runTests); From f9c8022af640076a5bf2cf23ccae0ac0946c2039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20L=C3=B3pez?= Date: Fri, 29 Oct 2010 16:54:01 -0400 Subject: [PATCH 067/263] Bug 488037: certManager entities should use the .label/.accesskey convention, r=johnath, a=bsmedberg --HG-- extra : rebase_source : d817fe39ff9df258fa6824b0fdbee0e10947983c --- security/manager/locales/en-US/chrome/pippki/certManager.dtd | 4 ++-- security/manager/pki/resources/content/exceptionDialog.xul | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/security/manager/locales/en-US/chrome/pippki/certManager.dtd b/security/manager/locales/en-US/chrome/pippki/certManager.dtd index 08f2f6673d2..6bd9537cc8d 100644 --- a/security/manager/locales/en-US/chrome/pippki/certManager.dtd +++ b/security/manager/locales/en-US/chrome/pippki/certManager.dtd @@ -133,8 +133,8 @@ - - + + diff --git a/security/manager/pki/resources/content/exceptionDialog.xul b/security/manager/pki/resources/content/exceptionDialog.xul index 7d58c9560e6..27b8b0b4da7 100644 --- a/security/manager/pki/resources/content/exceptionDialog.xul +++ b/security/manager/pki/resources/content/exceptionDialog.xul @@ -47,8 +47,8 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&exceptionMgr.title;" buttons="cancel,extra1,extra2" - buttonlabelextra1="&exceptionMgr.exceptionButton;" - buttonaccesskeyextra1="&exceptionMgr.exceptionButtonAccess;" + buttonlabelextra1="&exceptionMgr.exceptionButton.label;" + buttonaccesskeyextra1="&exceptionMgr.exceptionButton.accesskey;" style="width: 500px; height: 480px;" onload="initExceptionDialog();" ondialogextra1="addException();" From 268eba2fece3e1748ed6829943ca39d2aa1a9a52 Mon Sep 17 00:00:00 2001 From: Dietrich Ayala Date: Fri, 29 Oct 2010 16:55:53 -0400 Subject: [PATCH 068/263] Bug 604316: use "A" as access key for "Add-on Bar" in View->Toolbars, to avoid conflict with "Bookmarks Toolbar", r=dao, a=bsmedberg --HG-- extra : rebase_source : 12b0ac741c09e62a6c741f67100738bf4dab7b33 --- browser/locales/en-US/chrome/browser/browser.dtd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd index 7dd0176202e..8a284575341 100644 --- a/browser/locales/en-US/chrome/browser/browser.dtd +++ b/browser/locales/en-US/chrome/browser/browser.dtd @@ -71,7 +71,7 @@ can reach it easily. --> - + From 10e721a4e1b6c974c19b20bb33c64c54fcb46766 Mon Sep 17 00:00:00 2001 From: Gavin Sharp Date: Fri, 29 Oct 2010 17:17:36 -0400 Subject: [PATCH 069/263] Bug 608162: adjust margin on search textbox on about:home, r=mak, a=blocking --HG-- extra : rebase_source : ab87734b2a8bbb56a368216cded7752644ad2922 --- browser/base/content/aboutHome.css | 1 + browser/base/content/aboutHome.xhtml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/aboutHome.css b/browser/base/content/aboutHome.css index a7fa25da132..34fe486f38c 100644 --- a/browser/base/content/aboutHome.css +++ b/browser/base/content/aboutHome.css @@ -104,6 +104,7 @@ body[dir="rtl"] #searchEngineLinks { } #searchText { + margin-bottom: 10px; width: 100%; } diff --git a/browser/base/content/aboutHome.xhtml b/browser/base/content/aboutHome.xhtml index 0e32857e96a..49ac3e03a08 100644 --- a/browser/base/content/aboutHome.xhtml +++ b/browser/base/content/aboutHome.xhtml @@ -72,7 +72,6 @@
-
From 9e9e11865a273e663fcc8192b332bf3d686dc9b6 Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Thu, 28 Oct 2010 14:15:15 -0400 Subject: [PATCH 070/263] Bug 608036 - Cleanup some of client.mk r=khuey a=NPOTB --HG-- extra : rebase_source : fbf93e2ba4ea8c8e83dce84424c808accae6c566 --- client.mk | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/client.mk b/client.mk index bb338aea1b0..33a2bbef8ab 100644 --- a/client.mk +++ b/client.mk @@ -69,8 +69,7 @@ # ####################################################################### # Defines -# -CVS = cvs + comma := , CWD := $(CURDIR) @@ -107,7 +106,6 @@ endif PERL ?= perl PYTHON ?= python -RUN_AUTOCONF_LOCALLY = 1 CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess) ifdef CONFIG_GUESS_SCRIPT CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT)) @@ -170,7 +168,6 @@ CONFIGURES += $(TOPSRCDIR)/js/src/configure ####################################################################### # Rules -# # The default rule is build build:: @@ -272,7 +269,6 @@ else CONFIG_STATUS = $(wildcard $(OBJDIR)/config.status) CONFIG_CACHE = $(wildcard $(OBJDIR)/config.cache) -ifdef RUN_AUTOCONF_LOCALLY EXTRA_CONFIG_DEPS := \ $(TOPSRCDIR)/aclocal.m4 \ $(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \ @@ -282,7 +278,6 @@ EXTRA_CONFIG_DEPS := \ $(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS) @echo Generating $@ using autoconf cd $(@D); $(AUTOCONF) -endif CONFIG_STATUS_DEPS := \ $(wildcard $(CONFIGURES)) \ @@ -290,8 +285,7 @@ CONFIG_STATUS_DEPS := \ $(TOPSRCDIR)/.mozconfig.mk \ $(wildcard $(TOPSRCDIR)/nsprpub/configure) \ $(wildcard $(TOPSRCDIR)/config/milestone.txt) \ - $(wildcard $(TOPSRCDIR)/config/chrome-versions.sh) \ - $(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \ + $(wildcard $(addsuffix confvars.sh,$(wildcard $(TOPSRCDIR)/*/))) \ $(NULL) # configure uses the program name to determine @srcdir@. Calling it without @@ -303,10 +297,6 @@ else CONFIGURE = $(TOPSRCDIR)/configure endif -ifdef MOZ_TOOLS - CONFIGURE = $(TOPSRCDIR)/configure -endif - configure-files: $(CONFIGURES) configure:: configure-files @@ -417,4 +407,4 @@ echo-variable-%: # in parallel. .NOTPARALLEL: -.PHONY: checkout real_checkout depend build profiledbuild maybe_clobber_profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all +.PHONY: checkout real_checkout depend build profiledbuild maybe_clobber_profiledbuild export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything configure preflight_all preflight postflight postflight_all upload sdk From f5b600f75014d755a5f20258c5408f65281b7af8 Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Thu, 28 Oct 2010 14:28:21 -0400 Subject: [PATCH 071/263] Bug 608044 - m-c rules.mk needs whitespace and spelling fixes. rs+=khuey, a=NPOTB --HG-- extra : rebase_source : a2b2159faa8fcc8bf0a72427a5f5398de6e3981a --- config/rules.mk | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/config/rules.mk b/config/rules.mk index cf57ed38774..a2a00791169 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -171,8 +171,8 @@ SOLO_FILE ?= $(error Specify a test filename in SOLO_FILE when using check-inter libs:: $(foreach dir,$(XPCSHELL_TESTS),$(_INSTALL_TESTS)) $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \ - $(testxpcobjdir)/all-test-dirs.list \ - $(addprefix $(relativesrcdir)/,$(XPCSHELL_TESTS)) + $(testxpcobjdir)/all-test-dirs.list \ + $(addprefix $(relativesrcdir)/,$(XPCSHELL_TESTS)) testxpcsrcdir = $(topsrcdir)/testing/xpcshell @@ -180,39 +180,39 @@ testxpcsrcdir = $(topsrcdir)/testing/xpcshell # See also testsuite-targets.mk 'xpcshell-tests' target for global execution. xpcshell-tests: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - $(EXTRA_TEST_ARGS) \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + $(EXTRA_TEST_ARGS) \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE), but don't automatically # start the test. Instead, present the xpcshell prompt so the user can # attach a debugger and then start the test. check-interactive: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --interactive \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + --test-path=$(SOLO_FILE) \ + --profile-name=$(MOZ_APP_NAME) \ + --interactive \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE) check-one: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + --test-path=$(SOLO_FILE) \ + --profile-name=$(MOZ_APP_NAME) \ + --verbose \ + $(EXTRA_TEST_ARGS) \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) endif # XPCSHELL_TESTS @@ -846,7 +846,7 @@ ifdef MODULE_NAME @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME) endif endif # BUILD_STATIC_LIBS -else # !IS_COMPONENT +else # !IS_COMPONENT $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME) endif # IS_COMPONENT endif # EXPORT_LIBRARY @@ -874,7 +874,7 @@ endif # _LIBDIRS endif # _LIBNAME_RELATIVE_PATHS -# Dependancies which, if modified, should cause everything to rebuild +# Dependencies which, if modified, should cause everything to rebuild GLOBAL_DEPS += Makefile Makefile.in $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk ############################################## @@ -1198,7 +1198,7 @@ CLEANUP2 := true endif SUB_LOBJS = $(shell for lib in $(SHARED_LIBRARY_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;) endif # EXPAND_FAKELIBS -endif # SHARED_LIBARY_LIBS +endif # SHARED_LIBRARY_LIBS endif ifdef MOZILLA_PROBE_LIBS PROBE_LOBJS = $(shell for lib in $(MOZILLA_PROBE_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;) @@ -1578,7 +1578,7 @@ normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p))) else # assume MSYS # We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a nonexistent path, we cannot call 'pwd -W' directly +# could be a file or a non-existent path, we cannot call 'pwd -W' directly # on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' # on it, then merge with the rest of the path. root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") From ab2f3cf055559924135c274ed0556e719de6f68c Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Thu, 28 Oct 2010 22:51:00 -0400 Subject: [PATCH 072/263] Bug 608173 - Build system should provide an intelligible error when switching from gmake to pymake or vice versa on an absolutely configured objdir. r=khuey, a=NPOTB --HG-- extra : rebase_source : 821fd92d3e3473b47b39def3d2477a1195adc2f4 --- config/autoconf.mk.in | 13 +++++++++++++ js/src/config/autoconf.mk.in | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 059600bf0db..2528892cf80 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -696,3 +696,16 @@ ANDROID_TOOLS = @ANDROID_TOOLS@ ANDROID_VERSION = @ANDROID_VERSION@ JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@ + +# We only want to do the pymake sanity on Windows, other os's can cope +ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH))) +# Ensure invariants between GNU Make and pymake +# Checked here since we want the sane error in a file that +# actually can be found regardless of path-style. +ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir))) +$(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake]) +endif +ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(srcdir)))) +$(error MSYS-style srcdir being used with Pymake. Did you mean to run GNU Make instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake]) +endif +endif # Windows diff --git a/js/src/config/autoconf.mk.in b/js/src/config/autoconf.mk.in index fc3054663c1..ad44646a9a9 100644 --- a/js/src/config/autoconf.mk.in +++ b/js/src/config/autoconf.mk.in @@ -345,3 +345,16 @@ HAVE_ARM_SIMD= @HAVE_ARM_SIMD@ JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@ HAVE_LINUX_PERF_EVENT_H = @HAVE_LINUX_PERF_EVENT_H@ + +# We only want to do the pymake sanity on Windows, other os's can cope +ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH))) +# Ensure invariants between GNU Make and pymake +# Checked here since we want the sane error in a file that +# actually can be found regardless of path-style. +ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir))) +$(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake]) +endif +ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(srcdir)))) +$(error MSYS-style srcdir being used with Pymake. Did you mean to run GNU Make instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake]) +endif +endif # Windows From 45be115a63fbdad53edcfad0a09e5ffcb8fc775b Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Sun, 31 Oct 2010 22:39:52 -0400 Subject: [PATCH 073/263] Add debugging info for Bug 608634. rs+=cpearce over IRC, a=NPOTB (Bug 608634 - [SeaMonkey] [mochi-1] test_error_in_video_document.html failing) --HG-- extra : rebase_source : dd5c4049e24ce79e266e2b28038c36525a6fd52b --- content/media/test/test_error_in_video_document.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/media/test/test_error_in_video_document.html b/content/media/test/test_error_in_video_document.html index 8cbc66f3f37..7ec6f322d6c 100644 --- a/content/media/test/test_error_in_video_document.html +++ b/content/media/test/test_error_in_video_document.html @@ -26,6 +26,11 @@ var f = document.createElement("iframe"); function check() { var v = document.body.getElementsByTagName("iframe")[0].contentDocument.body.getElementsByTagName("video")[0]; + + // Debug info for Bug 608634 + info(document.body.getElementsByTagName("iframe")[0].src); + info(v.src); + ok(v.error && v.error.code == MediaError.MEDIA_ERR_DECODE, "Must have error set to MEDIA_ERR_DECODE"); SimpleTest.finish(); } From 34b63a20a1978b1d7f46b1e9691b2cb9641193ec Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Sun, 31 Oct 2010 23:09:38 -0400 Subject: [PATCH 074/263] Bug 608044 followout, sync rules.mk with js/src too. I hate this test. a=BustageFix. --- js/src/config/rules.mk | 58 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index cf57ed38774..a2a00791169 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -171,8 +171,8 @@ SOLO_FILE ?= $(error Specify a test filename in SOLO_FILE when using check-inter libs:: $(foreach dir,$(XPCSHELL_TESTS),$(_INSTALL_TESTS)) $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \ - $(testxpcobjdir)/all-test-dirs.list \ - $(addprefix $(relativesrcdir)/,$(XPCSHELL_TESTS)) + $(testxpcobjdir)/all-test-dirs.list \ + $(addprefix $(relativesrcdir)/,$(XPCSHELL_TESTS)) testxpcsrcdir = $(topsrcdir)/testing/xpcshell @@ -180,39 +180,39 @@ testxpcsrcdir = $(topsrcdir)/testing/xpcshell # See also testsuite-targets.mk 'xpcshell-tests' target for global execution. xpcshell-tests: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - $(EXTRA_TEST_ARGS) \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + $(EXTRA_TEST_ARGS) \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE), but don't automatically # start the test. Instead, present the xpcshell prompt so the user can # attach a debugger and then start the test. check-interactive: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --interactive \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + --test-path=$(SOLO_FILE) \ + --profile-name=$(MOZ_APP_NAME) \ + --interactive \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE) check-one: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build \ - $(testxpcsrcdir)/runxpcshelltests.py \ - --symbols-path=$(DIST)/crashreporter-symbols \ - --test-path=$(SOLO_FILE) \ - --profile-name=$(MOZ_APP_NAME) \ - --verbose \ - $(EXTRA_TEST_ARGS) \ - $(DIST)/bin/xpcshell \ - $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) + -I$(topsrcdir)/build \ + $(testxpcsrcdir)/runxpcshelltests.py \ + --symbols-path=$(DIST)/crashreporter-symbols \ + --test-path=$(SOLO_FILE) \ + --profile-name=$(MOZ_APP_NAME) \ + --verbose \ + $(EXTRA_TEST_ARGS) \ + $(DIST)/bin/xpcshell \ + $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) endif # XPCSHELL_TESTS @@ -846,7 +846,7 @@ ifdef MODULE_NAME @$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME) endif endif # BUILD_STATIC_LIBS -else # !IS_COMPONENT +else # !IS_COMPONENT $(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME) endif # IS_COMPONENT endif # EXPORT_LIBRARY @@ -874,7 +874,7 @@ endif # _LIBDIRS endif # _LIBNAME_RELATIVE_PATHS -# Dependancies which, if modified, should cause everything to rebuild +# Dependencies which, if modified, should cause everything to rebuild GLOBAL_DEPS += Makefile Makefile.in $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk ############################################## @@ -1198,7 +1198,7 @@ CLEANUP2 := true endif SUB_LOBJS = $(shell for lib in $(SHARED_LIBRARY_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;) endif # EXPAND_FAKELIBS -endif # SHARED_LIBARY_LIBS +endif # SHARED_LIBRARY_LIBS endif ifdef MOZILLA_PROBE_LIBS PROBE_LOBJS = $(shell for lib in $(MOZILLA_PROBE_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;) @@ -1578,7 +1578,7 @@ normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p))) else # assume MSYS # We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a nonexistent path, we cannot call 'pwd -W' directly +# could be a file or a non-existent path, we cannot call 'pwd -W' directly # on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' # on it, then merge with the rest of the path. root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") From 55862538df50ca043150d44253939abd0aaacf4f Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Sun, 31 Oct 2010 23:19:37 -0400 Subject: [PATCH 075/263] More bustage fix from mochi not having info(). a=bustage --- content/media/test/test_error_in_video_document.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/media/test/test_error_in_video_document.html b/content/media/test/test_error_in_video_document.html index 7ec6f322d6c..8bf4bc7e4f8 100644 --- a/content/media/test/test_error_in_video_document.html +++ b/content/media/test/test_error_in_video_document.html @@ -28,8 +28,8 @@ function check() { var v = document.body.getElementsByTagName("iframe")[0].contentDocument.body.getElementsByTagName("video")[0]; // Debug info for Bug 608634 - info(document.body.getElementsByTagName("iframe")[0].src); - info(v.src); + ok(true, "iframe src=" + document.body.getElementsByTagName("iframe")[0].src); + ok(true, "video src=" + v.src); ok(v.error && v.error.code == MediaError.MEDIA_ERR_DECODE, "Must have error set to MEDIA_ERR_DECODE"); SimpleTest.finish(); From 9368c457b602b94fc0c373de6bdd6333f31b5b18 Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Mon, 1 Nov 2010 11:50:04 +0100 Subject: [PATCH 076/263] bug 578643, add ast, es-CL, gd, km, mai, ta-LK to the mozilla-central firefox build, a=NPOTB --- browser/locales/all-locales | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/browser/locales/all-locales b/browser/locales/all-locales index 0b00d09a9c8..64292530872 100644 --- a/browser/locales/all-locales +++ b/browser/locales/all-locales @@ -2,6 +2,7 @@ af ak ar as +ast be bg bn-BD @@ -18,6 +19,7 @@ en-GB en-ZA eo es-AR +es-CL es-ES es-MX et @@ -27,6 +29,7 @@ fi fr fy-NL ga-IE +gd gl gu-IN he @@ -40,12 +43,14 @@ it ja ja-JP-mac ka +km kn ko ku lg lt lv +mai mk ml mn @@ -71,6 +76,7 @@ sq sr sv-SE ta +ta-LK te th tr From f6ae2fb75f68a29a99b574a6c301c818d524a0ae Mon Sep 17 00:00:00 2001 From: Bill Gianopoulos Date: Mon, 1 Nov 2010 14:15:13 +0100 Subject: [PATCH 077/263] Bug 585370 - Move app menu contents to a separate file. r=dao a=no-code-change --- browser/base/content/browser-appmenu.inc | 409 +++++++++++++++++++++++ browser/base/content/browser.xul | 366 +------------------- 2 files changed, 410 insertions(+), 365 deletions(-) create mode 100644 browser/base/content/browser-appmenu.inc diff --git a/browser/base/content/browser-appmenu.inc b/browser/base/content/browser-appmenu.inc new file mode 100644 index 00000000000..cf74a584e0e --- /dev/null +++ b/browser/base/content/browser-appmenu.inc @@ -0,0 +1,409 @@ +# -*- Mode: HTML -*- +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Firefox Application Menu. +# +# The Initial Developer of the Original Code is +# The Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2010 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Dão Gottwald +# Joshua M. +# Margaret Leibovic +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + + +#else + onpopupshowing="updateEditUIVisibility();"> +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#define ID_PREFIX appmenu_ +#include browser-charsetmenu.inc +#undef ID_PREFIX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ifdef MOZ_SERVICES_SYNC + + + + +#endif + + + diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index d629ad790fc..3939bb1046d 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -441,371 +441,7 @@ label="&appMenuButton.label;" #endif style="-moz-user-focus: ignore;"> - -#else - onpopupshowing="updateEditUIVisibility();"> -#endif - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define ID_PREFIX appmenu_ -#include browser-charsetmenu.inc -#undef ID_PREFIX - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef MOZ_SERVICES_SYNC - - - - -#endif - - - +#include browser-appmenu.inc From 024d857be87f4bcf2e88ff1cde29ee8f5061fa25 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 25 Oct 2010 15:17:38 +0300 Subject: [PATCH 078/263] Bug 594339 - Create a FromParser enum. r=hsivonen, sr=bzbarsky, a=jonas. --HG-- extra : rebase_source : 70d6b15b0b149a29d0cdb298209706bb5391f6b4 --- content/base/public/FromParser.h | 56 ++++++++++++++++++ content/base/public/Makefile.in | 5 +- .../base/public/nsContentCreatorFunctions.h | 18 ++---- content/base/public/nsIScriptElement.h | 13 ++--- content/base/src/nsDocument.cpp | 6 +- content/base/src/nsNameSpaceManager.cpp | 4 +- content/base/src/nsScriptElement.h | 2 +- content/base/src/nsScriptLoader.cpp | 6 +- .../html/content/public/nsHTMLAudioElement.h | 2 +- .../html/content/public/nsHTMLMediaElement.h | 2 +- .../html/content/public/nsHTMLVideoElement.h | 2 +- .../html/content/src/nsGenericHTMLElement.h | 57 ++++++++++--------- .../html/content/src/nsHTMLAudioElement.cpp | 6 +- .../html/content/src/nsHTMLCanvasElement.cpp | 3 +- content/html/content/src/nsHTMLElement.cpp | 3 +- .../html/content/src/nsHTMLFormElement.cpp | 7 +-- .../html/content/src/nsHTMLFrameElement.cpp | 5 +- .../html/content/src/nsHTMLIFrameElement.cpp | 12 ++-- .../html/content/src/nsHTMLImageElement.cpp | 4 +- .../html/content/src/nsHTMLInputElement.cpp | 11 ++-- content/html/content/src/nsHTMLInputElement.h | 2 +- .../html/content/src/nsHTMLMediaElement.cpp | 3 +- .../html/content/src/nsHTMLObjectElement.cpp | 17 +++--- .../html/content/src/nsHTMLOptionElement.cpp | 4 +- .../html/content/src/nsHTMLScriptElement.cpp | 12 ++-- .../html/content/src/nsHTMLSelectElement.cpp | 4 +- .../html/content/src/nsHTMLSelectElement.h | 2 +- .../content/src/nsHTMLSharedObjectElement.cpp | 16 +++--- .../content/src/nsHTMLTextAreaElement.cpp | 8 ++- .../html/content/src/nsHTMLVideoElement.cpp | 4 +- .../html/content/src/nsTextEditorState.cpp | 6 +- .../html/document/src/nsHTMLContentSink.cpp | 14 +++-- .../src/nsHTMLFragmentContentSink.cpp | 7 ++- .../html/document/src/nsPluginDocument.cpp | 2 +- content/html/document/src/nsVideoDocument.cpp | 2 +- content/svg/content/src/nsSVGElement.h | 2 +- .../svg/content/src/nsSVGElementFactory.cpp | 8 ++- content/svg/content/src/nsSVGSVGElement.cpp | 10 ++-- content/svg/content/src/nsSVGSVGElement.h | 6 +- .../svg/content/src/nsSVGScriptElement.cpp | 13 ++--- content/svg/content/src/nsSVGUseElement.cpp | 3 +- content/svg/content/src/nsSVGUseElement.h | 3 +- content/xbl/src/nsXBLContentSink.cpp | 2 +- content/xbl/src/nsXBLContentSink.h | 2 +- content/xml/document/src/nsXMLContentSink.cpp | 7 ++- content/xml/document/src/nsXMLContentSink.h | 3 +- .../document/src/nsXMLFragmentContentSink.cpp | 8 ++- content/xslt/src/xslt/txMozillaTextOutput.cpp | 5 +- content/xslt/src/xslt/txMozillaXMLOutput.cpp | 7 ++- content/xul/document/src/nsXULDocument.cpp | 5 +- .../xul/templates/src/nsXULContentBuilder.cpp | 2 +- layout/forms/nsComboboxControlFrame.cpp | 6 +- layout/forms/nsFileControlFrame.cpp | 11 +++- layout/forms/nsIsIndexFrame.cpp | 10 +++- parser/html/nsHtml5TreeOperation.cpp | 12 ++-- 55 files changed, 279 insertions(+), 173 deletions(-) create mode 100644 content/base/public/FromParser.h diff --git a/content/base/public/FromParser.h b/content/base/public/FromParser.h new file mode 100644 index 00000000000..7650b2e1260 --- /dev/null +++ b/content/base/public/FromParser.h @@ -0,0 +1,56 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla.org code. + * + * The Initial Developer of the Original Code is + * Ms2ger . + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla_dom_FromParser_h +#define mozilla_dom_FromParser_h + +namespace mozilla { +namespace dom { + +/** + * Constants for passing as aFromParser + */ +enum FromParser { + NOT_FROM_PARSER = 0, + FROM_PARSER_NETWORK = 1, + FROM_PARSER_DOCUMENT_WRITE = 1 << 1, + FROM_PARSER_FRAGMENT = 1 << 2 +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_FromParser_h diff --git a/content/base/public/Makefile.in b/content/base/public/Makefile.in index 3d662c3b745..3bdf344e745 100644 --- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -84,8 +84,9 @@ $(NULL) EXPORTS_NAMESPACES = mozilla/dom EXPORTS_mozilla/dom = \ -Element.h \ -$(NULL) + Element.h \ + FromParser.h \ + $(NULL) ifndef DISABLE_XFORMS_HOOKS EXPORTS += nsIXFormsUtilityService.h diff --git a/content/base/public/nsContentCreatorFunctions.h b/content/base/public/nsContentCreatorFunctions.h index 8b02d0be756..bd56f71372f 100644 --- a/content/base/public/nsContentCreatorFunctions.h +++ b/content/base/public/nsContentCreatorFunctions.h @@ -42,6 +42,7 @@ #include "nscore.h" #include "nsCOMPtr.h" +#include "mozilla/dom/FromParser.h" /** * Functions to create content, to be used only inside Gecko @@ -56,17 +57,10 @@ class imgIRequest; class nsNodeInfoManager; class nsGenericHTMLElement; -/** - * Constants for passing as aFromParser - */ -#define NS_NOT_FROM_PARSER 0 -#define NS_FROM_PARSER_NETWORK 1 -#define NS_FROM_PARSER_DOCUMENT_WRITE (1 << 1) -#define NS_FROM_PARSER_FRAGMENT (1 << 2) - nsresult NS_NewElement(nsIContent** aResult, PRInt32 aElementType, - already_AddRefed aNodeInfo, PRUint32 aFromParser); + already_AddRefed aNodeInfo, + mozilla::dom::FromParser aFromParser); nsresult NS_NewXMLElement(nsIContent** aResult, already_AddRefed aNodeInfo); @@ -109,13 +103,13 @@ NS_NewXMLCDATASection(nsIContent** aInstancePtrResult, nsresult NS_NewHTMLElement(nsIContent** aResult, already_AddRefed aNodeInfo, - PRUint32 aFromParser); + mozilla::dom::FromParser aFromParser); // First argument should be nsHTMLTag, but that adds dependency to parser // for a bunch of files. already_AddRefed CreateHTMLElement(PRUint32 aNodeType, already_AddRefed aNodeInfo, - PRUint32 aFromParser); + mozilla::dom::FromParser aFromParser); #ifdef MOZ_MATHML nsresult @@ -134,7 +128,7 @@ NS_TrustedNewXULElement(nsIContent** aResult, already_AddRefed aNod #ifdef MOZ_SVG nsresult NS_NewSVGElement(nsIContent** aResult, already_AddRefed aNodeInfo, - PRUint32 aFromParser); + mozilla::dom::FromParser aFromParser); #endif nsresult diff --git a/content/base/public/nsIScriptElement.h b/content/base/public/nsIScriptElement.h index 5e7e1b99e06..7922d9abbe1 100644 --- a/content/base/public/nsIScriptElement.h +++ b/content/base/public/nsIScriptElement.h @@ -58,7 +58,7 @@ class nsIScriptElement : public nsIScriptLoaderObserver { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID) - nsIScriptElement(PRUint32 aFromParser) + nsIScriptElement(mozilla::dom::FromParser aFromParser) : mLineNumber(0), mAlreadyStarted(PR_FALSE), mMalformed(PR_FALSE), @@ -66,7 +66,7 @@ public: mFrozen(PR_FALSE), mDefer(PR_FALSE), mAsync(PR_FALSE), - mParserCreated((PRUint8)aFromParser), + mParserCreated(aFromParser), mCreatorParser(nsnull) { } @@ -120,10 +120,9 @@ public: } /** - * Returns a constant defined in nsContentCreatorFunctions.h. Non-zero - * values mean parser-created and zero means not parser-created. + * Returns how the element was created. */ - PRUint32 GetParserCreated() + mozilla::dom::FromParser GetParserCreated() { return mParserCreated; } @@ -156,7 +155,7 @@ public: mFrozen = PR_FALSE; mUri = nsnull; mCreatorParser = nsnull; - mParserCreated = NS_NOT_FROM_PARSER; + mParserCreated = mozilla::dom::NOT_FROM_PARSER; } void SetCreatorParser(nsIParser* aParser) @@ -234,7 +233,7 @@ protected: /** * Whether this element was parser-created. */ - PRUint8 mParserCreated; + mozilla::dom::FromParser mParserCreated; /** * The effective src (or null if no src). diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 1ce43f198dd..439cbb6d185 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -4371,7 +4371,8 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI, nsCOMPtr content; PRInt32 ns = nodeInfo->NamespaceID(); - rv = NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), PR_FALSE); + rv = NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), + NOT_FROM_PARSER); NS_ENSURE_SUCCESS(rv, rv); return CallQueryInterface(content, aReturn); @@ -6848,7 +6849,8 @@ nsDocument::CreateElem(const nsAString& aName, nsIAtom *aPrefix, PRInt32 aNamesp getter_AddRefs(nodeInfo)); NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - return NS_NewElement(aResult, elementType, nodeInfo.forget(), PR_FALSE); + return NS_NewElement(aResult, elementType, nodeInfo.forget(), + NOT_FROM_PARSER); } PRBool diff --git a/content/base/src/nsNameSpaceManager.cpp b/content/base/src/nsNameSpaceManager.cpp index 5bad0608999..ebf708b3973 100644 --- a/content/base/src/nsNameSpaceManager.cpp +++ b/content/base/src/nsNameSpaceManager.cpp @@ -57,6 +57,8 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #endif +using namespace mozilla::dom; + #ifdef MOZ_SVG PRBool NS_SVGEnabled(); #endif @@ -227,7 +229,7 @@ NameSpaceManagerImpl::GetNameSpaceID(const nsAString& aURI) nsresult NS_NewElement(nsIContent** aResult, PRInt32 aElementType, - already_AddRefed aNodeInfo, PRUint32 aFromParser) + already_AddRefed aNodeInfo, FromParser aFromParser) { if (aElementType == kNameSpaceID_XHTML) { return NS_NewHTMLElement(aResult, aNodeInfo, aFromParser); diff --git a/content/base/src/nsScriptElement.h b/content/base/src/nsScriptElement.h index be983c46660..d68bce09ca1 100644 --- a/content/base/src/nsScriptElement.h +++ b/content/base/src/nsScriptElement.h @@ -59,7 +59,7 @@ public: NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED - nsScriptElement(PRUint32 aFromParser) + nsScriptElement(mozilla::dom::FromParser aFromParser) : nsIScriptElement(aFromParser) { } diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 3a0915c8bb2..1132056086f 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -595,7 +595,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // The request has already been loaded and there are no pending style // sheets. If the script comes from the network stream, cheat for // performance reasons and avoid a trip through the event loop. - if (aElement->GetParserCreated() == NS_FROM_PARSER_NETWORK) { + if (aElement->GetParserCreated() == FROM_PARSER_NETWORK) { return ProcessRequest(request); } // Otherwise, we've got a document.written script, make a trip through @@ -641,14 +641,14 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) request->mURI = mDocument->GetDocumentURI(); request->mLineNo = aElement->GetScriptLineNumber(); - if (aElement->GetParserCreated() == NS_NOT_FROM_PARSER) { + if (aElement->GetParserCreated() == NOT_FROM_PARSER) { NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), "A script-inserted script is inserted without an update batch?"); nsContentUtils::AddScriptRunner(new nsScriptRequestProcessor(this, request)); return NS_OK; } - if (aElement->GetParserCreated() == NS_FROM_PARSER_NETWORK && + if (aElement->GetParserCreated() == FROM_PARSER_NETWORK && !ReadyToExecuteScripts()) { NS_ASSERTION(!mParserBlockingRequest, "There can be only one parser-blocking script at a time"); diff --git a/content/html/content/public/nsHTMLAudioElement.h b/content/html/content/public/nsHTMLAudioElement.h index 30752066b1a..2ba6666ea3e 100644 --- a/content/html/content/public/nsHTMLAudioElement.h +++ b/content/html/content/public/nsHTMLAudioElement.h @@ -51,7 +51,7 @@ class nsHTMLAudioElement : public nsHTMLMediaElement, { public: nsHTMLAudioElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLAudioElement(); // nsISupports diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 115a95d1887..14b191231f4 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -71,7 +71,7 @@ public: }; nsHTMLMediaElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLMediaElement(); /** diff --git a/content/html/content/public/nsHTMLVideoElement.h b/content/html/content/public/nsHTMLVideoElement.h index ce5b5bf4838..56507b89f89 100644 --- a/content/html/content/public/nsHTMLVideoElement.h +++ b/content/html/content/public/nsHTMLVideoElement.h @@ -46,7 +46,7 @@ class nsHTMLVideoElement : public nsHTMLMediaElement, { public: nsHTMLVideoElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLVideoElement(); // nsISupports diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index e4f8599d153..22da06325f1 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -987,10 +987,10 @@ class nsGenericHTMLFrameElement : public nsGenericHTMLElement, { public: nsGenericHTMLFrameElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + mozilla::dom::FromParser aFromParser) : nsGenericHTMLElement(aNodeInfo) { - mNetworkCreated = aFromParser == NS_FROM_PARSER_NETWORK; + mNetworkCreated = aFromParser == mozilla::dom::FROM_PARSER_NETWORK; } virtual ~nsGenericHTMLFrameElement(); @@ -1045,25 +1045,6 @@ protected: //---------------------------------------------------------------------- -/** - * A macro to implement the NS_NewHTMLXXXElement() functions. - */ -#define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \ -nsGenericHTMLElement* \ -NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ - PRUint32 aFromParser) \ -{ \ - return new nsHTML##_elementName##Element(aNodeInfo); \ -} - -#define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ -nsGenericHTMLElement* \ -NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ - PRUint32 aFromParser) \ -{ \ - return new nsHTML##_elementName##Element(aNodeInfo, aFromParser); \ -} - /** * A macro to implement the getter and setter for a given string * valued content property. The method uses the generic GetAttr and @@ -1073,12 +1054,12 @@ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ NS_IMETHODIMP \ _class::Get##_method(nsAString& aValue) \ { \ - return GetAttrHelper(nsGkAtoms::_atom, aValue); \ + return GetAttrHelper(nsGkAtoms::_atom, aValue); \ } \ NS_IMETHODIMP \ _class::Set##_method(const nsAString& aValue) \ { \ - return SetAttrHelper(nsGkAtoms::_atom, aValue); \ + return SetAttrHelper(nsGkAtoms::_atom, aValue); \ } /** @@ -1430,26 +1411,46 @@ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ NS_OFFSET_AND_INTERFACE_TABLE_END -// Element class factory methods - +/** + * A macro to declare the NS_NewHTMLXXXElement() functions. + */ #define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \ nsGenericHTMLElement* \ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); #define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName) \ inline nsGenericHTMLElement* \ NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ - PRUint32 aFromParser = 0) \ + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER) \ { \ return NS_NewHTMLSharedElement(aNodeInfo, aFromParser); \ } +/** + * A macro to implement the NS_NewHTMLXXXElement() functions. + */ +#define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \ +nsGenericHTMLElement* \ +NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ + mozilla::dom::FromParser aFromParser) \ +{ \ + return new nsHTML##_elementName##Element(aNodeInfo); \ +} + +#define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ +nsGenericHTMLElement* \ +NS_NewHTML##_elementName##Element(already_AddRefed aNodeInfo, \ + mozilla::dom::FromParser aFromParser) \ +{ \ + return new nsHTML##_elementName##Element(aNodeInfo, aFromParser); \ +} + // Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand. // (Calling the macro directly (with no args) produces compiler warnings.) nsGenericHTMLElement* NS_NewHTMLElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index 9369cc9e3b9..c20246729fe 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -68,9 +68,11 @@ #include "nsIDOMDocumentEvent.h" #include "nsIDOMProgressEvent.h" +using namespace mozilla::dom; + nsGenericHTMLElement* NS_NewHTMLAudioElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { /* * nsHTMLAudioElement's will be created without a nsINodeInfo passed in @@ -107,7 +109,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLAudioElement) nsHTMLAudioElement::nsHTMLAudioElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsHTMLMediaElement(aNodeInfo, aFromParser) { } diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index 4f7cb13c2f4..5b2f6bb87d9 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -56,11 +56,12 @@ #define DEFAULT_CANVAS_HEIGHT 150 using namespace mozilla; +using namespace mozilla::dom; using namespace mozilla::layers; nsGenericHTMLElement* NS_NewHTMLCanvasElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { return new nsHTMLCanvasElement(aNodeInfo); } diff --git a/content/html/content/src/nsHTMLElement.cpp b/content/html/content/src/nsHTMLElement.cpp index 826df9f20d2..92391b106ec 100644 --- a/content/html/content/src/nsHTMLElement.cpp +++ b/content/html/content/src/nsHTMLElement.cpp @@ -38,6 +38,7 @@ #include "nsGenericHTMLElement.h" #include "nsIDOMHTMLElement.h" +using namespace mozilla::dom; class nsHTMLElement : public nsGenericHTMLElement, public nsIDOMHTMLElement @@ -69,7 +70,7 @@ public: // (Calling the macro directly (with no args) produces compiler warnings.) nsGenericHTMLElement* NS_NewHTMLElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { return new nsHTMLElement(aNodeInfo); } diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 22fbb02bed4..b965e3d9391 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -85,6 +85,8 @@ #include "nsIDOMHTMLButtonElement.h" +using namespace mozilla::dom; + static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16; static const PRUint8 NS_FORM_AUTOCOMPLETE_ON = 1; @@ -234,12 +236,9 @@ ShouldBeInElements(nsIFormControl* aFormControl) // construction, destruction nsGenericHTMLElement* NS_NewHTMLFormElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { nsHTMLFormElement* it = new nsHTMLFormElement(aNodeInfo); - if (!it) { - return nsnull; - } nsresult rv = it->Init(); diff --git a/content/html/content/src/nsHTMLFrameElement.cpp b/content/html/content/src/nsHTMLFrameElement.cpp index d71526bd881..3c6fd50710d 100644 --- a/content/html/content/src/nsHTMLFrameElement.cpp +++ b/content/html/content/src/nsHTMLFrameElement.cpp @@ -41,13 +41,14 @@ #include "nsIDOMDocument.h" #include "nsDOMError.h" +using namespace mozilla::dom; class nsHTMLFrameElement : public nsGenericHTMLFrameElement, public nsIDOMHTMLFrameElement { public: nsHTMLFrameElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = NS_NOT_FROM_PARSER); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLFrameElement(); // nsISupports @@ -81,7 +82,7 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Frame) nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsGenericHTMLFrameElement(aNodeInfo, aFromParser) { } diff --git a/content/html/content/src/nsHTMLIFrameElement.cpp b/content/html/content/src/nsHTMLIFrameElement.cpp index dd99403803d..7a51adf394f 100644 --- a/content/html/content/src/nsHTMLIFrameElement.cpp +++ b/content/html/content/src/nsHTMLIFrameElement.cpp @@ -48,15 +48,17 @@ #include "nsRuleData.h" #include "nsStyleConsts.h" -class nsHTMLIFrameElement : public nsGenericHTMLFrameElement, - public nsIDOMHTMLIFrameElement +using namespace mozilla::dom; + +class nsHTMLIFrameElement : public nsGenericHTMLFrameElement + , public nsIDOMHTMLIFrameElement #ifdef MOZ_SVG - , public nsIDOMGetSVGDocument + , public nsIDOMGetSVGDocument #endif { public: nsHTMLIFrameElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = NS_NOT_FROM_PARSER); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLIFrameElement(); // nsISupports @@ -96,7 +98,7 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame) nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsGenericHTMLFrameElement(aNodeInfo, aFromParser) { } diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index ba7d1880de7..054f25b56a9 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -76,6 +76,8 @@ #include "nsLayoutUtils.h" +using namespace mozilla::dom; + // XXX nav attrs: suppress class nsHTMLImageElement : public nsGenericHTMLElement, @@ -154,7 +156,7 @@ protected: nsGenericHTMLElement* NS_NewHTMLImageElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { /* * nsHTMLImageElement's will be created without a nsINodeInfo passed in diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index a88c13def26..bd2a5c38570 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -127,6 +127,8 @@ #include "nsHTMLInputElement.h" +using namespace mozilla::dom; + // XXX align=left, hspace, vspace, border? other nav4 attrs static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID); @@ -612,14 +614,14 @@ static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget, NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Input) nsHTMLInputElement::nsHTMLInputElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsGenericHTMLFormElement(aNodeInfo), mType(kInputDefaultType->value), mBitField(0) { SET_BOOLBIT(mBitField, BF_PARSER_CREATING, aFromParser); SET_BOOLBIT(mBitField, BF_INHIBIT_RESTORATION, - aFromParser & NS_FROM_PARSER_FRAGMENT); + aFromParser & mozilla::dom::FROM_PARSER_FRAGMENT); mInputData.mState = new nsTextEditorState(this); NS_ADDREF(mInputData.mState); @@ -702,10 +704,7 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const *aResult = nsnull; nsCOMPtr ni = aNodeInfo; - nsHTMLInputElement *it = new nsHTMLInputElement(ni.forget(), PR_FALSE); - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } + nsHTMLInputElement *it = new nsHTMLInputElement(ni.forget(), NOT_FROM_PARSER); nsCOMPtr kungFuDeathGrip = it; nsresult rv = CopyInnerTo(it); diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index c3b442458ba..f2daddd334b 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -123,7 +123,7 @@ public: using nsIConstraintValidation::GetValidationMessage; nsHTMLInputElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser); + mozilla::dom::FromParser aFromParser); virtual ~nsHTMLInputElement(); // nsISupports diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index e1b01623bec..3999c112b13 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -121,6 +121,7 @@ static PRLogModuleInfo* gMediaElementEventsLog; #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" +using namespace mozilla::dom; using namespace mozilla::layers; // Under certain conditions there may be no-one holding references to @@ -1265,7 +1266,7 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMuted(PRBool aMuted) } nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsGenericHTMLElement(aNodeInfo), mCurrentLoadID(0), mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY), diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index 37ed6ae587e..1410153cc02 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -52,20 +52,21 @@ #include "nsIPluginInstance.h" #include "nsIConstraintValidation.h" +using namespace mozilla::dom; -class nsHTMLObjectElement : public nsGenericHTMLFormElement, - public nsObjectLoadingContent, - public nsIDOMHTMLObjectElement, - public nsIConstraintValidation +class nsHTMLObjectElement : public nsGenericHTMLFormElement + , public nsObjectLoadingContent + , public nsIDOMHTMLObjectElement + , public nsIConstraintValidation #ifdef MOZ_SVG - , public nsIDOMGetSVGDocument + , public nsIDOMGetSVGDocument #endif { public: using nsIConstraintValidation::GetValidationMessage; nsHTMLObjectElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser = 0); + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); virtual ~nsHTMLObjectElement(); // nsISupports @@ -158,12 +159,12 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object) nsHTMLObjectElement::nsHTMLObjectElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) : nsGenericHTMLFormElement(aNodeInfo), mIsDoneAddingChildren(!aFromParser) { RegisterFreezableElement(); - SetIsNetworkCreated(aFromParser == NS_FROM_PARSER_NETWORK); + SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK); // is always barred from constraint validation. SetBarredFromConstraintValidation(PR_TRUE); diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp index 8881caa677c..fcd63ec43f0 100644 --- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -66,13 +66,15 @@ #include "nsContentCreatorFunctions.h" #include "mozAutoDocUpdate.h" +using namespace mozilla::dom; + /** * Implementation of <option> */ nsGenericHTMLElement* NS_NewHTMLOptionElement(already_AddRefed aNodeInfo, - PRUint32 aFromParser) + FromParser aFromParser) { /* * nsHTMLOptionElement's will be created without a nsINodeInfo passed in diff --git a/content/html/content/src/nsHTMLScriptElement.cpp b/content/html/content/src/nsHTMLScriptElement.cpp index a250dc17e0c..fc16e8ee392 100644 --- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -58,6 +58,8 @@ #include "nsTArray.h" #include "nsDOMJSUtils.h" +using namespace mozilla::dom; + // // Helper class used to support diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index d52f4171db7..fd9cd8e6992 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -858,8 +858,7 @@ random-if(cocoaWidget) HTTP(..) == 404149-1.xul 404149-1-ref.xul # HTTP for font == 404301-1.html 404301-1-ref.html == 404309-1a.html 404309-1-ref.html == 404309-1b.html 404309-1-ref.html -# Disabled due to compartments for now. -#!= data:application/xml, data:text/plain, # ensure we pretty-print this XML instead of letting it appear blank (test for bug 404419) +!= data:application/xml, data:text/plain, # ensure we pretty-print this XML instead of letting it appear blank (test for bug 404419) == 404553-1.html 404553-1-ref.html # assertion test, also tests that marquee binding is applied correctly == 404666-1.html 404666-1-ref.html == 404666-2.html 404666-2-ref.html From f4cc47737928593d0723c2ece1c6429118a81dd4 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 26 Oct 2010 19:48:51 -0700 Subject: [PATCH 087/263] Bug 607174 - Add assertions to jsdbgapi.cpp and enter compartments where it isn't possible for the caller to do so. landing with r=gal --HG-- extra : rebase_source : f0e69380a0ef144e07af7d75b859712fe67bb753 --- js/jsd/jsd_xpc.cpp | 6 ++++++ js/src/jsapi.h | 4 ++-- js/src/jscntxtinlines.h | 4 ++++ js/src/jsdbgapi.cpp | 21 +++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 582852fb0fe..d044f1eafde 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -2316,7 +2316,13 @@ jsdValue::GetWrappedValue() if (result) { + JSContext *cx; + rv = cc->GetJSContext(&cx); + if (NS_FAILED(rv)) + return rv; *result = JSD_GetValueWrappedJSVal (mCx, mValue); + if (!JS_WrapValue(cx, result)) + return NS_ERROR_FAILURE; cc->SetReturnValueWasSet(PR_TRUE); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 72c2fdc7c25..ebbdd558e1c 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2635,10 +2635,10 @@ Call(JSContext *cx, jsval thisv, JSObject *funObj, uintN argc, jsval *argv, jsva return Call(cx, thisv, OBJECT_TO_JSVAL(funObj), argc, argv, rval); } -} // namespace JS +} /* namespace JS */ JS_BEGIN_EXTERN_C -#endif // __cplusplus +#endif /* __cplusplus */ /* * These functions allow setting an operation callback that will be called diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 4e02ffe5255..9697cd43815 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -570,6 +570,10 @@ class CompartmentChecker } } + void check(JSStackFrame *fp) { + check(&fp->scopeChain()); + } + void check(JSString *) { /* nothing for now */ } }; diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index b4b9deb1321..25d993e5743 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,6 +62,7 @@ #include "jsscript.h" #include "jsstaticcheck.h" #include "jsstr.h" +#include "jswrapper.h" #include "jsatominlines.h" #include "jsinterpinlines.h" @@ -1180,6 +1181,10 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp) { JS_ASSERT(cx->stack().contains(fp)); + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return NULL; + /* Force creation of argument and call objects if not yet created */ (void) JS_GetFrameCallObject(cx, fp); return js_GetScopeChain(cx, fp); @@ -1193,6 +1198,10 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp) if (!fp->isFunctionFrame()) return NULL; + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return NULL; + /* Force creation of argument object if not yet created */ (void) js_GetArgsObject(cx, fp); @@ -1208,6 +1217,11 @@ JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv) { if (fp->isDummyFrame()) return false; + + js::AutoCompartment ac(cx, &fp->scopeChain()); + if (!ac.enter()) + return false; + if (!fp->computeThis(cx)) return false; *thisv = Jsvalify(fp->thisValue()); @@ -1269,6 +1283,7 @@ JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp) JS_PUBLIC_API(void) JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval) { + assertSameCompartment(cx, fp, rval); fp->setReturnValue(Valueify(rval)); } @@ -1332,6 +1347,10 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp, if (!scobj) return false; + js::AutoCompartment ac(cx, scobj); + if (!ac.enter()) + return NULL; + /* * NB: This function breaks the assumption that the compiler can see all * calls and properly compute a static level. In order to get around this, @@ -1404,6 +1423,7 @@ JS_PUBLIC_API(JSBool) JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JSPropertyDesc *pd) { + assertSameCompartment(cx, obj); Shape *shape = (Shape *) sprop; pd->id = IdToJsval(shape->id); @@ -1457,6 +1477,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JS_PUBLIC_API(JSBool) JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) { + assertSameCompartment(cx, obj); Class *clasp = obj->getClass(); if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, From 6b833b5f93614b5fe6226d804ea29e7b900784dc Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 26 Oct 2010 19:54:06 -0700 Subject: [PATCH 088/263] Revert accidental change. --- layout/reftests/bugs/reftest.list | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index fd9cd8e6992..d52f4171db7 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -858,7 +858,8 @@ random-if(cocoaWidget) HTTP(..) == 404149-1.xul 404149-1-ref.xul # HTTP for font == 404301-1.html 404301-1-ref.html == 404309-1a.html 404309-1-ref.html == 404309-1b.html 404309-1-ref.html -!= data:application/xml, data:text/plain, # ensure we pretty-print this XML instead of letting it appear blank (test for bug 404419) +# Disabled due to compartments for now. +#!= data:application/xml, data:text/plain, # ensure we pretty-print this XML instead of letting it appear blank (test for bug 404419) == 404553-1.html 404553-1-ref.html # assertion test, also tests that marquee binding is applied correctly == 404666-1.html 404666-1-ref.html == 404666-2.html 404666-2-ref.html From 4e8f68915aafcdc55ab720b25c58f00959c29140 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 26 Oct 2010 20:21:39 -0700 Subject: [PATCH 089/263] Bug 606441 - TM: specialize Math.abs() for integers when possible. r=dvander. --- js/src/jsmath.cpp | 27 +++++++++++++-------------- js/src/jsmath.h | 3 +++ js/src/jstracer.cpp | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 814dbf01056..9feba7c72cf 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -115,8 +115,8 @@ Class js_MathClass = { ConvertStub }; -static JSBool -math_abs(JSContext *cx, uintN argc, Value *vp) +JSBool +js_math_abs(JSContext *cx, uintN argc, Value *vp) { jsdouble x, z; @@ -669,20 +669,19 @@ math_toSource(JSContext *cx, uintN argc, Value *vp) #ifdef JS_TRACER -#define MATH_BUILTIN_1(name) MATH_BUILTIN_CFUN_1(name, name) -#define MATH_BUILTIN_CFUN_1(name, cfun) \ - static jsdouble FASTCALL math_##name##_tn(MathCache *cache, jsdouble d) { \ +#define MATH_BUILTIN_1(name, cfun) \ + static jsdouble FASTCALL name##_tn(MathCache *cache, jsdouble d) { \ return cache->lookup(cfun, d); \ } \ - JS_DEFINE_TRCINFO_1(math_##name, \ - (2, (static, DOUBLE, math_##name##_tn, MATHCACHE, DOUBLE, 1, nanojit::ACCSET_NONE))) + JS_DEFINE_TRCINFO_1(name, \ + (2, (static, DOUBLE, name##_tn, MATHCACHE, DOUBLE, 1, nanojit::ACCSET_NONE))) -MATH_BUILTIN_CFUN_1(abs, fabs) -MATH_BUILTIN_1(atan) -MATH_BUILTIN_1(sin) -MATH_BUILTIN_1(cos) -MATH_BUILTIN_1(sqrt) -MATH_BUILTIN_1(tan) +MATH_BUILTIN_1(js_math_abs, fabs) +MATH_BUILTIN_1(math_atan, atan) +MATH_BUILTIN_1(math_sin, sin) +MATH_BUILTIN_1(math_cos, cos) +MATH_BUILTIN_1(math_sqrt, sqrt) +MATH_BUILTIN_1(math_tan, tan) static jsdouble FASTCALL math_acos_tn(MathCache *cache, jsdouble d) @@ -833,7 +832,7 @@ static JSFunctionSpec math_static_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, math_toSource, 0, 0), #endif - JS_TN("abs", math_abs, 1, 0, &math_abs_trcinfo), + JS_TN("abs", js_math_abs, 1, 0, &js_math_abs_trcinfo), JS_TN("acos", math_acos, 1, 0, &math_acos_trcinfo), JS_TN("asin", math_asin, 1, 0, &math_asin_trcinfo), JS_TN("atan", math_atan, 1, 0, &math_atan_trcinfo), diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 4a47d32129d..b6e059d3b1a 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -93,6 +93,9 @@ js_IsMathFunction(JSNative native); extern void js_InitRandom(JSContext *cx); +extern JSBool +js_math_abs(JSContext *cx, uintN argc, js::Value *vp); + extern JSBool js_math_ceil(JSContext *cx, uintN argc, js::Value *vp); diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 738cd6b9fb6..45a45d794c2 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -11529,6 +11529,23 @@ TraceRecorder::callNative(uintN argc, JSOp mode) if (roundReturningInt(vp[2].toNumber(), &result)) return callFloatReturningInt(argc, &roundReturningInt_ci); } + } else if (native == js_math_abs) { + LIns* a = get(&vp[2]); + if (isPromoteInt(a)) { + a = demote(lir, a); + /* abs(INT_MIN) can't be done using integers; exit if we see it. */ + LIns* intMin_ins = addName(lir->insImmI(0x80000000), "INT_MIN"); + LIns* isIntMin_ins = addName(lir->ins2(LIR_eqi, a, intMin_ins), "isIntMin"); + guard(false, isIntMin_ins, MISMATCH_EXIT); + LIns* neg_ins = lir->ins1(LIR_negi, a); + LIns* isNeg_ins = addName(lir->ins2ImmI(LIR_lti, a, 0), "isNeg"); + LIns* abs_ins = addName(lir->insChoose(isNeg_ins, neg_ins, a, + avmplus::AvmCore::use_cmov()), + "abs"); + set(&vp[0], i2d(abs_ins)); + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + return RECORD_CONTINUE; + } } if (vp[1].isString()) { JSString *str = vp[1].toString(); From 705886a03f2876b2c16274d9df80bfb14a582bc0 Mon Sep 17 00:00:00 2001 From: Leon Sha Date: Wed, 27 Oct 2010 14:09:47 +0800 Subject: [PATCH 090/263] Bug 607553 - [JAEGER] Multiple cases failed in MONOIC only build. r=dvander --- js/src/methodjit/Compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 76ba19bce33..38430a33672 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -3454,7 +3454,7 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) if (usePropCache) { stubcc.call(stubs::BindName); } else { - masm.move(ImmPtr(script->getAtom(index)), Registers::ArgReg1); + stubcc.masm.move(ImmPtr(script->getAtom(index)), Registers::ArgReg1); stubcc.call(stubs::BindNameNoCache); } From cee380ffc0a4cbe9f4268e950ab32454deb12aef Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Wed, 27 Oct 2010 12:33:55 -0700 Subject: [PATCH 091/263] Bug 601299: Find RegExpStatics in cx->globalObject if necessary. (r=mrbkap) --- js/src/jscntxtinlines.h | 9 +-------- js/src/xpconnect/tests/mochitest/Makefile.in | 1 + js/src/xpconnect/tests/mochitest/test_bug601299.html | 9 +++++++++ 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 js/src/xpconnect/tests/mochitest/test_bug601299.html diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 9697cd43815..5663f39207c 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -51,14 +51,7 @@ inline js::RegExpStatics * JSContext::regExpStatics() { - VOUCH_HAVE_STACK(); - /* - * Whether we're on trace or not, the scope chain associated with cx->fp - * will lead us to the appropriate global. Although cx->fp is stale on - * trace, trace execution never crosses globals. - */ - JS_ASSERT(hasfp()); - JSObject *global = fp()->scopeChain().getGlobal(); + JSObject *global = JS_GetGlobalForScopeChain(this); js::RegExpStatics *res = js::RegExpStatics::extractFrom(global); return res; } diff --git a/js/src/xpconnect/tests/mochitest/Makefile.in b/js/src/xpconnect/tests/mochitest/Makefile.in index 4c02b536537..66f6469a8a6 100644 --- a/js/src/xpconnect/tests/mochitest/Makefile.in +++ b/js/src/xpconnect/tests/mochitest/Makefile.in @@ -75,6 +75,7 @@ _TEST_FILES = bug500931_helper.html \ test_bug589028.html \ bug589028_helper.html \ test_bug605167.html \ + test_bug601299.html \ $(NULL) #test_bug484107.html \ diff --git a/js/src/xpconnect/tests/mochitest/test_bug601299.html b/js/src/xpconnect/tests/mochitest/test_bug601299.html new file mode 100644 index 00000000000..2e01c5c7729 --- /dev/null +++ b/js/src/xpconnect/tests/mochitest/test_bug601299.html @@ -0,0 +1,9 @@ + + + + + From f501d8198353efc16c8eef40af9eb53345113a45 Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Wed, 27 Oct 2010 14:21:09 -0700 Subject: [PATCH 092/263] Fix bad mochitest for bug 601299. (rs=Waldo) --- js/src/xpconnect/tests/mochitest/test_bug601299.html | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/js/src/xpconnect/tests/mochitest/test_bug601299.html b/js/src/xpconnect/tests/mochitest/test_bug601299.html index 2e01c5c7729..ee911b0ce58 100644 --- a/js/src/xpconnect/tests/mochitest/test_bug601299.html +++ b/js/src/xpconnect/tests/mochitest/test_bug601299.html @@ -2,8 +2,18 @@ + + Test for Bug 601299 + + + + + + From d224dbf55358cdd039feb9137fdb6bf9b44f3790 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 27 Oct 2010 15:49:04 -0700 Subject: [PATCH 093/263] Bug 607555 - TM: fix interleaving of bytecode and LIR with TMFLAGS=recorder. r=edwsmith. --HG-- extra : convert_revision : 53c69eca7d94694ff55d59d39c0d8a26f8d8c111 --- js/src/nanojit/LIR.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index 51e1a20d986..c66b7dc0ae2 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -1826,14 +1826,9 @@ namespace nanojit { if (!code.isEmpty()) { InsBuf b; - int32_t count = 0; - for (Seq* p = code.get(); p != NULL; p = p->tail) { + for (Seq* p = code.get(); p != NULL; p = p->tail) logc->printf("%s %s\n", prefix, printer->formatIns(&b, p->head)); - count++; - } code.clear(); - if (count > 1) - logc->printf("\n"); } } @@ -1842,7 +1837,7 @@ namespace nanojit } LIns* insGuardXov(LOpcode op, LIns* a, LIns* b, GuardRecord *gr) { - return add_flush(out->insGuardXov(op,a,b,gr)); + return add(out->insGuardXov(op,a,b,gr)); } LIns* insBranch(LOpcode v, LIns* condition, LIns* to) { @@ -1850,7 +1845,7 @@ namespace nanojit } LIns* insBranchJov(LOpcode v, LIns* a, LIns* b, LIns* to) { - return add_flush(out->insBranchJov(v, a, b, to)); + return add(out->insBranchJov(v, a, b, to)); } LIns* insJtbl(LIns* index, uint32_t size) { @@ -1883,7 +1878,7 @@ namespace nanojit return add(out->insLoad(v, base, disp, accSet, loadQual)); } LIns* insStore(LOpcode op, LIns* v, LIns* b, int32_t d, AccSet accSet) { - return add(out->insStore(op, v, b, d, accSet)); + return add_flush(out->insStore(op, v, b, d, accSet)); } LIns* insAlloc(int32_t size) { return add(out->insAlloc(size)); @@ -1901,7 +1896,7 @@ namespace nanojit } LIns* insComment(const char* str) { - return add(out->insComment(str)); + return add_flush(out->insComment(str)); } }; From fb95a073485718820b4bb64269958514c40e8e36 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 27 Oct 2010 16:14:55 -0700 Subject: [PATCH 094/263] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index 7e9a4d41ab1..7281e41d861 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -50bb48a9d8ce1c6bca6163d73abcddea8f6c5afc +53c69eca7d94694ff55d59d39c0d8a26f8d8c111 From 8692140272606096f8561dbda8901004d555565f Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Wed, 27 Oct 2010 16:18:16 -0700 Subject: [PATCH 095/263] Bug 607724: Minor scope chain function cleanup. (r=mrbkap) --- js/src/jsapi.cpp | 49 +++------------------------- js/src/jscntxtinlines.h | 37 ++++++++++++++++++--- js/src/jsdbgapi.cpp | 2 +- js/src/jsfun.cpp | 4 +-- js/src/jsinterp.cpp | 59 +++++++++++++++++++++++++--------- js/src/jsinterp.h | 14 ++++---- js/src/jsobj.cpp | 4 +-- js/src/jstracer.cpp | 4 +-- js/src/jsxml.cpp | 4 +-- js/src/methodjit/StubCalls.cpp | 10 +++--- 10 files changed, 99 insertions(+), 88 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 29e1d72bd55..3d4807861e0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1881,31 +1881,8 @@ JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp) JS_PUBLIC_API(JSObject *) JS_GetScopeChain(JSContext *cx) { - JSStackFrame *fp; - CHECK_REQUEST(cx); - fp = js_GetTopStackFrame(cx); - if (!fp) { - /* - * There is no code active on this context. In place of an actual - * scope chain, use the context's global object, which is set in - * js_InitFunctionAndObjectClasses, and which represents the default - * scope chain for the embedding. See also js_FindClassObject. - * - * For embeddings that use the inner and outer object hooks, the inner - * object represents the ultimate global object, with the outer object - * acting as a stand-in. - */ - JSObject *obj = cx->globalObject; - if (!obj) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE); - return NULL; - } - - OBJ_TO_INNER_OBJECT(cx, obj); - return obj; - } - return js_GetScopeChain(cx, fp); + return GetScopeChain(cx); } JS_PUBLIC_API(JSObject *) @@ -1918,26 +1895,8 @@ JS_GetGlobalForObject(JSContext *cx, JSObject *obj) JS_PUBLIC_API(JSObject *) JS_GetGlobalForScopeChain(JSContext *cx) { - /* - * This is essentially JS_GetScopeChain(cx)->getGlobal(), but without - * falling off trace. - * - * This use of cx->fp, possibly on trace, is deliberate: - * cx->fp->scopeChain->getGlobal() returns the same object whether we're on - * trace or not, since we do not trace calls across global objects. - */ - VOUCH_DOES_NOT_REQUIRE_STACK(); - - if (cx->hasfp()) - return cx->fp()->scopeChain().getGlobal(); - - JSObject *scope = cx->globalObject; - if (!scope) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE); - return NULL; - } - OBJ_TO_INNER_OBJECT(cx, scope); - return scope; + CHECK_REQUEST(cx); + return GetGlobalForScopeChain(cx); } JS_PUBLIC_API(jsval) @@ -4172,7 +4131,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) assertSameCompartment(cx, parent); // XXX no funobj for now if (!parent) { if (cx->hasfp()) - parent = js_GetScopeChain(cx, cx->fp()); + parent = GetScopeChain(cx, cx->fp()); if (!parent) parent = cx->globalObject; JS_ASSERT(parent); diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 5663f39207c..d3b05b813e8 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -48,12 +48,33 @@ #include "jsregexp.h" #include "jsgc.h" -inline js::RegExpStatics * -JSContext::regExpStatics() +namespace js { + +static inline JSObject * +GetGlobalForScopeChain(JSContext *cx) { - JSObject *global = JS_GetGlobalForScopeChain(this); - js::RegExpStatics *res = js::RegExpStatics::extractFrom(global); - return res; + /* + * This is essentially GetScopeChain(cx)->getGlobal(), but without + * falling off trace. + * + * This use of cx->fp, possibly on trace, is deliberate: + * cx->fp->scopeChain->getGlobal() returns the same object whether we're on + * trace or not, since we do not trace calls across global objects. + */ + VOUCH_DOES_NOT_REQUIRE_STACK(); + + if (cx->hasfp()) + return cx->fp()->scopeChain().getGlobal(); + + JSObject *scope = cx->globalObject; + if (!scope) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE); + return NULL; + } + OBJ_TO_INNER_OBJECT(cx, scope); + return scope; +} + } inline bool @@ -80,6 +101,12 @@ JSContext::computeNextFrame(JSStackFrame *fp) } } +inline js::RegExpStatics * +JSContext::regExpStatics() +{ + return js::RegExpStatics::extractFrom(js::GetGlobalForScopeChain(this)); +} + namespace js { JS_REQUIRES_STACK JS_ALWAYS_INLINE JSFrameRegs * diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 25d993e5743..21e3bf5212a 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -1187,7 +1187,7 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp) /* Force creation of argument and call objects if not yet created */ (void) JS_GetFrameCallObject(cx, fp); - return js_GetScopeChain(cx, fp); + return GetScopeChain(cx, fp); } JS_PUBLIC_API(JSObject *) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 4d84c948b59..4bd399312f7 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -358,7 +358,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSFunction *fun) * _DBG* opcodes used by wrappers created here must cope with unresolved * upvars and throw them as reference errors. Caveat debuggers! */ - JSObject *scopeChain = js_GetScopeChain(cx, fp); + JSObject *scopeChain = GetScopeChain(cx, fp); if (!scopeChain) return NULL; @@ -2928,7 +2928,7 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen) * Flat closures can be partial, they may need to search enclosing scope * objects via JSOP_NAME, etc. */ - JSObject *scopeChain = js_GetScopeChainFast(cx, cx->fp(), op, oplen); + JSObject *scopeChain = GetScopeChainFast(cx, cx->fp(), op, oplen); if (!scopeChain) return NULL; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index a19ea9b44a8..b8d1dcb25c8 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -162,6 +162,33 @@ JSStackFrame::pc(JSContext *cx, JSStackFrame *next) #endif } +JSObject * +js::GetScopeChain(JSContext *cx) +{ + JSStackFrame *fp = js_GetTopStackFrame(cx); + if (!fp) { + /* + * There is no code active on this context. In place of an actual + * scope chain, use the context's global object, which is set in + * js_InitFunctionAndObjectClasses, and which represents the default + * scope chain for the embedding. See also js_FindClassObject. + * + * For embeddings that use the inner and outer object hooks, the inner + * object represents the ultimate global object, with the outer object + * acting as a stand-in. + */ + JSObject *obj = cx->globalObject; + if (!obj) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE); + return NULL; + } + + OBJ_TO_INNER_OBJECT(cx, obj); + return obj; + } + return GetScopeChain(cx, fp); +} + /* * This computes the blockChain by iterating through the bytecode * of the current script until it reaches the PC. Each time it sees @@ -170,7 +197,7 @@ JSStackFrame::pc(JSContext *cx, JSStackFrame *next) * require bytecode scanning appears below. */ JSObject * -js_GetBlockChain(JSContext *cx, JSStackFrame *fp) +js::GetBlockChain(JSContext *cx, JSStackFrame *fp) { if (!fp->isScriptFrame()) return NULL; @@ -218,7 +245,7 @@ js_GetBlockChain(JSContext *cx, JSStackFrame *fp) * |oplen| is the length of opcode at the current PC. */ JSObject * -js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen) +js::GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen) { /* Assume that we're in a script frame. */ jsbytecode *pc = fp->pc(cx); @@ -274,11 +301,11 @@ js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen) * closure's scope chain. If we never close over a lexical block, we never * place a mutable clone of it on scopeChain. * - * This lazy cloning is implemented in js_GetScopeChain, which is also used in + * This lazy cloning is implemented in GetScopeChain, which is also used in * some other cases --- entering 'with' blocks, for example. */ static JSObject * -js_GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain) +GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain) { JSObject *sharedBlock = blockChain; @@ -399,15 +426,15 @@ js_GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain) } JSObject * -js_GetScopeChain(JSContext *cx, JSStackFrame *fp) +js::GetScopeChain(JSContext *cx, JSStackFrame *fp) { - return js_GetScopeChainFull(cx, fp, js_GetBlockChain(cx, fp)); + return GetScopeChainFull(cx, fp, GetBlockChain(cx, fp)); } JSObject * -js_GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen) +js::GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen) { - return js_GetScopeChainFull(cx, fp, js_GetBlockChainFast(cx, fp, op, oplen)); + return GetScopeChainFull(cx, fp, GetBlockChainFast(cx, fp, op, oplen)); } /* Some objects (e.g., With) delegate 'this' to another object. */ @@ -716,7 +743,7 @@ Invoke(JSContext *cx, const CallArgs &argsRef, uint32 flags) * * Compute |this|. Currently, this must happen after the frame is pushed * and fp->scopeChain is correct because the thisObject hook may call - * JS_GetScopeChain. + * GetScopeChain. */ if (!(flags & JSINVOKE_CONSTRUCT)) { Value &thisv = fp->functionThis(); @@ -1348,7 +1375,7 @@ js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen) sp[-1].setObject(*obj); } - JSObject *parent = js_GetScopeChainFast(cx, fp, op, oplen); + JSObject *parent = GetScopeChainFast(cx, fp, op, oplen); if (!parent) return JS_FALSE; @@ -2716,7 +2743,7 @@ BEGIN_CASE(JSOP_POPN) regs.sp -= GET_UINT16(regs.pc); #ifdef DEBUG JS_ASSERT(regs.fp->base() <= regs.sp); - JSObject *obj = js_GetBlockChain(cx, regs.fp); + JSObject *obj = GetBlockChain(cx, regs.fp); JS_ASSERT_IF(obj, OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj) <= (size_t) (regs.sp - regs.fp->base())); @@ -4908,7 +4935,7 @@ BEGIN_CASE(JSOP_REGEXP) * bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was * flouted by many browser-based implementations. * - * We avoid the js_GetScopeChain call here and pass fp->scopeChain as + * We avoid the GetScopeChain call here and pass fp->scopeChain as * js_GetClassPrototype uses the latter only to locate the global. */ jsatomid index = GET_FULL_INDEX(0); @@ -5368,7 +5395,7 @@ BEGIN_CASE(JSOP_DEFFUN) } else { JS_ASSERT(!FUN_FLAT_CLOSURE(fun)); - obj2 = js_GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH); + obj2 = GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH); if (!obj2) goto error; } @@ -5515,8 +5542,8 @@ BEGIN_CASE(JSOP_DEFLOCALFUN) if (!obj) goto error; } else { - JSObject *parent = js_GetScopeChainFast(cx, regs.fp, JSOP_DEFLOCALFUN, - JSOP_DEFLOCALFUN_LENGTH); + JSObject *parent = GetScopeChainFast(cx, regs.fp, JSOP_DEFLOCALFUN, + JSOP_DEFLOCALFUN_LENGTH); if (!parent) goto error; @@ -5679,7 +5706,7 @@ BEGIN_CASE(JSOP_LAMBDA) } #endif } else { - parent = js_GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH); + parent = GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH); if (!parent) goto error; } diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index cdf955c96c1..a0475135db2 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -783,14 +783,14 @@ namespace js { static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value); -} /* namespace js */ - +extern JSObject * +GetBlockChain(JSContext *cx, JSStackFrame *fp); extern JSObject * -js_GetBlockChain(JSContext *cx, JSStackFrame *fp); +GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen); extern JSObject * -js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen); +GetScopeChain(JSContext *cx); /* * Refresh and return fp->scopeChain. It may be stale if block scopes are @@ -800,12 +800,10 @@ js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen); * must reflect at runtime. */ extern JSObject * -js_GetScopeChain(JSContext *cx, JSStackFrame *fp); +GetScopeChain(JSContext *cx, JSStackFrame *fp); extern JSObject * -js_GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen); - -namespace js { +GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen); /* * Report an error that the this value passed as |this| in the given arguments diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 3fef7d80701..a5ee89518a9 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1155,8 +1155,8 @@ eval(JSContext *cx, uintN argc, Value *vp) if (directCall) { /* Compile using the caller's current scope object. */ staticLevel = caller->script()->staticLevel + 1; - scopeobj = js_GetScopeChainFast(cx, caller, JSOP_EVAL, - JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH); + scopeobj = GetScopeChainFast(cx, caller, JSOP_EVAL, + JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH); if (!scopeobj) return false; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 45a45d794c2..9a5789879de 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -15468,7 +15468,7 @@ TraceRecorder::record_JSOP_LAMBDA() return ARECORD_CONTINUE; } - if (js_GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH)) + if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH)) RETURN_STOP_A("Unable to trace creating lambda in let"); LIns *proto_ins; @@ -15494,7 +15494,7 @@ TraceRecorder::record_JSOP_LAMBDA_FC() if (FUN_OBJECT(fun)->getParent() != globalObj) return ARECORD_STOP; - if (js_GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH)) + if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH)) RETURN_STOP_A("Unable to trace creating lambda in let"); LIns* args[] = { diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 063297a548f..f61320e2ec9 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1763,7 +1763,7 @@ ParseXMLSource(JSContext *cx, JSString *src) { Parser parser(cx); if (parser.init(chars, length, NULL, filename, lineno)) { - JSObject *scopeChain = JS_GetScopeChain(cx); + JSObject *scopeChain = GetScopeChain(cx); if (!scopeChain) return NULL; JSParseNode *pn = parser.parseXMLText(scopeChain, false); @@ -7210,7 +7210,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) JSObject *ns, *obj, *tmp; jsval v; - JSObject *scopeChain = JS_GetScopeChain(cx); + JSObject *scopeChain = GetScopeChain(cx); obj = NULL; for (tmp = scopeChain; tmp; tmp = tmp->getParent()) { diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 956e8c07c3f..659c76b76b0 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -817,7 +817,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun) } else { JS_ASSERT(!FUN_FLAT_CLOSURE(fun)); - obj2 = js_GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH); + obj2 = GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH); if (!obj2) THROW(); } @@ -1467,8 +1467,8 @@ stubs::DefLocalFun(VMFrame &f, JSFunction *fun) if (!obj) THROWV(NULL); } else { - JSObject *parent = js_GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN, - JSOP_DEFLOCALFUN_LENGTH); + JSObject *parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN, + JSOP_DEFLOCALFUN_LENGTH); if (!parent) THROWV(NULL); @@ -1499,7 +1499,7 @@ stubs::RegExp(VMFrame &f, JSObject *regex) * bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was * flouted by many browser-based implementations. * - * We avoid the js_GetScopeChain call here and pass fp->scopeChain() as + * We avoid the GetScopeChain call here and pass fp->scopeChain() as * js_GetClassPrototype uses the latter only to locate the global. */ JSObject *proto; @@ -1597,7 +1597,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun) if (FUN_NULL_CLOSURE(fun)) { parent = &f.fp()->scopeChain(); } else { - parent = js_GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH); + parent = GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH); if (!parent) THROWV(NULL); } From 929c78da003c89a63bc6dab2e57066fb1602cd02 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 27 Oct 2010 16:45:16 -0700 Subject: [PATCH 096/263] Bug 607555 - TM: fix interleaving of bytecode and LIR with TMFLAGS=recorder (TM-specific part). r=dmandelin. --- js/src/jstracer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 9a5789879de..0152a3d0f67 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2491,6 +2491,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag insComment("begin-loop"); InitConst(loopLabel) = lir->ins0(LIR_label); } + insComment("begin-setup"); // if profiling, drop a label, so the assembler knows to put a // frag-entry-counter increment at this point. If there's a @@ -2569,6 +2570,8 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag addName(loadFromState(LIR_ldp, outermostTreeExitGuard), "outermostTreeExitGuard"); guard(true, lir->ins2(LIR_eqp, nested_ins, INS_CONSTPTR(innermost)), NESTED_EXIT); } + + insComment("end-setup"); } TraceRecorder::~TraceRecorder() @@ -7425,6 +7428,7 @@ TraceRecorder::monitorRecording(JSOp op) debug_only_stmt( if (LogController.lcbits & LC_TMRecorder) { + debug_only_print0(LC_TMRecorder, "\n"); js_Disassemble1(cx, cx->fp()->script(), cx->regs->pc, cx->fp()->hasImacropc() ? 0 : cx->regs->pc - cx->fp()->script()->code, From a5d01b38c73975b624fd6e3f183be255cf0e22cf Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 27 Oct 2010 21:04:13 -0700 Subject: [PATCH 097/263] Refactor and improve GETELEM IC (bug 602641, r=dmandelin). --- js/src/methodjit/BaseAssembler.h | 26 +- js/src/methodjit/BaseCompiler.h | 38 +- js/src/methodjit/Compiler.cpp | 188 ++--- js/src/methodjit/Compiler.h | 42 +- js/src/methodjit/FastOps.cpp | 238 +++--- js/src/methodjit/FrameEntry.h | 6 + js/src/methodjit/MethodJIT.cpp | 8 +- js/src/methodjit/MethodJIT.h | 4 + js/src/methodjit/NunboxAssembler.h | 23 +- js/src/methodjit/PolyIC.cpp | 1251 +++++++++++++--------------- js/src/methodjit/PolyIC.h | 202 +++-- js/src/methodjit/PunboxAssembler.h | 14 +- js/src/methodjit/StubCompiler.h | 1 + 13 files changed, 954 insertions(+), 1087 deletions(-) diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index bd230d6b0b4..04f3d9c90b5 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -50,6 +50,8 @@ #include "methodjit/MethodJIT.h" #include "methodjit/MachineRegs.h" #include "CodeGenIncludes.h" +#include "jsobjinlines.h" +#include "jsscopeinlines.h" namespace js { namespace mjit { @@ -209,9 +211,9 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste load32(Address(obj, offsetof(JSObject, objShape)), shape); } - Jump guardShape(RegisterID obj, uint32 shape) { - return branch32(NotEqual, Address(obj, offsetof(JSObject, objShape)), - Imm32(shape)); + Jump guardShape(RegisterID objReg, JSObject *obj) { + return branch32(NotEqual, Address(objReg, offsetof(JSObject, objShape)), + Imm32(obj->shape())); } Jump testFunction(Condition cond, RegisterID fun) { @@ -427,6 +429,24 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste else move(remat.reg(), reg); } + + void loadDynamicSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + loadPtr(Address(objReg, offsetof(JSObject, slots)), dataReg); + loadValueAsComponents(Address(dataReg, slot * sizeof(Value)), typeReg, dataReg); + } + + void loadObjProp(JSObject *obj, RegisterID objReg, + const js::Shape *shape, + RegisterID typeReg, RegisterID dataReg) + { + if (shape->isMethod()) + loadValueAsComponents(ObjectValue(shape->methodObject()), typeReg, dataReg); + else if (obj->hasSlotsArray()) + loadDynamicSlot(objReg, shape->slot, typeReg, dataReg); + else + loadInlineSlot(objReg, shape->slot, typeReg, dataReg); + } }; /* Return f if the script is strict mode code, f otherwise. */ diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index ad1ff5ad804..d4ccce0ca1e 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -48,19 +48,7 @@ namespace js { namespace mjit { -class BaseCompiler -{ - protected: - JSContext *cx; - - public: - BaseCompiler() : cx(NULL) - { } - - BaseCompiler(JSContext *cx) : cx(cx) - { } - - protected: +struct MacroAssemblerTypedefs { typedef JSC::MacroAssembler::Label Label; typedef JSC::MacroAssembler::Imm32 Imm32; typedef JSC::MacroAssembler::ImmPtr ImmPtr; @@ -77,11 +65,25 @@ class BaseCompiler typedef JSC::MacroAssembler::DataLabel32 DataLabel32; typedef JSC::FunctionPtr FunctionPtr; typedef JSC::RepatchBuffer RepatchBuffer; - typedef JSC::CodeBlock CodeBlock; typedef JSC::CodeLocationLabel CodeLocationLabel; - typedef JSC::JITCode JITCode; + typedef JSC::CodeLocationCall CodeLocationCall; typedef JSC::ReturnAddressPtr ReturnAddressPtr; typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr; +}; + +class BaseCompiler : public MacroAssemblerTypedefs +{ + protected: + JSContext *cx; + + public: + BaseCompiler() : cx(NULL) + { } + + BaseCompiler(JSContext *cx) : cx(cx) + { } + + protected: JSC::ExecutablePool * getExecPool(size_t size) { @@ -127,6 +129,12 @@ class LinkerHelper : public JSC::LinkBuffer } return ep; } + + void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) { + if (!jump.isSet()) + return; + link(jump.get(), label); + } }; } /* namespace js */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 38430a33672..0a895bbc838 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -103,6 +103,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp) #endif #if defined JS_POLYIC pics(ContextAllocPolicy(cx)), + getElemICs(ContextAllocPolicy(cx)), #endif callPatches(ContextAllocPolicy(cx)), callSites(ContextAllocPolicy(cx)), @@ -390,6 +391,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp) #endif #if defined JS_POLYIC sizeof(ic::PICInfo) * pics.length() + + sizeof(ic::GetElementIC) * getElemICs.length() + #endif sizeof(CallSite) * callSites.length(); @@ -586,6 +588,38 @@ mjit::Compiler::finishThisUp(JITScript **jitp) } #if defined JS_POLYIC + jit->nGetElems = getElemICs.length(); + if (getElemICs.length()) { + jit->getElems = (ic::GetElementIC *)cursor; + cursor += sizeof(ic::GetElementIC) * getElemICs.length(); + } else { + jit->getElems = NULL; + } + + for (size_t i = 0; i < getElemICs.length(); i++) { + ic::GetElementIC &to = jit->getElems[i]; + GetElementICInfo &from = getElemICs[i]; + to.init(); + from.copyTo(to, fullCode, stubCode); + + to.typeReg = from.typeReg; + to.objReg = from.objReg; + to.idRemat = from.id; + + if (from.typeGuard.isSet()) { + int inlineTypeGuard = fullCode.locationOf(from.typeGuard.get()) - + fullCode.locationOf(from.fastPathStart); + to.inlineTypeGuard = inlineTypeGuard; + JS_ASSERT(to.inlineTypeGuard == inlineTypeGuard); + } + int inlineClaspGuard = fullCode.locationOf(from.claspGuard) - + fullCode.locationOf(from.fastPathStart); + to.inlineClaspGuard = inlineClaspGuard; + JS_ASSERT(to.inlineClaspGuard == inlineClaspGuard); + + stubCode.patch(from.paramAddr, &to); + } + jit->nPICs = pics.length(); if (pics.length()) { jit->pics = (ic::PICInfo *)cursor; @@ -596,11 +630,9 @@ mjit::Compiler::finishThisUp(JITScript **jitp) if (ic::PICInfo *scriptPICs = jit->pics) { for (size_t i = 0; i < pics.length(); i++) { + scriptPICs[i].init(); + pics[i].copyTo(scriptPICs[i], fullCode, stubCode); pics[i].copySimpleMembersTo(scriptPICs[i]); - scriptPICs[i].fastPathStart = fullCode.locationOf(pics[i].fastPathStart); - scriptPICs[i].fastPathRejoin = fullCode.locationOf(pics[i].fastPathRejoin); - scriptPICs[i].slowPathStart = stubCode.locationOf(pics[i].slowPathStart); - scriptPICs[i].slowPathCall = stubCode.locationOf(pics[i].slowPathCall); scriptPICs[i].shapeGuard = masm.distanceOf(pics[i].shapeGuard) - masm.distanceOf(pics[i].fastPathStart); JS_ASSERT(scriptPICs[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) - @@ -623,8 +655,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp) scriptPICs[i].u.get.typeCheckOffset = distance; } } - new (&scriptPICs[i].execPools) ic::PICInfo::ExecPoolVector(SystemAllocPolicy()); - scriptPICs[i].reset(); stubCode.patch(pics[i].paramAddr, &scriptPICs[i]); } } @@ -2593,9 +2623,9 @@ mjit::Compiler::passMICAddress(MICGenInfo &mic) #if defined JS_POLYIC void -mjit::Compiler::passPICAddress(PICGenInfo &pic) +mjit::Compiler::passICAddress(BaseICInfo *ic) { - pic.paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); + ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); } bool @@ -2623,7 +2653,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) shapeReg = frame.allocReg(); } - PICGenInfo pic(ic::PICInfo::GET, usePropCache); + PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache); /* Guard that the type is an object. */ Jump typeCheck; @@ -2654,7 +2684,6 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -2669,7 +2698,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::GetProp); /* Load dslots. */ @@ -2727,113 +2756,6 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) return true; } -#ifdef JS_POLYIC -bool -mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - RegisterID idReg, RegisterID shapeReg) -{ - PICGenInfo pic(ic::PICInfo::GETELEM, true); - - pic.objRemat = frame.dataRematInfo(obj); - pic.idRemat = frame.dataRematInfo(id); - pic.shapeReg = shapeReg; - pic.hasTypeCheck = false; - - pic.fastPathStart = masm.label(); - - /* Guard on shape. */ - masm.loadShape(objReg, shapeReg); - pic.shapeGuard = masm.label(); - - DataLabel32 inlineShapeOffsetLabel; - Jump jmpShapeGuard = masm.branch32WithPatch(Assembler::NotEqual, shapeReg, - Imm32(int32(JSObjectMap::INVALID_SHAPE)), - inlineShapeOffsetLabel); - DBGLABEL(dbgInlineShapeJump); - - /* Guard on id identity. */ -#if defined JS_NUNBOX32 - static const void *BOGUS_ATOM = (void *)0xdeadbeef; -#elif defined JS_PUNBOX64 - static const void *BOGUS_ATOM = (void *)0xfeedfacedeadbeef; -#endif - - DataLabelPtr inlineAtomOffsetLabel; - Jump idGuard = masm.branchPtrWithPatch(Assembler::NotEqual, idReg, - inlineAtomOffsetLabel, ImmPtr(BOGUS_ATOM)); - DBGLABEL(dbgInlineAtomJump); - - /* - * The state between these two exits is identical, so this safe. The - * GETELEM PIC repatches both jumps to the slowPathStart on reset. - */ - stubcc.linkExit(idGuard, Uses(2)); - pic.slowPathStart = stubcc.linkExit(jmpShapeGuard, Uses(2)); - - stubcc.leave(); - passPICAddress(pic); - pic.slowPathCall = stubcc.call(ic::GetElem); - - /* Load dslots. */ -#if defined JS_NUNBOX32 - DBGLABEL(dbgDslotsLoad); -#elif defined JS_PUNBOX64 - Label dslotsLoadLabel = masm.label(); -#endif - masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); - - /* Copy the slot value to the expression stack. */ - Address slot(objReg, 1 << 24); -#if defined JS_NUNBOX32 - masm.loadTypeTag(slot, shapeReg); - DBGLABEL(dbgTypeLoad); - masm.loadPayload(slot, objReg); - DBGLABEL(dbgDataLoad); -#elif defined JS_PUNBOX64 - Label inlineValueOffsetLabel = - masm.loadValueAsComponents(slot, shapeReg, objReg); -#endif - pic.fastPathRejoin = masm.label(); - - pic.objReg = objReg; - pic.idReg = idReg; - - RETURN_IF_OOM(false); -#if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel) == GETELEM_INLINE_ATOM_OFFSET); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == GETELEM_INLINE_ATOM_JUMP); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == GETELEM_INLINE_SHAPE_OFFSET); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); -#elif defined JS_PUNBOX64 - pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); - JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); - - pic.labels.getelem.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel)); - - pic.labels.getelem.inlineAtomOffset = masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineAtomOffset == masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel)); - - pic.labels.getelem.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel)); - - JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == - pic.labels.getelem.inlineAtomOffset + GETELEM_INLINE_ATOM_JUMP); -#endif - - JS_ASSERT(pic.idReg != pic.objReg); - JS_ASSERT(pic.idReg != pic.shapeReg); - JS_ASSERT(pic.objReg != pic.shapeReg); - - pics.append(pic); - return true; -} -#endif - bool mjit::Compiler::jsop_callprop_generic(JSAtom *atom) { @@ -2847,7 +2769,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) RegisterID objReg = frame.copyDataIntoReg(top); RegisterID shapeReg = frame.allocReg(); - PICGenInfo pic(ic::PICInfo::CALL, true); + PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); pic.pc = PC; @@ -2871,7 +2793,6 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) pic.objReg = objReg; pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* * Store the type and object back. Don't bother keeping them in registers, @@ -2901,7 +2822,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) /* Slow path. */ stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Adjust the frame. None of this will generate code. */ @@ -3019,7 +2940,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) { FrameEntry *top = frame.peek(-1); - PICGenInfo pic(ic::PICInfo::CALL, true); + PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); JS_ASSERT(top->isTypeKnown()); JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT); @@ -3034,7 +2955,6 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -3049,7 +2969,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Load dslots. */ @@ -3151,7 +3071,10 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) JSOp op = JSOp(*PC); - PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET, usePropCache); + ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD) + ? ic::PICInfo::SETMETHOD + : ic::PICInfo::SET; + PICGenInfo pic(kind, op, usePropCache); pic.atom = atom; /* Guard that the type is an object. */ @@ -3191,7 +3114,6 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) RegisterID shapeReg = frame.allocReg(); pic.shapeReg = shapeReg; - pic.objRemat = frame.dataRematInfo(lhs); frame.unpinEntry(vr); @@ -3209,7 +3131,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(2)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::SetProp); } @@ -3276,7 +3198,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) void mjit::Compiler::jsop_name(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::NAME, true); + PICGenInfo pic(ic::PICInfo::NAME, JSOp(*PC), true); pic.shapeReg = frame.allocReg(); pic.objReg = frame.allocReg(); @@ -3291,7 +3213,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::Name); } @@ -3308,7 +3230,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) bool mjit::Compiler::jsop_xname(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::XNAME, true); + PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true); FrameEntry *fe = frame.peek(-1); if (fe->isNotType(JSVAL_TYPE_OBJECT)) { @@ -3333,7 +3255,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::XName); } @@ -3352,7 +3274,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) void mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { - PICGenInfo pic(ic::PICInfo::BIND, usePropCache); + PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC), usePropCache); // 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 @@ -3382,7 +3304,7 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::BindName); } diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 4483e4f8185..3bf27b46e14 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -160,18 +160,39 @@ class Compiler : public BaseCompiler bool hasSlowNcode; }; -#if defined JS_POLYIC struct BaseICInfo { + BaseICInfo(JSOp op) : op(op) + { } Label fastPathStart; Label fastPathRejoin; Label slowPathStart; Call slowPathCall; DataLabelPtr paramAddr; + JSOp op; + + void copyTo(ic::BaseIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) { + to.fastPathStart = full.locationOf(fastPathStart); + to.fastPathRejoin = full.locationOf(fastPathRejoin); + to.slowPathStart = stub.locationOf(slowPathStart); + to.slowPathCall = stub.locationOf(slowPathCall); + to.op = op; + JS_ASSERT(to.op == op); + } + }; + + struct GetElementICInfo : public BaseICInfo { + GetElementICInfo(JSOp op) : BaseICInfo(op) + { } + RegisterID typeReg; + RegisterID objReg; + ValueRemat id; + MaybeJump typeGuard; + Jump claspGuard; }; struct PICGenInfo : public BaseICInfo { - PICGenInfo(ic::PICInfo::Kind kind, bool usePropCache) - : kind(kind), usePropCache(usePropCache) + PICGenInfo(ic::PICInfo::Kind kind, JSOp op, bool usePropCache) + : BaseICInfo(op), kind(kind), usePropCache(usePropCache) { } ic::PICInfo::Kind kind; Label typeCheck; @@ -183,8 +204,6 @@ class Compiler : public BaseCompiler Label shapeGuard; jsbytecode *pc; JSAtom *atom; - StateRemat objRemat; - StateRemat idRemat; bool hasTypeCheck; ValueRemat vr; # if defined JS_CPU_X64 @@ -200,15 +219,12 @@ class Compiler : public BaseCompiler if (ic.isSet()) { ic.u.vr = vr; } else if (ic.isGet()) { - ic.u.get.idReg = idReg; ic.u.get.typeReg = typeReg; ic.u.get.hasTypeCheck = hasTypeCheck; - ic.setObjRemat(objRemat); } } }; -#endif struct Defs { Defs(uint32 ndefs) @@ -250,6 +266,7 @@ class Compiler : public BaseCompiler #endif #if defined JS_POLYIC js::Vector pics; + js::Vector getElemICs; #endif js::Vector callPatches; js::Vector callSites; @@ -298,7 +315,7 @@ class Compiler : public BaseCompiler void iterEnd(); MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg); #ifdef JS_POLYIC - void passPICAddress(PICGenInfo &pic); + void passICAddress(BaseICInfo *ic); #endif #ifdef JS_MONOIC void passMICAddress(MICGenInfo &mic); @@ -400,13 +417,6 @@ class Compiler : public BaseCompiler void jsop_localinc(JSOp op, uint32 slot, bool popped); void jsop_setelem(); bool jsop_getelem(); - bool jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - bool jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - bool jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg, - RegisterID shapeReg); - void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - MaybeRegisterID &idReg, RegisterID shapeReg); void jsop_stricteq(JSOp op); void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void 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 76cf06f3f24..2f9dc0c77b5 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1360,135 +1360,6 @@ mjit::Compiler::jsop_setelem() stubcc.rejoin(Changes(0)); } -void -mjit::Compiler::jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - MaybeRegisterID &idReg, RegisterID tmpReg) -{ - /* Note: idReg is only valid if id is not a constant. */ - Jump guardDense = masm.testObjClass(Assembler::NotEqual, objReg, &js_ArrayClass); - stubcc.linkExit(guardDense, Uses(2)); - - Int32Key key = idReg.isSet() - ? Int32Key::FromRegister(idReg.reg()) - : Int32Key::FromConstant(id->getValue().toInt32()); - - Assembler::FastArrayLoadFails fails = - masm.fastArrayLoad(objReg, key, tmpReg, objReg); - - stubcc.linkExit(fails.rangeCheck, Uses(2)); - stubcc.linkExit(fails.holeCheck, Uses(2)); -} - -bool -mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - switch (id->getKnownType()) { - case JSVAL_TYPE_INT32: - { - /* Prologue. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg; - if (!id->isConstant()) - idReg.setReg(frame.copyDataIntoReg(id)); - - /* Meat. */ - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - stubcc.leave(); - stubcc.call(stubs::GetElem); - - /* Epilogue. */ - if (idReg.isSet()) - frame.freeReg(idReg.reg()); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - stubcc.rejoin(Changes(1)); - break; - } -#ifdef JS_POLYIC - case JSVAL_TYPE_STRING: - { - /* Prologue. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - RegisterID idReg = frame.copyDataIntoReg(id); - - /* Meat. */ - if (!jsop_getelem_pic(obj, id, objReg, idReg, tmpReg)) - return false; - - /* Epilogue. */ - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - frame.freeReg(idReg); - stubcc.rejoin(Changes(1)); - break; - } -#endif - default: - JS_NOT_REACHED("Invalid known id type."); - } - return true; -} - -#ifdef JS_POLYIC -bool -mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - JS_ASSERT(!id->isTypeKnown()); - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg(frame.copyDataIntoReg(id)); - - RegisterID typeReg = frame.tempRegForType(id, tmpReg); - Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); - - JaegerSpew(JSpew_Insns, " ==== BEGIN DENSE ARRAY CODE ==== \n"); - - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - Jump performedDense = masm.jump(); - - JaegerSpew(JSpew_Insns, " ==== END DENSE ARRAY CODE ==== \n"); - - intGuard.linkTo(masm.label(), &masm); - Jump stringGuard = masm.testString(Assembler::NotEqual, typeReg); - stubcc.linkExit(stringGuard, Uses(2)); /* Neither int nor string at this point. */ - - stubcc.leave(); - stubcc.call(stubs::GetElem); - Jump toFinalMerge = stubcc.masm.jump(); - - if (!jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg)) - return false; - performedDense.linkTo(masm.label(), &masm); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - frame.freeReg(idReg.reg()); - toFinalMerge.linkTo(stubcc.masm.label(), &stubcc.masm); - stubcc.rejoin(Changes(1)); - return true; -} -#endif - -void -mjit::Compiler::jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - /* Only handle the int32 case. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg(frame.copyDataIntoReg(id)); - RegisterID typeReg = frame.tempRegForType(id, tmpReg); - Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); - stubcc.linkExit(intGuard, Uses(2)); - - /* Meat. */ - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - stubcc.leave(); - stubcc.call(stubs::GetElem); - - /* Epilogue. */ - frame.freeReg(idReg.reg()); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - stubcc.rejoin(Changes(1)); -} - bool mjit::Compiler::jsop_getelem() { @@ -1516,30 +1387,107 @@ mjit::Compiler::jsop_getelem() return true; } - if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_STRING && id->isConstant()) { - /* Never happens, or I'd optimize it. */ - 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); + + MaybeJump objTypeGuard; + if (!obj->isTypeKnown()) { + // Test the type of the object without spilling the payload. + MaybeRegisterID pinnedObjData = frame.maybePinData(obj); + Jump guard = frame.testObject(Assembler::NotEqual, obj); + frame.maybeUnpinReg(pinnedObjData); + + // Create a sync path, which we'll rejoin manually later. This is safe + // as long as the IC does not build a stub; it won't, because |obj| + // won't be an object. If we extend this IC to support strings, all + // that needs to change is a little code movement. + stubcc.linkExit(guard, Uses(2)); + objTypeGuard = stubcc.masm.jump(); } - RegisterID tmpReg; - if (obj->isTypeKnown()) { - tmpReg = frame.allocReg(); + // Get a mutable register for the object. This will be the data reg. + ic.objReg = frame.copyDataIntoReg(obj); + + // 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); + + // Fill in the id value. + frame.maybeUnpinReg(pinnedIdData); + if (id->isConstant()) { + ic.id = ValueRemat::FromConstant(id->getValue()); } else { - tmpReg = frame.copyTypeIntoReg(obj); - Jump objGuard = masm.testObject(Assembler::NotEqual, tmpReg); - stubcc.linkExit(objGuard, Uses(2)); + RegisterID dataReg = frame.tempRegForData(id); + if (id->isTypeKnown()) + ic.id = ValueRemat::FromKnownType(id->getKnownType(), dataReg); + else + ic.id = ValueRemat::FromRegisters(ic.typeReg, dataReg); } - if (id->isTypeKnown()) - return jsop_getelem_known_type(obj, id, tmpReg); + ic.fastPathStart = masm.label(); + + // Note: slow path here is safe, since the frame will not be modified. + ic.slowPathStart = stubcc.masm.label(); + frame.sync(stubcc.masm, Uses(2)); + + if (id->mightBeType(JSVAL_TYPE_INT32)) { + // Always test the type first (see comment in PolyIC.h). + if (!id->isTypeKnown()) { + ic.typeGuard = masm.testInt32(Assembler::NotEqual, ic.typeReg); + stubcc.linkExitDirect(ic.typeGuard.get(), ic.slowPathStart); + } + + // Guard on the clasp. + ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &js_ArrayClass); + stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); + + 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); + + 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); + ic.slowPathCall = stubcc.call(ic::GetElement); +#else + ic.slowPathCall = stubcc.call(stubs::GetElem); +#endif + + ic.fastPathRejoin = masm.label(); + + frame.popn(2); + frame.pushRegs(ic.typeReg, ic.objReg); + + stubcc.rejoin(Changes(2)); #ifdef JS_POLYIC - return jsop_getelem_with_pic(obj, id, tmpReg); -#else - jsop_getelem_nopic(obj, id, tmpReg); - return true; + if (!getElemICs.append(ic)) + return false; #endif + + return true; } static inline bool diff --git a/js/src/methodjit/FrameEntry.h b/js/src/methodjit/FrameEntry.h index 56a4dc72ac1..7cea4a464e3 100644 --- a/js/src/methodjit/FrameEntry.h +++ b/js/src/methodjit/FrameEntry.h @@ -97,6 +97,12 @@ class FrameEntry return isTypeKnown() && getKnownType() != type_; } + // Return true if the type of this value is definitely type_, or is unknown + // and thus potentially type_ at runtime. + bool mightBeType(JSValueType type_) const { + return !isNotType(type_); + } + #if defined JS_NUNBOX32 uint32 getPayload() const { //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced()); diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index 64e6ffe984a..ae9ad37af7f 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -811,10 +811,10 @@ mjit::JITScript::release() code.m_executablePool->release(); #if defined JS_POLYIC - for (uint32 i = 0; i < nPICs; i++) { - pics[i].releasePools(); - Destroy(pics[i].execPools); - } + for (uint32 i = 0; i < nPICs; i++) + pics[i].finish(); + for (uint32 i = 0; i < nGetElems; i++) + getElems[i].finish(); #endif #if defined JS_MONOIC diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index e5332942a09..1bcca198b9b 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -143,6 +143,7 @@ namespace mjit { namespace ic { # if defined JS_POLYIC struct PICInfo; + struct GetElementIC; # endif # if defined JS_MONOIC struct MICInfo; @@ -182,6 +183,7 @@ typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceI #endif #ifdef JS_POLYIC typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *); +typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *); #endif namespace mjit { @@ -212,6 +214,8 @@ struct JITScript { #ifdef JS_POLYIC ic::PICInfo *pics; /* PICs in this script */ uint32 nPICs; /* number of PolyICs */ + ic::GetElementIC *getElems; + uint32 nGetElems; #endif void *invokeEntry; /* invoke address */ void *fastEntry; /* cached entry, fastest */ diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index 6715b388688..d2dc6191641 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -90,22 +90,15 @@ class NunboxAssembler : public JSC::MacroAssembler return BaseIndex(address.base, address.index, address.scale, address.offset + TAG_OFFSET); } - void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, - RegisterID type, RegisterID data) { - JS_ASSERT(type != data); - Address address(obj, JSObject::getFixedSlotOffset(slot)); - RegisterID activeAddressReg = obj; - if (!inlineAccess) { - loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); - address = Address(clobber, slot * sizeof(Value)); - activeAddressReg = clobber; - } - if (activeAddressReg == type) { - loadPayload(address, data); - loadTypeTag(address, type); + void loadInlineSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + Address address(objReg, JSObject::getFixedSlotOffset(slot)); + if (objReg == typeReg) { + loadPayload(address, dataReg); + loadTypeTag(address, typeReg); } else { - loadTypeTag(address, type); - loadPayload(address, data); + loadTypeTag(address, typeReg); + loadPayload(address, dataReg); } } diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index d0084df2927..719e5ee33fa 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -45,6 +45,7 @@ #include "assembler/assembler/RepatchBuffer.h" #include "jsscope.h" #include "jsnum.h" +#include "jsatominlines.h" #include "jsobjinlines.h" #include "jsscopeinlines.h" #include "jspropertycache.h" @@ -57,6 +58,9 @@ using namespace js; using namespace js::mjit; using namespace js::mjit::ic; +typedef JSC::RepatchBuffer RepatchBuffer; +typedef JSC::FunctionPtr FunctionPtr; + /* Rough over-estimate of how much memory we need to unprotect. */ static const uint32 INLINE_PATH_LENGTH = 64; @@ -65,18 +69,18 @@ static const uint32 INLINE_PATH_LENGTH = 64; // are instantiated and rooted. class PICLinker : public LinkerHelper { - ic::PICInfo &pic; + ic::BaseIC ⁣ public: - PICLinker(JSContext *cx, ic::PICInfo &pic) - : LinkerHelper(cx), pic(pic) + PICLinker(JSContext *cx, ic::BaseIC &ic) + : LinkerHelper(cx), ic(ic) { } bool init(Assembler &masm) { JSC::ExecutablePool *pool = LinkerHelper::init(masm); if (!pool) return false; - if (!pic.execPools.append(pool)) { + if (!ic.execPools.append(pool)) { pool->release(); js_ReportOutOfMemory(cx); return false; @@ -92,42 +96,38 @@ class PICStubCompiler : public BaseCompiler VMFrame &f; JSScript *script; ic::PICInfo &pic; + void *stub; public: - PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic) - : BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic) + 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) { } - bool isCallOp() const - { + bool isCallOp() const { if (pic.kind == ic::PICInfo::CALL) return true; - JSOp op = JSOp(*f.regs.pc); - return !!(js_CodeSpec[op].format & JOF_CALLOP); + return !!(js_CodeSpec[pic.op].format & JOF_CALLOP); } - bool disable(const char *reason, VoidStub stub) - { - return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); + LookupStatus error() { + disable("error"); + return Lookup_Error; } - bool disable(const char *reason, VoidStubPIC stub) { - return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); + LookupStatus error(JSContext *cx) { + return error(); } - bool disable(const char *reason, void *stub) - { - spew("disabled", reason); - JITCode jitCode(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - CodeBlock codeBlock(jitCode); - RepatchBuffer repatcher(&codeBlock); - repatcher.relink(pic.slowPathCall, FunctionPtr(stub)); - return true; + LookupStatus disable(const char *reason) { + return disable(f.cx, reason); + } + + LookupStatus disable(JSContext *cx, const char *reason) { + return pic.disable(cx, reason, stub); } protected: - void spew(const char *event, const char *op) - { + void spew(const char *event, const char *op) { #ifdef JS_METHODJIT_SPEW JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n", type, event, op, script->filename, @@ -138,13 +138,13 @@ class PICStubCompiler : public BaseCompiler class PICRepatchBuffer : public JSC::RepatchBuffer { - ic::PICInfo &pic; + ic::BaseIC ⁣ JSC::CodeLocationLabel label; public: - PICRepatchBuffer(ic::PICInfo &ic, JSC::CodeLocationLabel path) + PICRepatchBuffer(ic::BaseIC &ic, JSC::CodeLocationLabel path) : JSC::RepatchBuffer(path.executableAddress(), INLINE_PATH_LENGTH), - pic(ic), label(path) + ic(ic), label(path) { } void relink(int32 offset, JSC::CodeLocationLabel target) { @@ -156,7 +156,6 @@ class SetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; - VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 dslotsLoadOffset(ic::PICInfo &pic) { @@ -222,15 +221,10 @@ class SetPropCompiler : public PICStubCompiler public: SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("setprop", f, script, pic), obj(obj), atom(atom), stub(stub), - lastStubSecondShapeGuard(pic.secondShapeGuard) + : PICStubCompiler("setprop", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + obj(obj), atom(atom), lastStubSecondShapeGuard(pic.secondShapeGuard) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -247,7 +241,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - bool patchInline(const Shape *shape, bool inlineSlot) + LookupStatus patchInline(const Shape *shape, bool inlineSlot) { JS_ASSERT(!pic.inlinePathPatched); JaegerSpew(JSpew_PICs, "patch setprop inline at %p\n", pic.fastPathStart.executableAddress()); @@ -286,7 +280,7 @@ class SetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return true; + return Lookup_Cacheable; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -308,7 +302,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - bool generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) + LookupStatus generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) { /* Exits to the slow path. */ Vector slowExits(cx); @@ -346,9 +340,9 @@ class SetPropCompiler : public PICStubCompiler RegisterID lastReg = pic.objReg; while (proto) { masm.loadPtr(Address(lastReg, offsetof(JSObject, proto)), pic.shapeReg); - Jump protoGuard = masm.guardShape(pic.shapeReg, proto->shape()); + Jump protoGuard = masm.guardShape(pic.shapeReg, proto); if (!otherGuards.append(protoGuard)) - return false; + return error(); proto = proto->getProto(); lastReg = pic.shapeReg; @@ -367,7 +361,7 @@ class SetPropCompiler : public PICStubCompiler Jump mismatchedFunction = masm.branchPtr(Assembler::NotEqual, pic.u.vr.dataReg(), ImmPtr(funobj)); if (!slowExits.append(mismatchedFunction)) - return false; + return error(); } } @@ -382,7 +376,7 @@ class SetPropCompiler : public PICStubCompiler Jump overCapacity = masm.branch32(Assembler::LessThanOrEqual, pic.shapeReg, Imm32(shape->slot)); if (!slowExits.append(overCapacity)) - return false; + return error(); masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.shapeReg); Address address(pic.shapeReg, shape->slot * sizeof(Value)); @@ -420,7 +414,7 @@ class SetPropCompiler : public PICStubCompiler masm.loadPayload(address, pic.shapeReg); Jump rebrand = masm.testFunction(Assembler::Equal, pic.shapeReg); if (!slowExits.append(rebrand)) - return false; + return error(); skip.linkTo(masm.label(), &masm); pic.shapeRegHasBaseShape = false; } @@ -476,7 +470,7 @@ class SetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(shapeGuard, pic.slowPathStart); if (slowExit.isSet()) @@ -511,16 +505,12 @@ class SetPropCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } - bool update() + LookupStatus update() { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } + JS_ASSERT(pic.hit); if (obj->isDenseArray()) return disable("dense array"); @@ -541,7 +531,7 @@ class SetPropCompiler : public PICStubCompiler JSObject *holder; JSProperty *prop = NULL; if (!obj->lookupProperty(cx, id, &holder, &prop)) - return false; + return error(); /* If the property exists but is on a prototype, treat as addprop. */ if (prop && holder != obj) { @@ -581,7 +571,7 @@ class SetPropCompiler : public PICStubCompiler uint32 initialShape = obj->shape(); if (!obj->ensureClassReservedSlots(cx)) - return false; + return error(); uint32 slots = obj->numSlots(); uintN flags = 0; @@ -604,7 +594,7 @@ class SetPropCompiler : public PICStubCompiler SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) - return false; + return error(); /* * Test after calling putProperty since it can switch obj into @@ -667,11 +657,84 @@ class SetPropCompiler : public PICStubCompiler } }; +static bool +IsCacheableProtoChain(JSObject *obj, JSObject *holder) +{ + while (obj != holder) { + JSObject *proto = obj->getProto(); + if (!proto->isNative()) + return false; + obj = proto; + } + return true; +} + +template +struct GetPropertyHelper { + JSContext *cx; + JSObject *obj; + JSAtom *atom; + IC ⁣ + + JSObject *aobj; + JSObject *holder; + const Shape *shape; + + GetPropertyHelper(JSContext *cx, JSObject *obj, JSAtom *atom, IC &ic) + : cx(cx), obj(obj), atom(atom), ic(ic), holder(NULL), shape(NULL) + { } + + public: + LookupStatus bind() { + JSProperty *prop; + if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) + return ic.error(cx); + if (!prop) + return ic.disable(cx, "lookup failed"); + shape = (const Shape *)prop; + return Lookup_Cacheable; + } + + LookupStatus lookup() { + JSObject *aobj = js_GetProtoIfDenseArray(obj); + if (!aobj->isNative()) + return ic.disable(cx, "non-native"); + JSProperty *prop; + if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return ic.error(cx); + if (!prop) + return ic.disable(cx, "lookup failed"); + if (!IsCacheableProtoChain(obj, holder)) + return ic.disable(cx, "non-native holder"); + shape = (const Shape *)prop; + return Lookup_Cacheable; + } + + LookupStatus testForGet() { + if (!shape->hasDefaultGetter()) { + if (!shape->isMethod()) + return ic.disable(cx, "getter"); + if (!ic.isCallOp()) + return ic.disable(cx, "method valued shape"); + } else if (!shape->hasSlot()) { + return ic.disable(cx, "no slot"); + } + + return Lookup_Cacheable; + } + + LookupStatus lookupAndTest() { + LookupStatus status = lookup(); + if (status != Lookup_Cacheable) + return status; + return testForGet(); + } +}; + class GetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; - VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 inlineShapeOffset(ic::PICInfo &pic) { @@ -713,10 +776,10 @@ class GetPropCompiler : public PICStubCompiler public: GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic), + : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic, + JS_FUNC_TO_DATA_PTR(void *, stub)), obj(obj), atom(atom), - stub(stub), lastStubSecondShapeGuard(pic.secondShapeGuard) { } @@ -754,7 +817,7 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - bool generateArgsLengthStub() + LookupStatus generateArgsLengthStub() { Assembler masm; @@ -772,7 +835,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notArgs, pic.slowPathStart); buffer.link(overridden, pic.slowPathStart); @@ -787,10 +850,10 @@ class GetPropCompiler : public PICStubCompiler disable("args length done"); - return true; + return Lookup_Cacheable; } - bool generateArrayLengthStub() + LookupStatus generateArrayLengthStub() { Assembler masm; @@ -806,7 +869,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notArray, pic.slowPathStart); buffer.link(oob, pic.slowPathStart); @@ -821,10 +884,10 @@ class GetPropCompiler : public PICStubCompiler disable("array length done"); - return true; + return Lookup_Cacheable; } - bool generateStringCallStub() + LookupStatus generateStringCallStub() { JS_ASSERT(pic.hasTypeCheck()); JS_ASSERT(pic.kind == ic::PICInfo::CALL); @@ -832,24 +895,12 @@ class GetPropCompiler : public PICStubCompiler if (!f.fp()->script()->compileAndGo) return disable("String.prototype without compile-and-go"); - JSObject *holder; - JSProperty *prop; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - if (!prop) - return disable("property not found"); - - const Shape *shape = (const Shape *)prop; - if (holder != obj) + GetPropertyHelper getprop(cx, obj, atom, *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; + if (getprop.obj != getprop.holder) return disable("proto walk on String.prototype"); - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - JS_ASSERT(holder->isNative()); Assembler masm; @@ -858,8 +909,7 @@ class GetPropCompiler : public PICStubCompiler ImmType(JSVAL_TYPE_STRING)); /* - * Sink pic.objReg, since we're about to lose it. This is optimistic, - * we could reload it from objRemat if we wanted. + * 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 @@ -880,19 +930,13 @@ class GetPropCompiler : public PICStubCompiler masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeMismatch = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(obj->shape())); - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !obj->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(shapeMismatch, pic.slowPathStart); @@ -911,10 +955,10 @@ class GetPropCompiler : public PICStubCompiler /* Disable the PIC so we don't keep generating stubs on the above shape mismatch. */ disable("generated string call stub"); - return true; + return Lookup_Cacheable; } - bool generateStringLengthStub() + LookupStatus generateStringLengthStub() { JS_ASSERT(pic.hasTypeCheck()); @@ -929,7 +973,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(done, pic.fastPathRejoin); @@ -945,10 +989,10 @@ class GetPropCompiler : public PICStubCompiler disable("generated string length stub"); - return true; + return Lookup_Cacheable; } - bool patchInline(JSObject *holder, const Shape *shape) + LookupStatus patchInline(JSObject *holder, const Shape *shape) { spew("patch", "inline"); PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -985,20 +1029,15 @@ class GetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return true; + return Lookup_Cacheable; } - bool generateStub(JSObject *holder, const Shape *shape) + LookupStatus generateStub(JSObject *holder, const Shape *shape) { Vector shapeMismatches(cx); Assembler masm; - if (pic.objNeedsRemat()) { - masm.rematPayload(pic.objRemat(), pic.objReg); - pic.u.get.objNeedsRemat = false; - } - Label start; Jump shapeGuard; Jump argsLenGuard; @@ -1028,63 +1067,33 @@ class GetPropCompiler : public PICStubCompiler Label stubShapeJumpLabel = masm.label(); #endif - if (!shapeMismatches.append(shapeGuard)) - return false; + return error(); + RegisterID holderReg = pic.objReg; if (obj != holder) { - // Emit code that walks the prototype chain. - JSObject *tempObj = obj; - Address proto(pic.objReg, offsetof(JSObject, proto)); - do { - tempObj = tempObj->getProto(); - // FIXME: we should find out why this condition occurs. It is probably - // related to PICs on globals. - if (!tempObj) - return disable("null object in prototype chain"); - JS_ASSERT(tempObj); + // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. + holderReg = pic.shapeReg; + masm.move(ImmPtr(holder), holderReg); + pic.shapeRegHasBaseShape = false; - /* - * If there is a non-native along the prototype chain the shape is technically - * invalid. - */ - if (!tempObj->isNative()) - return disable("non-JS-native in prototype chain"); - - masm.loadPtr(proto, pic.objReg); - pic.shapeRegHasBaseShape = false; - pic.u.get.objNeedsRemat = true; - - Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); - if (!shapeMismatches.append(j)) - return false; - } while (tempObj != holder); - - // Load the shape out of the holder and check it. - masm.loadShape(pic.objReg, pic.shapeReg); - Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(holder->shape())); + // Guard on the holder's shape. + Jump j = masm.guardShape(holderReg, holder); if (!shapeMismatches.append(j)) - return false; + return error(); + pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); } else { - JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ pic.secondShapeGuard = 0; } /* Load the value out of the object. */ - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + masm.loadObjProp(holder, holderReg, shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); // The guard exit jumps to the original slow case. for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) @@ -1111,7 +1120,7 @@ class GetPropCompiler : public PICStubCompiler if (obj->isDenseArray()) disable("dense array"); - return true; + return Lookup_Cacheable; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -1133,373 +1142,19 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - bool update() + LookupStatus update() { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } + JS_ASSERT(pic.hit); - JSObject *aobj = js_GetProtoIfDenseArray(obj); - if (!aobj->isNative()) - return disable("non-native"); + GetPropertyHelper getprop(cx, obj, atom, *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; - JSObject *holder; - JSProperty *prop; - if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - if (!prop) - return disable("lookup failed"); - - if (!holder->isNative()) - return disable("non-native holder"); - - const Shape *shape = (const Shape *)prop; - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - if (obj == holder && !pic.inlinePathPatched) - return patchInline(holder, shape); + if (obj == getprop.holder && !pic.inlinePathPatched) + return patchInline(getprop.holder, getprop.shape); - return generateStub(holder, shape); - } - - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } -}; - -class GetElemCompiler : public PICStubCompiler -{ - JSObject *obj; - JSString *id; - void *stub; - int lastStubSecondShapeGuard; - - static int32 dslotsLoad(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_DSLOTS_LOAD; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.dslotsLoadOffset; -#endif - } - - inline int32 dslotsLoad() { - return dslotsLoad(pic); - } - - static int32 inlineShapeOffset(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_SHAPE_OFFSET; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.inlineShapeOffset; -#endif - } - - inline int32 inlineShapeOffset() { - return inlineShapeOffset(pic); - } - - static int32 inlineShapeJump(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_SHAPE_JUMP; -#elif defined JS_PUNBOX64 - return inlineShapeOffset(pic) + GETELEM_INLINE_SHAPE_JUMP; -#endif - } - - inline int32 inlineShapeJump() { - return inlineShapeJump(pic); - } - - static int32 inlineAtomOffset(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_ATOM_OFFSET; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.inlineAtomOffset; -#endif - } - - inline int32 inlineAtomOffset() { - return inlineAtomOffset(pic); - } - - static int32 inlineAtomJump(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_ATOM_JUMP; -#elif defined JS_PUNBOX64 - return inlineAtomOffset(pic) + GETELEM_INLINE_ATOM_JUMP; -#endif - } - - inline int32 inlineAtomJump() { - return inlineAtomJump(pic); - } - - public: - GetElemCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSString *id, - VoidStub stub) - : PICStubCompiler("getelem", f, script, pic), obj(obj), id(id), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)), - lastStubSecondShapeGuard(pic.secondShapeGuard) - {} - - static void reset(ic::PICInfo &pic) - { - JS_ASSERT(pic.kind == ic::PICInfo::GETELEM); - - RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic))); - - /* Only the shape needs to be patched to fail -- atom jump will never be taken. */ - repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( - pic.shapeGuard + inlineShapeOffset(pic)), - int32(JSObjectMap::INVALID_SHAPE)); - repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineShapeJump(pic)), - pic.slowPathStart); - repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineAtomJump(pic)), - pic.slowPathStart); - - RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - - FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetElem)); - repatcher.relink(pic.slowPathCall, target); - } - - bool patchInline(JSObject *holder, const Shape *shape) - { - spew("patch", "inline"); - PICRepatchBuffer repatcher(pic, pic.fastPathStart); - - int32 offset; - if (!holder->hasSlotsArray()) { - JSC::CodeLocationInstruction istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad()); - repatcher.repatchLoadPtrToLEA(istr); - - // - // We've patched | mov dslots, [obj + DSLOTS_OFFSET] - // To: | lea fslots, [obj + DSLOTS_OFFSET] - // - // Because the offset is wrong, it's necessary to correct it - // below. - // - int32 diff = int32(JSObject::getFixedSlotOffset(0)) - int32(offsetof(JSObject, slots)); - JS_ASSERT(diff != 0); - offset = (int32(shape->slot) * sizeof(Value)) + diff; - } else { - offset = shape->slot * sizeof(Value); - } - - uint32 shapeOffset = pic.shapeGuard + inlineShapeOffset(); - repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffset), obj->shape()); - uint32 idOffset = pic.shapeGuard + inlineAtomOffset(); - repatcher.repatch(pic.fastPathStart.dataLabelPtrAtOffset(idOffset), id); -#if defined JS_NUNBOX32 - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_TYPE_LOAD), offset + 4); - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_DATA_LOAD), offset); -#elif defined JS_PUNBOX64 - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getelem.inlineValueOffset), offset); -#endif - pic.inlinePathPatched = true; - - return true; - } - - void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) - { - // Patch either the inline fast path or a generated stub. The stub - // omits the prefix of the inline fast path that loads the shape, so - // the offsets are different. - int shapeGuardJumpOffset; - int atomGuardJumpOffset; - if (pic.stubsGenerated) { -#if defined JS_NUNBOX32 - shapeGuardJumpOffset = GETELEM_STUB_SHAPE_JUMP; -#elif defined JS_PUNBOX64 - shapeGuardJumpOffset = pic.labels.getelem.stubShapeJump; -#endif - atomGuardJumpOffset = GETELEM_STUB_ATOM_JUMP; - } else { - shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump(); - atomGuardJumpOffset = pic.shapeGuard + inlineAtomJump(); - } - repatcher.relink(shapeGuardJumpOffset, cs); - repatcher.relink(atomGuardJumpOffset, cs); - if (lastStubSecondShapeGuard) - repatcher.relink(lastStubSecondShapeGuard, cs); - } - - bool generateStub(JSObject *holder, const Shape *shape) - { - JS_ASSERT(pic.u.get.idReg != pic.shapeReg); - Vector shapeMismatches(cx); - - Assembler masm; - - if (pic.objNeedsRemat()) { - masm.rematPayload(pic.objRemat(), pic.objReg); - pic.u.get.objNeedsRemat = false; - } - - if (pic.shapeNeedsRemat()) { - masm.loadShape(pic.objReg, pic.shapeReg); - pic.shapeRegHasBaseShape = true; - } - - Label start = masm.label(); - Jump atomGuard = masm.branchPtr(Assembler::NotEqual, pic.u.get.idReg, ImmPtr(id)); - DBGLABEL(dbgStubAtomJump); - Jump shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(obj->shape())); - -#if (defined JS_NUNBOX32 && defined DEBUG) || defined JS_PUNBOX64 - Label stubShapeJump = masm.label(); -#endif - - JS_ASSERT(masm.differenceBetween(start, dbgStubAtomJump) == GETELEM_STUB_ATOM_JUMP); -#if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(start, stubShapeJump) == GETELEM_STUB_SHAPE_JUMP); -#endif - - if (!(shapeMismatches.append(shapeGuard) && shapeMismatches.append(atomGuard))) - return false; - - if (obj != holder) { - // Emit code that walks the prototype chain. - JSObject *tempObj = obj; - Address proto(pic.objReg, offsetof(JSObject, proto)); - do { - tempObj = tempObj->getProto(); - // FIXME: we should find out why this condition occurs. It is probably - // related to PICs on globals. - if (!tempObj) - return disable("null object in prototype chain"); - JS_ASSERT(tempObj); - - /* - * If there is a non-native along the prototype chain the shape is technically - * invalid. - */ - if (!tempObj->isNative()) - return disable("non-JS-native in prototype chain"); - - masm.loadPtr(proto, pic.objReg); - pic.shapeRegHasBaseShape = false; - pic.u.get.objNeedsRemat = true; - - Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); - if (!shapeMismatches.append(j)) - return false; - } while (tempObj != holder); - - // Load the shape out of the holder and check it. - masm.loadShape(pic.objReg, pic.shapeReg); - Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(holder->shape())); - if (!shapeMismatches.append(j)) - return false; - pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); - } else { - JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ - pic.secondShapeGuard = 0; - } - - /* Load the value out of the object. */ - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } - Jump done = masm.jump(); - - PICLinker buffer(cx, pic); - if (!buffer.init(masm)) - return false; - - // The guard exit jumps to the original slow case. - for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) - buffer.link(*pj, pic.slowPathStart); - - // The final exit jumps to the store-back in the inline stub. - buffer.link(done, pic.fastPathRejoin); - CodeLocationLabel cs = buffer.finalizeCodeAddendum(); -#if DEBUG - char *chars = js_DeflateString(cx, id->chars(), id->length()); - JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n", - type, cs.executableAddress(), id, chars, holder->shape(), script->filename, - js_FramePCToLineNumber(cx, f.fp())); - cx->free(chars); -#endif - - PICRepatchBuffer repatcher(pic, pic.lastPathStart()); - patchPreviousToHere(repatcher, cs); - - pic.stubsGenerated++; - pic.lastStubStart = buffer.locationOf(start); - -#if defined JS_PUNBOX64 - pic.labels.getelem.stubShapeJump = masm.differenceBetween(start, stubShapeJump); - JS_ASSERT(pic.labels.getelem.stubShapeJump == masm.differenceBetween(start, stubShapeJump)); -#endif - - if (pic.stubsGenerated == MAX_PIC_STUBS) - disable("max stubs reached"); - if (obj->isDenseArray()) - disable("dense array"); - - return true; - } - - bool update() - { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } - - JSAtom *atom = js_AtomizeString(cx, id, 0); - if (!atom) - return false; - JSObject *holder; - JSProperty *prop; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - if (!prop) - return disable("lookup failed"); - - if (!obj->isNative()) - return disable("non-native obj"); - if (!holder->isNative()) - return disable("non-native holder"); - - const Shape *shape = (const Shape *)prop; - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - if (obj == holder && !pic.inlinePathPatched) - return patchInline(holder, shape); - - return generateStub(holder, shape); - } - - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); + return generateStub(getprop.holder, getprop.shape); } }; @@ -1507,25 +1162,17 @@ class ScopeNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; - void *stub; - JSObject *obj; - JSObject *holder; - JSProperty *prop; - const Shape *shape; + GetPropertyHelper getprop; public: ScopeNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("name", f, script, pic), scopeChain(scopeChain), atom(atom), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)), obj(NULL), holder(NULL), prop(NULL) + : PICStubCompiler("name", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + scopeChain(scopeChain), atom(atom), + getprop(f.cx, NULL, atom, *this) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -1540,16 +1187,16 @@ class ScopeNameCompiler : public PICStubCompiler typedef Vector JumpList; - bool walkScopeChain(Assembler &masm, JumpList &fails, bool &found) + LookupStatus walkScopeChain(Assembler &masm, JumpList &fails) { /* Walk the scope chain. */ JSObject *tobj = scopeChain; /* For GETXPROP, we'll never enter this loop. */ - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == holder); - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, obj == tobj); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == getprop.holder); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, getprop.obj == tobj); - while (tobj && tobj != holder) { + while (tobj && tobj != getprop.holder) { if (!js_IsCacheableNonGlobalScope(tobj)) return disable("non-cacheable scope chain object"); JS_ASSERT(tobj->isNative()); @@ -1558,14 +1205,14 @@ class ScopeNameCompiler : public PICStubCompiler /* scopeChain will never be NULL, but parents can be NULL. */ Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(j)) - return false; + return error(); } /* Guard on intervening shapes. */ masm.loadShape(pic.objReg, pic.shapeReg); Jump j = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); if (!fails.append(j)) - return false; + return error(); /* Load the next link in the scope chain. */ Address parent(pic.objReg, offsetof(JSObject, parent)); @@ -1574,12 +1221,13 @@ class ScopeNameCompiler : public PICStubCompiler tobj = tobj->getParent(); } - found = tobj == holder; + if (tobj != getprop.holder) + return disable("scope chain walk terminated early"); - return true; + return Lookup_Cacheable; } - bool generateGlobalStub() + LookupStatus generateGlobalStub(JSObject *obj) { Assembler masm; JumpList fails(cx); @@ -1588,29 +1236,21 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == holder); - JS_ASSERT(holder == scopeChain->getGlobal()); + JS_ASSERT(obj == getprop.holder); + JS_ASSERT(getprop.holder == scopeChain->getGlobal()); - bool found = false; - if (!walkScopeChain(masm, fails, found)) - return false; - if (!found) - return disable("scope chain walk terminated early"); + 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) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); - - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, false, pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); + masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); // All failures flow to here, so there is a common point to patch. @@ -1627,7 +1267,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1644,7 +1284,7 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } enum CallObjPropKind { @@ -1652,7 +1292,7 @@ class ScopeNameCompiler : public PICStubCompiler VAR }; - bool generateCallStub() + LookupStatus generateCallStub(JSObject *obj) { Assembler masm; Vector fails(cx); @@ -1661,10 +1301,11 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == holder); - JS_ASSERT(holder != scopeChain->getGlobal()); + JS_ASSERT(obj == getprop.holder); + JS_ASSERT(getprop.holder != scopeChain->getGlobal()); CallObjPropKind kind; + const Shape *shape = getprop.shape; if (shape->getterOp() == js_GetCallArg) { kind = ARG; } else if (shape->getterOp() == js_GetCallVar) { @@ -1673,23 +1314,21 @@ class ScopeNameCompiler : public PICStubCompiler return disable("unhandled callobj sprop getter"); } - bool found = false; - if (!walkScopeChain(masm, fails, found)) - return false; - if (!found) - return disable("scope chain walk terminated early"); + 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) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); /* Get callobj's stack frame. */ masm.loadFunctionPrivate(pic.objReg, pic.shapeReg); - JSFunction *fun = holder->getCallObjCalleeFunction(); + JSFunction *fun = getprop.holder->getCallObjCalleeFunction(); uint16 slot = uint16(shape->shortid); Jump skipOver; @@ -1731,7 +1370,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1747,67 +1386,56 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } - bool updateForName() + LookupStatus updateForName() { - if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) - return false; + // |getprop.obj| is filled by bind() + LookupStatus status = getprop.bind(); + if (status != Lookup_Cacheable) + return status; - return update(); + return update(getprop.obj); } - bool updateForXName() + LookupStatus updateForXName() { - obj = scopeChain; + // |obj| and |getprop.obj| are NULL, but should be the given scopeChain. + getprop.obj = scopeChain; + LookupStatus status = getprop.lookup(); + if (status != Lookup_Cacheable) + return status; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - return update(); + return update(getprop.obj); } - bool update() + LookupStatus update(JSObject *obj) { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } - - if (!prop) - return disable("property not found"); - if (!obj->isNative() || !holder->isNative()) - return disable("non-native scope object"); - if (obj != holder) - return disable("property is on proto of a scope object"); - - shape = (const Shape *)prop; - if (obj->getClass() == &js_CallClass) - return generateCallStub(); + return generateCallStub(obj); - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); + LookupStatus status = getprop.testForGet(); + if (status != Lookup_Cacheable) + return status; if (!obj->getParent()) - return generateGlobalStub(); + return generateGlobalStub(obj); return disable("scope object not handled yet"); } bool retrieve(Value *vp) { - if (prop && (!obj->isNative() || !holder->isNative())) { + JSObject *obj = getprop.obj; + JSObject *holder = getprop.holder; + const Shape *shape = getprop.shape; + + if (shape && (!obj->isNative() || !holder->isNative())) { if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp)) return false; } else { - if (!prop) { + if (!shape) { /* Kludge to allow (typeof foo == "undefined") tests. */ disable("property not found"); if (pic.kind == ic::PICInfo::NAME) { @@ -1820,12 +1448,10 @@ class ScopeNameCompiler : public PICStubCompiler ReportAtomNotDefined(cx, atom); return false; } - const Shape *shape = (const Shape *)prop; JSObject *normalized = obj; if (obj->getClass() == &js_WithClass && !shape->hasDefaultGetter()) normalized = js_UnwrapWithObject(cx, obj); - NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, - return false); + NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); } return true; @@ -1836,7 +1462,6 @@ class BindNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; - void *stub; static int32 inlineJumpOffset(ic::PICInfo &pic) { #if defined JS_NUNBOX32 @@ -1853,15 +1478,10 @@ class BindNameCompiler : public PICStubCompiler public: BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("bind", f, script, pic), scopeChain(scopeChain), atom(atom), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)) + : PICStubCompiler("bind", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + scopeChain(scopeChain), atom(atom) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -1872,7 +1492,7 @@ class BindNameCompiler : public PICStubCompiler repatcher2.relink(pic.slowPathCall, target); } - bool generateStub(JSObject *obj) + LookupStatus generateStub(JSObject *obj) { Assembler masm; js::Vector fails(cx); @@ -1892,7 +1512,7 @@ class BindNameCompiler : public PICStubCompiler masm.loadPtr(parent, pic.objReg); Jump nullTest = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(nullTest)) - return false; + return error(); masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeTest = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); @@ -1915,7 +1535,7 @@ class BindNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1934,7 +1554,7 @@ class BindNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } JSObject *update() @@ -1951,7 +1571,8 @@ class BindNameCompiler : public PICStubCompiler return obj; } - if (!generateStub(obj)) + LookupStatus status = generateStub(obj); + if (status == Lookup_Error) return NULL; return obj; @@ -1985,10 +1606,9 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (atom == f.cx->runtime->atomState.lengthAtom) { if (f.regs.sp[-1].isString()) { GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledLengthIC); - if (!cc.generateStringLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateStringLengthStub(); + if (status == Lookup_Error) THROW(); - } JSString *str = f.regs.sp[-1].toString(); f.regs.sp[-1].setInt32(str->length()); return; @@ -1997,16 +1617,14 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (obj->isArray() || (obj->isArguments() && !obj->isArgsLengthOverridden())) { GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledLengthIC); if (obj->isArray()) { - if (!cc.generateArrayLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateArrayLengthStub(); + if (status == Lookup_Error) THROW(); - } f.regs.sp[-1].setNumber(obj->getArrayLength()); } else if (obj->isArguments()) { - if (!cc.generateArgsLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateArgsLengthStub(); + if (status == Lookup_Error) THROW(); - } f.regs.sp[-1].setInt32(int32_t(obj->getArgsInitialLength())); } return; @@ -2019,7 +1637,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (!obj) THROW(); - if (pic->shouldGenerate()) { + if (pic->shouldUpdate(f.cx)) { VoidStubPIC stub = pic->usePropCache ? DisabledGetPropIC : DisabledGetPropICNoCache; @@ -2036,35 +1654,6 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) f.regs.sp[-1] = v; } -void JS_FASTCALL -ic::GetElem(VMFrame &f, ic::PICInfo *pic) -{ - JSScript *script = f.fp()->script(); - - JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]); - if (!obj) - THROW(); - - Value idval = f.regs.sp[-1]; - JS_ASSERT(idval.isString()); - JSString *id = idval.toString(); - if (pic->shouldGenerate()) { - GetElemCompiler cc(f, script, obj, *pic, id, stubs::GetElem); - if (!cc.update()) { - cc.disable("error"); - THROW(); - } - } - - JSAtom *atom = js_AtomizeString(f.cx, id, 0); - if (!atom) - THROW(); - Value v; - if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v)) - THROW(); - f.regs.sp[-2] = v; -} - template static void JS_FASTCALL DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic) @@ -2089,6 +1678,10 @@ 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); + // // Important: We update the PIC before looking up the property so that the // PIC is updated only if the property already exists. The PIC doesn't try @@ -2096,16 +1689,12 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic) // // Also note, we can't use SetName for PROPINC PICs because the property // cache can't handle a GET and SET from the same scripted PC. - // + if (pic->shouldUpdate(f.cx)) { - VoidStubPIC stub = pic->usePropCache - ? STRICT_VARIANT(DisabledSetPropIC) - : STRICT_VARIANT(DisabledSetPropICNoCache); - - SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); - if (!cc.update()) { - cc.disable("error"); - THROW(); + SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); + LookupStatus status = cc.update(); + if (status == Lookup_Error) + THROW(); } Value rval = f.regs.sp[-1]; @@ -2154,8 +1743,6 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject()); Value rval; - bool usePIC = true; - PropertyCacheEntry *entry; JSObject *obj2; JSAtom *atom; @@ -2208,22 +1795,18 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) } GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, DisabledCallPropIC); - if (usePIC) { - if (lval.isObject()) { - if (!cc.update()) { - cc.disable("error"); + if (lval.isObject()) { + if (pic->shouldUpdate(cx)) { + LookupStatus status = cc.update(); + if (status == Lookup_Error) THROW(); - } - } else if (lval.isString()) { - if (!cc.generateStringCallStub()) { - cc.disable("error"); - THROW(); - } - } else { - cc.disable("non-string primitive"); } + } else if (lval.isString()) { + LookupStatus status = cc.generateStringCallStub(); + if (status == Lookup_Error) + THROW(); } else { - cc.disable("wrapped primitive"); + cc.disable("non-string primitive"); } #if JS_HAS_NO_SUCH_METHOD @@ -2257,10 +1840,9 @@ ic::XName(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, DisabledXNameIC); - if (!cc.updateForXName()) { - cc.disable("error"); + LookupStatus status = cc.updateForXName(); + if (status == Lookup_Error) THROW(); - } Value rval; if (!cc.retrieve(&rval)) @@ -2275,10 +1857,9 @@ ic::Name(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledNameIC); - if (!cc.updateForName()) { - cc.disable("error"); + LookupStatus status = cc.updateForName(); + if (status == Lookup_Error) THROW(); - } Value rval; if (!cc.retrieve(&rval)) @@ -2317,6 +1898,308 @@ ic::BindName(VMFrame &f, ic::PICInfo *pic) 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, + js_FramePCToLineNumber(cx, cx->fp())); +#endif +} + +LookupStatus +BaseIC::disable(JSContext *cx, const char *reason, void *stub) +{ + spew(cx, "disabled", reason); + RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + repatcher.relink(slowPathCall, FunctionPtr(stub)); + return Lookup_Uncacheable; +} + +bool +BaseIC::shouldUpdate(JSContext *cx) +{ + if (!hit) { + hit = true; + spew(cx, "ignored", "first hit"); + return false; + } + JS_ASSERT(stubsGenerated < MAX_PIC_STUBS); + return true; +} + +static void JS_FASTCALL +DisabledGetElem(VMFrame &f, ic::GetElementIC *ic) +{ + stubs::GetElem(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; + 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; +} + +void +GetElementIC::purge() +{ + if (inlineTypeGuardPatched || inlineClaspGuardPatched) { + RepatchBuffer repatcher(fastPathStart.executableAddress(), INLINE_PATH_LENGTH); + + // Repatch the inline jumps. + if (inlineTypeGuardPatched) + repatcher.relink(fastPathStart.jumpAtOffset(inlineTypeGuard), slowPathStart); + if (inlineClaspGuardPatched) + repatcher.relink(fastPathStart.jumpAtOffset(inlineClaspGuard), slowPathStart); + } + + if (slowCallPatched) { + RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + repatcher.relink(slowPathCall, FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::GetElement))); + } + + reset(); +} + +LookupStatus +GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp) +{ + JS_ASSERT(v.isString()); + + GetPropertyHelper getprop(cx, obj, JSID_TO_ATOM(id), *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; + + Assembler masm; + + // Guard on the string's type and identity. + MaybeJump atomTypeGuard; + if (hasInlineTypeGuard() && !inlineTypeGuardPatched) { + // We link all string-key dependent stubs together, and store the + // first set of guards in the IC, separately, from int-key dependent + // stubs. As long as we guarantee that the first string-key dependent + // stub guards on the key type, then all other string-key stubs can + // omit the guard. + JS_ASSERT(!idRemat.isTypeKnown()); + atomTypeGuard = masm.testString(Assembler::NotEqual, typeReg); + } else { + // If there was no inline type guard, then a string type is guaranteed. + // Otherwise, we are guaranteed the type has already been checked, via + // the comment above. + JS_ASSERT_IF(!hasInlineTypeGuard(), idRemat.knownType() == JSVAL_TYPE_STRING); + } + + // Reify the shape before guards that could flow into shape guarding stubs. + if (!obj->isDenseArray() && !typeRegHasBaseShape) { + masm.loadShape(objReg, typeReg); + typeRegHasBaseShape = true; + } + + MaybeJump atomIdGuard; + if (!idRemat.isConstant()) + atomIdGuard = masm.branchPtr(Assembler::NotEqual, idRemat.dataReg(), ImmPtr(v.toString())); + + // Guard on the base shape (or in the dense array case, the clasp). + Jump shapeGuard; + if (obj->isDenseArray()) { + shapeGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass()); + } else { + shapeGuard = masm.branch32(Assembler::NotEqual, typeReg, Imm32(obj->shape())); + } + + // Guard on the prototype, if applicable. + MaybeJump protoGuard; + JSObject *holder = getprop.holder; + RegisterID holderReg = objReg; + if (obj != holder) { + // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. + holderReg = typeReg; + masm.move(ImmPtr(holder), holderReg); + typeRegHasBaseShape = false; + + // Guard on the holder's shape. + protoGuard = masm.guardShape(holderReg, holder); + } + + // 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)) + return error(cx); + + // Patch all guards. + buffer.maybeLink(atomIdGuard, slowPathStart); + 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 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()) { + // A type guard is present in the inline path, and this is the + // first string stub, so patch it now. + JS_ASSERT(!inlineTypeGuardPatched); + JS_ASSERT(atomTypeGuard.isSet()); + + repatcher.relink(inlineTypeGuard, cs); + inlineTypeGuardPatched = true; + } + + if (shouldPatchUnconditionalClaspGuard()) { + // The clasp guard is unconditional, meaning there is no type + // check. This is the first stub, so it has to be patched. Note + // that it is wrong to patch the inline clasp guard otherwise, + // because it follows an integer-id guard. + JS_ASSERT(!hasInlineTypeGuard()); + + repatcher.relink(inlineClaspGuard, cs); + inlineClaspGuardPatched = true; + } + } + + // If there were previous stub guards, patch them now. + if (hasLastStringStub) { + PICRepatchBuffer repatcher(*this, lastStringStub); + if (atomGuard) + repatcher.relink(atomGuard, cs); + repatcher.relink(firstShapeGuard, cs); + if (secondShapeGuard) + repatcher.relink(secondShapeGuard, cs); + } + + // Update state. + hasLastStringStub = true; + lastStringStub = cs; + if (atomIdGuard.isSet()) { + atomGuard = buffer.locationOf(atomIdGuard.get()) - cs; + JS_ASSERT(atomGuard == buffer.locationOf(atomIdGuard.get()) - cs); + JS_ASSERT(atomGuard); + } else { + atomGuard = 0; + } + if (protoGuard.isSet()) { + secondShapeGuard = buffer.locationOf(protoGuard.get()) - cs; + JS_ASSERT(secondShapeGuard == buffer.locationOf(protoGuard.get()) - cs); + JS_ASSERT(secondShapeGuard); + } else { + secondShapeGuard = 0; + } + firstShapeGuard = buffer.locationOf(shapeGuard) - cs; + JS_ASSERT(firstShapeGuard == buffer.locationOf(shapeGuard) - cs); + JS_ASSERT(firstShapeGuard); + + stubsGenerated++; + + if (stubsGenerated == MAX_GETELEM_IC_STUBS) + disable(cx, "max stubs reached"); + + // Finally, fetch the value to avoid redoing the property lookup. + if (shape->isMethod()) + *vp = ObjectValue(shape->methodObject()); + else + *vp = holder->getSlot(shape->slot); + + return Lookup_Cacheable; +} + +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::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); + return; + } + + JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]); + if (!obj) + THROW(); + + Value idval = f.regs.sp[-1]; + + 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)) + THROW(); + } + + if (ic->shouldUpdate(cx)) { +#ifdef DEBUG + f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC); +#endif + LookupStatus status = ic->update(cx, obj, 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()); + return; + } + } + + if (!obj->getProperty(cx, id, &f.regs.sp[-2])) + THROW(); +} + void JITScript::purgePICs() { @@ -2338,15 +2221,15 @@ JITScript::purgePICs() case ic::PICInfo::GET: GetPropCompiler::reset(pic); break; - case ic::PICInfo::GETELEM: - GetElemCompiler::reset(pic); - break; default: JS_NOT_REACHED("Unhandled PIC kind"); break; } pic.reset(); } + + for (uint32 i = 0; i < nGetElems; i++) + getElems[i].purge(); } void diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 774a771047d..8bda651d572 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -37,7 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ -#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT && defined JS_POLYIC +#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT #define jsjaeger_poly_ic_h__ #include "jscntxt.h" @@ -46,7 +46,9 @@ #include "assembler/assembler/MacroAssembler.h" #include "assembler/assembler/CodeLocation.h" #include "methodjit/MethodJIT.h" +#include "BaseAssembler.h" #include "RematInfo.h" +#include "BaseCompiler.h" namespace js { namespace mjit { @@ -54,6 +56,7 @@ namespace ic { /* Maximum number of stubs for a given callsite. */ static const uint32 MAX_PIC_STUBS = 16; +static const uint32 MAX_GETELEM_IC_STUBS = 17; /* SetPropCompiler */ #if defined JS_CPU_X86 @@ -159,26 +162,6 @@ union PICLabels { int32 stubShapeJump : 8; } getprop; - /* GetElemCompiler */ - struct { - /* Offset from storeBack to beginning of 'mov dslots, addr' */ - int32 dslotsLoadOffset : 8; - - /* Offset from shapeGuard to end of shape comparison. */ - int32 inlineShapeOffset : 8; - - /* Offset from shapeGuard to end of atom comparison. */ - int32 inlineAtomOffset : 8; - - /* Offset from storeBack to end of value load. */ - int32 inlineValueOffset : 8; - - /* Offset from lastStubStart to end of shape jump. */ - // TODO: We can redefine the location of lastStubStart to be - // after the jump -- at which point this is always 0. - int32 stubShapeJump : 8; - } getelem; - /* BindNameCompiler */ struct { /* Offset from shapeGuard to end of shape jump. */ @@ -187,21 +170,27 @@ union PICLabels { }; #endif -struct BaseIC { +enum LookupStatus { + Lookup_Error = 0, + Lookup_Uncacheable, + Lookup_Cacheable +}; + +struct BaseIC : public MacroAssemblerTypedefs { // Address of inline fast-path. - JSC::CodeLocationLabel fastPathStart; + CodeLocationLabel fastPathStart; // Address to rejoin to the fast-path. - JSC::CodeLocationLabel fastPathRejoin; + CodeLocationLabel fastPathRejoin; // Start of the slow path. - JSC::CodeLocationLabel slowPathStart; + CodeLocationLabel slowPathStart; // Slow path stub call. - JSC::CodeLocationCall slowPathCall; + CodeLocationCall slowPathCall; // Address of the start of the last generated stub, if any. - JSC::CodeLocationLabel lastStubStart; + CodeLocationLabel lastStubStart; typedef Vector ExecPoolVector; @@ -210,16 +199,25 @@ struct BaseIC { // Return the start address of the last path in this PIC, which is the // inline path if no stubs have been generated yet. - JSC::CodeLocationLabel lastPathStart() { + CodeLocationLabel lastPathStart() { return stubsGenerated > 0 ? lastStubStart : fastPathStart; } // Whether or not the callsite has been hit at least once. bool hit : 1; + bool slowCallPatched : 1; // Number of stubs generated. uint32 stubsGenerated : 5; + // Offset from start of stub to jump target of second shape guard as Nitro + // asm data location. This is 0 if there is only one shape guard in the + // last stub. + int secondShapeGuard : 11; + + // Opcode this was compiled for. + JSOp op : 8; + // Release ExecutablePools referred to by this PIC. void releasePools() { for (JSC::ExecutablePool **pExecPool = execPools.begin(); @@ -229,17 +227,122 @@ struct BaseIC { } } + void init() { + new (&execPools) ExecPoolVector(SystemAllocPolicy()); + } + void finish() { + releasePools(); + this->~BaseIC(); + } + void reset() { hit = false; + slowCallPatched = false; stubsGenerated = 0; + secondShapeGuard = 0; releasePools(); execPools.clear(); } + bool shouldUpdate(JSContext *cx); + void spew(JSContext *cx, const char *event, const char *reason); + LookupStatus disable(JSContext *cx, const char *reason, void *stub); + bool isCallOp(); +}; + +struct GetElementIC : public BaseIC { + // On stub entry: + // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is false, + // - typeReg contains the type of the |id| parameter. + // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is true, + // - typeReg contains the shape of |objReg| iff typeRegHasBaseShape + // is true. + // Otherwise, typeReg is garbage. + // + // On stub exit, typeReg must contain the type of the result value. + RegisterID typeReg : 5; + + // On stub entry, objReg contains the object pointer for the |obj| parameter. + // On stub exit, objReg must contain the payload of the result value. + RegisterID objReg : 5; + + // Offset from the fast path to the inline type check. + // This is only set if hasInlineTypeCheck() is true. + int inlineTypeGuard : 6; + + // Offset from the fast path to the inline clasp guard. This is always + // set; if |id| is known to not be int32, then it's an unconditional + // jump to the slow path. + int inlineClaspGuard : 6; + + // This is usable if hasInlineTypeGuard() returns true, which implies + // that a dense array fast path exists. The inline type guard serves as + // the head of the chain of all string-based element stubs. + bool inlineTypeGuardPatched : 1; + + // This is always usable, and specifies whether the inline clasp guard + // has been patched. If hasInlineTypeGuard() is true, it guards against + // a dense array, and guarantees the inline type guard has passed. + // Otherwise, there is no inline type guard, and the clasp guard is just + // an unconditional jump. + bool inlineClaspGuardPatched : 1; + + //////////////////////////////////////////// + // State for string-based property stubs. // + //////////////////////////////////////////// + + // True if typeReg is guaranteed to have the shape of objReg. + bool typeRegHasBaseShape : 1; + + // These offsets are used for string-key dependent stubs, such as named + // property accesses. They are separated from the int-key dependent stubs, + // in order to guarantee that the id type needs only one guard per type. + int atomGuard : 8; // optional, non-zero if present + int firstShapeGuard : 8; // always set + int secondShapeGuard : 8; // optional, non-zero if present + + bool hasLastStringStub : 1; + CodeLocationLabel lastStringStub; + + // A limited ValueRemat instance. It may contains either: + // 1) A constant, or + // 2) A known type and data reg, or + // 3) A data reg. + // The sync bits are not set, and the type reg is never set and should not + // be used, as it is encapsulated more accurately in |typeReg|. Also, note + // carefully that the data reg is immutable. + ValueRemat idRemat; + + bool hasInlineTypeGuard() const { + return !idRemat.isTypeKnown(); + } + bool shouldPatchInlineTypeGuard() { + return hasInlineTypeGuard() && !inlineTypeGuardPatched; + } + bool shouldPatchUnconditionalClaspGuard() { + return !hasInlineTypeGuard() && !inlineClaspGuardPatched; + } + + void init() { + BaseIC::init(); + reset(); + } + void reset() { + BaseIC::reset(); + inlineTypeGuardPatched = false; + inlineClaspGuardPatched = false; + typeRegHasBaseShape = false; + hasLastStringStub = false; + } + void purge(); + LookupStatus update(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp); + LookupStatus attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, + Value *vp); + LookupStatus disable(JSContext *cx, const char *reason); + LookupStatus error(JSContext *cx); + bool shouldUpdate(JSContext *cx); }; struct PICInfo : public BaseIC { - typedef JSC::MacroAssembler::RegisterID RegisterID; - // Operation this is a PIC for. enum Kind #ifdef _MSC_VER @@ -252,7 +355,6 @@ struct PICInfo : public BaseIC { SETMETHOD, // JSOP_SETMETHOD NAME, // JSOP_NAME BIND, // JSOP_BINDNAME - GETELEM, // JSOP_GETELEM XNAME // JSOP_GETXPROP }; @@ -263,20 +365,10 @@ struct PICInfo : public BaseIC { // Reverse offset from slowPathStart to the type check slow path. int32 typeCheckOffset; - - // Remat info for the object reg. - int32 objRemat : MIN_STATE_REMAT_BITS; - bool objNeedsRemat : 1; - RegisterID idReg : 5; // only used in GETELEM PICs. } get; ValueRemat vr; } u; - // Offset from start of stub to jump target of second shape guard as Nitro - // asm data location. This is 0 if there is only one shape guard in the - // last stub. - int secondShapeGuard : 11; - Kind kind : 3; // True if register R holds the base object shape along exits from the @@ -299,7 +391,7 @@ struct PICInfo : public BaseIC { return kind == SET || kind == SETMETHOD; } inline bool isGet() const { - return kind == GET || kind == CALL || kind == GETELEM; + return kind == GET || kind == CALL; } inline RegisterID typeReg() { JS_ASSERT(isGet()); @@ -309,14 +401,6 @@ struct PICInfo : public BaseIC { JS_ASSERT(isGet()); return u.get.hasTypeCheck; } - inline const StateRemat objRemat() const { - JS_ASSERT(isGet()); - return StateRemat::FromInt32(u.get.objRemat); - } - inline bool objNeedsRemat() { - JS_ASSERT(isGet()); - return u.get.objNeedsRemat; - } inline bool shapeNeedsRemat() { return !shapeRegHasBaseShape; } @@ -325,12 +409,6 @@ struct PICInfo : public BaseIC { return !hasTypeCheck(); } - inline void setObjRemat(const StateRemat &sr) { - JS_ASSERT(isGet()); - u.get.objRemat = sr.toInt32(); - JS_ASSERT(u.get.objRemat == sr.toInt32()); - } - #if defined JS_CPU_X64 // Required labels for platform-specific patching. PICLabels labels; @@ -342,30 +420,30 @@ struct PICInfo : public BaseIC { // Index into the script's atom table. JSAtom *atom; - bool shouldGenerate() { - return stubsGenerated < MAX_PIC_STUBS || !inlinePathPatched; + void init() { + BaseIC::init(); + reset(); } // Reset the data members to the state of a fresh PIC before any patching // or stub generation was done. void reset() { inlinePathPatched = false; - if (kind == GET || kind == CALL || kind == GETELEM) - u.get.objNeedsRemat = false; - secondShapeGuard = 0; shapeRegHasBaseShape = true; BaseIC::reset(); } }; +#ifdef JS_POLYIC void PurgePICs(JSContext *cx, JSScript *script); void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *); -void JS_FASTCALL GetElem(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 *); +#endif } /* namespace ic */ } /* namespace mjit */ diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index eabe3d9f3ff..0e14f5b3b90 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -93,16 +93,10 @@ class PunboxAssembler : public JSC::MacroAssembler return address; } - void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, - RegisterID type, RegisterID data) { - JS_ASSERT(type != data); - Address address(obj, JSObject::getFixedSlotOffset(slot)); - if (!inlineAccess) { - loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); - address = Address(clobber, slot * sizeof(Value)); - } - - loadValueAsComponents(address, type, data); + void loadInlineSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + Address address(objReg, JSObject::getFixedSlotOffset(slot)); + loadValueAsComponents(address, typeReg, dataReg); } template diff --git a/js/src/methodjit/StubCompiler.h b/js/src/methodjit/StubCompiler.h index 9dcf1784a1b..9d3099ac83c 100644 --- a/js/src/methodjit/StubCompiler.h +++ b/js/src/methodjit/StubCompiler.h @@ -127,6 +127,7 @@ class StubCompiler STUB_CALL_TYPE(VoidStubPC); #ifdef JS_POLYIC STUB_CALL_TYPE(VoidStubPIC); + STUB_CALL_TYPE(VoidStubGetElemIC); #endif #ifdef JS_MONOIC STUB_CALL_TYPE(VoidStubMIC); From d4bbfae64f7a70bc557130d35d8ffa4504e50105 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 27 Oct 2010 21:35:47 -0700 Subject: [PATCH 098/263] Backed out changeset 921334ab1ea5 --- js/src/methodjit/BaseAssembler.h | 26 +- js/src/methodjit/BaseCompiler.h | 38 +- js/src/methodjit/Compiler.cpp | 188 +++-- js/src/methodjit/Compiler.h | 42 +- js/src/methodjit/FastOps.cpp | 236 ++++-- js/src/methodjit/FrameEntry.h | 6 - js/src/methodjit/MethodJIT.cpp | 8 +- js/src/methodjit/MethodJIT.h | 4 - js/src/methodjit/NunboxAssembler.h | 23 +- js/src/methodjit/PolyIC.cpp | 1251 +++++++++++++++------------- js/src/methodjit/PolyIC.h | 202 ++--- js/src/methodjit/PunboxAssembler.h | 14 +- js/src/methodjit/StubCompiler.h | 1 - 13 files changed, 1086 insertions(+), 953 deletions(-) diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 04f3d9c90b5..bd230d6b0b4 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -50,8 +50,6 @@ #include "methodjit/MethodJIT.h" #include "methodjit/MachineRegs.h" #include "CodeGenIncludes.h" -#include "jsobjinlines.h" -#include "jsscopeinlines.h" namespace js { namespace mjit { @@ -211,9 +209,9 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste load32(Address(obj, offsetof(JSObject, objShape)), shape); } - Jump guardShape(RegisterID objReg, JSObject *obj) { - return branch32(NotEqual, Address(objReg, offsetof(JSObject, objShape)), - Imm32(obj->shape())); + Jump guardShape(RegisterID obj, uint32 shape) { + return branch32(NotEqual, Address(obj, offsetof(JSObject, objShape)), + Imm32(shape)); } Jump testFunction(Condition cond, RegisterID fun) { @@ -429,24 +427,6 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste else move(remat.reg(), reg); } - - void loadDynamicSlot(RegisterID objReg, uint32 slot, - RegisterID typeReg, RegisterID dataReg) { - loadPtr(Address(objReg, offsetof(JSObject, slots)), dataReg); - loadValueAsComponents(Address(dataReg, slot * sizeof(Value)), typeReg, dataReg); - } - - void loadObjProp(JSObject *obj, RegisterID objReg, - const js::Shape *shape, - RegisterID typeReg, RegisterID dataReg) - { - if (shape->isMethod()) - loadValueAsComponents(ObjectValue(shape->methodObject()), typeReg, dataReg); - else if (obj->hasSlotsArray()) - loadDynamicSlot(objReg, shape->slot, typeReg, dataReg); - else - loadInlineSlot(objReg, shape->slot, typeReg, dataReg); - } }; /* Return f if the script is strict mode code, f otherwise. */ diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index d4ccce0ca1e..ad1ff5ad804 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -48,7 +48,19 @@ namespace js { namespace mjit { -struct MacroAssemblerTypedefs { +class BaseCompiler +{ + protected: + JSContext *cx; + + public: + BaseCompiler() : cx(NULL) + { } + + BaseCompiler(JSContext *cx) : cx(cx) + { } + + protected: typedef JSC::MacroAssembler::Label Label; typedef JSC::MacroAssembler::Imm32 Imm32; typedef JSC::MacroAssembler::ImmPtr ImmPtr; @@ -65,25 +77,11 @@ struct MacroAssemblerTypedefs { typedef JSC::MacroAssembler::DataLabel32 DataLabel32; typedef JSC::FunctionPtr FunctionPtr; typedef JSC::RepatchBuffer RepatchBuffer; + typedef JSC::CodeBlock CodeBlock; typedef JSC::CodeLocationLabel CodeLocationLabel; - typedef JSC::CodeLocationCall CodeLocationCall; + typedef JSC::JITCode JITCode; typedef JSC::ReturnAddressPtr ReturnAddressPtr; typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr; -}; - -class BaseCompiler : public MacroAssemblerTypedefs -{ - protected: - JSContext *cx; - - public: - BaseCompiler() : cx(NULL) - { } - - BaseCompiler(JSContext *cx) : cx(cx) - { } - - protected: JSC::ExecutablePool * getExecPool(size_t size) { @@ -129,12 +127,6 @@ class LinkerHelper : public JSC::LinkBuffer } return ep; } - - void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) { - if (!jump.isSet()) - return; - link(jump.get(), label); - } }; } /* namespace js */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 0a895bbc838..38430a33672 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -103,7 +103,6 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp) #endif #if defined JS_POLYIC pics(ContextAllocPolicy(cx)), - getElemICs(ContextAllocPolicy(cx)), #endif callPatches(ContextAllocPolicy(cx)), callSites(ContextAllocPolicy(cx)), @@ -391,7 +390,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp) #endif #if defined JS_POLYIC sizeof(ic::PICInfo) * pics.length() + - sizeof(ic::GetElementIC) * getElemICs.length() + #endif sizeof(CallSite) * callSites.length(); @@ -588,38 +586,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp) } #if defined JS_POLYIC - jit->nGetElems = getElemICs.length(); - if (getElemICs.length()) { - jit->getElems = (ic::GetElementIC *)cursor; - cursor += sizeof(ic::GetElementIC) * getElemICs.length(); - } else { - jit->getElems = NULL; - } - - for (size_t i = 0; i < getElemICs.length(); i++) { - ic::GetElementIC &to = jit->getElems[i]; - GetElementICInfo &from = getElemICs[i]; - to.init(); - from.copyTo(to, fullCode, stubCode); - - to.typeReg = from.typeReg; - to.objReg = from.objReg; - to.idRemat = from.id; - - if (from.typeGuard.isSet()) { - int inlineTypeGuard = fullCode.locationOf(from.typeGuard.get()) - - fullCode.locationOf(from.fastPathStart); - to.inlineTypeGuard = inlineTypeGuard; - JS_ASSERT(to.inlineTypeGuard == inlineTypeGuard); - } - int inlineClaspGuard = fullCode.locationOf(from.claspGuard) - - fullCode.locationOf(from.fastPathStart); - to.inlineClaspGuard = inlineClaspGuard; - JS_ASSERT(to.inlineClaspGuard == inlineClaspGuard); - - stubCode.patch(from.paramAddr, &to); - } - jit->nPICs = pics.length(); if (pics.length()) { jit->pics = (ic::PICInfo *)cursor; @@ -630,9 +596,11 @@ mjit::Compiler::finishThisUp(JITScript **jitp) if (ic::PICInfo *scriptPICs = jit->pics) { for (size_t i = 0; i < pics.length(); i++) { - scriptPICs[i].init(); - pics[i].copyTo(scriptPICs[i], fullCode, stubCode); pics[i].copySimpleMembersTo(scriptPICs[i]); + scriptPICs[i].fastPathStart = fullCode.locationOf(pics[i].fastPathStart); + scriptPICs[i].fastPathRejoin = fullCode.locationOf(pics[i].fastPathRejoin); + scriptPICs[i].slowPathStart = stubCode.locationOf(pics[i].slowPathStart); + scriptPICs[i].slowPathCall = stubCode.locationOf(pics[i].slowPathCall); scriptPICs[i].shapeGuard = masm.distanceOf(pics[i].shapeGuard) - masm.distanceOf(pics[i].fastPathStart); JS_ASSERT(scriptPICs[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) - @@ -655,6 +623,8 @@ mjit::Compiler::finishThisUp(JITScript **jitp) scriptPICs[i].u.get.typeCheckOffset = distance; } } + new (&scriptPICs[i].execPools) ic::PICInfo::ExecPoolVector(SystemAllocPolicy()); + scriptPICs[i].reset(); stubCode.patch(pics[i].paramAddr, &scriptPICs[i]); } } @@ -2623,9 +2593,9 @@ mjit::Compiler::passMICAddress(MICGenInfo &mic) #if defined JS_POLYIC void -mjit::Compiler::passICAddress(BaseICInfo *ic) +mjit::Compiler::passPICAddress(PICGenInfo &pic) { - ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); + pic.paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); } bool @@ -2653,7 +2623,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) shapeReg = frame.allocReg(); } - PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache); + PICGenInfo pic(ic::PICInfo::GET, usePropCache); /* Guard that the type is an object. */ Jump typeCheck; @@ -2684,6 +2654,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.shapeReg = shapeReg; pic.atom = atom; + pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -2698,7 +2669,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::GetProp); /* Load dslots. */ @@ -2756,6 +2727,113 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) return true; } +#ifdef JS_POLYIC +bool +mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, + RegisterID idReg, RegisterID shapeReg) +{ + PICGenInfo pic(ic::PICInfo::GETELEM, true); + + pic.objRemat = frame.dataRematInfo(obj); + pic.idRemat = frame.dataRematInfo(id); + pic.shapeReg = shapeReg; + pic.hasTypeCheck = false; + + pic.fastPathStart = masm.label(); + + /* Guard on shape. */ + masm.loadShape(objReg, shapeReg); + pic.shapeGuard = masm.label(); + + DataLabel32 inlineShapeOffsetLabel; + Jump jmpShapeGuard = masm.branch32WithPatch(Assembler::NotEqual, shapeReg, + Imm32(int32(JSObjectMap::INVALID_SHAPE)), + inlineShapeOffsetLabel); + DBGLABEL(dbgInlineShapeJump); + + /* Guard on id identity. */ +#if defined JS_NUNBOX32 + static const void *BOGUS_ATOM = (void *)0xdeadbeef; +#elif defined JS_PUNBOX64 + static const void *BOGUS_ATOM = (void *)0xfeedfacedeadbeef; +#endif + + DataLabelPtr inlineAtomOffsetLabel; + Jump idGuard = masm.branchPtrWithPatch(Assembler::NotEqual, idReg, + inlineAtomOffsetLabel, ImmPtr(BOGUS_ATOM)); + DBGLABEL(dbgInlineAtomJump); + + /* + * The state between these two exits is identical, so this safe. The + * GETELEM PIC repatches both jumps to the slowPathStart on reset. + */ + stubcc.linkExit(idGuard, Uses(2)); + pic.slowPathStart = stubcc.linkExit(jmpShapeGuard, Uses(2)); + + stubcc.leave(); + passPICAddress(pic); + pic.slowPathCall = stubcc.call(ic::GetElem); + + /* Load dslots. */ +#if defined JS_NUNBOX32 + DBGLABEL(dbgDslotsLoad); +#elif defined JS_PUNBOX64 + Label dslotsLoadLabel = masm.label(); +#endif + masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); + + /* Copy the slot value to the expression stack. */ + Address slot(objReg, 1 << 24); +#if defined JS_NUNBOX32 + masm.loadTypeTag(slot, shapeReg); + DBGLABEL(dbgTypeLoad); + masm.loadPayload(slot, objReg); + DBGLABEL(dbgDataLoad); +#elif defined JS_PUNBOX64 + Label inlineValueOffsetLabel = + masm.loadValueAsComponents(slot, shapeReg, objReg); +#endif + pic.fastPathRejoin = masm.label(); + + pic.objReg = objReg; + pic.idReg = idReg; + + RETURN_IF_OOM(false); +#if defined JS_NUNBOX32 + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); + JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel) == GETELEM_INLINE_ATOM_OFFSET); + JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == GETELEM_INLINE_ATOM_JUMP); + JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == GETELEM_INLINE_SHAPE_OFFSET); + JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); +#elif defined JS_PUNBOX64 + pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); + JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); + + pic.labels.getelem.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel); + JS_ASSERT(pic.labels.getelem.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel)); + + pic.labels.getelem.inlineAtomOffset = masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel); + JS_ASSERT(pic.labels.getelem.inlineAtomOffset == masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel)); + + pic.labels.getelem.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel); + JS_ASSERT(pic.labels.getelem.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel)); + + JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); + JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == + pic.labels.getelem.inlineAtomOffset + GETELEM_INLINE_ATOM_JUMP); +#endif + + JS_ASSERT(pic.idReg != pic.objReg); + JS_ASSERT(pic.idReg != pic.shapeReg); + JS_ASSERT(pic.objReg != pic.shapeReg); + + pics.append(pic); + return true; +} +#endif + bool mjit::Compiler::jsop_callprop_generic(JSAtom *atom) { @@ -2769,7 +2847,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) RegisterID objReg = frame.copyDataIntoReg(top); RegisterID shapeReg = frame.allocReg(); - PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); + PICGenInfo pic(ic::PICInfo::CALL, true); pic.pc = PC; @@ -2793,6 +2871,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) pic.objReg = objReg; pic.shapeReg = shapeReg; pic.atom = atom; + pic.objRemat = frame.dataRematInfo(top); /* * Store the type and object back. Don't bother keeping them in registers, @@ -2822,7 +2901,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) /* Slow path. */ stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Adjust the frame. None of this will generate code. */ @@ -2940,7 +3019,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) { FrameEntry *top = frame.peek(-1); - PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); + PICGenInfo pic(ic::PICInfo::CALL, true); JS_ASSERT(top->isTypeKnown()); JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT); @@ -2955,6 +3034,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.shapeReg = shapeReg; pic.atom = atom; + pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -2969,7 +3049,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Load dslots. */ @@ -3071,10 +3151,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) JSOp op = JSOp(*PC); - ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD) - ? ic::PICInfo::SETMETHOD - : ic::PICInfo::SET; - PICGenInfo pic(kind, op, usePropCache); + PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET, usePropCache); pic.atom = atom; /* Guard that the type is an object. */ @@ -3114,6 +3191,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) RegisterID shapeReg = frame.allocReg(); pic.shapeReg = shapeReg; + pic.objRemat = frame.dataRematInfo(lhs); frame.unpinEntry(vr); @@ -3131,7 +3209,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(2)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::SetProp); } @@ -3198,7 +3276,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) void mjit::Compiler::jsop_name(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::NAME, JSOp(*PC), true); + PICGenInfo pic(ic::PICInfo::NAME, true); pic.shapeReg = frame.allocReg(); pic.objReg = frame.allocReg(); @@ -3213,7 +3291,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::Name); } @@ -3230,7 +3308,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) bool mjit::Compiler::jsop_xname(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true); + PICGenInfo pic(ic::PICInfo::XNAME, true); FrameEntry *fe = frame.peek(-1); if (fe->isNotType(JSVAL_TYPE_OBJECT)) { @@ -3255,7 +3333,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::XName); } @@ -3274,7 +3352,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) void mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { - PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC), usePropCache); + PICGenInfo pic(ic::PICInfo::BIND, usePropCache); // 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 @@ -3304,7 +3382,7 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passICAddress(&pic); + passPICAddress(pic); pic.slowPathCall = stubcc.call(ic::BindName); } diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 3bf27b46e14..4483e4f8185 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -160,39 +160,18 @@ class Compiler : public BaseCompiler bool hasSlowNcode; }; +#if defined JS_POLYIC struct BaseICInfo { - BaseICInfo(JSOp op) : op(op) - { } Label fastPathStart; Label fastPathRejoin; Label slowPathStart; Call slowPathCall; DataLabelPtr paramAddr; - JSOp op; - - void copyTo(ic::BaseIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) { - to.fastPathStart = full.locationOf(fastPathStart); - to.fastPathRejoin = full.locationOf(fastPathRejoin); - to.slowPathStart = stub.locationOf(slowPathStart); - to.slowPathCall = stub.locationOf(slowPathCall); - to.op = op; - JS_ASSERT(to.op == op); - } - }; - - struct GetElementICInfo : public BaseICInfo { - GetElementICInfo(JSOp op) : BaseICInfo(op) - { } - RegisterID typeReg; - RegisterID objReg; - ValueRemat id; - MaybeJump typeGuard; - Jump claspGuard; }; struct PICGenInfo : public BaseICInfo { - PICGenInfo(ic::PICInfo::Kind kind, JSOp op, bool usePropCache) - : BaseICInfo(op), kind(kind), usePropCache(usePropCache) + PICGenInfo(ic::PICInfo::Kind kind, bool usePropCache) + : kind(kind), usePropCache(usePropCache) { } ic::PICInfo::Kind kind; Label typeCheck; @@ -204,6 +183,8 @@ class Compiler : public BaseCompiler Label shapeGuard; jsbytecode *pc; JSAtom *atom; + StateRemat objRemat; + StateRemat idRemat; bool hasTypeCheck; ValueRemat vr; # if defined JS_CPU_X64 @@ -219,12 +200,15 @@ class Compiler : public BaseCompiler if (ic.isSet()) { ic.u.vr = vr; } else if (ic.isGet()) { + ic.u.get.idReg = idReg; ic.u.get.typeReg = typeReg; ic.u.get.hasTypeCheck = hasTypeCheck; + ic.setObjRemat(objRemat); } } }; +#endif struct Defs { Defs(uint32 ndefs) @@ -266,7 +250,6 @@ class Compiler : public BaseCompiler #endif #if defined JS_POLYIC js::Vector pics; - js::Vector getElemICs; #endif js::Vector callPatches; js::Vector callSites; @@ -315,7 +298,7 @@ class Compiler : public BaseCompiler void iterEnd(); MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg); #ifdef JS_POLYIC - void passICAddress(BaseICInfo *ic); + void passPICAddress(PICGenInfo &pic); #endif #ifdef JS_MONOIC void passMICAddress(MICGenInfo &mic); @@ -417,6 +400,13 @@ class Compiler : public BaseCompiler void jsop_localinc(JSOp op, uint32 slot, bool popped); void jsop_setelem(); bool jsop_getelem(); + bool jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); + bool jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); + void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); + bool jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg, + RegisterID shapeReg); + void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, + MaybeRegisterID &idReg, RegisterID shapeReg); void jsop_stricteq(JSOp op); void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void 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 2f9dc0c77b5..76cf06f3f24 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1360,6 +1360,135 @@ mjit::Compiler::jsop_setelem() stubcc.rejoin(Changes(0)); } +void +mjit::Compiler::jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, + MaybeRegisterID &idReg, RegisterID tmpReg) +{ + /* Note: idReg is only valid if id is not a constant. */ + Jump guardDense = masm.testObjClass(Assembler::NotEqual, objReg, &js_ArrayClass); + stubcc.linkExit(guardDense, Uses(2)); + + Int32Key key = idReg.isSet() + ? Int32Key::FromRegister(idReg.reg()) + : Int32Key::FromConstant(id->getValue().toInt32()); + + Assembler::FastArrayLoadFails fails = + masm.fastArrayLoad(objReg, key, tmpReg, objReg); + + stubcc.linkExit(fails.rangeCheck, Uses(2)); + stubcc.linkExit(fails.holeCheck, Uses(2)); +} + +bool +mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) +{ + switch (id->getKnownType()) { + case JSVAL_TYPE_INT32: + { + /* Prologue. */ + RegisterID objReg = frame.copyDataIntoReg(obj); + MaybeRegisterID idReg; + if (!id->isConstant()) + idReg.setReg(frame.copyDataIntoReg(id)); + + /* Meat. */ + jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); + stubcc.leave(); + stubcc.call(stubs::GetElem); + + /* Epilogue. */ + if (idReg.isSet()) + frame.freeReg(idReg.reg()); + frame.popn(2); + frame.pushRegs(tmpReg, objReg); + stubcc.rejoin(Changes(1)); + break; + } +#ifdef JS_POLYIC + case JSVAL_TYPE_STRING: + { + /* Prologue. */ + RegisterID objReg = frame.copyDataIntoReg(obj); + RegisterID idReg = frame.copyDataIntoReg(id); + + /* Meat. */ + if (!jsop_getelem_pic(obj, id, objReg, idReg, tmpReg)) + return false; + + /* Epilogue. */ + frame.popn(2); + frame.pushRegs(tmpReg, objReg); + frame.freeReg(idReg); + stubcc.rejoin(Changes(1)); + break; + } +#endif + default: + JS_NOT_REACHED("Invalid known id type."); + } + return true; +} + +#ifdef JS_POLYIC +bool +mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) +{ + JS_ASSERT(!id->isTypeKnown()); + RegisterID objReg = frame.copyDataIntoReg(obj); + MaybeRegisterID idReg(frame.copyDataIntoReg(id)); + + RegisterID typeReg = frame.tempRegForType(id, tmpReg); + Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); + + JaegerSpew(JSpew_Insns, " ==== BEGIN DENSE ARRAY CODE ==== \n"); + + jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); + Jump performedDense = masm.jump(); + + JaegerSpew(JSpew_Insns, " ==== END DENSE ARRAY CODE ==== \n"); + + intGuard.linkTo(masm.label(), &masm); + Jump stringGuard = masm.testString(Assembler::NotEqual, typeReg); + stubcc.linkExit(stringGuard, Uses(2)); /* Neither int nor string at this point. */ + + stubcc.leave(); + stubcc.call(stubs::GetElem); + Jump toFinalMerge = stubcc.masm.jump(); + + if (!jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg)) + return false; + performedDense.linkTo(masm.label(), &masm); + frame.popn(2); + frame.pushRegs(tmpReg, objReg); + frame.freeReg(idReg.reg()); + toFinalMerge.linkTo(stubcc.masm.label(), &stubcc.masm); + stubcc.rejoin(Changes(1)); + return true; +} +#endif + +void +mjit::Compiler::jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) +{ + /* Only handle the int32 case. */ + RegisterID objReg = frame.copyDataIntoReg(obj); + MaybeRegisterID idReg(frame.copyDataIntoReg(id)); + RegisterID typeReg = frame.tempRegForType(id, tmpReg); + Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); + stubcc.linkExit(intGuard, Uses(2)); + + /* Meat. */ + jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); + stubcc.leave(); + stubcc.call(stubs::GetElem); + + /* Epilogue. */ + frame.freeReg(idReg.reg()); + frame.popn(2); + frame.pushRegs(tmpReg, objReg); + stubcc.rejoin(Changes(1)); +} + bool mjit::Compiler::jsop_getelem() { @@ -1387,107 +1516,30 @@ mjit::Compiler::jsop_getelem() 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); - - MaybeJump objTypeGuard; - if (!obj->isTypeKnown()) { - // Test the type of the object without spilling the payload. - MaybeRegisterID pinnedObjData = frame.maybePinData(obj); - Jump guard = frame.testObject(Assembler::NotEqual, obj); - frame.maybeUnpinReg(pinnedObjData); - - // Create a sync path, which we'll rejoin manually later. This is safe - // as long as the IC does not build a stub; it won't, because |obj| - // won't be an object. If we extend this IC to support strings, all - // that needs to change is a little code movement. - stubcc.linkExit(guard, Uses(2)); - objTypeGuard = stubcc.masm.jump(); + if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_STRING && id->isConstant()) { + /* Never happens, or I'd optimize it. */ + jsop_getelem_slow(); + return true; } - // Get a mutable register for the object. This will be the data reg. - ic.objReg = frame.copyDataIntoReg(obj); - - // 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); - - // Fill in the id value. - frame.maybeUnpinReg(pinnedIdData); - if (id->isConstant()) { - ic.id = ValueRemat::FromConstant(id->getValue()); + RegisterID tmpReg; + if (obj->isTypeKnown()) { + tmpReg = frame.allocReg(); } else { - RegisterID dataReg = frame.tempRegForData(id); - if (id->isTypeKnown()) - ic.id = ValueRemat::FromKnownType(id->getKnownType(), dataReg); - else - ic.id = ValueRemat::FromRegisters(ic.typeReg, dataReg); + tmpReg = frame.copyTypeIntoReg(obj); + Jump objGuard = masm.testObject(Assembler::NotEqual, tmpReg); + stubcc.linkExit(objGuard, Uses(2)); } - ic.fastPathStart = masm.label(); + if (id->isTypeKnown()) + return jsop_getelem_known_type(obj, id, tmpReg); - // Note: slow path here is safe, since the frame will not be modified. - ic.slowPathStart = stubcc.masm.label(); - frame.sync(stubcc.masm, Uses(2)); - - if (id->mightBeType(JSVAL_TYPE_INT32)) { - // Always test the type first (see comment in PolyIC.h). - if (!id->isTypeKnown()) { - ic.typeGuard = masm.testInt32(Assembler::NotEqual, ic.typeReg); - stubcc.linkExitDirect(ic.typeGuard.get(), ic.slowPathStart); - } - - // Guard on the clasp. - ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &js_ArrayClass); - stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); - - 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); - - 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); - ic.slowPathCall = stubcc.call(ic::GetElement); + return jsop_getelem_with_pic(obj, id, tmpReg); #else - ic.slowPathCall = stubcc.call(stubs::GetElem); -#endif - - ic.fastPathRejoin = masm.label(); - - frame.popn(2); - frame.pushRegs(ic.typeReg, ic.objReg); - - stubcc.rejoin(Changes(2)); - -#ifdef JS_POLYIC - if (!getElemICs.append(ic)) - return false; -#endif - + jsop_getelem_nopic(obj, id, tmpReg); return true; +#endif } static inline bool diff --git a/js/src/methodjit/FrameEntry.h b/js/src/methodjit/FrameEntry.h index 7cea4a464e3..56a4dc72ac1 100644 --- a/js/src/methodjit/FrameEntry.h +++ b/js/src/methodjit/FrameEntry.h @@ -97,12 +97,6 @@ class FrameEntry return isTypeKnown() && getKnownType() != type_; } - // Return true if the type of this value is definitely type_, or is unknown - // and thus potentially type_ at runtime. - bool mightBeType(JSValueType type_) const { - return !isNotType(type_); - } - #if defined JS_NUNBOX32 uint32 getPayload() const { //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced()); diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index ae9ad37af7f..64e6ffe984a 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -811,10 +811,10 @@ mjit::JITScript::release() code.m_executablePool->release(); #if defined JS_POLYIC - for (uint32 i = 0; i < nPICs; i++) - pics[i].finish(); - for (uint32 i = 0; i < nGetElems; i++) - getElems[i].finish(); + for (uint32 i = 0; i < nPICs; i++) { + pics[i].releasePools(); + Destroy(pics[i].execPools); + } #endif #if defined JS_MONOIC diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 1bcca198b9b..e5332942a09 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -143,7 +143,6 @@ namespace mjit { namespace ic { # if defined JS_POLYIC struct PICInfo; - struct GetElementIC; # endif # if defined JS_MONOIC struct MICInfo; @@ -183,7 +182,6 @@ typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceI #endif #ifdef JS_POLYIC typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *); -typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *); #endif namespace mjit { @@ -214,8 +212,6 @@ struct JITScript { #ifdef JS_POLYIC ic::PICInfo *pics; /* PICs in this script */ uint32 nPICs; /* number of PolyICs */ - ic::GetElementIC *getElems; - uint32 nGetElems; #endif void *invokeEntry; /* invoke address */ void *fastEntry; /* cached entry, fastest */ diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index d2dc6191641..6715b388688 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -90,15 +90,22 @@ class NunboxAssembler : public JSC::MacroAssembler return BaseIndex(address.base, address.index, address.scale, address.offset + TAG_OFFSET); } - void loadInlineSlot(RegisterID objReg, uint32 slot, - RegisterID typeReg, RegisterID dataReg) { - Address address(objReg, JSObject::getFixedSlotOffset(slot)); - if (objReg == typeReg) { - loadPayload(address, dataReg); - loadTypeTag(address, typeReg); + void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, + RegisterID type, RegisterID data) { + JS_ASSERT(type != data); + Address address(obj, JSObject::getFixedSlotOffset(slot)); + RegisterID activeAddressReg = obj; + if (!inlineAccess) { + loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); + address = Address(clobber, slot * sizeof(Value)); + activeAddressReg = clobber; + } + if (activeAddressReg == type) { + loadPayload(address, data); + loadTypeTag(address, type); } else { - loadTypeTag(address, typeReg); - loadPayload(address, dataReg); + loadTypeTag(address, type); + loadPayload(address, data); } } diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 719e5ee33fa..d0084df2927 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -45,7 +45,6 @@ #include "assembler/assembler/RepatchBuffer.h" #include "jsscope.h" #include "jsnum.h" -#include "jsatominlines.h" #include "jsobjinlines.h" #include "jsscopeinlines.h" #include "jspropertycache.h" @@ -58,9 +57,6 @@ using namespace js; using namespace js::mjit; using namespace js::mjit::ic; -typedef JSC::RepatchBuffer RepatchBuffer; -typedef JSC::FunctionPtr FunctionPtr; - /* Rough over-estimate of how much memory we need to unprotect. */ static const uint32 INLINE_PATH_LENGTH = 64; @@ -69,18 +65,18 @@ static const uint32 INLINE_PATH_LENGTH = 64; // are instantiated and rooted. class PICLinker : public LinkerHelper { - ic::BaseIC ⁣ + ic::PICInfo &pic; public: - PICLinker(JSContext *cx, ic::BaseIC &ic) - : LinkerHelper(cx), ic(ic) + PICLinker(JSContext *cx, ic::PICInfo &pic) + : LinkerHelper(cx), pic(pic) { } bool init(Assembler &masm) { JSC::ExecutablePool *pool = LinkerHelper::init(masm); if (!pool) return false; - if (!ic.execPools.append(pool)) { + if (!pic.execPools.append(pool)) { pool->release(); js_ReportOutOfMemory(cx); return false; @@ -96,38 +92,42 @@ class PICStubCompiler : public BaseCompiler VMFrame &f; JSScript *script; ic::PICInfo &pic; - void *stub; public: - 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) + PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic) + : BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic) { } - bool isCallOp() const { + bool isCallOp() const + { if (pic.kind == ic::PICInfo::CALL) return true; - return !!(js_CodeSpec[pic.op].format & JOF_CALLOP); + JSOp op = JSOp(*f.regs.pc); + return !!(js_CodeSpec[op].format & JOF_CALLOP); } - LookupStatus error() { - disable("error"); - return Lookup_Error; + bool disable(const char *reason, VoidStub stub) + { + return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); } - LookupStatus error(JSContext *cx) { - return error(); + bool disable(const char *reason, VoidStubPIC stub) { + return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); } - LookupStatus disable(const char *reason) { - return disable(f.cx, reason); - } - - LookupStatus disable(JSContext *cx, const char *reason) { - return pic.disable(cx, reason, stub); + bool disable(const char *reason, void *stub) + { + spew("disabled", reason); + JITCode jitCode(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + CodeBlock codeBlock(jitCode); + RepatchBuffer repatcher(&codeBlock); + repatcher.relink(pic.slowPathCall, FunctionPtr(stub)); + return true; } protected: - void spew(const char *event, const char *op) { + void spew(const char *event, const char *op) + { #ifdef JS_METHODJIT_SPEW JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n", type, event, op, script->filename, @@ -138,13 +138,13 @@ class PICStubCompiler : public BaseCompiler class PICRepatchBuffer : public JSC::RepatchBuffer { - ic::BaseIC ⁣ + ic::PICInfo &pic; JSC::CodeLocationLabel label; public: - PICRepatchBuffer(ic::BaseIC &ic, JSC::CodeLocationLabel path) + PICRepatchBuffer(ic::PICInfo &ic, JSC::CodeLocationLabel path) : JSC::RepatchBuffer(path.executableAddress(), INLINE_PATH_LENGTH), - ic(ic), label(path) + pic(ic), label(path) { } void relink(int32 offset, JSC::CodeLocationLabel target) { @@ -156,6 +156,7 @@ class SetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; + VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 dslotsLoadOffset(ic::PICInfo &pic) { @@ -221,10 +222,15 @@ class SetPropCompiler : public PICStubCompiler public: SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("setprop", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), - obj(obj), atom(atom), lastStubSecondShapeGuard(pic.secondShapeGuard) + : PICStubCompiler("setprop", f, script, pic), obj(obj), atom(atom), stub(stub), + lastStubSecondShapeGuard(pic.secondShapeGuard) { } + bool disable(const char *reason) + { + return PICStubCompiler::disable(reason, stub); + } + static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -241,7 +247,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - LookupStatus patchInline(const Shape *shape, bool inlineSlot) + bool patchInline(const Shape *shape, bool inlineSlot) { JS_ASSERT(!pic.inlinePathPatched); JaegerSpew(JSpew_PICs, "patch setprop inline at %p\n", pic.fastPathStart.executableAddress()); @@ -280,7 +286,7 @@ class SetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return Lookup_Cacheable; + return true; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -302,7 +308,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - LookupStatus generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) + bool generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) { /* Exits to the slow path. */ Vector slowExits(cx); @@ -340,9 +346,9 @@ class SetPropCompiler : public PICStubCompiler RegisterID lastReg = pic.objReg; while (proto) { masm.loadPtr(Address(lastReg, offsetof(JSObject, proto)), pic.shapeReg); - Jump protoGuard = masm.guardShape(pic.shapeReg, proto); + Jump protoGuard = masm.guardShape(pic.shapeReg, proto->shape()); if (!otherGuards.append(protoGuard)) - return error(); + return false; proto = proto->getProto(); lastReg = pic.shapeReg; @@ -361,7 +367,7 @@ class SetPropCompiler : public PICStubCompiler Jump mismatchedFunction = masm.branchPtr(Assembler::NotEqual, pic.u.vr.dataReg(), ImmPtr(funobj)); if (!slowExits.append(mismatchedFunction)) - return error(); + return false; } } @@ -376,7 +382,7 @@ class SetPropCompiler : public PICStubCompiler Jump overCapacity = masm.branch32(Assembler::LessThanOrEqual, pic.shapeReg, Imm32(shape->slot)); if (!slowExits.append(overCapacity)) - return error(); + return false; masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.shapeReg); Address address(pic.shapeReg, shape->slot * sizeof(Value)); @@ -414,7 +420,7 @@ class SetPropCompiler : public PICStubCompiler masm.loadPayload(address, pic.shapeReg); Jump rebrand = masm.testFunction(Assembler::Equal, pic.shapeReg); if (!slowExits.append(rebrand)) - return error(); + return false; skip.linkTo(masm.label(), &masm); pic.shapeRegHasBaseShape = false; } @@ -470,7 +476,7 @@ class SetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(shapeGuard, pic.slowPathStart); if (slowExit.isSet()) @@ -505,12 +511,16 @@ class SetPropCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return Lookup_Cacheable; + return true; } - LookupStatus update() + bool update() { - JS_ASSERT(pic.hit); + if (!pic.hit) { + spew("first hit", "nop"); + pic.hit = true; + return true; + } if (obj->isDenseArray()) return disable("dense array"); @@ -531,7 +541,7 @@ class SetPropCompiler : public PICStubCompiler JSObject *holder; JSProperty *prop = NULL; if (!obj->lookupProperty(cx, id, &holder, &prop)) - return error(); + return false; /* If the property exists but is on a prototype, treat as addprop. */ if (prop && holder != obj) { @@ -571,7 +581,7 @@ class SetPropCompiler : public PICStubCompiler uint32 initialShape = obj->shape(); if (!obj->ensureClassReservedSlots(cx)) - return error(); + return false; uint32 slots = obj->numSlots(); uintN flags = 0; @@ -594,7 +604,7 @@ class SetPropCompiler : public PICStubCompiler SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) - return error(); + return false; /* * Test after calling putProperty since it can switch obj into @@ -657,84 +667,11 @@ class SetPropCompiler : public PICStubCompiler } }; -static bool -IsCacheableProtoChain(JSObject *obj, JSObject *holder) -{ - while (obj != holder) { - JSObject *proto = obj->getProto(); - if (!proto->isNative()) - return false; - obj = proto; - } - return true; -} - -template -struct GetPropertyHelper { - JSContext *cx; - JSObject *obj; - JSAtom *atom; - IC ⁣ - - JSObject *aobj; - JSObject *holder; - const Shape *shape; - - GetPropertyHelper(JSContext *cx, JSObject *obj, JSAtom *atom, IC &ic) - : cx(cx), obj(obj), atom(atom), ic(ic), holder(NULL), shape(NULL) - { } - - public: - LookupStatus bind() { - JSProperty *prop; - if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) - return ic.error(cx); - if (!prop) - return ic.disable(cx, "lookup failed"); - shape = (const Shape *)prop; - return Lookup_Cacheable; - } - - LookupStatus lookup() { - JSObject *aobj = js_GetProtoIfDenseArray(obj); - if (!aobj->isNative()) - return ic.disable(cx, "non-native"); - JSProperty *prop; - if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return ic.error(cx); - if (!prop) - return ic.disable(cx, "lookup failed"); - if (!IsCacheableProtoChain(obj, holder)) - return ic.disable(cx, "non-native holder"); - shape = (const Shape *)prop; - return Lookup_Cacheable; - } - - LookupStatus testForGet() { - if (!shape->hasDefaultGetter()) { - if (!shape->isMethod()) - return ic.disable(cx, "getter"); - if (!ic.isCallOp()) - return ic.disable(cx, "method valued shape"); - } else if (!shape->hasSlot()) { - return ic.disable(cx, "no slot"); - } - - return Lookup_Cacheable; - } - - LookupStatus lookupAndTest() { - LookupStatus status = lookup(); - if (status != Lookup_Cacheable) - return status; - return testForGet(); - } -}; - class GetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; + VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 inlineShapeOffset(ic::PICInfo &pic) { @@ -776,10 +713,10 @@ class GetPropCompiler : public PICStubCompiler public: GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic, - JS_FUNC_TO_DATA_PTR(void *, stub)), + : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic), obj(obj), atom(atom), + stub(stub), lastStubSecondShapeGuard(pic.secondShapeGuard) { } @@ -817,7 +754,7 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - LookupStatus generateArgsLengthStub() + bool generateArgsLengthStub() { Assembler masm; @@ -835,7 +772,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(notArgs, pic.slowPathStart); buffer.link(overridden, pic.slowPathStart); @@ -850,10 +787,10 @@ class GetPropCompiler : public PICStubCompiler disable("args length done"); - return Lookup_Cacheable; + return true; } - LookupStatus generateArrayLengthStub() + bool generateArrayLengthStub() { Assembler masm; @@ -869,7 +806,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(notArray, pic.slowPathStart); buffer.link(oob, pic.slowPathStart); @@ -884,10 +821,10 @@ class GetPropCompiler : public PICStubCompiler disable("array length done"); - return Lookup_Cacheable; + return true; } - LookupStatus generateStringCallStub() + bool generateStringCallStub() { JS_ASSERT(pic.hasTypeCheck()); JS_ASSERT(pic.kind == ic::PICInfo::CALL); @@ -895,12 +832,24 @@ class GetPropCompiler : public PICStubCompiler if (!f.fp()->script()->compileAndGo) return disable("String.prototype without compile-and-go"); - GetPropertyHelper getprop(cx, obj, atom, *this); - LookupStatus status = getprop.lookupAndTest(); - if (status != Lookup_Cacheable) - return status; - if (getprop.obj != getprop.holder) + JSObject *holder; + JSProperty *prop; + if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return false; + if (!prop) + return disable("property not found"); + + const Shape *shape = (const Shape *)prop; + if (holder != obj) return disable("proto walk on String.prototype"); + if (!shape->hasDefaultGetterOrIsMethod()) + return disable("getter"); + if (shape->isMethod() && !isCallOp()) + return disable("method valued shape"); + if (!shape->hasSlot()) + return disable("invalid slot"); + + JS_ASSERT(holder->isNative()); Assembler masm; @@ -909,7 +858,8 @@ class GetPropCompiler : public PICStubCompiler ImmType(JSVAL_TYPE_STRING)); /* - * Sink pic.objReg, since we're about to lose it. + * Sink pic.objReg, since we're about to lose it. This is optimistic, + * we could reload it from objRemat if we wanted. * * Note: This is really hacky, and relies on f.regs.sp being set * correctly in ic::CallProp. Should we just move the store higher @@ -930,13 +880,19 @@ class GetPropCompiler : public PICStubCompiler masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeMismatch = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(obj->shape())); - masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); + if (!shape->isMethod()) { + masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !obj->hasSlotsArray(), + pic.shapeReg, pic.objReg); + } else { + masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, + pic.objReg); + } Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(shapeMismatch, pic.slowPathStart); @@ -955,10 +911,10 @@ class GetPropCompiler : public PICStubCompiler /* Disable the PIC so we don't keep generating stubs on the above shape mismatch. */ disable("generated string call stub"); - return Lookup_Cacheable; + return true; } - LookupStatus generateStringLengthStub() + bool generateStringLengthStub() { JS_ASSERT(pic.hasTypeCheck()); @@ -973,7 +929,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(done, pic.fastPathRejoin); @@ -989,10 +945,10 @@ class GetPropCompiler : public PICStubCompiler disable("generated string length stub"); - return Lookup_Cacheable; + return true; } - LookupStatus patchInline(JSObject *holder, const Shape *shape) + bool patchInline(JSObject *holder, const Shape *shape) { spew("patch", "inline"); PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -1029,15 +985,20 @@ class GetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return Lookup_Cacheable; + return true; } - LookupStatus generateStub(JSObject *holder, const Shape *shape) + bool generateStub(JSObject *holder, const Shape *shape) { Vector shapeMismatches(cx); Assembler masm; + if (pic.objNeedsRemat()) { + masm.rematPayload(pic.objRemat(), pic.objReg); + pic.u.get.objNeedsRemat = false; + } + Label start; Jump shapeGuard; Jump argsLenGuard; @@ -1067,33 +1028,63 @@ class GetPropCompiler : public PICStubCompiler Label stubShapeJumpLabel = masm.label(); #endif + if (!shapeMismatches.append(shapeGuard)) - return error(); + return false; - RegisterID holderReg = pic.objReg; if (obj != holder) { - // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. - holderReg = pic.shapeReg; - masm.move(ImmPtr(holder), holderReg); - pic.shapeRegHasBaseShape = false; + // Emit code that walks the prototype chain. + JSObject *tempObj = obj; + Address proto(pic.objReg, offsetof(JSObject, proto)); + do { + tempObj = tempObj->getProto(); + // FIXME: we should find out why this condition occurs. It is probably + // related to PICs on globals. + if (!tempObj) + return disable("null object in prototype chain"); + JS_ASSERT(tempObj); - // Guard on the holder's shape. - Jump j = masm.guardShape(holderReg, holder); + /* + * If there is a non-native along the prototype chain the shape is technically + * invalid. + */ + if (!tempObj->isNative()) + return disable("non-JS-native in prototype chain"); + + masm.loadPtr(proto, pic.objReg); + pic.shapeRegHasBaseShape = false; + pic.u.get.objNeedsRemat = true; + + Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); + if (!shapeMismatches.append(j)) + return false; + } while (tempObj != holder); + + // Load the shape out of the holder and check it. + masm.loadShape(pic.objReg, pic.shapeReg); + Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, + Imm32(holder->shape())); if (!shapeMismatches.append(j)) - return error(); - + return false; pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); } else { + JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ pic.secondShapeGuard = 0; } /* Load the value out of the object. */ - masm.loadObjProp(holder, holderReg, shape, pic.shapeReg, pic.objReg); + if (!shape->isMethod()) { + masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), + pic.shapeReg, pic.objReg); + } else { + masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, + pic.objReg); + } Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; // The guard exit jumps to the original slow case. for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) @@ -1120,7 +1111,7 @@ class GetPropCompiler : public PICStubCompiler if (obj->isDenseArray()) disable("dense array"); - return Lookup_Cacheable; + return true; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -1142,19 +1133,373 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - LookupStatus update() + bool update() { - JS_ASSERT(pic.hit); + if (!pic.hit) { + spew("first hit", "nop"); + pic.hit = true; + return true; + } - GetPropertyHelper getprop(cx, obj, atom, *this); - LookupStatus status = getprop.lookupAndTest(); - if (status != Lookup_Cacheable) - return status; + JSObject *aobj = js_GetProtoIfDenseArray(obj); + if (!aobj->isNative()) + return disable("non-native"); - if (obj == getprop.holder && !pic.inlinePathPatched) - return patchInline(getprop.holder, getprop.shape); + JSObject *holder; + JSProperty *prop; + if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return false; + + if (!prop) + return disable("lookup failed"); + + if (!holder->isNative()) + return disable("non-native holder"); + + const Shape *shape = (const Shape *)prop; + if (!shape->hasDefaultGetterOrIsMethod()) + return disable("getter"); + if (shape->isMethod() && !isCallOp()) + return disable("method valued shape"); + if (!shape->hasSlot()) + return disable("invalid slot"); + + if (obj == holder && !pic.inlinePathPatched) + return patchInline(holder, shape); - return generateStub(getprop.holder, getprop.shape); + return generateStub(holder, shape); + } + + bool disable(const char *reason) + { + return PICStubCompiler::disable(reason, stub); + } +}; + +class GetElemCompiler : public PICStubCompiler +{ + JSObject *obj; + JSString *id; + void *stub; + int lastStubSecondShapeGuard; + + static int32 dslotsLoad(ic::PICInfo &pic) { +#if defined JS_NUNBOX32 + return GETELEM_DSLOTS_LOAD; +#elif defined JS_PUNBOX64 + return pic.labels.getelem.dslotsLoadOffset; +#endif + } + + inline int32 dslotsLoad() { + return dslotsLoad(pic); + } + + static int32 inlineShapeOffset(ic::PICInfo &pic) { +#if defined JS_NUNBOX32 + return GETELEM_INLINE_SHAPE_OFFSET; +#elif defined JS_PUNBOX64 + return pic.labels.getelem.inlineShapeOffset; +#endif + } + + inline int32 inlineShapeOffset() { + return inlineShapeOffset(pic); + } + + static int32 inlineShapeJump(ic::PICInfo &pic) { +#if defined JS_NUNBOX32 + return GETELEM_INLINE_SHAPE_JUMP; +#elif defined JS_PUNBOX64 + return inlineShapeOffset(pic) + GETELEM_INLINE_SHAPE_JUMP; +#endif + } + + inline int32 inlineShapeJump() { + return inlineShapeJump(pic); + } + + static int32 inlineAtomOffset(ic::PICInfo &pic) { +#if defined JS_NUNBOX32 + return GETELEM_INLINE_ATOM_OFFSET; +#elif defined JS_PUNBOX64 + return pic.labels.getelem.inlineAtomOffset; +#endif + } + + inline int32 inlineAtomOffset() { + return inlineAtomOffset(pic); + } + + static int32 inlineAtomJump(ic::PICInfo &pic) { +#if defined JS_NUNBOX32 + return GETELEM_INLINE_ATOM_JUMP; +#elif defined JS_PUNBOX64 + return inlineAtomOffset(pic) + GETELEM_INLINE_ATOM_JUMP; +#endif + } + + inline int32 inlineAtomJump() { + return inlineAtomJump(pic); + } + + public: + GetElemCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSString *id, + VoidStub stub) + : PICStubCompiler("getelem", f, script, pic), obj(obj), id(id), + stub(JS_FUNC_TO_DATA_PTR(void *, stub)), + lastStubSecondShapeGuard(pic.secondShapeGuard) + {} + + static void reset(ic::PICInfo &pic) + { + JS_ASSERT(pic.kind == ic::PICInfo::GETELEM); + + RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); + repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic))); + + /* Only the shape needs to be patched to fail -- atom jump will never be taken. */ + repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( + pic.shapeGuard + inlineShapeOffset(pic)), + int32(JSObjectMap::INVALID_SHAPE)); + repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineShapeJump(pic)), + pic.slowPathStart); + repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineAtomJump(pic)), + pic.slowPathStart); + + RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetElem)); + repatcher.relink(pic.slowPathCall, target); + } + + bool patchInline(JSObject *holder, const Shape *shape) + { + spew("patch", "inline"); + PICRepatchBuffer repatcher(pic, pic.fastPathStart); + + int32 offset; + if (!holder->hasSlotsArray()) { + JSC::CodeLocationInstruction istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad()); + repatcher.repatchLoadPtrToLEA(istr); + + // + // We've patched | mov dslots, [obj + DSLOTS_OFFSET] + // To: | lea fslots, [obj + DSLOTS_OFFSET] + // + // Because the offset is wrong, it's necessary to correct it + // below. + // + int32 diff = int32(JSObject::getFixedSlotOffset(0)) - int32(offsetof(JSObject, slots)); + JS_ASSERT(diff != 0); + offset = (int32(shape->slot) * sizeof(Value)) + diff; + } else { + offset = shape->slot * sizeof(Value); + } + + uint32 shapeOffset = pic.shapeGuard + inlineShapeOffset(); + repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffset), obj->shape()); + uint32 idOffset = pic.shapeGuard + inlineAtomOffset(); + repatcher.repatch(pic.fastPathStart.dataLabelPtrAtOffset(idOffset), id); +#if defined JS_NUNBOX32 + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_TYPE_LOAD), offset + 4); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_DATA_LOAD), offset); +#elif defined JS_PUNBOX64 + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getelem.inlineValueOffset), offset); +#endif + pic.inlinePathPatched = true; + + return true; + } + + void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) + { + // Patch either the inline fast path or a generated stub. The stub + // omits the prefix of the inline fast path that loads the shape, so + // the offsets are different. + int shapeGuardJumpOffset; + int atomGuardJumpOffset; + if (pic.stubsGenerated) { +#if defined JS_NUNBOX32 + shapeGuardJumpOffset = GETELEM_STUB_SHAPE_JUMP; +#elif defined JS_PUNBOX64 + shapeGuardJumpOffset = pic.labels.getelem.stubShapeJump; +#endif + atomGuardJumpOffset = GETELEM_STUB_ATOM_JUMP; + } else { + shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump(); + atomGuardJumpOffset = pic.shapeGuard + inlineAtomJump(); + } + repatcher.relink(shapeGuardJumpOffset, cs); + repatcher.relink(atomGuardJumpOffset, cs); + if (lastStubSecondShapeGuard) + repatcher.relink(lastStubSecondShapeGuard, cs); + } + + bool generateStub(JSObject *holder, const Shape *shape) + { + JS_ASSERT(pic.u.get.idReg != pic.shapeReg); + Vector shapeMismatches(cx); + + Assembler masm; + + if (pic.objNeedsRemat()) { + masm.rematPayload(pic.objRemat(), pic.objReg); + pic.u.get.objNeedsRemat = false; + } + + if (pic.shapeNeedsRemat()) { + masm.loadShape(pic.objReg, pic.shapeReg); + pic.shapeRegHasBaseShape = true; + } + + Label start = masm.label(); + Jump atomGuard = masm.branchPtr(Assembler::NotEqual, pic.u.get.idReg, ImmPtr(id)); + DBGLABEL(dbgStubAtomJump); + Jump shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, + Imm32(obj->shape())); + +#if (defined JS_NUNBOX32 && defined DEBUG) || defined JS_PUNBOX64 + Label stubShapeJump = masm.label(); +#endif + + JS_ASSERT(masm.differenceBetween(start, dbgStubAtomJump) == GETELEM_STUB_ATOM_JUMP); +#if defined JS_NUNBOX32 + JS_ASSERT(masm.differenceBetween(start, stubShapeJump) == GETELEM_STUB_SHAPE_JUMP); +#endif + + if (!(shapeMismatches.append(shapeGuard) && shapeMismatches.append(atomGuard))) + return false; + + if (obj != holder) { + // Emit code that walks the prototype chain. + JSObject *tempObj = obj; + Address proto(pic.objReg, offsetof(JSObject, proto)); + do { + tempObj = tempObj->getProto(); + // FIXME: we should find out why this condition occurs. It is probably + // related to PICs on globals. + if (!tempObj) + return disable("null object in prototype chain"); + JS_ASSERT(tempObj); + + /* + * If there is a non-native along the prototype chain the shape is technically + * invalid. + */ + if (!tempObj->isNative()) + return disable("non-JS-native in prototype chain"); + + masm.loadPtr(proto, pic.objReg); + pic.shapeRegHasBaseShape = false; + pic.u.get.objNeedsRemat = true; + + Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); + if (!shapeMismatches.append(j)) + return false; + } while (tempObj != holder); + + // Load the shape out of the holder and check it. + masm.loadShape(pic.objReg, pic.shapeReg); + Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, + Imm32(holder->shape())); + if (!shapeMismatches.append(j)) + return false; + pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); + } else { + JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ + pic.secondShapeGuard = 0; + } + + /* Load the value out of the object. */ + if (!shape->isMethod()) { + masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), + pic.shapeReg, pic.objReg); + } else { + masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, + pic.objReg); + } + Jump done = masm.jump(); + + PICLinker buffer(cx, pic); + if (!buffer.init(masm)) + return false; + + // The guard exit jumps to the original slow case. + for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) + buffer.link(*pj, pic.slowPathStart); + + // The final exit jumps to the store-back in the inline stub. + buffer.link(done, pic.fastPathRejoin); + CodeLocationLabel cs = buffer.finalizeCodeAddendum(); +#if DEBUG + char *chars = js_DeflateString(cx, id->chars(), id->length()); + JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n", + type, cs.executableAddress(), id, chars, holder->shape(), script->filename, + js_FramePCToLineNumber(cx, f.fp())); + cx->free(chars); +#endif + + PICRepatchBuffer repatcher(pic, pic.lastPathStart()); + patchPreviousToHere(repatcher, cs); + + pic.stubsGenerated++; + pic.lastStubStart = buffer.locationOf(start); + +#if defined JS_PUNBOX64 + pic.labels.getelem.stubShapeJump = masm.differenceBetween(start, stubShapeJump); + JS_ASSERT(pic.labels.getelem.stubShapeJump == masm.differenceBetween(start, stubShapeJump)); +#endif + + if (pic.stubsGenerated == MAX_PIC_STUBS) + disable("max stubs reached"); + if (obj->isDenseArray()) + disable("dense array"); + + return true; + } + + bool update() + { + if (!pic.hit) { + spew("first hit", "nop"); + pic.hit = true; + return true; + } + + JSAtom *atom = js_AtomizeString(cx, id, 0); + if (!atom) + return false; + JSObject *holder; + JSProperty *prop; + if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return false; + + if (!prop) + return disable("lookup failed"); + + if (!obj->isNative()) + return disable("non-native obj"); + if (!holder->isNative()) + return disable("non-native holder"); + + const Shape *shape = (const Shape *)prop; + if (!shape->hasDefaultGetterOrIsMethod()) + return disable("getter"); + if (shape->isMethod() && !isCallOp()) + return disable("method valued shape"); + if (!shape->hasSlot()) + return disable("invalid slot"); + + if (obj == holder && !pic.inlinePathPatched) + return patchInline(holder, shape); + + return generateStub(holder, shape); + } + + bool disable(const char *reason) + { + return PICStubCompiler::disable(reason, stub); } }; @@ -1162,17 +1507,25 @@ class ScopeNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; + void *stub; - GetPropertyHelper getprop; + JSObject *obj; + JSObject *holder; + JSProperty *prop; + const Shape *shape; public: ScopeNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("name", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), - scopeChain(scopeChain), atom(atom), - getprop(f.cx, NULL, atom, *this) + : PICStubCompiler("name", f, script, pic), scopeChain(scopeChain), atom(atom), + stub(JS_FUNC_TO_DATA_PTR(void *, stub)), obj(NULL), holder(NULL), prop(NULL) { } + bool disable(const char *reason) + { + return PICStubCompiler::disable(reason, stub); + } + static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -1187,16 +1540,16 @@ class ScopeNameCompiler : public PICStubCompiler typedef Vector JumpList; - LookupStatus walkScopeChain(Assembler &masm, JumpList &fails) + bool walkScopeChain(Assembler &masm, JumpList &fails, bool &found) { /* Walk the scope chain. */ JSObject *tobj = scopeChain; /* For GETXPROP, we'll never enter this loop. */ - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == getprop.holder); - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, getprop.obj == tobj); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == holder); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, obj == tobj); - while (tobj && tobj != getprop.holder) { + while (tobj && tobj != holder) { if (!js_IsCacheableNonGlobalScope(tobj)) return disable("non-cacheable scope chain object"); JS_ASSERT(tobj->isNative()); @@ -1205,14 +1558,14 @@ class ScopeNameCompiler : public PICStubCompiler /* scopeChain will never be NULL, but parents can be NULL. */ Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(j)) - return error(); + return false; } /* Guard on intervening shapes. */ masm.loadShape(pic.objReg, pic.shapeReg); Jump j = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); if (!fails.append(j)) - return error(); + return false; /* Load the next link in the scope chain. */ Address parent(pic.objReg, offsetof(JSObject, parent)); @@ -1221,13 +1574,12 @@ class ScopeNameCompiler : public PICStubCompiler tobj = tobj->getParent(); } - if (tobj != getprop.holder) - return disable("scope chain walk terminated early"); + found = tobj == holder; - return Lookup_Cacheable; + return true; } - LookupStatus generateGlobalStub(JSObject *obj) + bool generateGlobalStub() { Assembler masm; JumpList fails(cx); @@ -1236,21 +1588,29 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == getprop.holder); - JS_ASSERT(getprop.holder == scopeChain->getGlobal()); + JS_ASSERT(obj == holder); + JS_ASSERT(holder == scopeChain->getGlobal()); - LookupStatus status = walkScopeChain(masm, fails); - if (status != Lookup_Cacheable) - return status; + bool found = false; + if (!walkScopeChain(masm, fails, found)) + return false; + if (!found) + return disable("scope chain walk terminated early"); /* If a scope chain walk was required, the final object needs a NULL test. */ MaybeJump finalNull; if (pic.kind == ic::PICInfo::NAME) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); + + if (!shape->isMethod()) { + masm.loadSlot(pic.objReg, pic.objReg, shape->slot, false, pic.shapeReg, pic.objReg); + } else { + masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, + pic.objReg); + } - masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); // All failures flow to here, so there is a common point to patch. @@ -1267,7 +1627,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1284,7 +1644,7 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return Lookup_Cacheable; + return true; } enum CallObjPropKind { @@ -1292,7 +1652,7 @@ class ScopeNameCompiler : public PICStubCompiler VAR }; - LookupStatus generateCallStub(JSObject *obj) + bool generateCallStub() { Assembler masm; Vector fails(cx); @@ -1301,11 +1661,10 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == getprop.holder); - JS_ASSERT(getprop.holder != scopeChain->getGlobal()); + JS_ASSERT(obj == holder); + JS_ASSERT(holder != scopeChain->getGlobal()); CallObjPropKind kind; - const Shape *shape = getprop.shape; if (shape->getterOp() == js_GetCallArg) { kind = ARG; } else if (shape->getterOp() == js_GetCallVar) { @@ -1314,21 +1673,23 @@ class ScopeNameCompiler : public PICStubCompiler return disable("unhandled callobj sprop getter"); } - LookupStatus status = walkScopeChain(masm, fails); - if (status != Lookup_Cacheable) - return status; + bool found = false; + if (!walkScopeChain(masm, fails, found)) + return false; + if (!found) + return disable("scope chain walk terminated early"); /* If a scope chain walk was required, the final object needs a NULL test. */ MaybeJump finalNull; if (pic.kind == ic::PICInfo::NAME) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); /* Get callobj's stack frame. */ masm.loadFunctionPrivate(pic.objReg, pic.shapeReg); - JSFunction *fun = getprop.holder->getCallObjCalleeFunction(); + JSFunction *fun = holder->getCallObjCalleeFunction(); uint16 slot = uint16(shape->shortid); Jump skipOver; @@ -1370,7 +1731,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1386,56 +1747,67 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return Lookup_Cacheable; + return true; } - LookupStatus updateForName() + bool updateForName() { - // |getprop.obj| is filled by bind() - LookupStatus status = getprop.bind(); - if (status != Lookup_Cacheable) - return status; + if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) + return false; - return update(getprop.obj); + return update(); } - LookupStatus updateForXName() + bool updateForXName() { - // |obj| and |getprop.obj| are NULL, but should be the given scopeChain. - getprop.obj = scopeChain; - LookupStatus status = getprop.lookup(); - if (status != Lookup_Cacheable) - return status; + obj = scopeChain; - return update(getprop.obj); + if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return false; + + return update(); } - LookupStatus update(JSObject *obj) + bool update() { + if (!pic.hit) { + spew("first hit", "nop"); + pic.hit = true; + return true; + } + + if (!prop) + return disable("property not found"); + if (!obj->isNative() || !holder->isNative()) + return disable("non-native scope object"); + if (obj != holder) + return disable("property is on proto of a scope object"); + + shape = (const Shape *)prop; + if (obj->getClass() == &js_CallClass) - return generateCallStub(obj); + return generateCallStub(); - LookupStatus status = getprop.testForGet(); - if (status != Lookup_Cacheable) - return status; + if (!shape->hasDefaultGetterOrIsMethod()) + return disable("getter"); + if (shape->isMethod() && !isCallOp()) + return disable("method valued shape"); + if (!shape->hasSlot()) + return disable("invalid slot"); if (!obj->getParent()) - return generateGlobalStub(obj); + return generateGlobalStub(); return disable("scope object not handled yet"); } bool retrieve(Value *vp) { - JSObject *obj = getprop.obj; - JSObject *holder = getprop.holder; - const Shape *shape = getprop.shape; - - if (shape && (!obj->isNative() || !holder->isNative())) { + if (prop && (!obj->isNative() || !holder->isNative())) { if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp)) return false; } else { - if (!shape) { + if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ disable("property not found"); if (pic.kind == ic::PICInfo::NAME) { @@ -1448,10 +1820,12 @@ class ScopeNameCompiler : public PICStubCompiler ReportAtomNotDefined(cx, atom); return false; } + const Shape *shape = (const Shape *)prop; JSObject *normalized = obj; if (obj->getClass() == &js_WithClass && !shape->hasDefaultGetter()) normalized = js_UnwrapWithObject(cx, obj); - NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); + NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, + return false); } return true; @@ -1462,6 +1836,7 @@ class BindNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; + void *stub; static int32 inlineJumpOffset(ic::PICInfo &pic) { #if defined JS_NUNBOX32 @@ -1478,10 +1853,15 @@ class BindNameCompiler : public PICStubCompiler public: BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("bind", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), - scopeChain(scopeChain), atom(atom) + : PICStubCompiler("bind", f, script, pic), scopeChain(scopeChain), atom(atom), + stub(JS_FUNC_TO_DATA_PTR(void *, stub)) { } + bool disable(const char *reason) + { + return PICStubCompiler::disable(reason, stub); + } + static void reset(ic::PICInfo &pic) { PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -1492,7 +1872,7 @@ class BindNameCompiler : public PICStubCompiler repatcher2.relink(pic.slowPathCall, target); } - LookupStatus generateStub(JSObject *obj) + bool generateStub(JSObject *obj) { Assembler masm; js::Vector fails(cx); @@ -1512,7 +1892,7 @@ class BindNameCompiler : public PICStubCompiler masm.loadPtr(parent, pic.objReg); Jump nullTest = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(nullTest)) - return error(); + return false; masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeTest = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); @@ -1535,7 +1915,7 @@ class BindNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return error(); + return false; buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1554,7 +1934,7 @@ class BindNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return Lookup_Cacheable; + return true; } JSObject *update() @@ -1571,8 +1951,7 @@ class BindNameCompiler : public PICStubCompiler return obj; } - LookupStatus status = generateStub(obj); - if (status == Lookup_Error) + if (!generateStub(obj)) return NULL; return obj; @@ -1606,9 +1985,10 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (atom == f.cx->runtime->atomState.lengthAtom) { if (f.regs.sp[-1].isString()) { GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledLengthIC); - LookupStatus status = cc.generateStringLengthStub(); - if (status == Lookup_Error) + if (!cc.generateStringLengthStub()) { + cc.disable("error"); THROW(); + } JSString *str = f.regs.sp[-1].toString(); f.regs.sp[-1].setInt32(str->length()); return; @@ -1617,14 +1997,16 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (obj->isArray() || (obj->isArguments() && !obj->isArgsLengthOverridden())) { GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledLengthIC); if (obj->isArray()) { - LookupStatus status = cc.generateArrayLengthStub(); - if (status == Lookup_Error) + if (!cc.generateArrayLengthStub()) { + cc.disable("error"); THROW(); + } f.regs.sp[-1].setNumber(obj->getArrayLength()); } else if (obj->isArguments()) { - LookupStatus status = cc.generateArgsLengthStub(); - if (status == Lookup_Error) + if (!cc.generateArgsLengthStub()) { + cc.disable("error"); THROW(); + } f.regs.sp[-1].setInt32(int32_t(obj->getArgsInitialLength())); } return; @@ -1637,7 +2019,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (!obj) THROW(); - if (pic->shouldUpdate(f.cx)) { + if (pic->shouldGenerate()) { VoidStubPIC stub = pic->usePropCache ? DisabledGetPropIC : DisabledGetPropICNoCache; @@ -1654,6 +2036,35 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) f.regs.sp[-1] = v; } +void JS_FASTCALL +ic::GetElem(VMFrame &f, ic::PICInfo *pic) +{ + JSScript *script = f.fp()->script(); + + JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]); + if (!obj) + THROW(); + + Value idval = f.regs.sp[-1]; + JS_ASSERT(idval.isString()); + JSString *id = idval.toString(); + if (pic->shouldGenerate()) { + GetElemCompiler cc(f, script, obj, *pic, id, stubs::GetElem); + if (!cc.update()) { + cc.disable("error"); + THROW(); + } + } + + JSAtom *atom = js_AtomizeString(f.cx, id, 0); + if (!atom) + THROW(); + Value v; + if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v)) + THROW(); + f.regs.sp[-2] = v; +} + template static void JS_FASTCALL DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic) @@ -1678,10 +2089,6 @@ 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); - // // Important: We update the PIC before looking up the property so that the // PIC is updated only if the property already exists. The PIC doesn't try @@ -1689,12 +2096,16 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic) // // Also note, we can't use SetName for PROPINC PICs because the property // cache can't handle a GET and SET from the same scripted PC. - if (pic->shouldUpdate(f.cx)) { + // - SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); - LookupStatus status = cc.update(); - if (status == Lookup_Error) - THROW(); + VoidStubPIC stub = pic->usePropCache + ? STRICT_VARIANT(DisabledSetPropIC) + : STRICT_VARIANT(DisabledSetPropICNoCache); + + SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); + if (!cc.update()) { + cc.disable("error"); + THROW(); } Value rval = f.regs.sp[-1]; @@ -1743,6 +2154,8 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject()); Value rval; + bool usePIC = true; + PropertyCacheEntry *entry; JSObject *obj2; JSAtom *atom; @@ -1795,18 +2208,22 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) } GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, DisabledCallPropIC); - if (lval.isObject()) { - if (pic->shouldUpdate(cx)) { - LookupStatus status = cc.update(); - if (status == Lookup_Error) + if (usePIC) { + if (lval.isObject()) { + if (!cc.update()) { + cc.disable("error"); THROW(); + } + } else if (lval.isString()) { + if (!cc.generateStringCallStub()) { + cc.disable("error"); + THROW(); + } + } else { + cc.disable("non-string primitive"); } - } else if (lval.isString()) { - LookupStatus status = cc.generateStringCallStub(); - if (status == Lookup_Error) - THROW(); } else { - cc.disable("non-string primitive"); + cc.disable("wrapped primitive"); } #if JS_HAS_NO_SUCH_METHOD @@ -1840,9 +2257,10 @@ ic::XName(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, DisabledXNameIC); - LookupStatus status = cc.updateForXName(); - if (status == Lookup_Error) + if (!cc.updateForXName()) { + cc.disable("error"); THROW(); + } Value rval; if (!cc.retrieve(&rval)) @@ -1857,9 +2275,10 @@ ic::Name(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledNameIC); - LookupStatus status = cc.updateForName(); - if (status == Lookup_Error) + if (!cc.updateForName()) { + cc.disable("error"); THROW(); + } Value rval; if (!cc.retrieve(&rval)) @@ -1898,308 +2317,6 @@ ic::BindName(VMFrame &f, ic::PICInfo *pic) 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, - js_FramePCToLineNumber(cx, cx->fp())); -#endif -} - -LookupStatus -BaseIC::disable(JSContext *cx, const char *reason, void *stub) -{ - spew(cx, "disabled", reason); - RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.relink(slowPathCall, FunctionPtr(stub)); - return Lookup_Uncacheable; -} - -bool -BaseIC::shouldUpdate(JSContext *cx) -{ - if (!hit) { - hit = true; - spew(cx, "ignored", "first hit"); - return false; - } - JS_ASSERT(stubsGenerated < MAX_PIC_STUBS); - return true; -} - -static void JS_FASTCALL -DisabledGetElem(VMFrame &f, ic::GetElementIC *ic) -{ - stubs::GetElem(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; - 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; -} - -void -GetElementIC::purge() -{ - if (inlineTypeGuardPatched || inlineClaspGuardPatched) { - RepatchBuffer repatcher(fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - - // Repatch the inline jumps. - if (inlineTypeGuardPatched) - repatcher.relink(fastPathStart.jumpAtOffset(inlineTypeGuard), slowPathStart); - if (inlineClaspGuardPatched) - repatcher.relink(fastPathStart.jumpAtOffset(inlineClaspGuard), slowPathStart); - } - - if (slowCallPatched) { - RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.relink(slowPathCall, FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::GetElement))); - } - - reset(); -} - -LookupStatus -GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp) -{ - JS_ASSERT(v.isString()); - - GetPropertyHelper getprop(cx, obj, JSID_TO_ATOM(id), *this); - LookupStatus status = getprop.lookupAndTest(); - if (status != Lookup_Cacheable) - return status; - - Assembler masm; - - // Guard on the string's type and identity. - MaybeJump atomTypeGuard; - if (hasInlineTypeGuard() && !inlineTypeGuardPatched) { - // We link all string-key dependent stubs together, and store the - // first set of guards in the IC, separately, from int-key dependent - // stubs. As long as we guarantee that the first string-key dependent - // stub guards on the key type, then all other string-key stubs can - // omit the guard. - JS_ASSERT(!idRemat.isTypeKnown()); - atomTypeGuard = masm.testString(Assembler::NotEqual, typeReg); - } else { - // If there was no inline type guard, then a string type is guaranteed. - // Otherwise, we are guaranteed the type has already been checked, via - // the comment above. - JS_ASSERT_IF(!hasInlineTypeGuard(), idRemat.knownType() == JSVAL_TYPE_STRING); - } - - // Reify the shape before guards that could flow into shape guarding stubs. - if (!obj->isDenseArray() && !typeRegHasBaseShape) { - masm.loadShape(objReg, typeReg); - typeRegHasBaseShape = true; - } - - MaybeJump atomIdGuard; - if (!idRemat.isConstant()) - atomIdGuard = masm.branchPtr(Assembler::NotEqual, idRemat.dataReg(), ImmPtr(v.toString())); - - // Guard on the base shape (or in the dense array case, the clasp). - Jump shapeGuard; - if (obj->isDenseArray()) { - shapeGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass()); - } else { - shapeGuard = masm.branch32(Assembler::NotEqual, typeReg, Imm32(obj->shape())); - } - - // Guard on the prototype, if applicable. - MaybeJump protoGuard; - JSObject *holder = getprop.holder; - RegisterID holderReg = objReg; - if (obj != holder) { - // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. - holderReg = typeReg; - masm.move(ImmPtr(holder), holderReg); - typeRegHasBaseShape = false; - - // Guard on the holder's shape. - protoGuard = masm.guardShape(holderReg, holder); - } - - // 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)) - return error(cx); - - // Patch all guards. - buffer.maybeLink(atomIdGuard, slowPathStart); - 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 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()) { - // A type guard is present in the inline path, and this is the - // first string stub, so patch it now. - JS_ASSERT(!inlineTypeGuardPatched); - JS_ASSERT(atomTypeGuard.isSet()); - - repatcher.relink(inlineTypeGuard, cs); - inlineTypeGuardPatched = true; - } - - if (shouldPatchUnconditionalClaspGuard()) { - // The clasp guard is unconditional, meaning there is no type - // check. This is the first stub, so it has to be patched. Note - // that it is wrong to patch the inline clasp guard otherwise, - // because it follows an integer-id guard. - JS_ASSERT(!hasInlineTypeGuard()); - - repatcher.relink(inlineClaspGuard, cs); - inlineClaspGuardPatched = true; - } - } - - // If there were previous stub guards, patch them now. - if (hasLastStringStub) { - PICRepatchBuffer repatcher(*this, lastStringStub); - if (atomGuard) - repatcher.relink(atomGuard, cs); - repatcher.relink(firstShapeGuard, cs); - if (secondShapeGuard) - repatcher.relink(secondShapeGuard, cs); - } - - // Update state. - hasLastStringStub = true; - lastStringStub = cs; - if (atomIdGuard.isSet()) { - atomGuard = buffer.locationOf(atomIdGuard.get()) - cs; - JS_ASSERT(atomGuard == buffer.locationOf(atomIdGuard.get()) - cs); - JS_ASSERT(atomGuard); - } else { - atomGuard = 0; - } - if (protoGuard.isSet()) { - secondShapeGuard = buffer.locationOf(protoGuard.get()) - cs; - JS_ASSERT(secondShapeGuard == buffer.locationOf(protoGuard.get()) - cs); - JS_ASSERT(secondShapeGuard); - } else { - secondShapeGuard = 0; - } - firstShapeGuard = buffer.locationOf(shapeGuard) - cs; - JS_ASSERT(firstShapeGuard == buffer.locationOf(shapeGuard) - cs); - JS_ASSERT(firstShapeGuard); - - stubsGenerated++; - - if (stubsGenerated == MAX_GETELEM_IC_STUBS) - disable(cx, "max stubs reached"); - - // Finally, fetch the value to avoid redoing the property lookup. - if (shape->isMethod()) - *vp = ObjectValue(shape->methodObject()); - else - *vp = holder->getSlot(shape->slot); - - return Lookup_Cacheable; -} - -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::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); - return; - } - - JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]); - if (!obj) - THROW(); - - Value idval = f.regs.sp[-1]; - - 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)) - THROW(); - } - - if (ic->shouldUpdate(cx)) { -#ifdef DEBUG - f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC); -#endif - LookupStatus status = ic->update(cx, obj, 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()); - return; - } - } - - if (!obj->getProperty(cx, id, &f.regs.sp[-2])) - THROW(); -} - void JITScript::purgePICs() { @@ -2221,15 +2338,15 @@ JITScript::purgePICs() case ic::PICInfo::GET: GetPropCompiler::reset(pic); break; + case ic::PICInfo::GETELEM: + GetElemCompiler::reset(pic); + break; default: JS_NOT_REACHED("Unhandled PIC kind"); break; } pic.reset(); } - - for (uint32 i = 0; i < nGetElems; i++) - getElems[i].purge(); } void diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 8bda651d572..774a771047d 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -37,7 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ -#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT +#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT && defined JS_POLYIC #define jsjaeger_poly_ic_h__ #include "jscntxt.h" @@ -46,9 +46,7 @@ #include "assembler/assembler/MacroAssembler.h" #include "assembler/assembler/CodeLocation.h" #include "methodjit/MethodJIT.h" -#include "BaseAssembler.h" #include "RematInfo.h" -#include "BaseCompiler.h" namespace js { namespace mjit { @@ -56,7 +54,6 @@ namespace ic { /* Maximum number of stubs for a given callsite. */ static const uint32 MAX_PIC_STUBS = 16; -static const uint32 MAX_GETELEM_IC_STUBS = 17; /* SetPropCompiler */ #if defined JS_CPU_X86 @@ -162,6 +159,26 @@ union PICLabels { int32 stubShapeJump : 8; } getprop; + /* GetElemCompiler */ + struct { + /* Offset from storeBack to beginning of 'mov dslots, addr' */ + int32 dslotsLoadOffset : 8; + + /* Offset from shapeGuard to end of shape comparison. */ + int32 inlineShapeOffset : 8; + + /* Offset from shapeGuard to end of atom comparison. */ + int32 inlineAtomOffset : 8; + + /* Offset from storeBack to end of value load. */ + int32 inlineValueOffset : 8; + + /* Offset from lastStubStart to end of shape jump. */ + // TODO: We can redefine the location of lastStubStart to be + // after the jump -- at which point this is always 0. + int32 stubShapeJump : 8; + } getelem; + /* BindNameCompiler */ struct { /* Offset from shapeGuard to end of shape jump. */ @@ -170,27 +187,21 @@ union PICLabels { }; #endif -enum LookupStatus { - Lookup_Error = 0, - Lookup_Uncacheable, - Lookup_Cacheable -}; - -struct BaseIC : public MacroAssemblerTypedefs { +struct BaseIC { // Address of inline fast-path. - CodeLocationLabel fastPathStart; + JSC::CodeLocationLabel fastPathStart; // Address to rejoin to the fast-path. - CodeLocationLabel fastPathRejoin; + JSC::CodeLocationLabel fastPathRejoin; // Start of the slow path. - CodeLocationLabel slowPathStart; + JSC::CodeLocationLabel slowPathStart; // Slow path stub call. - CodeLocationCall slowPathCall; + JSC::CodeLocationCall slowPathCall; // Address of the start of the last generated stub, if any. - CodeLocationLabel lastStubStart; + JSC::CodeLocationLabel lastStubStart; typedef Vector ExecPoolVector; @@ -199,25 +210,16 @@ struct BaseIC : public MacroAssemblerTypedefs { // Return the start address of the last path in this PIC, which is the // inline path if no stubs have been generated yet. - CodeLocationLabel lastPathStart() { + JSC::CodeLocationLabel lastPathStart() { return stubsGenerated > 0 ? lastStubStart : fastPathStart; } // Whether or not the callsite has been hit at least once. bool hit : 1; - bool slowCallPatched : 1; // Number of stubs generated. uint32 stubsGenerated : 5; - // Offset from start of stub to jump target of second shape guard as Nitro - // asm data location. This is 0 if there is only one shape guard in the - // last stub. - int secondShapeGuard : 11; - - // Opcode this was compiled for. - JSOp op : 8; - // Release ExecutablePools referred to by this PIC. void releasePools() { for (JSC::ExecutablePool **pExecPool = execPools.begin(); @@ -227,122 +229,17 @@ struct BaseIC : public MacroAssemblerTypedefs { } } - void init() { - new (&execPools) ExecPoolVector(SystemAllocPolicy()); - } - void finish() { - releasePools(); - this->~BaseIC(); - } - void reset() { hit = false; - slowCallPatched = false; stubsGenerated = 0; - secondShapeGuard = 0; releasePools(); execPools.clear(); } - bool shouldUpdate(JSContext *cx); - void spew(JSContext *cx, const char *event, const char *reason); - LookupStatus disable(JSContext *cx, const char *reason, void *stub); - bool isCallOp(); -}; - -struct GetElementIC : public BaseIC { - // On stub entry: - // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is false, - // - typeReg contains the type of the |id| parameter. - // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is true, - // - typeReg contains the shape of |objReg| iff typeRegHasBaseShape - // is true. - // Otherwise, typeReg is garbage. - // - // On stub exit, typeReg must contain the type of the result value. - RegisterID typeReg : 5; - - // On stub entry, objReg contains the object pointer for the |obj| parameter. - // On stub exit, objReg must contain the payload of the result value. - RegisterID objReg : 5; - - // Offset from the fast path to the inline type check. - // This is only set if hasInlineTypeCheck() is true. - int inlineTypeGuard : 6; - - // Offset from the fast path to the inline clasp guard. This is always - // set; if |id| is known to not be int32, then it's an unconditional - // jump to the slow path. - int inlineClaspGuard : 6; - - // This is usable if hasInlineTypeGuard() returns true, which implies - // that a dense array fast path exists. The inline type guard serves as - // the head of the chain of all string-based element stubs. - bool inlineTypeGuardPatched : 1; - - // This is always usable, and specifies whether the inline clasp guard - // has been patched. If hasInlineTypeGuard() is true, it guards against - // a dense array, and guarantees the inline type guard has passed. - // Otherwise, there is no inline type guard, and the clasp guard is just - // an unconditional jump. - bool inlineClaspGuardPatched : 1; - - //////////////////////////////////////////// - // State for string-based property stubs. // - //////////////////////////////////////////// - - // True if typeReg is guaranteed to have the shape of objReg. - bool typeRegHasBaseShape : 1; - - // These offsets are used for string-key dependent stubs, such as named - // property accesses. They are separated from the int-key dependent stubs, - // in order to guarantee that the id type needs only one guard per type. - int atomGuard : 8; // optional, non-zero if present - int firstShapeGuard : 8; // always set - int secondShapeGuard : 8; // optional, non-zero if present - - bool hasLastStringStub : 1; - CodeLocationLabel lastStringStub; - - // A limited ValueRemat instance. It may contains either: - // 1) A constant, or - // 2) A known type and data reg, or - // 3) A data reg. - // The sync bits are not set, and the type reg is never set and should not - // be used, as it is encapsulated more accurately in |typeReg|. Also, note - // carefully that the data reg is immutable. - ValueRemat idRemat; - - bool hasInlineTypeGuard() const { - return !idRemat.isTypeKnown(); - } - bool shouldPatchInlineTypeGuard() { - return hasInlineTypeGuard() && !inlineTypeGuardPatched; - } - bool shouldPatchUnconditionalClaspGuard() { - return !hasInlineTypeGuard() && !inlineClaspGuardPatched; - } - - void init() { - BaseIC::init(); - reset(); - } - void reset() { - BaseIC::reset(); - inlineTypeGuardPatched = false; - inlineClaspGuardPatched = false; - typeRegHasBaseShape = false; - hasLastStringStub = false; - } - void purge(); - LookupStatus update(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp); - LookupStatus attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, - Value *vp); - LookupStatus disable(JSContext *cx, const char *reason); - LookupStatus error(JSContext *cx); - bool shouldUpdate(JSContext *cx); }; struct PICInfo : public BaseIC { + typedef JSC::MacroAssembler::RegisterID RegisterID; + // Operation this is a PIC for. enum Kind #ifdef _MSC_VER @@ -355,6 +252,7 @@ struct PICInfo : public BaseIC { SETMETHOD, // JSOP_SETMETHOD NAME, // JSOP_NAME BIND, // JSOP_BINDNAME + GETELEM, // JSOP_GETELEM XNAME // JSOP_GETXPROP }; @@ -365,10 +263,20 @@ struct PICInfo : public BaseIC { // Reverse offset from slowPathStart to the type check slow path. int32 typeCheckOffset; + + // Remat info for the object reg. + int32 objRemat : MIN_STATE_REMAT_BITS; + bool objNeedsRemat : 1; + RegisterID idReg : 5; // only used in GETELEM PICs. } get; ValueRemat vr; } u; + // Offset from start of stub to jump target of second shape guard as Nitro + // asm data location. This is 0 if there is only one shape guard in the + // last stub. + int secondShapeGuard : 11; + Kind kind : 3; // True if register R holds the base object shape along exits from the @@ -391,7 +299,7 @@ struct PICInfo : public BaseIC { return kind == SET || kind == SETMETHOD; } inline bool isGet() const { - return kind == GET || kind == CALL; + return kind == GET || kind == CALL || kind == GETELEM; } inline RegisterID typeReg() { JS_ASSERT(isGet()); @@ -401,6 +309,14 @@ struct PICInfo : public BaseIC { JS_ASSERT(isGet()); return u.get.hasTypeCheck; } + inline const StateRemat objRemat() const { + JS_ASSERT(isGet()); + return StateRemat::FromInt32(u.get.objRemat); + } + inline bool objNeedsRemat() { + JS_ASSERT(isGet()); + return u.get.objNeedsRemat; + } inline bool shapeNeedsRemat() { return !shapeRegHasBaseShape; } @@ -409,6 +325,12 @@ struct PICInfo : public BaseIC { return !hasTypeCheck(); } + inline void setObjRemat(const StateRemat &sr) { + JS_ASSERT(isGet()); + u.get.objRemat = sr.toInt32(); + JS_ASSERT(u.get.objRemat == sr.toInt32()); + } + #if defined JS_CPU_X64 // Required labels for platform-specific patching. PICLabels labels; @@ -420,30 +342,30 @@ struct PICInfo : public BaseIC { // Index into the script's atom table. JSAtom *atom; - void init() { - BaseIC::init(); - reset(); + bool shouldGenerate() { + return stubsGenerated < MAX_PIC_STUBS || !inlinePathPatched; } // Reset the data members to the state of a fresh PIC before any patching // or stub generation was done. void reset() { inlinePathPatched = false; + if (kind == GET || kind == CALL || kind == GETELEM) + u.get.objNeedsRemat = false; + secondShapeGuard = 0; shapeRegHasBaseShape = true; BaseIC::reset(); } }; -#ifdef JS_POLYIC void PurgePICs(JSContext *cx, JSScript *script); void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *); +void JS_FASTCALL GetElem(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 *); -#endif } /* namespace ic */ } /* namespace mjit */ diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index 0e14f5b3b90..eabe3d9f3ff 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -93,10 +93,16 @@ class PunboxAssembler : public JSC::MacroAssembler return address; } - void loadInlineSlot(RegisterID objReg, uint32 slot, - RegisterID typeReg, RegisterID dataReg) { - Address address(objReg, JSObject::getFixedSlotOffset(slot)); - loadValueAsComponents(address, typeReg, dataReg); + void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, + RegisterID type, RegisterID data) { + JS_ASSERT(type != data); + Address address(obj, JSObject::getFixedSlotOffset(slot)); + if (!inlineAccess) { + loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); + address = Address(clobber, slot * sizeof(Value)); + } + + loadValueAsComponents(address, type, data); } template diff --git a/js/src/methodjit/StubCompiler.h b/js/src/methodjit/StubCompiler.h index 9d3099ac83c..9dcf1784a1b 100644 --- a/js/src/methodjit/StubCompiler.h +++ b/js/src/methodjit/StubCompiler.h @@ -127,7 +127,6 @@ class StubCompiler STUB_CALL_TYPE(VoidStubPC); #ifdef JS_POLYIC STUB_CALL_TYPE(VoidStubPIC); - STUB_CALL_TYPE(VoidStubGetElemIC); #endif #ifdef JS_MONOIC STUB_CALL_TYPE(VoidStubMIC); From bcf5f8be5263165fed524deaac391eca160be7ef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 27 Oct 2010 21:03:29 -0700 Subject: [PATCH 099/263] Bug 575850 - nanojit: generated better code for LIR_eqd on i386. --HG-- extra : convert_revision : 8cb17c62aaa615416ac901106292b69f691c51cf --- js/src/nanojit/Nativei386.cpp | 142 ++++++++++++++++++++-------------- js/src/nanojit/Nativei386.h | 5 +- 2 files changed, 86 insertions(+), 61 deletions(-) diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index c4677efcef4..aac903cd569 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -55,6 +55,9 @@ namespace nanojit "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "f0" }; + + const char *gpRegNames8lo[] = { "al", "cl", "dl", "bl" }; + const char *gpRegNames8hi[] = { "ah", "ch", "dh", "bh" }; #endif #define TODO(x) do{ verbose_only(outputf(#x);) NanoAssertMsgf(false, "%s", #x); } while(0) @@ -70,6 +73,9 @@ namespace nanojit 0 /* ABI_CDECL */ }; + #define RB(r) gpRegNames8lo[REGNUM(r)] + #define RBhi(r) gpRegNames8hi[REGNUM(r)] + typedef Register R; typedef int32_t I32; @@ -214,8 +220,12 @@ namespace nanojit *(--_nIns) = uint8_t(c>>8); } - inline void Assembler::LAHF() { count_alu(); ALU0(0x9F); asm_output("lahf"); } - inline void Assembler::SAHF() { count_alu(); ALU0(0x9E); asm_output("sahf"); } + inline Register Assembler::AL2AHReg(R r) { + NanoAssert(REGNUM(r) < 4); // one of: al, cl, dl, bl + Register r2 = { REGNUM(r) | 4 }; // convert to one of: ah, ch, dh, bh + return r2; + } + inline void Assembler::OR(R l, R r) { count_alu(); ALU(0x0b, REGNUM(l), r); asm_output("or %s,%s", gpn(l), gpn(r)); } inline void Assembler::AND(R l, R r) { count_alu(); ALU(0x23, REGNUM(l), r); asm_output("and %s,%s", gpn(l), gpn(r)); } inline void Assembler::XOR(R l, R r) { count_alu(); ALU(0x33, REGNUM(l), r); asm_output("xor %s,%s", gpn(l), gpn(r)); } @@ -225,6 +235,7 @@ namespace nanojit inline void Assembler::DIV(R r) { count_alu(); ALU(0xf7, 7, r); asm_output("idiv edx:eax, %s", gpn(r)); } inline void Assembler::NOT(R r) { count_alu(); ALU(0xf7, 2, r); asm_output("not %s", gpn(r)); } inline void Assembler::NEG(R r) { count_alu(); ALU(0xf7, 3, r); asm_output("neg %s", gpn(r)); } + inline void Assembler::AND8R(R r) { count_alu(); ALU(0x22, REGNUM(r), AL2AHReg(r)); asm_output("andb %s, %s", RB(r), RBhi(r)); } inline void Assembler::SHR(R r, R s) { count_alu(); @@ -295,6 +306,7 @@ namespace nanojit inline void Assembler::SETE( R r) { count_alu(); ALU2(0x0f94, r, r); asm_output("sete %s", gpn(r)); } inline void Assembler::SETNP(R r) { count_alu(); ALU2(0x0f9B, r, r); asm_output("setnp %s", gpn(r)); } + inline void Assembler::SETNPH(R r) { count_alu(); ALU2(0x0f9B, AL2AHReg(r), AL2AHReg(r)); asm_output("setnp %s", RBhi(r)); } inline void Assembler::SETL( R r) { count_alu(); ALU2(0x0f9C, r, r); asm_output("setl %s", gpn(r)); } inline void Assembler::SETLE(R r) { count_alu(); ALU2(0x0f9E, r, r); asm_output("setle %s", gpn(r)); } inline void Assembler::SETG( R r) { count_alu(); ALU2(0x0f9F, r, r); asm_output("setg %s", gpn(r)); } @@ -1681,7 +1693,16 @@ namespace nanojit // asm_cmpd() converts LIR_ltd(a,b) to LIR_gtd(b,a). Likewise // for LIR_led/LIR_ged. switch (opcode) { - case LIR_eqd: SETNP(r); break; + case LIR_eqd: + if (ins->oprnd1() == ins->oprnd2()) { + SETNP(r); + } else { + // result = ZF & !PF, must do logic on flags + AND8R(r); // and rl,rh rl &= rh + SETNPH(r); // setnp rh rh = !PF + SETE(r); // sete rl rl = ZF + } + break; case LIR_ltd: case LIR_gtd: SETA(r); break; case LIR_led: @@ -2602,7 +2623,7 @@ namespace nanojit NIns* Assembler::asm_branchd(bool branchOnFalse, LIns *cond, NIns *targ) { - NIns* at; + NIns* at = 0; LOpcode opcode = cond->opcode(); if (_config.i386_sse2) { @@ -2612,7 +2633,14 @@ namespace nanojit if (branchOnFalse) { // op == LIR_xf switch (opcode) { - case LIR_eqd: JP(targ); break; + case LIR_eqd: + if (cond->oprnd1() == cond->oprnd2()) { + JP(targ); + } else { + JP(targ); + JNE(targ); + } + break; case LIR_ltd: case LIR_gtd: JNA(targ); break; case LIR_led: @@ -2622,7 +2650,20 @@ namespace nanojit } else { // op == LIR_xt switch (opcode) { - case LIR_eqd: JNP(targ); break; + case LIR_eqd: + if (cond->oprnd1() == cond->oprnd2()) { + JNP(targ); + } else { + // jp skip (2byte) + // je target + // skip: ... + underrunProtect(16); // underrun of 7 needed but we write 2 instr --> 16 + NIns *skip = _nIns; + JE(targ); + at = _nIns; + JP(skip); + } + break; case LIR_ltd: case LIR_gtd: JA(targ); break; case LIR_led: @@ -2637,7 +2678,8 @@ namespace nanojit JNP(targ); } - at = _nIns; + if (!at) + at = _nIns; asm_cmpd(cond); return at; @@ -2664,59 +2706,41 @@ namespace nanojit LIns* t = lhs; lhs = rhs; rhs = t; } - if (condop == LIR_eqd) { - if (lhs == rhs) { - // We can generate better code for LIR_eqd when lhs==rhs (NaN test). - // ucomisd ZPC outcome (SETNP/JNP succeeds if P==0) - // ------- --- ------- - // UNORDERED 111 SETNP/JNP fails - // EQUAL 100 SETNP/JNP succeeds + // LIR_eqd, if lhs == rhs: + // ucomisd ZPC outcome (SETNP/JNP succeeds if P==0) + // ------- --- ------- + // UNORDERED 111 SETNP/JNP fails + // EQUAL 100 SETNP/JNP succeeds + // + // LIR_eqd, if lsh != rhs; + // ucomisd ZPC outcome (SETP/JP succeeds if P==0, + // SETE/JE succeeds if Z==0) + // ------- --- ------- + // UNORDERED 111 SETP/JP succeeds (and skips to fail target) + // EQUAL 100 SETP/JP fails, SETE/JE succeeds + // GREATER_THAN 000 SETP/JP fails, SETE/JE fails + // LESS_THAN 001 SETP/JP fails, SETE/JE fails + // + // LIR_gtd: + // ucomisd ZPC outcome (SETA/JA succeeds if CZ==00) + // ------- --- ------- + // UNORDERED 111 SETA/JA fails + // EQUAL 100 SETA/JA fails + // GREATER_THAN 000 SETA/JA succeeds + // LESS_THAN 001 SETA/JA fails + // + // LIR_ged: + // ucomisd ZPC outcome (SETAE/JAE succeeds if C==0) + // ------- --- ------- + // UNORDERED 111 SETAE/JAE fails + // EQUAL 100 SETAE/JAE succeeds + // GREATER_THAN 000 SETAE/JAE succeeds + // LESS_THAN 001 SETAE/JAE fails - Register r = findRegFor(lhs, XmmRegs); - SSE_UCOMISD(r, r); - } else { - // LAHF puts the flags into AH like so: SF:ZF:0:AF:0:PF:1:CF (aka. SZ0A_0P1C). - // We then mask out the bits as follows. - // - LIR_eqd: mask == 0x44 == 0100_0100b, which extracts 0Z00_0P00 from AH. - int mask = 0x44; - - // ucomisd ZPC lahf/test(0x44) SZP outcome - // ------- --- --------- --- ------- - // UNORDERED 111 0100_0100 001 SETNP/JNP fails - // EQUAL 100 0100_0000 000 SETNP/JNP succeeds - // GREATER_THAN 000 0000_0000 011 SETNP/JNP fails - // LESS_THAN 001 0000_0000 011 SETNP/JNP fails - - evictIfActive(rEAX); - Register ra, rb; - findRegFor2(XmmRegs, lhs, ra, XmmRegs, rhs, rb); - - TEST_AH(mask); - LAHF(); - SSE_UCOMISD(ra, rb); - } - } else { - // LIR_gtd: - // ucomisd ZPC outcome (SETA/JA succeeds if CZ==00) - // ------- --- ------- - // UNORDERED 111 SETA/JA fails - // EQUAL 100 SETA/JA fails - // GREATER_THAN 000 SETA/JA succeeds - // LESS_THAN 001 SETA/JA fails - // - // LIR_ged: - // ucomisd ZPC outcome (SETAE/JAE succeeds if C==0) - // ------- --- ------- - // UNORDERED 111 SETAE/JAE fails - // EQUAL 100 SETAE/JAE succeeds - // GREATER_THAN 000 SETAE/JAE succeeds - // LESS_THAN 001 SETAE/JAE fails - - Register ra, rb; - findRegFor2(XmmRegs, lhs, ra, XmmRegs, rhs, rb); - SSE_UCOMISD(ra, rb); - } + Register ra, rb; + findRegFor2(XmmRegs, lhs, ra, XmmRegs, rhs, rb); + SSE_UCOMISD(ra, rb); } else { // First, we convert (a > b) into (b < a), and (a >= b) into (b <= a). @@ -2745,7 +2769,7 @@ namespace nanojit // - LIR_ltd: mask == 0x05 == 0000_0101b, which extracts 0000_0P0C from AH. // - LIR_led: mask == 0x41 == 0100_0001b, which extracts 0Z00_000C from AH. // - // LIR_eqd (very similar to the sse2 case above): + // LIR_eqd: // ucomisd C3:C2:C0 lahf/test(0x44) SZP outcome // ------- -------- --------- --- ------- // UNORDERED 111 0100_0100 001 SETNP fails diff --git a/js/src/nanojit/Nativei386.h b/js/src/nanojit/Nativei386.h index 5f800de4444..20d231d1ff9 100644 --- a/js/src/nanojit/Nativei386.h +++ b/js/src/nanojit/Nativei386.h @@ -242,10 +242,10 @@ namespace nanojit void ALUi(int32_t c, Register r, int32_t i); \ void ALUmi(int32_t c, int32_t d, Register b, int32_t i); \ void ALU2(int32_t c, Register d, Register s); \ - void LAHF(); \ - void SAHF(); \ + Register AL2AHReg(Register r); \ void OR(Register l, Register r); \ void AND(Register l, Register r); \ + void AND8R(Register r); \ void XOR(Register l, Register r); \ void ADD(Register l, Register r); \ void SUB(Register l, Register r); \ @@ -281,6 +281,7 @@ namespace nanojit void INCLi(int32_t p); \ void SETE( Register r); \ void SETNP(Register r); \ + void SETNPH(Register r); \ void SETL( Register r); \ void SETLE(Register r); \ void SETG( Register r); \ From 3a40c011d1f7fea953575c9bb6a076352ad48c44 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 27 Oct 2010 21:45:20 -0700 Subject: [PATCH 100/263] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index 7281e41d861..ba24b773b8f 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -53c69eca7d94694ff55d59d39c0d8a26f8d8c111 +8cb17c62aaa615416ac901106292b69f691c51cf From 41328585a955abd39c66dee405d2b3d85cd307d1 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 27 Oct 2010 21:04:13 -0700 Subject: [PATCH 101/263] Refactor and improve GETELEM IC (bug 602641, r=dmandelin). --- js/src/methodjit/BaseAssembler.h | 26 +- js/src/methodjit/BaseCompiler.h | 38 +- js/src/methodjit/Compiler.cpp | 188 ++--- js/src/methodjit/Compiler.h | 42 +- js/src/methodjit/FastOps.cpp | 238 +++--- js/src/methodjit/FrameEntry.h | 6 + js/src/methodjit/MethodJIT.cpp | 8 +- js/src/methodjit/MethodJIT.h | 4 + js/src/methodjit/NunboxAssembler.h | 23 +- js/src/methodjit/PolyIC.cpp | 1250 +++++++++++++--------------- js/src/methodjit/PolyIC.h | 202 +++-- js/src/methodjit/PunboxAssembler.h | 14 +- js/src/methodjit/StubCompiler.h | 1 + 13 files changed, 955 insertions(+), 1085 deletions(-) diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index bd230d6b0b4..04f3d9c90b5 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -50,6 +50,8 @@ #include "methodjit/MethodJIT.h" #include "methodjit/MachineRegs.h" #include "CodeGenIncludes.h" +#include "jsobjinlines.h" +#include "jsscopeinlines.h" namespace js { namespace mjit { @@ -209,9 +211,9 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste load32(Address(obj, offsetof(JSObject, objShape)), shape); } - Jump guardShape(RegisterID obj, uint32 shape) { - return branch32(NotEqual, Address(obj, offsetof(JSObject, objShape)), - Imm32(shape)); + Jump guardShape(RegisterID objReg, JSObject *obj) { + return branch32(NotEqual, Address(objReg, offsetof(JSObject, objShape)), + Imm32(obj->shape())); } Jump testFunction(Condition cond, RegisterID fun) { @@ -427,6 +429,24 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste else move(remat.reg(), reg); } + + void loadDynamicSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + loadPtr(Address(objReg, offsetof(JSObject, slots)), dataReg); + loadValueAsComponents(Address(dataReg, slot * sizeof(Value)), typeReg, dataReg); + } + + void loadObjProp(JSObject *obj, RegisterID objReg, + const js::Shape *shape, + RegisterID typeReg, RegisterID dataReg) + { + if (shape->isMethod()) + loadValueAsComponents(ObjectValue(shape->methodObject()), typeReg, dataReg); + else if (obj->hasSlotsArray()) + loadDynamicSlot(objReg, shape->slot, typeReg, dataReg); + else + loadInlineSlot(objReg, shape->slot, typeReg, dataReg); + } }; /* Return f if the script is strict mode code, f otherwise. */ diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index ad1ff5ad804..d4ccce0ca1e 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -48,19 +48,7 @@ namespace js { namespace mjit { -class BaseCompiler -{ - protected: - JSContext *cx; - - public: - BaseCompiler() : cx(NULL) - { } - - BaseCompiler(JSContext *cx) : cx(cx) - { } - - protected: +struct MacroAssemblerTypedefs { typedef JSC::MacroAssembler::Label Label; typedef JSC::MacroAssembler::Imm32 Imm32; typedef JSC::MacroAssembler::ImmPtr ImmPtr; @@ -77,11 +65,25 @@ class BaseCompiler typedef JSC::MacroAssembler::DataLabel32 DataLabel32; typedef JSC::FunctionPtr FunctionPtr; typedef JSC::RepatchBuffer RepatchBuffer; - typedef JSC::CodeBlock CodeBlock; typedef JSC::CodeLocationLabel CodeLocationLabel; - typedef JSC::JITCode JITCode; + typedef JSC::CodeLocationCall CodeLocationCall; typedef JSC::ReturnAddressPtr ReturnAddressPtr; typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr; +}; + +class BaseCompiler : public MacroAssemblerTypedefs +{ + protected: + JSContext *cx; + + public: + BaseCompiler() : cx(NULL) + { } + + BaseCompiler(JSContext *cx) : cx(cx) + { } + + protected: JSC::ExecutablePool * getExecPool(size_t size) { @@ -127,6 +129,12 @@ class LinkerHelper : public JSC::LinkBuffer } return ep; } + + void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) { + if (!jump.isSet()) + return; + link(jump.get(), label); + } }; } /* namespace js */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 38430a33672..0a895bbc838 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -103,6 +103,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp) #endif #if defined JS_POLYIC pics(ContextAllocPolicy(cx)), + getElemICs(ContextAllocPolicy(cx)), #endif callPatches(ContextAllocPolicy(cx)), callSites(ContextAllocPolicy(cx)), @@ -390,6 +391,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp) #endif #if defined JS_POLYIC sizeof(ic::PICInfo) * pics.length() + + sizeof(ic::GetElementIC) * getElemICs.length() + #endif sizeof(CallSite) * callSites.length(); @@ -586,6 +588,38 @@ mjit::Compiler::finishThisUp(JITScript **jitp) } #if defined JS_POLYIC + jit->nGetElems = getElemICs.length(); + if (getElemICs.length()) { + jit->getElems = (ic::GetElementIC *)cursor; + cursor += sizeof(ic::GetElementIC) * getElemICs.length(); + } else { + jit->getElems = NULL; + } + + for (size_t i = 0; i < getElemICs.length(); i++) { + ic::GetElementIC &to = jit->getElems[i]; + GetElementICInfo &from = getElemICs[i]; + to.init(); + from.copyTo(to, fullCode, stubCode); + + to.typeReg = from.typeReg; + to.objReg = from.objReg; + to.idRemat = from.id; + + if (from.typeGuard.isSet()) { + int inlineTypeGuard = fullCode.locationOf(from.typeGuard.get()) - + fullCode.locationOf(from.fastPathStart); + to.inlineTypeGuard = inlineTypeGuard; + JS_ASSERT(to.inlineTypeGuard == inlineTypeGuard); + } + int inlineClaspGuard = fullCode.locationOf(from.claspGuard) - + fullCode.locationOf(from.fastPathStart); + to.inlineClaspGuard = inlineClaspGuard; + JS_ASSERT(to.inlineClaspGuard == inlineClaspGuard); + + stubCode.patch(from.paramAddr, &to); + } + jit->nPICs = pics.length(); if (pics.length()) { jit->pics = (ic::PICInfo *)cursor; @@ -596,11 +630,9 @@ mjit::Compiler::finishThisUp(JITScript **jitp) if (ic::PICInfo *scriptPICs = jit->pics) { for (size_t i = 0; i < pics.length(); i++) { + scriptPICs[i].init(); + pics[i].copyTo(scriptPICs[i], fullCode, stubCode); pics[i].copySimpleMembersTo(scriptPICs[i]); - scriptPICs[i].fastPathStart = fullCode.locationOf(pics[i].fastPathStart); - scriptPICs[i].fastPathRejoin = fullCode.locationOf(pics[i].fastPathRejoin); - scriptPICs[i].slowPathStart = stubCode.locationOf(pics[i].slowPathStart); - scriptPICs[i].slowPathCall = stubCode.locationOf(pics[i].slowPathCall); scriptPICs[i].shapeGuard = masm.distanceOf(pics[i].shapeGuard) - masm.distanceOf(pics[i].fastPathStart); JS_ASSERT(scriptPICs[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) - @@ -623,8 +655,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp) scriptPICs[i].u.get.typeCheckOffset = distance; } } - new (&scriptPICs[i].execPools) ic::PICInfo::ExecPoolVector(SystemAllocPolicy()); - scriptPICs[i].reset(); stubCode.patch(pics[i].paramAddr, &scriptPICs[i]); } } @@ -2593,9 +2623,9 @@ mjit::Compiler::passMICAddress(MICGenInfo &mic) #if defined JS_POLYIC void -mjit::Compiler::passPICAddress(PICGenInfo &pic) +mjit::Compiler::passICAddress(BaseICInfo *ic) { - pic.paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); + ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); } bool @@ -2623,7 +2653,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) shapeReg = frame.allocReg(); } - PICGenInfo pic(ic::PICInfo::GET, usePropCache); + PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache); /* Guard that the type is an object. */ Jump typeCheck; @@ -2654,7 +2684,6 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -2669,7 +2698,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::GetProp); /* Load dslots. */ @@ -2727,113 +2756,6 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) return true; } -#ifdef JS_POLYIC -bool -mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - RegisterID idReg, RegisterID shapeReg) -{ - PICGenInfo pic(ic::PICInfo::GETELEM, true); - - pic.objRemat = frame.dataRematInfo(obj); - pic.idRemat = frame.dataRematInfo(id); - pic.shapeReg = shapeReg; - pic.hasTypeCheck = false; - - pic.fastPathStart = masm.label(); - - /* Guard on shape. */ - masm.loadShape(objReg, shapeReg); - pic.shapeGuard = masm.label(); - - DataLabel32 inlineShapeOffsetLabel; - Jump jmpShapeGuard = masm.branch32WithPatch(Assembler::NotEqual, shapeReg, - Imm32(int32(JSObjectMap::INVALID_SHAPE)), - inlineShapeOffsetLabel); - DBGLABEL(dbgInlineShapeJump); - - /* Guard on id identity. */ -#if defined JS_NUNBOX32 - static const void *BOGUS_ATOM = (void *)0xdeadbeef; -#elif defined JS_PUNBOX64 - static const void *BOGUS_ATOM = (void *)0xfeedfacedeadbeef; -#endif - - DataLabelPtr inlineAtomOffsetLabel; - Jump idGuard = masm.branchPtrWithPatch(Assembler::NotEqual, idReg, - inlineAtomOffsetLabel, ImmPtr(BOGUS_ATOM)); - DBGLABEL(dbgInlineAtomJump); - - /* - * The state between these two exits is identical, so this safe. The - * GETELEM PIC repatches both jumps to the slowPathStart on reset. - */ - stubcc.linkExit(idGuard, Uses(2)); - pic.slowPathStart = stubcc.linkExit(jmpShapeGuard, Uses(2)); - - stubcc.leave(); - passPICAddress(pic); - pic.slowPathCall = stubcc.call(ic::GetElem); - - /* Load dslots. */ -#if defined JS_NUNBOX32 - DBGLABEL(dbgDslotsLoad); -#elif defined JS_PUNBOX64 - Label dslotsLoadLabel = masm.label(); -#endif - masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); - - /* Copy the slot value to the expression stack. */ - Address slot(objReg, 1 << 24); -#if defined JS_NUNBOX32 - masm.loadTypeTag(slot, shapeReg); - DBGLABEL(dbgTypeLoad); - masm.loadPayload(slot, objReg); - DBGLABEL(dbgDataLoad); -#elif defined JS_PUNBOX64 - Label inlineValueOffsetLabel = - masm.loadValueAsComponents(slot, shapeReg, objReg); -#endif - pic.fastPathRejoin = masm.label(); - - pic.objReg = objReg; - pic.idReg = idReg; - - RETURN_IF_OOM(false); -#if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel) == GETELEM_INLINE_ATOM_OFFSET); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == GETELEM_INLINE_ATOM_JUMP); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == GETELEM_INLINE_SHAPE_OFFSET); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); -#elif defined JS_PUNBOX64 - pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); - JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); - - pic.labels.getelem.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel)); - - pic.labels.getelem.inlineAtomOffset = masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineAtomOffset == masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel)); - - pic.labels.getelem.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel)); - - JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); - JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == - pic.labels.getelem.inlineAtomOffset + GETELEM_INLINE_ATOM_JUMP); -#endif - - JS_ASSERT(pic.idReg != pic.objReg); - JS_ASSERT(pic.idReg != pic.shapeReg); - JS_ASSERT(pic.objReg != pic.shapeReg); - - pics.append(pic); - return true; -} -#endif - bool mjit::Compiler::jsop_callprop_generic(JSAtom *atom) { @@ -2847,7 +2769,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) RegisterID objReg = frame.copyDataIntoReg(top); RegisterID shapeReg = frame.allocReg(); - PICGenInfo pic(ic::PICInfo::CALL, true); + PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); pic.pc = PC; @@ -2871,7 +2793,6 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) pic.objReg = objReg; pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* * Store the type and object back. Don't bother keeping them in registers, @@ -2901,7 +2822,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) /* Slow path. */ stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Adjust the frame. None of this will generate code. */ @@ -3019,7 +2940,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) { FrameEntry *top = frame.peek(-1); - PICGenInfo pic(ic::PICInfo::CALL, true); + PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true); JS_ASSERT(top->isTypeKnown()); JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT); @@ -3034,7 +2955,6 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.shapeReg = shapeReg; pic.atom = atom; - pic.objRemat = frame.dataRematInfo(top); /* Guard on shape. */ masm.loadShape(objReg, shapeReg); @@ -3049,7 +2969,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::CallProp); /* Load dslots. */ @@ -3151,7 +3071,10 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) JSOp op = JSOp(*PC); - PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET, usePropCache); + ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD) + ? ic::PICInfo::SETMETHOD + : ic::PICInfo::SET; + PICGenInfo pic(kind, op, usePropCache); pic.atom = atom; /* Guard that the type is an object. */ @@ -3191,7 +3114,6 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) RegisterID shapeReg = frame.allocReg(); pic.shapeReg = shapeReg; - pic.objRemat = frame.dataRematInfo(lhs); frame.unpinEntry(vr); @@ -3209,7 +3131,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(2)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::SetProp); } @@ -3276,7 +3198,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) void mjit::Compiler::jsop_name(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::NAME, true); + PICGenInfo pic(ic::PICInfo::NAME, JSOp(*PC), true); pic.shapeReg = frame.allocReg(); pic.objReg = frame.allocReg(); @@ -3291,7 +3213,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::Name); } @@ -3308,7 +3230,7 @@ mjit::Compiler::jsop_name(JSAtom *atom) bool mjit::Compiler::jsop_xname(JSAtom *atom) { - PICGenInfo pic(ic::PICInfo::XNAME, true); + PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true); FrameEntry *fe = frame.peek(-1); if (fe->isNotType(JSVAL_TYPE_OBJECT)) { @@ -3333,7 +3255,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) { pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::XName); } @@ -3352,7 +3274,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom) void mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { - PICGenInfo pic(ic::PICInfo::BIND, usePropCache); + PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC), usePropCache); // 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 @@ -3382,7 +3304,7 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); - passPICAddress(pic); + passICAddress(&pic); pic.slowPathCall = stubcc.call(ic::BindName); } diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 4483e4f8185..3bf27b46e14 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -160,18 +160,39 @@ class Compiler : public BaseCompiler bool hasSlowNcode; }; -#if defined JS_POLYIC struct BaseICInfo { + BaseICInfo(JSOp op) : op(op) + { } Label fastPathStart; Label fastPathRejoin; Label slowPathStart; Call slowPathCall; DataLabelPtr paramAddr; + JSOp op; + + void copyTo(ic::BaseIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) { + to.fastPathStart = full.locationOf(fastPathStart); + to.fastPathRejoin = full.locationOf(fastPathRejoin); + to.slowPathStart = stub.locationOf(slowPathStart); + to.slowPathCall = stub.locationOf(slowPathCall); + to.op = op; + JS_ASSERT(to.op == op); + } + }; + + struct GetElementICInfo : public BaseICInfo { + GetElementICInfo(JSOp op) : BaseICInfo(op) + { } + RegisterID typeReg; + RegisterID objReg; + ValueRemat id; + MaybeJump typeGuard; + Jump claspGuard; }; struct PICGenInfo : public BaseICInfo { - PICGenInfo(ic::PICInfo::Kind kind, bool usePropCache) - : kind(kind), usePropCache(usePropCache) + PICGenInfo(ic::PICInfo::Kind kind, JSOp op, bool usePropCache) + : BaseICInfo(op), kind(kind), usePropCache(usePropCache) { } ic::PICInfo::Kind kind; Label typeCheck; @@ -183,8 +204,6 @@ class Compiler : public BaseCompiler Label shapeGuard; jsbytecode *pc; JSAtom *atom; - StateRemat objRemat; - StateRemat idRemat; bool hasTypeCheck; ValueRemat vr; # if defined JS_CPU_X64 @@ -200,15 +219,12 @@ class Compiler : public BaseCompiler if (ic.isSet()) { ic.u.vr = vr; } else if (ic.isGet()) { - ic.u.get.idReg = idReg; ic.u.get.typeReg = typeReg; ic.u.get.hasTypeCheck = hasTypeCheck; - ic.setObjRemat(objRemat); } } }; -#endif struct Defs { Defs(uint32 ndefs) @@ -250,6 +266,7 @@ class Compiler : public BaseCompiler #endif #if defined JS_POLYIC js::Vector pics; + js::Vector getElemICs; #endif js::Vector callPatches; js::Vector callSites; @@ -298,7 +315,7 @@ class Compiler : public BaseCompiler void iterEnd(); MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg); #ifdef JS_POLYIC - void passPICAddress(PICGenInfo &pic); + void passICAddress(BaseICInfo *ic); #endif #ifdef JS_MONOIC void passMICAddress(MICGenInfo &mic); @@ -400,13 +417,6 @@ class Compiler : public BaseCompiler void jsop_localinc(JSOp op, uint32 slot, bool popped); void jsop_setelem(); bool jsop_getelem(); - bool jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - bool jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg); - bool jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg, - RegisterID shapeReg); - void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - MaybeRegisterID &idReg, RegisterID shapeReg); void jsop_stricteq(JSOp op); void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void 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 76cf06f3f24..2f9dc0c77b5 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1360,135 +1360,6 @@ mjit::Compiler::jsop_setelem() stubcc.rejoin(Changes(0)); } -void -mjit::Compiler::jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg, - MaybeRegisterID &idReg, RegisterID tmpReg) -{ - /* Note: idReg is only valid if id is not a constant. */ - Jump guardDense = masm.testObjClass(Assembler::NotEqual, objReg, &js_ArrayClass); - stubcc.linkExit(guardDense, Uses(2)); - - Int32Key key = idReg.isSet() - ? Int32Key::FromRegister(idReg.reg()) - : Int32Key::FromConstant(id->getValue().toInt32()); - - Assembler::FastArrayLoadFails fails = - masm.fastArrayLoad(objReg, key, tmpReg, objReg); - - stubcc.linkExit(fails.rangeCheck, Uses(2)); - stubcc.linkExit(fails.holeCheck, Uses(2)); -} - -bool -mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - switch (id->getKnownType()) { - case JSVAL_TYPE_INT32: - { - /* Prologue. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg; - if (!id->isConstant()) - idReg.setReg(frame.copyDataIntoReg(id)); - - /* Meat. */ - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - stubcc.leave(); - stubcc.call(stubs::GetElem); - - /* Epilogue. */ - if (idReg.isSet()) - frame.freeReg(idReg.reg()); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - stubcc.rejoin(Changes(1)); - break; - } -#ifdef JS_POLYIC - case JSVAL_TYPE_STRING: - { - /* Prologue. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - RegisterID idReg = frame.copyDataIntoReg(id); - - /* Meat. */ - if (!jsop_getelem_pic(obj, id, objReg, idReg, tmpReg)) - return false; - - /* Epilogue. */ - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - frame.freeReg(idReg); - stubcc.rejoin(Changes(1)); - break; - } -#endif - default: - JS_NOT_REACHED("Invalid known id type."); - } - return true; -} - -#ifdef JS_POLYIC -bool -mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - JS_ASSERT(!id->isTypeKnown()); - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg(frame.copyDataIntoReg(id)); - - RegisterID typeReg = frame.tempRegForType(id, tmpReg); - Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); - - JaegerSpew(JSpew_Insns, " ==== BEGIN DENSE ARRAY CODE ==== \n"); - - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - Jump performedDense = masm.jump(); - - JaegerSpew(JSpew_Insns, " ==== END DENSE ARRAY CODE ==== \n"); - - intGuard.linkTo(masm.label(), &masm); - Jump stringGuard = masm.testString(Assembler::NotEqual, typeReg); - stubcc.linkExit(stringGuard, Uses(2)); /* Neither int nor string at this point. */ - - stubcc.leave(); - stubcc.call(stubs::GetElem); - Jump toFinalMerge = stubcc.masm.jump(); - - if (!jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg)) - return false; - performedDense.linkTo(masm.label(), &masm); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - frame.freeReg(idReg.reg()); - toFinalMerge.linkTo(stubcc.masm.label(), &stubcc.masm); - stubcc.rejoin(Changes(1)); - return true; -} -#endif - -void -mjit::Compiler::jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg) -{ - /* Only handle the int32 case. */ - RegisterID objReg = frame.copyDataIntoReg(obj); - MaybeRegisterID idReg(frame.copyDataIntoReg(id)); - RegisterID typeReg = frame.tempRegForType(id, tmpReg); - Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg); - stubcc.linkExit(intGuard, Uses(2)); - - /* Meat. */ - jsop_getelem_dense(obj, id, objReg, idReg, tmpReg); - stubcc.leave(); - stubcc.call(stubs::GetElem); - - /* Epilogue. */ - frame.freeReg(idReg.reg()); - frame.popn(2); - frame.pushRegs(tmpReg, objReg); - stubcc.rejoin(Changes(1)); -} - bool mjit::Compiler::jsop_getelem() { @@ -1516,30 +1387,107 @@ mjit::Compiler::jsop_getelem() return true; } - if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_STRING && id->isConstant()) { - /* Never happens, or I'd optimize it. */ - 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); + + MaybeJump objTypeGuard; + if (!obj->isTypeKnown()) { + // Test the type of the object without spilling the payload. + MaybeRegisterID pinnedObjData = frame.maybePinData(obj); + Jump guard = frame.testObject(Assembler::NotEqual, obj); + frame.maybeUnpinReg(pinnedObjData); + + // Create a sync path, which we'll rejoin manually later. This is safe + // as long as the IC does not build a stub; it won't, because |obj| + // won't be an object. If we extend this IC to support strings, all + // that needs to change is a little code movement. + stubcc.linkExit(guard, Uses(2)); + objTypeGuard = stubcc.masm.jump(); } - RegisterID tmpReg; - if (obj->isTypeKnown()) { - tmpReg = frame.allocReg(); + // Get a mutable register for the object. This will be the data reg. + ic.objReg = frame.copyDataIntoReg(obj); + + // 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); + + // Fill in the id value. + frame.maybeUnpinReg(pinnedIdData); + if (id->isConstant()) { + ic.id = ValueRemat::FromConstant(id->getValue()); } else { - tmpReg = frame.copyTypeIntoReg(obj); - Jump objGuard = masm.testObject(Assembler::NotEqual, tmpReg); - stubcc.linkExit(objGuard, Uses(2)); + RegisterID dataReg = frame.tempRegForData(id); + if (id->isTypeKnown()) + ic.id = ValueRemat::FromKnownType(id->getKnownType(), dataReg); + else + ic.id = ValueRemat::FromRegisters(ic.typeReg, dataReg); } - if (id->isTypeKnown()) - return jsop_getelem_known_type(obj, id, tmpReg); + ic.fastPathStart = masm.label(); + + // Note: slow path here is safe, since the frame will not be modified. + ic.slowPathStart = stubcc.masm.label(); + frame.sync(stubcc.masm, Uses(2)); + + if (id->mightBeType(JSVAL_TYPE_INT32)) { + // Always test the type first (see comment in PolyIC.h). + if (!id->isTypeKnown()) { + ic.typeGuard = masm.testInt32(Assembler::NotEqual, ic.typeReg); + stubcc.linkExitDirect(ic.typeGuard.get(), ic.slowPathStart); + } + + // Guard on the clasp. + ic.claspGuard = masm.testObjClass(Assembler::NotEqual, ic.objReg, &js_ArrayClass); + stubcc.linkExitDirect(ic.claspGuard, ic.slowPathStart); + + 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); + + 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); + ic.slowPathCall = stubcc.call(ic::GetElement); +#else + ic.slowPathCall = stubcc.call(stubs::GetElem); +#endif + + ic.fastPathRejoin = masm.label(); + + frame.popn(2); + frame.pushRegs(ic.typeReg, ic.objReg); + + stubcc.rejoin(Changes(2)); #ifdef JS_POLYIC - return jsop_getelem_with_pic(obj, id, tmpReg); -#else - jsop_getelem_nopic(obj, id, tmpReg); - return true; + if (!getElemICs.append(ic)) + return false; #endif + + return true; } static inline bool diff --git a/js/src/methodjit/FrameEntry.h b/js/src/methodjit/FrameEntry.h index 56a4dc72ac1..7cea4a464e3 100644 --- a/js/src/methodjit/FrameEntry.h +++ b/js/src/methodjit/FrameEntry.h @@ -97,6 +97,12 @@ class FrameEntry return isTypeKnown() && getKnownType() != type_; } + // Return true if the type of this value is definitely type_, or is unknown + // and thus potentially type_ at runtime. + bool mightBeType(JSValueType type_) const { + return !isNotType(type_); + } + #if defined JS_NUNBOX32 uint32 getPayload() const { //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced()); diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index 64e6ffe984a..ae9ad37af7f 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -811,10 +811,10 @@ mjit::JITScript::release() code.m_executablePool->release(); #if defined JS_POLYIC - for (uint32 i = 0; i < nPICs; i++) { - pics[i].releasePools(); - Destroy(pics[i].execPools); - } + for (uint32 i = 0; i < nPICs; i++) + pics[i].finish(); + for (uint32 i = 0; i < nGetElems; i++) + getElems[i].finish(); #endif #if defined JS_MONOIC diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index e5332942a09..1bcca198b9b 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -143,6 +143,7 @@ namespace mjit { namespace ic { # if defined JS_POLYIC struct PICInfo; + struct GetElementIC; # endif # if defined JS_MONOIC struct MICInfo; @@ -182,6 +183,7 @@ typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceI #endif #ifdef JS_POLYIC typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *); +typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *); #endif namespace mjit { @@ -212,6 +214,8 @@ struct JITScript { #ifdef JS_POLYIC ic::PICInfo *pics; /* PICs in this script */ uint32 nPICs; /* number of PolyICs */ + ic::GetElementIC *getElems; + uint32 nGetElems; #endif void *invokeEntry; /* invoke address */ void *fastEntry; /* cached entry, fastest */ diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index 6715b388688..d2dc6191641 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -90,22 +90,15 @@ class NunboxAssembler : public JSC::MacroAssembler return BaseIndex(address.base, address.index, address.scale, address.offset + TAG_OFFSET); } - void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, - RegisterID type, RegisterID data) { - JS_ASSERT(type != data); - Address address(obj, JSObject::getFixedSlotOffset(slot)); - RegisterID activeAddressReg = obj; - if (!inlineAccess) { - loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); - address = Address(clobber, slot * sizeof(Value)); - activeAddressReg = clobber; - } - if (activeAddressReg == type) { - loadPayload(address, data); - loadTypeTag(address, type); + void loadInlineSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + Address address(objReg, JSObject::getFixedSlotOffset(slot)); + if (objReg == typeReg) { + loadPayload(address, dataReg); + loadTypeTag(address, typeReg); } else { - loadTypeTag(address, type); - loadPayload(address, data); + loadTypeTag(address, typeReg); + loadPayload(address, dataReg); } } diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index d0084df2927..df2b29e24e5 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -45,6 +45,7 @@ #include "assembler/assembler/RepatchBuffer.h" #include "jsscope.h" #include "jsnum.h" +#include "jsatominlines.h" #include "jsobjinlines.h" #include "jsscopeinlines.h" #include "jspropertycache.h" @@ -57,6 +58,9 @@ using namespace js; using namespace js::mjit; using namespace js::mjit::ic; +typedef JSC::RepatchBuffer RepatchBuffer; +typedef JSC::FunctionPtr FunctionPtr; + /* Rough over-estimate of how much memory we need to unprotect. */ static const uint32 INLINE_PATH_LENGTH = 64; @@ -65,18 +69,18 @@ static const uint32 INLINE_PATH_LENGTH = 64; // are instantiated and rooted. class PICLinker : public LinkerHelper { - ic::PICInfo &pic; + ic::BaseIC ⁣ public: - PICLinker(JSContext *cx, ic::PICInfo &pic) - : LinkerHelper(cx), pic(pic) + PICLinker(JSContext *cx, ic::BaseIC &ic) + : LinkerHelper(cx), ic(ic) { } bool init(Assembler &masm) { JSC::ExecutablePool *pool = LinkerHelper::init(masm); if (!pool) return false; - if (!pic.execPools.append(pool)) { + if (!ic.execPools.append(pool)) { pool->release(); js_ReportOutOfMemory(cx); return false; @@ -92,42 +96,38 @@ class PICStubCompiler : public BaseCompiler VMFrame &f; JSScript *script; ic::PICInfo &pic; + void *stub; public: - PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic) - : BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic) + 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) { } - bool isCallOp() const - { + bool isCallOp() const { if (pic.kind == ic::PICInfo::CALL) return true; - JSOp op = JSOp(*f.regs.pc); - return !!(js_CodeSpec[op].format & JOF_CALLOP); + return !!(js_CodeSpec[pic.op].format & JOF_CALLOP); } - bool disable(const char *reason, VoidStub stub) - { - return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); + LookupStatus error() { + disable("error"); + return Lookup_Error; } - bool disable(const char *reason, VoidStubPIC stub) { - return disable(reason, JS_FUNC_TO_DATA_PTR(void *, stub)); + LookupStatus error(JSContext *cx) { + return error(); } - bool disable(const char *reason, void *stub) - { - spew("disabled", reason); - JITCode jitCode(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - CodeBlock codeBlock(jitCode); - RepatchBuffer repatcher(&codeBlock); - repatcher.relink(pic.slowPathCall, FunctionPtr(stub)); - return true; + LookupStatus disable(const char *reason) { + return disable(f.cx, reason); + } + + LookupStatus disable(JSContext *cx, const char *reason) { + return pic.disable(cx, reason, stub); } protected: - void spew(const char *event, const char *op) - { + void spew(const char *event, const char *op) { #ifdef JS_METHODJIT_SPEW JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n", type, event, op, script->filename, @@ -138,13 +138,13 @@ class PICStubCompiler : public BaseCompiler class PICRepatchBuffer : public JSC::RepatchBuffer { - ic::PICInfo &pic; + ic::BaseIC ⁣ JSC::CodeLocationLabel label; public: - PICRepatchBuffer(ic::PICInfo &ic, JSC::CodeLocationLabel path) + PICRepatchBuffer(ic::BaseIC &ic, JSC::CodeLocationLabel path) : JSC::RepatchBuffer(path.executableAddress(), INLINE_PATH_LENGTH), - pic(ic), label(path) + ic(ic), label(path) { } void relink(int32 offset, JSC::CodeLocationLabel target) { @@ -156,7 +156,6 @@ class SetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; - VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 dslotsLoadOffset(ic::PICInfo &pic) { @@ -222,15 +221,10 @@ class SetPropCompiler : public PICStubCompiler public: SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("setprop", f, script, pic), obj(obj), atom(atom), stub(stub), - lastStubSecondShapeGuard(pic.secondShapeGuard) + : PICStubCompiler("setprop", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + obj(obj), atom(atom), lastStubSecondShapeGuard(pic.secondShapeGuard) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -247,7 +241,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - bool patchInline(const Shape *shape, bool inlineSlot) + LookupStatus patchInline(const Shape *shape, bool inlineSlot) { JS_ASSERT(!pic.inlinePathPatched); JaegerSpew(JSpew_PICs, "patch setprop inline at %p\n", pic.fastPathStart.executableAddress()); @@ -286,7 +280,7 @@ class SetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return true; + return Lookup_Cacheable; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -308,7 +302,7 @@ class SetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - bool generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) + LookupStatus generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot) { /* Exits to the slow path. */ Vector slowExits(cx); @@ -346,9 +340,9 @@ class SetPropCompiler : public PICStubCompiler RegisterID lastReg = pic.objReg; while (proto) { masm.loadPtr(Address(lastReg, offsetof(JSObject, proto)), pic.shapeReg); - Jump protoGuard = masm.guardShape(pic.shapeReg, proto->shape()); + Jump protoGuard = masm.guardShape(pic.shapeReg, proto); if (!otherGuards.append(protoGuard)) - return false; + return error(); proto = proto->getProto(); lastReg = pic.shapeReg; @@ -367,7 +361,7 @@ class SetPropCompiler : public PICStubCompiler Jump mismatchedFunction = masm.branchPtr(Assembler::NotEqual, pic.u.vr.dataReg(), ImmPtr(funobj)); if (!slowExits.append(mismatchedFunction)) - return false; + return error(); } } @@ -382,7 +376,7 @@ class SetPropCompiler : public PICStubCompiler Jump overCapacity = masm.branch32(Assembler::LessThanOrEqual, pic.shapeReg, Imm32(shape->slot)); if (!slowExits.append(overCapacity)) - return false; + return error(); masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.shapeReg); Address address(pic.shapeReg, shape->slot * sizeof(Value)); @@ -420,7 +414,7 @@ class SetPropCompiler : public PICStubCompiler masm.loadPayload(address, pic.shapeReg); Jump rebrand = masm.testFunction(Assembler::Equal, pic.shapeReg); if (!slowExits.append(rebrand)) - return false; + return error(); skip.linkTo(masm.label(), &masm); pic.shapeRegHasBaseShape = false; } @@ -476,7 +470,7 @@ class SetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(shapeGuard, pic.slowPathStart); if (slowExit.isSet()) @@ -511,16 +505,12 @@ class SetPropCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } - bool update() + LookupStatus update() { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } + JS_ASSERT(pic.hit); if (obj->isDenseArray()) return disable("dense array"); @@ -541,7 +531,7 @@ class SetPropCompiler : public PICStubCompiler JSObject *holder; JSProperty *prop = NULL; if (!obj->lookupProperty(cx, id, &holder, &prop)) - return false; + return error(); /* If the property exists but is on a prototype, treat as addprop. */ if (prop && holder != obj) { @@ -581,7 +571,7 @@ class SetPropCompiler : public PICStubCompiler uint32 initialShape = obj->shape(); if (!obj->ensureClassReservedSlots(cx)) - return false; + return error(); uint32 slots = obj->numSlots(); uintN flags = 0; @@ -604,7 +594,7 @@ class SetPropCompiler : public PICStubCompiler SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0); if (!shape) - return false; + return error(); /* * Test after calling putProperty since it can switch obj into @@ -667,11 +657,84 @@ class SetPropCompiler : public PICStubCompiler } }; +static bool +IsCacheableProtoChain(JSObject *obj, JSObject *holder) +{ + while (obj != holder) { + JSObject *proto = obj->getProto(); + if (!proto->isNative()) + return false; + obj = proto; + } + return true; +} + +template +struct GetPropertyHelper { + JSContext *cx; + JSObject *obj; + JSAtom *atom; + IC ⁣ + + JSObject *aobj; + JSObject *holder; + const Shape *shape; + + GetPropertyHelper(JSContext *cx, JSObject *obj, JSAtom *atom, IC &ic) + : cx(cx), obj(obj), atom(atom), ic(ic), holder(NULL), shape(NULL) + { } + + public: + LookupStatus bind() { + JSProperty *prop; + if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) + return ic.error(cx); + if (!prop) + return ic.disable(cx, "lookup failed"); + shape = (const Shape *)prop; + return Lookup_Cacheable; + } + + LookupStatus lookup() { + JSObject *aobj = js_GetProtoIfDenseArray(obj); + if (!aobj->isNative()) + return ic.disable(cx, "non-native"); + JSProperty *prop; + if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) + return ic.error(cx); + if (!prop) + return ic.disable(cx, "lookup failed"); + if (!IsCacheableProtoChain(obj, holder)) + return ic.disable(cx, "non-native holder"); + shape = (const Shape *)prop; + return Lookup_Cacheable; + } + + LookupStatus testForGet() { + if (!shape->hasDefaultGetter()) { + if (!shape->isMethod()) + return ic.disable(cx, "getter"); + if (!ic.isCallOp()) + return ic.disable(cx, "method valued shape"); + } else if (!shape->hasSlot()) { + return ic.disable(cx, "no slot"); + } + + return Lookup_Cacheable; + } + + LookupStatus lookupAndTest() { + LookupStatus status = lookup(); + if (status != Lookup_Cacheable) + return status; + return testForGet(); + } +}; + class GetPropCompiler : public PICStubCompiler { JSObject *obj; JSAtom *atom; - VoidStubPIC stub; int lastStubSecondShapeGuard; static int32 inlineShapeOffset(ic::PICInfo &pic) { @@ -713,10 +776,10 @@ class GetPropCompiler : public PICStubCompiler public: GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic), + : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic, + JS_FUNC_TO_DATA_PTR(void *, stub)), obj(obj), atom(atom), - stub(stub), lastStubSecondShapeGuard(pic.secondShapeGuard) { } @@ -754,7 +817,7 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(pic.slowPathCall, target); } - bool generateArgsLengthStub() + LookupStatus generateArgsLengthStub() { Assembler masm; @@ -772,7 +835,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notArgs, pic.slowPathStart); buffer.link(overridden, pic.slowPathStart); @@ -787,10 +850,10 @@ class GetPropCompiler : public PICStubCompiler disable("args length done"); - return true; + return Lookup_Cacheable; } - bool generateArrayLengthStub() + LookupStatus generateArrayLengthStub() { Assembler masm; @@ -806,7 +869,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notArray, pic.slowPathStart); buffer.link(oob, pic.slowPathStart); @@ -821,10 +884,10 @@ class GetPropCompiler : public PICStubCompiler disable("array length done"); - return true; + return Lookup_Cacheable; } - bool generateStringCallStub() + LookupStatus generateStringCallStub() { JS_ASSERT(pic.hasTypeCheck()); JS_ASSERT(pic.kind == ic::PICInfo::CALL); @@ -832,24 +895,12 @@ class GetPropCompiler : public PICStubCompiler if (!f.fp()->script()->compileAndGo) return disable("String.prototype without compile-and-go"); - JSObject *holder; - JSProperty *prop; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - if (!prop) - return disable("property not found"); - - const Shape *shape = (const Shape *)prop; - if (holder != obj) + GetPropertyHelper getprop(cx, obj, atom, *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; + if (getprop.obj != getprop.holder) return disable("proto walk on String.prototype"); - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - JS_ASSERT(holder->isNative()); Assembler masm; @@ -858,8 +909,7 @@ class GetPropCompiler : public PICStubCompiler ImmType(JSVAL_TYPE_STRING)); /* - * Sink pic.objReg, since we're about to lose it. This is optimistic, - * we could reload it from objRemat if we wanted. + * 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 @@ -880,19 +930,13 @@ class GetPropCompiler : public PICStubCompiler masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeMismatch = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(obj->shape())); - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !obj->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(shapeMismatch, pic.slowPathStart); @@ -911,10 +955,10 @@ class GetPropCompiler : public PICStubCompiler /* Disable the PIC so we don't keep generating stubs on the above shape mismatch. */ disable("generated string call stub"); - return true; + return Lookup_Cacheable; } - bool generateStringLengthStub() + LookupStatus generateStringLengthStub() { JS_ASSERT(pic.hasTypeCheck()); @@ -929,7 +973,7 @@ class GetPropCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(done, pic.fastPathRejoin); @@ -945,10 +989,10 @@ class GetPropCompiler : public PICStubCompiler disable("generated string length stub"); - return true; + return Lookup_Cacheable; } - bool patchInline(JSObject *holder, const Shape *shape) + LookupStatus patchInline(JSObject *holder, const Shape *shape) { spew("patch", "inline"); PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -985,20 +1029,15 @@ class GetPropCompiler : public PICStubCompiler pic.inlinePathPatched = true; - return true; + return Lookup_Cacheable; } - bool generateStub(JSObject *holder, const Shape *shape) + LookupStatus generateStub(JSObject *holder, const Shape *shape) { Vector shapeMismatches(cx); Assembler masm; - if (pic.objNeedsRemat()) { - masm.rematPayload(pic.objRemat(), pic.objReg); - pic.u.get.objNeedsRemat = false; - } - Label start; Jump shapeGuard; Jump argsLenGuard; @@ -1028,63 +1067,33 @@ class GetPropCompiler : public PICStubCompiler Label stubShapeJumpLabel = masm.label(); #endif - if (!shapeMismatches.append(shapeGuard)) - return false; + return error(); + RegisterID holderReg = pic.objReg; if (obj != holder) { - // Emit code that walks the prototype chain. - JSObject *tempObj = obj; - Address proto(pic.objReg, offsetof(JSObject, proto)); - do { - tempObj = tempObj->getProto(); - // FIXME: we should find out why this condition occurs. It is probably - // related to PICs on globals. - if (!tempObj) - return disable("null object in prototype chain"); - JS_ASSERT(tempObj); + // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. + holderReg = pic.shapeReg; + masm.move(ImmPtr(holder), holderReg); + pic.shapeRegHasBaseShape = false; - /* - * If there is a non-native along the prototype chain the shape is technically - * invalid. - */ - if (!tempObj->isNative()) - return disable("non-JS-native in prototype chain"); - - masm.loadPtr(proto, pic.objReg); - pic.shapeRegHasBaseShape = false; - pic.u.get.objNeedsRemat = true; - - Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); - if (!shapeMismatches.append(j)) - return false; - } while (tempObj != holder); - - // Load the shape out of the holder and check it. - masm.loadShape(pic.objReg, pic.shapeReg); - Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(holder->shape())); + // Guard on the holder's shape. + Jump j = masm.guardShape(holderReg, holder); if (!shapeMismatches.append(j)) - return false; + return error(); + pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); } else { - JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ pic.secondShapeGuard = 0; } /* Load the value out of the object. */ - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + masm.loadObjProp(holder, holderReg, shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); // The guard exit jumps to the original slow case. for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) @@ -1111,7 +1120,7 @@ class GetPropCompiler : public PICStubCompiler if (obj->isDenseArray()) disable("dense array"); - return true; + return Lookup_Cacheable; } void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) @@ -1133,373 +1142,19 @@ class GetPropCompiler : public PICStubCompiler repatcher.relink(lastStubSecondShapeGuard, cs); } - bool update() + LookupStatus update() { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } + JS_ASSERT(pic.hit); - JSObject *aobj = js_GetProtoIfDenseArray(obj); - if (!aobj->isNative()) - return disable("non-native"); + GetPropertyHelper getprop(cx, obj, atom, *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; - JSObject *holder; - JSProperty *prop; - if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - if (!prop) - return disable("lookup failed"); - - if (!holder->isNative()) - return disable("non-native holder"); - - const Shape *shape = (const Shape *)prop; - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - if (obj == holder && !pic.inlinePathPatched) - return patchInline(holder, shape); + if (obj == getprop.holder && !pic.inlinePathPatched) + return patchInline(getprop.holder, getprop.shape); - return generateStub(holder, shape); - } - - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } -}; - -class GetElemCompiler : public PICStubCompiler -{ - JSObject *obj; - JSString *id; - void *stub; - int lastStubSecondShapeGuard; - - static int32 dslotsLoad(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_DSLOTS_LOAD; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.dslotsLoadOffset; -#endif - } - - inline int32 dslotsLoad() { - return dslotsLoad(pic); - } - - static int32 inlineShapeOffset(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_SHAPE_OFFSET; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.inlineShapeOffset; -#endif - } - - inline int32 inlineShapeOffset() { - return inlineShapeOffset(pic); - } - - static int32 inlineShapeJump(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_SHAPE_JUMP; -#elif defined JS_PUNBOX64 - return inlineShapeOffset(pic) + GETELEM_INLINE_SHAPE_JUMP; -#endif - } - - inline int32 inlineShapeJump() { - return inlineShapeJump(pic); - } - - static int32 inlineAtomOffset(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_ATOM_OFFSET; -#elif defined JS_PUNBOX64 - return pic.labels.getelem.inlineAtomOffset; -#endif - } - - inline int32 inlineAtomOffset() { - return inlineAtomOffset(pic); - } - - static int32 inlineAtomJump(ic::PICInfo &pic) { -#if defined JS_NUNBOX32 - return GETELEM_INLINE_ATOM_JUMP; -#elif defined JS_PUNBOX64 - return inlineAtomOffset(pic) + GETELEM_INLINE_ATOM_JUMP; -#endif - } - - inline int32 inlineAtomJump() { - return inlineAtomJump(pic); - } - - public: - GetElemCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSString *id, - VoidStub stub) - : PICStubCompiler("getelem", f, script, pic), obj(obj), id(id), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)), - lastStubSecondShapeGuard(pic.secondShapeGuard) - {} - - static void reset(ic::PICInfo &pic) - { - JS_ASSERT(pic.kind == ic::PICInfo::GETELEM); - - RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic))); - - /* Only the shape needs to be patched to fail -- atom jump will never be taken. */ - repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( - pic.shapeGuard + inlineShapeOffset(pic)), - int32(JSObjectMap::INVALID_SHAPE)); - repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineShapeJump(pic)), - pic.slowPathStart); - repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineAtomJump(pic)), - pic.slowPathStart); - - RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - - FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetElem)); - repatcher.relink(pic.slowPathCall, target); - } - - bool patchInline(JSObject *holder, const Shape *shape) - { - spew("patch", "inline"); - PICRepatchBuffer repatcher(pic, pic.fastPathStart); - - int32 offset; - if (!holder->hasSlotsArray()) { - JSC::CodeLocationInstruction istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad()); - repatcher.repatchLoadPtrToLEA(istr); - - // - // We've patched | mov dslots, [obj + DSLOTS_OFFSET] - // To: | lea fslots, [obj + DSLOTS_OFFSET] - // - // Because the offset is wrong, it's necessary to correct it - // below. - // - int32 diff = int32(JSObject::getFixedSlotOffset(0)) - int32(offsetof(JSObject, slots)); - JS_ASSERT(diff != 0); - offset = (int32(shape->slot) * sizeof(Value)) + diff; - } else { - offset = shape->slot * sizeof(Value); - } - - uint32 shapeOffset = pic.shapeGuard + inlineShapeOffset(); - repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffset), obj->shape()); - uint32 idOffset = pic.shapeGuard + inlineAtomOffset(); - repatcher.repatch(pic.fastPathStart.dataLabelPtrAtOffset(idOffset), id); -#if defined JS_NUNBOX32 - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_TYPE_LOAD), offset + 4); - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_DATA_LOAD), offset); -#elif defined JS_PUNBOX64 - repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getelem.inlineValueOffset), offset); -#endif - pic.inlinePathPatched = true; - - return true; - } - - void patchPreviousToHere(PICRepatchBuffer &repatcher, CodeLocationLabel cs) - { - // Patch either the inline fast path or a generated stub. The stub - // omits the prefix of the inline fast path that loads the shape, so - // the offsets are different. - int shapeGuardJumpOffset; - int atomGuardJumpOffset; - if (pic.stubsGenerated) { -#if defined JS_NUNBOX32 - shapeGuardJumpOffset = GETELEM_STUB_SHAPE_JUMP; -#elif defined JS_PUNBOX64 - shapeGuardJumpOffset = pic.labels.getelem.stubShapeJump; -#endif - atomGuardJumpOffset = GETELEM_STUB_ATOM_JUMP; - } else { - shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump(); - atomGuardJumpOffset = pic.shapeGuard + inlineAtomJump(); - } - repatcher.relink(shapeGuardJumpOffset, cs); - repatcher.relink(atomGuardJumpOffset, cs); - if (lastStubSecondShapeGuard) - repatcher.relink(lastStubSecondShapeGuard, cs); - } - - bool generateStub(JSObject *holder, const Shape *shape) - { - JS_ASSERT(pic.u.get.idReg != pic.shapeReg); - Vector shapeMismatches(cx); - - Assembler masm; - - if (pic.objNeedsRemat()) { - masm.rematPayload(pic.objRemat(), pic.objReg); - pic.u.get.objNeedsRemat = false; - } - - if (pic.shapeNeedsRemat()) { - masm.loadShape(pic.objReg, pic.shapeReg); - pic.shapeRegHasBaseShape = true; - } - - Label start = masm.label(); - Jump atomGuard = masm.branchPtr(Assembler::NotEqual, pic.u.get.idReg, ImmPtr(id)); - DBGLABEL(dbgStubAtomJump); - Jump shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(obj->shape())); - -#if (defined JS_NUNBOX32 && defined DEBUG) || defined JS_PUNBOX64 - Label stubShapeJump = masm.label(); -#endif - - JS_ASSERT(masm.differenceBetween(start, dbgStubAtomJump) == GETELEM_STUB_ATOM_JUMP); -#if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(start, stubShapeJump) == GETELEM_STUB_SHAPE_JUMP); -#endif - - if (!(shapeMismatches.append(shapeGuard) && shapeMismatches.append(atomGuard))) - return false; - - if (obj != holder) { - // Emit code that walks the prototype chain. - JSObject *tempObj = obj; - Address proto(pic.objReg, offsetof(JSObject, proto)); - do { - tempObj = tempObj->getProto(); - // FIXME: we should find out why this condition occurs. It is probably - // related to PICs on globals. - if (!tempObj) - return disable("null object in prototype chain"); - JS_ASSERT(tempObj); - - /* - * If there is a non-native along the prototype chain the shape is technically - * invalid. - */ - if (!tempObj->isNative()) - return disable("non-JS-native in prototype chain"); - - masm.loadPtr(proto, pic.objReg); - pic.shapeRegHasBaseShape = false; - pic.u.get.objNeedsRemat = true; - - Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); - if (!shapeMismatches.append(j)) - return false; - } while (tempObj != holder); - - // Load the shape out of the holder and check it. - masm.loadShape(pic.objReg, pic.shapeReg); - Jump j = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg, - Imm32(holder->shape())); - if (!shapeMismatches.append(j)) - return false; - pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start); - } else { - JS_ASSERT(holder->isNative()); /* Precondition: already checked. */ - pic.secondShapeGuard = 0; - } - - /* Load the value out of the object. */ - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, !holder->hasSlotsArray(), - pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } - Jump done = masm.jump(); - - PICLinker buffer(cx, pic); - if (!buffer.init(masm)) - return false; - - // The guard exit jumps to the original slow case. - for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj) - buffer.link(*pj, pic.slowPathStart); - - // The final exit jumps to the store-back in the inline stub. - buffer.link(done, pic.fastPathRejoin); - CodeLocationLabel cs = buffer.finalizeCodeAddendum(); -#if DEBUG - char *chars = js_DeflateString(cx, id->chars(), id->length()); - JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n", - type, cs.executableAddress(), id, chars, holder->shape(), script->filename, - js_FramePCToLineNumber(cx, f.fp())); - cx->free(chars); -#endif - - PICRepatchBuffer repatcher(pic, pic.lastPathStart()); - patchPreviousToHere(repatcher, cs); - - pic.stubsGenerated++; - pic.lastStubStart = buffer.locationOf(start); - -#if defined JS_PUNBOX64 - pic.labels.getelem.stubShapeJump = masm.differenceBetween(start, stubShapeJump); - JS_ASSERT(pic.labels.getelem.stubShapeJump == masm.differenceBetween(start, stubShapeJump)); -#endif - - if (pic.stubsGenerated == MAX_PIC_STUBS) - disable("max stubs reached"); - if (obj->isDenseArray()) - disable("dense array"); - - return true; - } - - bool update() - { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } - - JSAtom *atom = js_AtomizeString(cx, id, 0); - if (!atom) - return false; - JSObject *holder; - JSProperty *prop; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - if (!prop) - return disable("lookup failed"); - - if (!obj->isNative()) - return disable("non-native obj"); - if (!holder->isNative()) - return disable("non-native holder"); - - const Shape *shape = (const Shape *)prop; - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); - - if (obj == holder && !pic.inlinePathPatched) - return patchInline(holder, shape); - - return generateStub(holder, shape); - } - - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); + return generateStub(getprop.holder, getprop.shape); } }; @@ -1507,25 +1162,17 @@ class ScopeNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; - void *stub; - JSObject *obj; - JSObject *holder; - JSProperty *prop; - const Shape *shape; + GetPropertyHelper getprop; public: ScopeNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("name", f, script, pic), scopeChain(scopeChain), atom(atom), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)), obj(NULL), holder(NULL), prop(NULL) + : PICStubCompiler("name", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + scopeChain(scopeChain), atom(atom), + getprop(f.cx, NULL, atom, *this) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); @@ -1540,16 +1187,16 @@ class ScopeNameCompiler : public PICStubCompiler typedef Vector JumpList; - bool walkScopeChain(Assembler &masm, JumpList &fails, bool &found) + LookupStatus walkScopeChain(Assembler &masm, JumpList &fails) { /* Walk the scope chain. */ JSObject *tobj = scopeChain; /* For GETXPROP, we'll never enter this loop. */ - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == holder); - JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, obj == tobj); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, tobj && tobj == getprop.holder); + JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, getprop.obj == tobj); - while (tobj && tobj != holder) { + while (tobj && tobj != getprop.holder) { if (!js_IsCacheableNonGlobalScope(tobj)) return disable("non-cacheable scope chain object"); JS_ASSERT(tobj->isNative()); @@ -1558,14 +1205,14 @@ class ScopeNameCompiler : public PICStubCompiler /* scopeChain will never be NULL, but parents can be NULL. */ Jump j = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(j)) - return false; + return error(); } /* Guard on intervening shapes. */ masm.loadShape(pic.objReg, pic.shapeReg); Jump j = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); if (!fails.append(j)) - return false; + return error(); /* Load the next link in the scope chain. */ Address parent(pic.objReg, offsetof(JSObject, parent)); @@ -1574,12 +1221,13 @@ class ScopeNameCompiler : public PICStubCompiler tobj = tobj->getParent(); } - found = tobj == holder; + if (tobj != getprop.holder) + return disable("scope chain walk terminated early"); - return true; + return Lookup_Cacheable; } - bool generateGlobalStub() + LookupStatus generateGlobalStub(JSObject *obj) { Assembler masm; JumpList fails(cx); @@ -1588,29 +1236,21 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == holder); - JS_ASSERT(holder == scopeChain->getGlobal()); + JS_ASSERT(obj == getprop.holder); + JS_ASSERT(getprop.holder == scopeChain->getGlobal()); - bool found = false; - if (!walkScopeChain(masm, fails, found)) - return false; - if (!found) - return disable("scope chain walk terminated early"); + 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) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); - - if (!shape->isMethod()) { - masm.loadSlot(pic.objReg, pic.objReg, shape->slot, false, pic.shapeReg, pic.objReg); - } else { - masm.loadValueAsComponents(ObjectValue(shape->methodObject()), pic.shapeReg, - pic.objReg); - } + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); + masm.loadObjProp(obj, pic.objReg, getprop.shape, pic.shapeReg, pic.objReg); Jump done = masm.jump(); // All failures flow to here, so there is a common point to patch. @@ -1627,7 +1267,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1644,7 +1284,7 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } enum CallObjPropKind { @@ -1652,7 +1292,7 @@ class ScopeNameCompiler : public PICStubCompiler VAR }; - bool generateCallStub() + LookupStatus generateCallStub(JSObject *obj) { Assembler masm; Vector fails(cx); @@ -1661,10 +1301,11 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.kind == ic::PICInfo::NAME) masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg); - JS_ASSERT(obj == holder); - JS_ASSERT(holder != scopeChain->getGlobal()); + JS_ASSERT(obj == getprop.holder); + JS_ASSERT(getprop.holder != scopeChain->getGlobal()); CallObjPropKind kind; + const Shape *shape = getprop.shape; if (shape->getterOp() == js_GetCallArg) { kind = ARG; } else if (shape->getterOp() == js_GetCallVar) { @@ -1673,23 +1314,21 @@ class ScopeNameCompiler : public PICStubCompiler return disable("unhandled callobj sprop getter"); } - bool found = false; - if (!walkScopeChain(masm, fails, found)) - return false; - if (!found) - return disable("scope chain walk terminated early"); + 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) finalNull = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); masm.loadShape(pic.objReg, pic.shapeReg); - Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(holder->shape())); + Jump finalShape = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(getprop.holder->shape())); /* Get callobj's stack frame. */ masm.loadFunctionPrivate(pic.objReg, pic.shapeReg); - JSFunction *fun = holder->getCallObjCalleeFunction(); + JSFunction *fun = getprop.holder->getCallObjCalleeFunction(); uint16 slot = uint16(shape->shortid); Jump skipOver; @@ -1731,7 +1370,7 @@ class ScopeNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1747,67 +1386,59 @@ class ScopeNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } - bool updateForName() + LookupStatus updateForName() { - if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop)) - return false; + // |getprop.obj| is filled by bind() + LookupStatus status = getprop.bind(); + if (status != Lookup_Cacheable) + return status; - return update(); + return update(getprop.obj); } - bool updateForXName() + LookupStatus updateForXName() { - obj = scopeChain; + // |obj| and |getprop.obj| are NULL, but should be the given scopeChain. + getprop.obj = scopeChain; + LookupStatus status = getprop.lookup(); + if (status != Lookup_Cacheable) + return status; - if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop)) - return false; - - return update(); + return update(getprop.obj); } - bool update() + LookupStatus update(JSObject *obj) { - if (!pic.hit) { - spew("first hit", "nop"); - pic.hit = true; - return true; - } - - if (!prop) - return disable("property not found"); - if (!obj->isNative() || !holder->isNative()) - return disable("non-native scope object"); - if (obj != holder) + if (obj != getprop.holder) return disable("property is on proto of a scope object"); - - shape = (const Shape *)prop; if (obj->getClass() == &js_CallClass) - return generateCallStub(); + return generateCallStub(obj); - if (!shape->hasDefaultGetterOrIsMethod()) - return disable("getter"); - if (shape->isMethod() && !isCallOp()) - return disable("method valued shape"); - if (!shape->hasSlot()) - return disable("invalid slot"); + LookupStatus status = getprop.testForGet(); + if (status != Lookup_Cacheable) + return status; if (!obj->getParent()) - return generateGlobalStub(); + return generateGlobalStub(obj); return disable("scope object not handled yet"); } bool retrieve(Value *vp) { - if (prop && (!obj->isNative() || !holder->isNative())) { + JSObject *obj = getprop.obj; + JSObject *holder = getprop.holder; + const Shape *shape = getprop.shape; + + if (shape && (!obj->isNative() || !holder->isNative())) { if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp)) return false; } else { - if (!prop) { + if (!shape) { /* Kludge to allow (typeof foo == "undefined") tests. */ disable("property not found"); if (pic.kind == ic::PICInfo::NAME) { @@ -1820,12 +1451,10 @@ class ScopeNameCompiler : public PICStubCompiler ReportAtomNotDefined(cx, atom); return false; } - const Shape *shape = (const Shape *)prop; JSObject *normalized = obj; if (obj->getClass() == &js_WithClass && !shape->hasDefaultGetter()) normalized = js_UnwrapWithObject(cx, obj); - NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, - return false); + NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); } return true; @@ -1836,7 +1465,6 @@ class BindNameCompiler : public PICStubCompiler { JSObject *scopeChain; JSAtom *atom; - void *stub; static int32 inlineJumpOffset(ic::PICInfo &pic) { #if defined JS_NUNBOX32 @@ -1853,15 +1481,10 @@ class BindNameCompiler : public PICStubCompiler public: BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, JSAtom *atom, VoidStubPIC stub) - : PICStubCompiler("bind", f, script, pic), scopeChain(scopeChain), atom(atom), - stub(JS_FUNC_TO_DATA_PTR(void *, stub)) + : PICStubCompiler("bind", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + scopeChain(scopeChain), atom(atom) { } - bool disable(const char *reason) - { - return PICStubCompiler::disable(reason, stub); - } - static void reset(ic::PICInfo &pic) { PICRepatchBuffer repatcher(pic, pic.fastPathStart); @@ -1872,7 +1495,7 @@ class BindNameCompiler : public PICStubCompiler repatcher2.relink(pic.slowPathCall, target); } - bool generateStub(JSObject *obj) + LookupStatus generateStub(JSObject *obj) { Assembler masm; js::Vector fails(cx); @@ -1892,7 +1515,7 @@ class BindNameCompiler : public PICStubCompiler masm.loadPtr(parent, pic.objReg); Jump nullTest = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg); if (!fails.append(nullTest)) - return false; + return error(); masm.loadShape(pic.objReg, pic.shapeReg); Jump shapeTest = masm.branch32(Assembler::NotEqual, pic.shapeReg, Imm32(tobj->shape())); @@ -1915,7 +1538,7 @@ class BindNameCompiler : public PICStubCompiler PICLinker buffer(cx, pic); if (!buffer.init(masm)) - return false; + return error(); buffer.link(failJump, pic.slowPathStart); buffer.link(done, pic.fastPathRejoin); @@ -1934,7 +1557,7 @@ class BindNameCompiler : public PICStubCompiler if (pic.stubsGenerated == MAX_PIC_STUBS) disable("max stubs reached"); - return true; + return Lookup_Cacheable; } JSObject *update() @@ -1951,7 +1574,8 @@ class BindNameCompiler : public PICStubCompiler return obj; } - if (!generateStub(obj)) + LookupStatus status = generateStub(obj); + if (status == Lookup_Error) return NULL; return obj; @@ -1985,10 +1609,9 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (atom == f.cx->runtime->atomState.lengthAtom) { if (f.regs.sp[-1].isString()) { GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledLengthIC); - if (!cc.generateStringLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateStringLengthStub(); + if (status == Lookup_Error) THROW(); - } JSString *str = f.regs.sp[-1].toString(); f.regs.sp[-1].setInt32(str->length()); return; @@ -1997,16 +1620,14 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (obj->isArray() || (obj->isArguments() && !obj->isArgsLengthOverridden())) { GetPropCompiler cc(f, script, obj, *pic, NULL, DisabledLengthIC); if (obj->isArray()) { - if (!cc.generateArrayLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateArrayLengthStub(); + if (status == Lookup_Error) THROW(); - } f.regs.sp[-1].setNumber(obj->getArrayLength()); } else if (obj->isArguments()) { - if (!cc.generateArgsLengthStub()) { - cc.disable("error"); + LookupStatus status = cc.generateArgsLengthStub(); + if (status == Lookup_Error) THROW(); - } f.regs.sp[-1].setInt32(int32_t(obj->getArgsInitialLength())); } return; @@ -2019,7 +1640,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (!obj) THROW(); - if (pic->shouldGenerate()) { + if (pic->shouldUpdate(f.cx)) { VoidStubPIC stub = pic->usePropCache ? DisabledGetPropIC : DisabledGetPropICNoCache; @@ -2036,35 +1657,6 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) f.regs.sp[-1] = v; } -void JS_FASTCALL -ic::GetElem(VMFrame &f, ic::PICInfo *pic) -{ - JSScript *script = f.fp()->script(); - - JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]); - if (!obj) - THROW(); - - Value idval = f.regs.sp[-1]; - JS_ASSERT(idval.isString()); - JSString *id = idval.toString(); - if (pic->shouldGenerate()) { - GetElemCompiler cc(f, script, obj, *pic, id, stubs::GetElem); - if (!cc.update()) { - cc.disable("error"); - THROW(); - } - } - - JSAtom *atom = js_AtomizeString(f.cx, id, 0); - if (!atom) - THROW(); - Value v; - if (!obj->getProperty(f.cx, ATOM_TO_JSID(atom), &v)) - THROW(); - f.regs.sp[-2] = v; -} - template static void JS_FASTCALL DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic) @@ -2089,6 +1681,10 @@ 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); + // // Important: We update the PIC before looking up the property so that the // PIC is updated only if the property already exists. The PIC doesn't try @@ -2096,16 +1692,12 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic) // // Also note, we can't use SetName for PROPINC PICs because the property // cache can't handle a GET and SET from the same scripted PC. - // + if (pic->shouldUpdate(f.cx)) { - VoidStubPIC stub = pic->usePropCache - ? STRICT_VARIANT(DisabledSetPropIC) - : STRICT_VARIANT(DisabledSetPropICNoCache); - - SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); - if (!cc.update()) { - cc.disable("error"); - THROW(); + SetPropCompiler cc(f, script, obj, *pic, pic->atom, stub); + LookupStatus status = cc.update(); + if (status == Lookup_Error) + THROW(); } Value rval = f.regs.sp[-1]; @@ -2154,8 +1746,6 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject()); Value rval; - bool usePIC = true; - PropertyCacheEntry *entry; JSObject *obj2; JSAtom *atom; @@ -2208,22 +1798,18 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) } GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, DisabledCallPropIC); - if (usePIC) { - if (lval.isObject()) { - if (!cc.update()) { - cc.disable("error"); + if (lval.isObject()) { + if (pic->shouldUpdate(cx)) { + LookupStatus status = cc.update(); + if (status == Lookup_Error) THROW(); - } - } else if (lval.isString()) { - if (!cc.generateStringCallStub()) { - cc.disable("error"); - THROW(); - } - } else { - cc.disable("non-string primitive"); } + } else if (lval.isString()) { + LookupStatus status = cc.generateStringCallStub(); + if (status == Lookup_Error) + THROW(); } else { - cc.disable("wrapped primitive"); + cc.disable("non-string primitive"); } #if JS_HAS_NO_SUCH_METHOD @@ -2257,10 +1843,9 @@ ic::XName(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, DisabledXNameIC); - if (!cc.updateForXName()) { - cc.disable("error"); + LookupStatus status = cc.updateForXName(); + if (status == Lookup_Error) THROW(); - } Value rval; if (!cc.retrieve(&rval)) @@ -2275,10 +1860,9 @@ ic::Name(VMFrame &f, ic::PICInfo *pic) ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledNameIC); - if (!cc.updateForName()) { - cc.disable("error"); + LookupStatus status = cc.updateForName(); + if (status == Lookup_Error) THROW(); - } Value rval; if (!cc.retrieve(&rval)) @@ -2317,6 +1901,308 @@ ic::BindName(VMFrame &f, ic::PICInfo *pic) 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, + js_FramePCToLineNumber(cx, cx->fp())); +#endif +} + +LookupStatus +BaseIC::disable(JSContext *cx, const char *reason, void *stub) +{ + spew(cx, "disabled", reason); + RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + repatcher.relink(slowPathCall, FunctionPtr(stub)); + return Lookup_Uncacheable; +} + +bool +BaseIC::shouldUpdate(JSContext *cx) +{ + if (!hit) { + hit = true; + spew(cx, "ignored", "first hit"); + return false; + } + JS_ASSERT(stubsGenerated < MAX_PIC_STUBS); + return true; +} + +static void JS_FASTCALL +DisabledGetElem(VMFrame &f, ic::GetElementIC *ic) +{ + stubs::GetElem(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; + 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; +} + +void +GetElementIC::purge() +{ + if (inlineTypeGuardPatched || inlineClaspGuardPatched) { + RepatchBuffer repatcher(fastPathStart.executableAddress(), INLINE_PATH_LENGTH); + + // Repatch the inline jumps. + if (inlineTypeGuardPatched) + repatcher.relink(fastPathStart.jumpAtOffset(inlineTypeGuard), slowPathStart); + if (inlineClaspGuardPatched) + repatcher.relink(fastPathStart.jumpAtOffset(inlineClaspGuard), slowPathStart); + } + + if (slowCallPatched) { + RepatchBuffer repatcher(slowPathStart.executableAddress(), INLINE_PATH_LENGTH); + repatcher.relink(slowPathCall, FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::GetElement))); + } + + reset(); +} + +LookupStatus +GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp) +{ + JS_ASSERT(v.isString()); + + GetPropertyHelper getprop(cx, obj, JSID_TO_ATOM(id), *this); + LookupStatus status = getprop.lookupAndTest(); + if (status != Lookup_Cacheable) + return status; + + Assembler masm; + + // Guard on the string's type and identity. + MaybeJump atomTypeGuard; + if (hasInlineTypeGuard() && !inlineTypeGuardPatched) { + // We link all string-key dependent stubs together, and store the + // first set of guards in the IC, separately, from int-key dependent + // stubs. As long as we guarantee that the first string-key dependent + // stub guards on the key type, then all other string-key stubs can + // omit the guard. + JS_ASSERT(!idRemat.isTypeKnown()); + atomTypeGuard = masm.testString(Assembler::NotEqual, typeReg); + } else { + // If there was no inline type guard, then a string type is guaranteed. + // Otherwise, we are guaranteed the type has already been checked, via + // the comment above. + JS_ASSERT_IF(!hasInlineTypeGuard(), idRemat.knownType() == JSVAL_TYPE_STRING); + } + + // Reify the shape before guards that could flow into shape guarding stubs. + if (!obj->isDenseArray() && !typeRegHasBaseShape) { + masm.loadShape(objReg, typeReg); + typeRegHasBaseShape = true; + } + + MaybeJump atomIdGuard; + if (!idRemat.isConstant()) + atomIdGuard = masm.branchPtr(Assembler::NotEqual, idRemat.dataReg(), ImmPtr(v.toString())); + + // Guard on the base shape (or in the dense array case, the clasp). + Jump shapeGuard; + if (obj->isDenseArray()) { + shapeGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass()); + } else { + shapeGuard = masm.branch32(Assembler::NotEqual, typeReg, Imm32(obj->shape())); + } + + // Guard on the prototype, if applicable. + MaybeJump protoGuard; + JSObject *holder = getprop.holder; + RegisterID holderReg = objReg; + if (obj != holder) { + // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it. + holderReg = typeReg; + masm.move(ImmPtr(holder), holderReg); + typeRegHasBaseShape = false; + + // Guard on the holder's shape. + protoGuard = masm.guardShape(holderReg, holder); + } + + // 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)) + return error(cx); + + // Patch all guards. + buffer.maybeLink(atomIdGuard, slowPathStart); + 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 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()) { + // A type guard is present in the inline path, and this is the + // first string stub, so patch it now. + JS_ASSERT(!inlineTypeGuardPatched); + JS_ASSERT(atomTypeGuard.isSet()); + + repatcher.relink(inlineTypeGuard, cs); + inlineTypeGuardPatched = true; + } + + if (shouldPatchUnconditionalClaspGuard()) { + // The clasp guard is unconditional, meaning there is no type + // check. This is the first stub, so it has to be patched. Note + // that it is wrong to patch the inline clasp guard otherwise, + // because it follows an integer-id guard. + JS_ASSERT(!hasInlineTypeGuard()); + + repatcher.relink(inlineClaspGuard, cs); + inlineClaspGuardPatched = true; + } + } + + // If there were previous stub guards, patch them now. + if (hasLastStringStub) { + PICRepatchBuffer repatcher(*this, lastStringStub); + if (atomGuard) + repatcher.relink(atomGuard, cs); + repatcher.relink(firstShapeGuard, cs); + if (secondShapeGuard) + repatcher.relink(secondShapeGuard, cs); + } + + // Update state. + hasLastStringStub = true; + lastStringStub = cs; + if (atomIdGuard.isSet()) { + atomGuard = buffer.locationOf(atomIdGuard.get()) - cs; + JS_ASSERT(atomGuard == buffer.locationOf(atomIdGuard.get()) - cs); + JS_ASSERT(atomGuard); + } else { + atomGuard = 0; + } + if (protoGuard.isSet()) { + secondShapeGuard = buffer.locationOf(protoGuard.get()) - cs; + JS_ASSERT(secondShapeGuard == buffer.locationOf(protoGuard.get()) - cs); + JS_ASSERT(secondShapeGuard); + } else { + secondShapeGuard = 0; + } + firstShapeGuard = buffer.locationOf(shapeGuard) - cs; + JS_ASSERT(firstShapeGuard == buffer.locationOf(shapeGuard) - cs); + JS_ASSERT(firstShapeGuard); + + stubsGenerated++; + + if (stubsGenerated == MAX_GETELEM_IC_STUBS) + disable(cx, "max stubs reached"); + + // Finally, fetch the value to avoid redoing the property lookup. + if (shape->isMethod()) + *vp = ObjectValue(shape->methodObject()); + else + *vp = holder->getSlot(shape->slot); + + return Lookup_Cacheable; +} + +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::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); + return; + } + + JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]); + if (!obj) + THROW(); + + Value idval = f.regs.sp[-1]; + + 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)) + THROW(); + } + + if (ic->shouldUpdate(cx)) { +#ifdef DEBUG + f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC); +#endif + LookupStatus status = ic->update(cx, obj, 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()); + return; + } + } + + if (!obj->getProperty(cx, id, &f.regs.sp[-2])) + THROW(); +} + void JITScript::purgePICs() { @@ -2338,15 +2224,15 @@ JITScript::purgePICs() case ic::PICInfo::GET: GetPropCompiler::reset(pic); break; - case ic::PICInfo::GETELEM: - GetElemCompiler::reset(pic); - break; default: JS_NOT_REACHED("Unhandled PIC kind"); break; } pic.reset(); } + + for (uint32 i = 0; i < nGetElems; i++) + getElems[i].purge(); } void diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 774a771047d..48bc8abc918 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -37,7 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ -#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT && defined JS_POLYIC +#if !defined jsjaeger_poly_ic_h__ && defined JS_METHODJIT #define jsjaeger_poly_ic_h__ #include "jscntxt.h" @@ -46,7 +46,9 @@ #include "assembler/assembler/MacroAssembler.h" #include "assembler/assembler/CodeLocation.h" #include "methodjit/MethodJIT.h" +#include "BaseAssembler.h" #include "RematInfo.h" +#include "BaseCompiler.h" namespace js { namespace mjit { @@ -54,6 +56,7 @@ namespace ic { /* Maximum number of stubs for a given callsite. */ static const uint32 MAX_PIC_STUBS = 16; +static const uint32 MAX_GETELEM_IC_STUBS = 17; /* SetPropCompiler */ #if defined JS_CPU_X86 @@ -159,26 +162,6 @@ union PICLabels { int32 stubShapeJump : 8; } getprop; - /* GetElemCompiler */ - struct { - /* Offset from storeBack to beginning of 'mov dslots, addr' */ - int32 dslotsLoadOffset : 8; - - /* Offset from shapeGuard to end of shape comparison. */ - int32 inlineShapeOffset : 8; - - /* Offset from shapeGuard to end of atom comparison. */ - int32 inlineAtomOffset : 8; - - /* Offset from storeBack to end of value load. */ - int32 inlineValueOffset : 8; - - /* Offset from lastStubStart to end of shape jump. */ - // TODO: We can redefine the location of lastStubStart to be - // after the jump -- at which point this is always 0. - int32 stubShapeJump : 8; - } getelem; - /* BindNameCompiler */ struct { /* Offset from shapeGuard to end of shape jump. */ @@ -187,21 +170,27 @@ union PICLabels { }; #endif -struct BaseIC { +enum LookupStatus { + Lookup_Error = 0, + Lookup_Uncacheable, + Lookup_Cacheable +}; + +struct BaseIC : public MacroAssemblerTypedefs { // Address of inline fast-path. - JSC::CodeLocationLabel fastPathStart; + CodeLocationLabel fastPathStart; // Address to rejoin to the fast-path. - JSC::CodeLocationLabel fastPathRejoin; + CodeLocationLabel fastPathRejoin; // Start of the slow path. - JSC::CodeLocationLabel slowPathStart; + CodeLocationLabel slowPathStart; // Slow path stub call. - JSC::CodeLocationCall slowPathCall; + CodeLocationCall slowPathCall; // Address of the start of the last generated stub, if any. - JSC::CodeLocationLabel lastStubStart; + CodeLocationLabel lastStubStart; typedef Vector ExecPoolVector; @@ -210,16 +199,25 @@ struct BaseIC { // Return the start address of the last path in this PIC, which is the // inline path if no stubs have been generated yet. - JSC::CodeLocationLabel lastPathStart() { + CodeLocationLabel lastPathStart() { return stubsGenerated > 0 ? lastStubStart : fastPathStart; } // Whether or not the callsite has been hit at least once. bool hit : 1; + bool slowCallPatched : 1; // Number of stubs generated. uint32 stubsGenerated : 5; + // Offset from start of stub to jump target of second shape guard as Nitro + // asm data location. This is 0 if there is only one shape guard in the + // last stub. + int secondShapeGuard : 11; + + // Opcode this was compiled for. + JSOp op : 8; + // Release ExecutablePools referred to by this PIC. void releasePools() { for (JSC::ExecutablePool **pExecPool = execPools.begin(); @@ -229,17 +227,122 @@ struct BaseIC { } } + void init() { + new (&execPools) ExecPoolVector(SystemAllocPolicy()); + } + void finish() { + releasePools(); + this->~BaseIC(); + } + void reset() { hit = false; + slowCallPatched = false; stubsGenerated = 0; + secondShapeGuard = 0; releasePools(); execPools.clear(); } + bool shouldUpdate(JSContext *cx); + void spew(JSContext *cx, const char *event, const char *reason); + LookupStatus disable(JSContext *cx, const char *reason, void *stub); + bool isCallOp(); +}; + +struct GetElementIC : public BaseIC { + // On stub entry: + // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is false, + // - typeReg contains the type of the |id| parameter. + // If hasInlineTypeCheck() is true, and inlineTypeCheckPatched is true, + // - typeReg contains the shape of |objReg| iff typeRegHasBaseShape + // is true. + // Otherwise, typeReg is garbage. + // + // On stub exit, typeReg must contain the type of the result value. + RegisterID typeReg : 5; + + // On stub entry, objReg contains the object pointer for the |obj| parameter. + // On stub exit, objReg must contain the payload of the result value. + RegisterID objReg : 5; + + // Offset from the fast path to the inline type check. + // This is only set if hasInlineTypeCheck() is true. + unsigned inlineTypeGuard : 8; + + // Offset from the fast path to the inline clasp guard. This is always + // set; if |id| is known to not be int32, then it's an unconditional + // jump to the slow path. + unsigned inlineClaspGuard : 8; + + // This is usable if hasInlineTypeGuard() returns true, which implies + // that a dense array fast path exists. The inline type guard serves as + // the head of the chain of all string-based element stubs. + bool inlineTypeGuardPatched : 1; + + // This is always usable, and specifies whether the inline clasp guard + // has been patched. If hasInlineTypeGuard() is true, it guards against + // a dense array, and guarantees the inline type guard has passed. + // Otherwise, there is no inline type guard, and the clasp guard is just + // an unconditional jump. + bool inlineClaspGuardPatched : 1; + + //////////////////////////////////////////// + // State for string-based property stubs. // + //////////////////////////////////////////// + + // True if typeReg is guaranteed to have the shape of objReg. + bool typeRegHasBaseShape : 1; + + // These offsets are used for string-key dependent stubs, such as named + // property accesses. They are separated from the int-key dependent stubs, + // in order to guarantee that the id type needs only one guard per type. + int atomGuard : 8; // optional, non-zero if present + int firstShapeGuard : 8; // always set + int secondShapeGuard : 8; // optional, non-zero if present + + bool hasLastStringStub : 1; + CodeLocationLabel lastStringStub; + + // A limited ValueRemat instance. It may contains either: + // 1) A constant, or + // 2) A known type and data reg, or + // 3) A data reg. + // The sync bits are not set, and the type reg is never set and should not + // be used, as it is encapsulated more accurately in |typeReg|. Also, note + // carefully that the data reg is immutable. + ValueRemat idRemat; + + bool hasInlineTypeGuard() const { + return !idRemat.isTypeKnown(); + } + bool shouldPatchInlineTypeGuard() { + return hasInlineTypeGuard() && !inlineTypeGuardPatched; + } + bool shouldPatchUnconditionalClaspGuard() { + return !hasInlineTypeGuard() && !inlineClaspGuardPatched; + } + + void init() { + BaseIC::init(); + reset(); + } + void reset() { + BaseIC::reset(); + inlineTypeGuardPatched = false; + inlineClaspGuardPatched = false; + typeRegHasBaseShape = false; + hasLastStringStub = false; + } + void purge(); + LookupStatus update(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp); + LookupStatus attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid id, + Value *vp); + LookupStatus disable(JSContext *cx, const char *reason); + LookupStatus error(JSContext *cx); + bool shouldUpdate(JSContext *cx); }; struct PICInfo : public BaseIC { - typedef JSC::MacroAssembler::RegisterID RegisterID; - // Operation this is a PIC for. enum Kind #ifdef _MSC_VER @@ -252,7 +355,6 @@ struct PICInfo : public BaseIC { SETMETHOD, // JSOP_SETMETHOD NAME, // JSOP_NAME BIND, // JSOP_BINDNAME - GETELEM, // JSOP_GETELEM XNAME // JSOP_GETXPROP }; @@ -263,20 +365,10 @@ struct PICInfo : public BaseIC { // Reverse offset from slowPathStart to the type check slow path. int32 typeCheckOffset; - - // Remat info for the object reg. - int32 objRemat : MIN_STATE_REMAT_BITS; - bool objNeedsRemat : 1; - RegisterID idReg : 5; // only used in GETELEM PICs. } get; ValueRemat vr; } u; - // Offset from start of stub to jump target of second shape guard as Nitro - // asm data location. This is 0 if there is only one shape guard in the - // last stub. - int secondShapeGuard : 11; - Kind kind : 3; // True if register R holds the base object shape along exits from the @@ -299,7 +391,7 @@ struct PICInfo : public BaseIC { return kind == SET || kind == SETMETHOD; } inline bool isGet() const { - return kind == GET || kind == CALL || kind == GETELEM; + return kind == GET || kind == CALL; } inline RegisterID typeReg() { JS_ASSERT(isGet()); @@ -309,14 +401,6 @@ struct PICInfo : public BaseIC { JS_ASSERT(isGet()); return u.get.hasTypeCheck; } - inline const StateRemat objRemat() const { - JS_ASSERT(isGet()); - return StateRemat::FromInt32(u.get.objRemat); - } - inline bool objNeedsRemat() { - JS_ASSERT(isGet()); - return u.get.objNeedsRemat; - } inline bool shapeNeedsRemat() { return !shapeRegHasBaseShape; } @@ -325,12 +409,6 @@ struct PICInfo : public BaseIC { return !hasTypeCheck(); } - inline void setObjRemat(const StateRemat &sr) { - JS_ASSERT(isGet()); - u.get.objRemat = sr.toInt32(); - JS_ASSERT(u.get.objRemat == sr.toInt32()); - } - #if defined JS_CPU_X64 // Required labels for platform-specific patching. PICLabels labels; @@ -342,30 +420,30 @@ struct PICInfo : public BaseIC { // Index into the script's atom table. JSAtom *atom; - bool shouldGenerate() { - return stubsGenerated < MAX_PIC_STUBS || !inlinePathPatched; + void init() { + BaseIC::init(); + reset(); } // Reset the data members to the state of a fresh PIC before any patching // or stub generation was done. void reset() { inlinePathPatched = false; - if (kind == GET || kind == CALL || kind == GETELEM) - u.get.objNeedsRemat = false; - secondShapeGuard = 0; shapeRegHasBaseShape = true; BaseIC::reset(); } }; +#ifdef JS_POLYIC void PurgePICs(JSContext *cx, JSScript *script); void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *); -void JS_FASTCALL GetElem(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 *); +#endif } /* namespace ic */ } /* namespace mjit */ diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index eabe3d9f3ff..0e14f5b3b90 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -93,16 +93,10 @@ class PunboxAssembler : public JSC::MacroAssembler return address; } - void loadSlot(RegisterID obj, RegisterID clobber, uint32 slot, bool inlineAccess, - RegisterID type, RegisterID data) { - JS_ASSERT(type != data); - Address address(obj, JSObject::getFixedSlotOffset(slot)); - if (!inlineAccess) { - loadPtr(Address(obj, offsetof(JSObject, slots)), clobber); - address = Address(clobber, slot * sizeof(Value)); - } - - loadValueAsComponents(address, type, data); + void loadInlineSlot(RegisterID objReg, uint32 slot, + RegisterID typeReg, RegisterID dataReg) { + Address address(objReg, JSObject::getFixedSlotOffset(slot)); + loadValueAsComponents(address, typeReg, dataReg); } template diff --git a/js/src/methodjit/StubCompiler.h b/js/src/methodjit/StubCompiler.h index 9dcf1784a1b..9d3099ac83c 100644 --- a/js/src/methodjit/StubCompiler.h +++ b/js/src/methodjit/StubCompiler.h @@ -127,6 +127,7 @@ class StubCompiler STUB_CALL_TYPE(VoidStubPC); #ifdef JS_POLYIC STUB_CALL_TYPE(VoidStubPIC); + STUB_CALL_TYPE(VoidStubGetElemIC); #endif #ifdef JS_MONOIC STUB_CALL_TYPE(VoidStubMIC); From ddabc8f166339522baeb8f0330aa17f90195dc64 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 28 Oct 2010 13:53:54 -0700 Subject: [PATCH 102/263] Fix Windows orange. --- js/src/methodjit/PolyIC.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 48bc8abc918..dad2448aedd 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -216,7 +216,7 @@ struct BaseIC : public MacroAssemblerTypedefs { int secondShapeGuard : 11; // Opcode this was compiled for. - JSOp op : 8; + JSOp op : 9; // Release ExecutablePools referred to by this PIC. void releasePools() { From c5760d4a28e9b86cfe619a5a6fc85c3f67c1509c Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 28 Oct 2010 14:33:32 -0700 Subject: [PATCH 103/263] Special case object lookup lambda in String.replace, bug 605317. r=jorendorff --- js/src/jit-test/tests/basic/testReplaceMap.js | 27 ++++++ js/src/jsatom.cpp | 41 ++------ js/src/jsobj.cpp | 25 +++-- js/src/jsstr.cpp | 95 ++++++++++++++++++- js/src/jsstr.h | 2 + js/src/jsstrinlines.h | 37 ++++++++ 6 files changed, 180 insertions(+), 47 deletions(-) create mode 100644 js/src/jit-test/tests/basic/testReplaceMap.js diff --git a/js/src/jit-test/tests/basic/testReplaceMap.js b/js/src/jit-test/tests/basic/testReplaceMap.js new file mode 100644 index 00000000000..929f52ce8e3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testReplaceMap.js @@ -0,0 +1,27 @@ + +// String.replace on functions returning hashmap elements. + +function first() { + var arr = {a: "hello", b: "there"}; + var s = 'a|b'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(first(), "hello|there"); + +function second() { + var arr = {a: "hello", c: "there"}; + var s = 'a|b|c'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(second(), "hello|undefined|there"); + +Object.defineProperty(Object.prototype, "b", {get: function() { return "what"; }}); + +assertEq(second(), "hello|what|there"); + +function third() { + var arr = {a: "hello", b: {toString: function() { arr = {}; return "three"; }}, c: "there"}; + var s = 'a|b|c'; + return s.replace(/[a-z]/g, function(a) { return arr[a]; }, 'g'); +} +assertEq(third(), "hello|three|undefined"); diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 88592c0fd7d..0d2fb111ce5 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -463,42 +463,13 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) if (str->isAtomized()) return STRING_TO_ATOM(str); - size_t length = str->length(); - if (length == 1) { - jschar c = str->chars()[0]; - if (c < UNIT_STRING_LIMIT) - return STRING_TO_ATOM(JSString::unitString(c)); - } + const jschar *chars; + size_t length; + str->getCharsAndLength(chars, length); - if (length == 2) { - jschar *chars = str->chars(); - if (JSString::fitsInSmallChar(chars[0]) && - JSString::fitsInSmallChar(chars[1])) { - return STRING_TO_ATOM(JSString::length2String(chars[0], chars[1])); - } - } - - /* - * Here we know that JSString::intStringTable covers only 256 (or at least - * not 1000 or more) chars. We rely on order here to resolve the unit vs. - * int string/length-2 string atom identity issue by giving priority to unit - * strings for "0" through "9" and length-2 strings for "10" through "99". - */ - JS_STATIC_ASSERT(INT_STRING_LIMIT <= 999); - if (length == 3) { - const jschar *chars = str->chars(); - - if ('1' <= chars[0] && chars[0] <= '9' && - '0' <= chars[1] && chars[1] <= '9' && - '0' <= chars[2] && chars[2] <= '9') { - jsint i = (chars[0] - '0') * 100 + - (chars[1] - '0') * 10 + - (chars[2] - '0'); - - if (jsuint(i) < INT_STRING_LIMIT) - return STRING_TO_ATOM(JSString::intString(i)); - } - } + JSString *staticStr = JSString::lookupStaticString(chars, length); + if (staticStr) + return STRING_TO_ATOM(staticStr); JSAtomState *state = &cx->runtime->atomState; AtomSet &atoms = state->atoms; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a5ee89518a9..c21d73ec623 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -4459,14 +4459,6 @@ error: // TRACE_2 jumps here on error. return false; } -JS_FRIEND_API(JSBool) -js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp) -{ - return js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, - objp, propp) >= 0; -} - #define SCOPE_DEPTH_ACCUM(bs,val) \ JS_SCOPE_DEPTH_METERING(JS_BASIC_STATS_ACCUM(bs, val)) @@ -4587,8 +4579,8 @@ static JS_ALWAYS_INLINE int js_LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp, JSProperty **propp) { - /* Convert string indices to integers if appropriate. */ - id = js_CheckForStringIndex(id); + /* We should not get string indices which aren't already integers here. */ + JS_ASSERT(id == js_CheckForStringIndex(id)); /* Search scopes starting with obj and following the prototype link. */ JSObject *start = obj; @@ -4636,10 +4628,23 @@ js_LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN fl return protoIndex; } +JS_FRIEND_API(JSBool) +js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, + JSProperty **propp) +{ + /* Convert string indices to integers if appropriate. */ + id = js_CheckForStringIndex(id); + + return js_LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp) >= 0; +} + int js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp, JSProperty **propp) { + /* Convert string indices to integers if appropriate. */ + id = js_CheckForStringIndex(id); + return js_LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp); } diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 721bdb3bf4a..40fa46a7160 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -81,6 +81,7 @@ #include "jsobjinlines.h" #include "jsregexpinlines.h" #include "jsstrinlines.h" +#include "jsautooplen.h" // generated headers last using namespace js; using namespace js::gc; @@ -1971,6 +1972,7 @@ struct ReplaceData JSString *str; /* 'this' parameter object as a string */ RegExpGuard g; /* regexp parameter object and private data */ JSObject *lambda; /* replacement function object or null */ + JSObject *elembase; /* object for function(a){return b[a]} replace */ JSString *repstr; /* replacement string */ jschar *dollar; /* null or pointer to first $ in repstr */ jschar *dollarEnd; /* limit pointer for js_strchr_limit */ @@ -2068,6 +2070,58 @@ class PreserveRegExpStatics static bool FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t *sizep) { + JSObject *base = rdata.elembase; + if (base) { + /* + * The base object is used when replace was passed a lambda which looks like + * 'function(a) { return b[a]; }' for the base object b. b will not change + * in the course of the replace unless we end up making a scripted call due + * to accessing a scripted getter or a value with a scripted toString. + */ + JS_ASSERT(rdata.lambda); + JS_ASSERT(!base->getOps()->lookupProperty); + JS_ASSERT(!base->getOps()->getProperty); + + Value match; + if (!res->createLastMatch(cx, &match)) + return false; + JSString *str = match.toString(); + + JSAtom *atom; + if (str->isAtomized()) { + atom = STRING_TO_ATOM(str); + } else { + atom = js_AtomizeString(cx, str, 0); + if (!atom) + return false; + } + jsid id = ATOM_TO_JSID(atom); + + JSObject *holder; + JSProperty *prop = NULL; + if (js_LookupPropertyWithFlags(cx, base, id, JSRESOLVE_QUALIFIED, &holder, &prop) < 0) + return false; + + /* Only handle the case where the property exists and is on this object. */ + if (prop && holder == base) { + Shape *shape = (Shape *) prop; + if (shape->slot != SHAPE_INVALID_SLOT && shape->hasDefaultGetter()) { + Value value = base->getSlot(shape->slot); + if (value.isString()) { + rdata.repstr = value.toString(); + *sizep = rdata.repstr->length(); + return true; + } + } + } + + /* + * Couldn't handle this property, fall through and despecialize to the + * general lambda case. + */ + rdata.elembase = NULL; + } + JSObject *lambda = rdata.lambda; if (lambda) { /* @@ -2438,10 +2492,46 @@ js::str_replace(JSContext *cx, uintN argc, Value *vp) /* Extract replacement string/function. */ if (argc >= optarg && js_IsCallable(vp[3])) { rdata.lambda = &vp[3].toObject(); + rdata.elembase = NULL; rdata.repstr = NULL; rdata.dollar = rdata.dollarEnd = NULL; + + if (rdata.lambda->isFunction()) { + JSFunction *fun = rdata.lambda->getFunctionPrivate(); + if (fun->isInterpreted()) { + /* + * Pattern match the script to check if it is is indexing into a + * particular object, e.g. 'function(a) { return b[a]; }'. Avoid + * calling the script in such cases, which are used by javascript + * packers (particularly the popular Dean Edwards packer) to efficiently + * encode large scripts. We only handle the code patterns generated + * by such packers here. + */ + JSScript *script = fun->u.i.script; + jsbytecode *pc = script->code; + + Value table = UndefinedValue(); + if (JSOp(*pc) == JSOP_GETFCSLOT) { + table = rdata.lambda->getFlatClosureUpvar(GET_UINT16(pc)); + pc += JSOP_GETFCSLOT_LENGTH; + } + + if (table.isObject() && + JSOp(*pc) == JSOP_GETARG && GET_SLOTNO(pc) == 0 && + JSOp(*(pc + JSOP_GETARG_LENGTH)) == JSOP_GETELEM && + JSOp(*(pc + JSOP_GETARG_LENGTH + JSOP_GETELEM_LENGTH)) == JSOP_RETURN) { + Class *clasp = table.toObject().getClass(); + if (clasp->isNative() && + !clasp->ops.lookupProperty && + !clasp->ops.getProperty) { + rdata.elembase = &table.toObject(); + } + } + } + } } else { rdata.lambda = NULL; + rdata.elembase = NULL; rdata.repstr = ArgToRootedString(cx, argc, vp, 1); if (!rdata.repstr) return false; @@ -3514,8 +3604,9 @@ js_NewDependentString(JSContext *cx, JSString *base, size_t start, jschar *chars = base->chars() + start; - if (length == 1 && *chars < UNIT_STRING_LIMIT) - return const_cast(&JSString::unitStringTable[*chars]); + JSString *staticStr = JSString::lookupStaticString(chars, length); + if (staticStr) + return staticStr; /* Try to avoid long chains of dependent strings. */ while (base->isDependent()) diff --git a/js/src/jsstr.h b/js/src/jsstr.h index 860d198a905..7ddda41acca 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -543,6 +543,8 @@ struct JSString { static JSString *getUnitString(JSContext *cx, JSString *str, size_t index); static JSString *length2String(jschar c1, jschar c2); static JSString *intString(jsint i); + + static JSString *lookupStaticString(const jschar *chars, size_t length); JS_ALWAYS_INLINE void finalize(JSContext *cx, unsigned thingKind); }; diff --git a/js/src/jsstrinlines.h b/js/src/jsstrinlines.h index 64dbd1c8a51..a908391eda3 100644 --- a/js/src/jsstrinlines.h +++ b/js/src/jsstrinlines.h @@ -76,6 +76,43 @@ JSString::intString(jsint i) return const_cast(JSString::intStringTable[u]); } +/* Get a static atomized string for chars if possible. */ +inline JSString * +JSString::lookupStaticString(const jschar *chars, size_t length) +{ + if (length == 1) { + if (chars[0] < UNIT_STRING_LIMIT) + return unitString(chars[0]); + } + + if (length == 2) { + if (fitsInSmallChar(chars[0]) && fitsInSmallChar(chars[1])) + return length2String(chars[0], chars[1]); + } + + /* + * Here we know that JSString::intStringTable covers only 256 (or at least + * not 1000 or more) chars. We rely on order here to resolve the unit vs. + * int string/length-2 string atom identity issue by giving priority to unit + * strings for "0" through "9" and length-2 strings for "10" through "99". + */ + JS_STATIC_ASSERT(INT_STRING_LIMIT <= 999); + if (length == 3) { + if ('1' <= chars[0] && chars[0] <= '9' && + '0' <= chars[1] && chars[1] <= '9' && + '0' <= chars[2] && chars[2] <= '9') { + jsint i = (chars[0] - '0') * 100 + + (chars[1] - '0') * 10 + + (chars[2] - '0'); + + if (jsuint(i) < INT_STRING_LIMIT) + return intString(i); + } + } + + return NULL; +} + inline void JSString::finalize(JSContext *cx, unsigned thingKind) { if (JS_LIKELY(thingKind == js::gc::FINALIZE_STRING)) { From a61b8d48e499fa485df7757998c61889f3439b44 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Oct 2010 15:08:10 -0700 Subject: [PATCH 104/263] Bug 607864 - TM: systematically annotate bytecode boundaries in LIR dumps. r=dmandelin. --- js/src/jstracer.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 0152a3d0f67..f880ade7d06 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -7452,9 +7452,10 @@ TraceRecorder::monitorRecording(JSOp op) AbortRecording(cx, "unsupported opcode"); status = ARECORD_ERROR; break; -# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \ - case x: \ - status = this->record_##x(); \ +# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + case op: \ + insComment(#op); \ + status = this->record_##op(); \ break; # include "jsopcode.tbl" # undef OPDEF @@ -13036,10 +13037,8 @@ TraceRecorder::record_JSOP_GETELEM() LIns* addr_ins; VMSideExit* branchExit = snapshot(BRANCH_EXIT); - insComment("begin-getelem(dense-array)"); guardDenseArray(obj_ins, branchExit); CHECK_STATUS_A(denseArrayElement(lval, idx, vp, v_ins, addr_ins, branchExit)); - insComment("end-getelem(dense-array)"); set(&lval, v_ins); if (call) set(&idx, obj_ins); @@ -13321,8 +13320,6 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) VMSideExit* branchExit = snapshot(BRANCH_EXIT); VMSideExit* mismatchExit = snapshot(MISMATCH_EXIT); - insComment("begin-setelem(dense-array)"); - // Make sure the array is actually dense. if (!obj->isDenseArray()) return ARECORD_STOP; @@ -13389,8 +13386,6 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) // Right, actually set the element. box_value_into(v, v_ins, addr_ins, 0, ACCSET_SLOTS); - - insComment("end-setelem(dense-array)"); } jsbytecode* pc = cx->regs->pc; From 49253f7a601dd8bdaae7dc63db7a544bd3e3de93 Mon Sep 17 00:00:00 2001 From: "Werner Sharp (wsharp@adobe.com)" Date: Thu, 28 Oct 2010 12:47:12 -0400 Subject: [PATCH 105/263] bug 607630. SoftFloatFilter needs to support LIR_d2i (sr+ nnethercote) --HG-- extra : convert_revision : f43789d6bdbd848b943f3aac937b545e0872beb9 --- js/src/nanojit/LIR.cpp | 17 +++++++++++++++-- js/src/nanojit/LIR.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index 9725f5201ce..46edd35fd4c 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -2943,6 +2943,7 @@ namespace nanojit } #if NJ_SOFTFLOAT_SUPPORTED + static int32_t FASTCALL d2i(double d) { return (int32_t) d; } static double FASTCALL i2d(int32_t i) { return i; } static double FASTCALL ui2d(uint32_t u) { return u; } static double FASTCALL negd(double a) { return -a; } @@ -2956,6 +2957,7 @@ namespace nanojit static int32_t FASTCALL led(double a, double b) { return a <= b; } static int32_t FASTCALL ged(double a, double b) { return a >= b; } + #define SIG_I_D CallInfo::typeSig1(ARGTYPE_I, ARGTYPE_D) #define SIG_D_I CallInfo::typeSig1(ARGTYPE_D, ARGTYPE_I) #define SIG_D_UI CallInfo::typeSig1(ARGTYPE_D, ARGTYPE_UI) #define SIG_D_D CallInfo::typeSig1(ARGTYPE_D, ARGTYPE_D) @@ -2966,6 +2968,7 @@ namespace nanojit static const CallInfo name##_ci = \ { (intptr_t)&name, typesig, ABI_FASTCALL, /*isPure*/1, ACCSET_NONE verbose_only(, #name) } + SF_CALLINFO(d2i, SIG_I_D); SF_CALLINFO(i2d, SIG_D_I); SF_CALLINFO(ui2d, SIG_D_UI); SF_CALLINFO(negd, SIG_D_D); @@ -2982,6 +2985,7 @@ namespace nanojit SoftFloatOps::SoftFloatOps() { memset(opmap, 0, sizeof(opmap)); + opmap[LIR_d2i] = &d2i_ci; opmap[LIR_i2d] = &i2d_ci; opmap[LIR_ui2d] = &ui2d_ci; opmap[LIR_negd] = &negd_ci; @@ -3020,6 +3024,11 @@ namespace nanojit return split(call, args); } + LIns* SoftFloatFilter::callI1(const CallInfo *call, LIns *a) { + LIns *args[] = { split(a) }; + return out->insCall(call, args); + } + LIns* SoftFloatFilter::callD2(const CallInfo *call, LIns *a, LIns *b) { LIns *args[] = { split(b), split(a) }; return split(call, args); @@ -3032,8 +3041,12 @@ namespace nanojit LIns* SoftFloatFilter::ins1(LOpcode op, LIns *a) { const CallInfo *ci = softFloatOps.opmap[op]; - if (ci) - return callD1(ci, a); + if (ci) { + if (ci->returnType() == ARGTYPE_D) + return callD1(ci, a); + else + return callI1(ci, a); + } if (op == LIR_retd) return out->ins1(op, split(a)); return out->ins1(op, a); diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index c66b7dc0ae2..744f27bce8e 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -2315,6 +2315,7 @@ namespace nanojit LIns *split(const CallInfo *call, LIns* args[]); LIns *callD1(const CallInfo *call, LIns *a); LIns *callD2(const CallInfo *call, LIns *a, LIns *b); + LIns *callI1(const CallInfo *call, LIns *a); LIns *cmpD(const CallInfo *call, LIns *a, LIns *b); LIns *ins1(LOpcode op, LIns *a); LIns *ins2(LOpcode op, LIns *a, LIns *b); From 18b2762a54022b26b8a3b70269f76592849c564d Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Fri, 29 Oct 2010 05:46:22 +0800 Subject: [PATCH 106/263] Bug 603876 Add support for addjovi and subjovi on Sparc platform r=wmaddox --HG-- extra : convert_revision : d372626d5b878cc31facbf9e58a5ab66e7af6a34 --- js/src/nanojit/NativeSparc.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 2e99e727cde..34e9b3ace7d 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -1107,7 +1107,7 @@ namespace nanojit } allow &= ~rmask(rb); } - else if ((op == LIR_addi || op == LIR_addxovi) && lhs->isop(LIR_allocp) && rhs->isImmI()) { + else if ((op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi) && lhs->isop(LIR_allocp) && rhs->isImmI()) { // add alloc+const, use lea Register rr = deprecated_prepResultReg(ins, allow); int d = findMemFor(lhs) + rhs->immI(); @@ -1128,9 +1128,9 @@ namespace nanojit if (lhs == rhs) rb = ra; - if (op == LIR_addi || op == LIR_addxovi) + if (op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi) ADDCC(rr, rb, rr); - else if (op == LIR_subi || op == LIR_subxovi) + else if (op == LIR_subi || op == LIR_subxovi || op == LIR_subjovi) SUBCC(rr, rb, rr); else if (op == LIR_muli) SMULCC(rr, rb, rr); @@ -1158,9 +1158,9 @@ namespace nanojit else { int c = rhs->immI(); - if (op == LIR_addi || op == LIR_addxovi) + if (op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi) ADDCC(rr, L2, rr); - else if (op == LIR_subi || op == LIR_subxovi) + else if (op == LIR_subi || op == LIR_subxovi || op == LIR_subjovi) SUBCC(rr, L2, rr); else if (op == LIR_andi) AND(rr, L2, rr); From ee7eccd45b01b7a8ab3a21e8fe8f056c3bf6c7d1 Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Fri, 29 Oct 2010 05:49:05 +0800 Subject: [PATCH 107/263] Bug 604334 add support for param number above 6 (many_params.in) for SPARC r=wmaddox --HG-- extra : convert_revision : 5a600b5166ea320289291a5b8bf085d4e5dc8653 --- js/src/nanojit/NativeSparc.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 34e9b3ace7d..5f5969a91fc 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -1270,9 +1270,19 @@ namespace nanojit void Assembler::asm_param(LIns* ins) { + underrunProtect(12); uint32_t a = ins->paramArg(); - uint32_t kind = ins->paramKind(); - deprecated_prepResultReg(ins, rmask(argRegs[a])); + NanoAssertMsg(ins->paramKind() == 0, "savedRegs are not used on SPARC"); + + if (a < sizeof(argRegs)/sizeof(argRegs[0])) { // i0 - i5 + prepareResultReg(ins, rmask(argRegs[a])); + } else { + // Incoming arg is on stack + Register r = prepareResultReg(ins, GpRegs); + int32_t d = a * sizeof (intptr_t) + kLinkageAreaSize; + LDSW32(FP, d, r); + } + freeResourcesOf(ins); } void Assembler::asm_immi(LIns* ins) From 6d2e0fc1022a57a2bd184458e829c91256f06380 Mon Sep 17 00:00:00 2001 From: Ginn Chen Date: Fri, 29 Oct 2010 05:51:39 +0800 Subject: [PATCH 108/263] Bug 605427 Implement FpReg move on icc or fcc for asm_cmov() on SPARC r=wmaddox --HG-- extra : convert_revision : ce344dfb7fcb8d6f8fea281074cac9c472cc9d0c --- js/src/nanojit/NativeSparc.cpp | 89 ++++++++++++++++++++++++++-------- js/src/nanojit/NativeSparc.h | 25 ++++++++-- 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index 5f5969a91fc..a78d3140859 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -322,21 +322,41 @@ namespace nanojit inline void Assembler::MOVCS (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x5, "movcs"); } inline void Assembler::MOVVC (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xf, "movvc"); } inline void Assembler::MOVEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x1, "move"); } - inline void Assembler::MOVFEI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x9, "movfe"); } inline void Assembler::MOVNEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x9, "movne"); } inline void Assembler::MOVLI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x3, "movl"); } - inline void Assembler::MOVFLI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x4, "movfl"); } inline void Assembler::MOVLEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x2, "movle"); } - inline void Assembler::MOVFLEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xd, "movfle"); } inline void Assembler::MOVGI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xa, "movg"); } - inline void Assembler::MOVFGI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x6, "movfg"); } inline void Assembler::MOVGEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xb, "movge"); } - inline void Assembler::MOVFGEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xb, "movfge"); } inline void Assembler::MOVLEUI(int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x4, "movleu"); } inline void Assembler::MOVGUI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xc, "movgu"); } inline void Assembler::MOVCCI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xd, "movcc"); } inline void Assembler::MOVCSI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x5, "movcs"); } inline void Assembler::MOVVSI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x7, "movvs"); } + inline void Assembler::MOVFEI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x9, "movfe"); } + inline void Assembler::MOVFLI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x4, "movfl"); } + inline void Assembler::MOVFLEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xd, "movfle"); } + inline void Assembler::MOVFGI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x6, "movfg"); } + inline void Assembler::MOVFGEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xb, "movfge"); } + + inline void Assembler::FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char *opcode) { + Format_4_5(rd, 0x35, cond, opt_cc, 0x2, rs); + asm_output("%s %s, %s", opcode, gpn(rs), gpn(rd)); + } + + inline void Assembler::FMOVDNE (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0x9, "fmovdne"); } + inline void Assembler::FMOVDL (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0x3, "fmovdl"); } + inline void Assembler::FMOVDLE (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0x2, "fmovdle"); } + inline void Assembler::FMOVDLEU (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0x4, "fmovdleu");} + inline void Assembler::FMOVDG (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0xa, "fmovdg"); } + inline void Assembler::FMOVDGU (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0xc, "fmovdgu"); } + inline void Assembler::FMOVDGE (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0xb, "fmovdfge");} + inline void Assembler::FMOVDCC (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0xd, "fmovdcc"); } + inline void Assembler::FMOVDCS (Register rs, Register rd) { FMOVDcc(rs, 0x4, rd, 0x5, "fmovdcs"); } + inline void Assembler::FMOVDFNE (Register rs, Register rd) { FMOVDcc(rs, 0x0, rd, 0x1, "fmovdfne"); } + inline void Assembler::FMOVDFUG (Register rs, Register rd) { FMOVDcc(rs, 0x0, rd, 0x5, "fmovdfug"); } + inline void Assembler::FMOVDFUGE(Register rs, Register rd) { FMOVDcc(rs, 0x0, rd, 0xc, "fmovdfuge");} + inline void Assembler::FMOVDFUL (Register rs, Register rd) { FMOVDcc(rs, 0x0, rd, 0x3, "fmovdful"); } + inline void Assembler::FMOVDFULE(Register rs, Register rd) { FMOVDcc(rs, 0x0, rd, 0xe, "fmovdfule");} inline void Assembler::NOP() { Format_2(0, 0x4, 0); @@ -1242,30 +1262,55 @@ namespace nanojit LIns* iffalse = ins->oprnd3(); NanoAssert(condval->isCmp()); - NanoAssert(op == LIR_cmovi && iftrue->isI() && iffalse->isI()); + NanoAssert(op == LIR_cmovi && iftrue->isI() && iffalse->isI() || + (op == LIR_cmovd && iftrue->isD() && iffalse->isD())); - const Register rr = deprecated_prepResultReg(ins, GpRegs); + RegisterMask rm = (op == LIR_cmovi) ? GpRegs : FpRegs; + const Register rr = deprecated_prepResultReg(ins, rm); + const Register iffalsereg = findRegFor(iffalse, rm & ~rmask(rr)); + bool isIcc = true; - // this code assumes that neither LD nor MR nor MRcc set any of the condition flags. - // (This is true on Intel, is it true on all architectures?) - const Register iffalsereg = findRegFor(iffalse, GpRegs & ~rmask(rr)); if (op == LIR_cmovi) { switch (condval->opcode()) { // note that these are all opposites... - case LIR_eqi: MOVNE (iffalsereg, rr); break; - case LIR_lti: MOVGE (iffalsereg, rr); break; - case LIR_lei: MOVG (iffalsereg, rr); break; - case LIR_gti: MOVLE (iffalsereg, rr); break; - case LIR_gei: MOVL (iffalsereg, rr); break; - case LIR_ltui: MOVCC (iffalsereg, rr); break; - case LIR_leui: MOVGU (iffalsereg, rr); break; - case LIR_gtui: MOVLEU(iffalsereg, rr); break; - case LIR_geui: MOVCS (iffalsereg, rr); break; + case LIR_eqi: MOVNE (iffalsereg, rr); break; + case LIR_lti: MOVGE (iffalsereg, rr); break; + case LIR_lei: MOVG (iffalsereg, rr); break; + case LIR_gti: MOVLE (iffalsereg, rr); break; + case LIR_gei: MOVL (iffalsereg, rr); break; + case LIR_ltui: MOVCC (iffalsereg, rr); break; + case LIR_leui: MOVGU (iffalsereg, rr); break; + case LIR_gtui: MOVLEU(iffalsereg, rr); break; + case LIR_geui: MOVCS (iffalsereg, rr); break; debug_only( default: NanoAssert(0); break; ) - } + } + } else { + switch (condval->opcode()) { + // note that these are all opposites... + case LIR_eqi: FMOVDNE (iffalsereg, rr); break; + case LIR_lti: FMOVDGE (iffalsereg, rr); break; + case LIR_lei: FMOVDG (iffalsereg, rr); break; + case LIR_gti: FMOVDLE (iffalsereg, rr); break; + case LIR_gei: FMOVDL (iffalsereg, rr); break; + case LIR_ltui: FMOVDCC (iffalsereg, rr); break; + case LIR_leui: FMOVDGU (iffalsereg, rr); break; + case LIR_gtui: FMOVDLEU (iffalsereg, rr); break; + case LIR_geui: FMOVDCS (iffalsereg, rr); break; + case LIR_eqd: FMOVDFNE (iffalsereg, rr); isIcc = false; break; + case LIR_led: FMOVDFUG (iffalsereg, rr); isIcc = false; break; + case LIR_ltd: FMOVDFUGE(iffalsereg, rr); isIcc = false; break; + case LIR_ged: FMOVDFUL (iffalsereg, rr); isIcc = false; break; + case LIR_gtd: FMOVDFULE(iffalsereg, rr); isIcc = false; break; + debug_only( default: NanoAssert(0); break; ) + } } + /*const Register iftruereg =*/ findSpecificRegFor(iftrue, rr); - asm_cmp(condval); + if (isIcc) + asm_cmp(condval); + else + asm_cmpd(condval); + } void Assembler::asm_param(LIns* ins) @@ -1392,6 +1437,7 @@ namespace nanojit } void Assembler::asm_d2i(LIns* ins) { + underrunProtect(28); LIns *lhs = ins->oprnd1(); Register rr = prepareResultReg(ins, GpRegs); Register ra = findRegFor(lhs, FpRegs); @@ -1399,6 +1445,7 @@ namespace nanojit LDSW32(FP, d, rr); STF32(ra, d, FP); FDTOI(ra, ra); + freeResourcesOf(ins); } void Assembler::asm_nongp_copy(Register r, Register s) diff --git a/js/src/nanojit/NativeSparc.h b/js/src/nanojit/NativeSparc.h index 70c91c3b0dc..f2268716d3a 100644 --- a/js/src/nanojit/NativeSparc.h +++ b/js/src/nanojit/NativeSparc.h @@ -303,6 +303,7 @@ namespace nanojit void LoadOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode); \ void MOVcc(Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \ void MOVccI(int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \ + void FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char *opcode); \ void ShiftOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \ void ShiftOperationI(Register rs1, int32_t shcnt32, Register rd, int32_t op3, const char* opcode); \ void Store(Register rd, Register rs1, Register rs2, int32_t op3, const char* opcode); \ @@ -379,21 +380,35 @@ namespace nanojit void MOVCS(Register rs, Register rd); \ void MOVVC(Register rs, Register rd); \ void MOVEI(int32_t simm11, Register rd); \ - void MOVFEI(int32_t simm11, Register rd); \ void MOVNEI(int32_t simm11, Register rd); \ void MOVLI(int32_t simm11, Register rd); \ - void MOVFLI(int32_t simm11, Register rd); \ void MOVLEI(int32_t simm11, Register rd); \ - void MOVFLEI(int32_t simm11, Register rd); \ void MOVGI(int32_t simm11, Register rd); \ - void MOVFGI(int32_t simm11, Register rd); \ void MOVGEI(int32_t simm11, Register rd); \ - void MOVFGEI(int32_t simm11, Register rd); \ void MOVLEUI(int32_t simm11, Register rd); \ void MOVGUI(int32_t simm11, Register rd); \ void MOVCCI(int32_t simm11, Register rd); \ void MOVCSI(int32_t simm11, Register rd); \ void MOVVSI(int32_t simm11, Register rd); \ + void MOVFEI(int32_t simm11, Register rd); \ + void MOVFLI(int32_t simm11, Register rd); \ + void MOVFLEI(int32_t simm11, Register rd); \ + void MOVFGI(int32_t simm11, Register rd); \ + void MOVFGEI(int32_t simm11, Register rd); \ + void FMOVDNE(Register rs, Register rd); \ + void FMOVDL(Register rs, Register rd); \ + void FMOVDLE(Register rs, Register rd); \ + void FMOVDLEU(Register rs, Register rd); \ + void FMOVDG(Register rs, Register rd); \ + void FMOVDGU(Register rs, Register rd); \ + void FMOVDGE(Register rs, Register rd); \ + void FMOVDCC(Register rs, Register rd); \ + void FMOVDCS(Register rs, Register rd); \ + void FMOVDFNE(Register rs, Register rd); \ + void FMOVDFUG(Register rs, Register rd); \ + void FMOVDFUGE(Register rs, Register rd); \ + void FMOVDFUL(Register rs, Register rd); \ + void FMOVDFULE(Register rs, Register rd); \ void NOP(); \ void RDY(Register rd); \ void RESTORE(Register rs1, Register rs2, Register rd); \ From e5312a6b543657126817f937285723a31863e75a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Oct 2010 15:22:05 -0700 Subject: [PATCH 109/263] Bug 607225 - nanojit: add MODRM() and SIB() to Nativei386.cpp, plus other clean-ups. r=rreitmai. --HG-- extra : convert_revision : 5012f8eb917c654d4756025fd90f1f98a1f07626 --- js/src/nanojit/Nativei386.cpp | 88 ++++++++++++++++------------------- js/src/nanojit/Nativei386.h | 31 +++++++----- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index aac903cd569..d09c543039d 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -79,48 +79,44 @@ namespace nanojit typedef Register R; typedef int32_t I32; - // XXX rearrange NanoAssert() expression to workaround apparent gcc 4.3 bug: - // XXX "error: logical && with non-zero constant will always evaluate as true" - // underrunProtect(6) is necessary for worst-case + // Length: 2--6 bytes. inline void Assembler::MODRMsib(I32 r, R b, R i, I32 s, I32 d) { - NanoAssert(REGNUM(i) < 8 && REGNUM(b) < 8 && unsigned(r) < 8); if (d == 0 && b != rEBP) { - *(--_nIns) = uint8_t(s << 6 | REGNUM(i) << 3 | REGNUM(b)); - *(--_nIns) = uint8_t(0 << 6 | r << 3 | 4); + SIB(s, REGNUM(i), REGNUM(b)); + MODRM(0, r, 4); // amode == (b + i<>3, REGNUM(r)); + MODRMr(c>>3, REGNUM(r)); *(--_nIns) = uint8_t(0x83); } else { IMM32(i); if ( r == rEAX) { *(--_nIns) = uint8_t(c); } else { - MODRM(c >> 3, REGNUM(r)); + MODRMr(c >> 3, REGNUM(r)); *(--_nIns) = uint8_t(0x81); } } @@ -215,7 +211,7 @@ namespace nanojit inline void Assembler::ALU2(I32 c, R d, R s) { underrunProtect(3); - MODRM(REGNUM(d), REGNUM(s)); + MODRMr(REGNUM(d), REGNUM(s)); *(--_nIns) = uint8_t(c); *(--_nIns) = uint8_t(c>>8); } @@ -261,7 +257,7 @@ namespace nanojit inline void Assembler::SHIFT(I32 c, R r, I32 i) { underrunProtect(3); *--_nIns = uint8_t(i); - MODRM(c, REGNUM(r)); + MODRMr(c, REGNUM(r)); *--_nIns = 0xc1; } @@ -284,13 +280,12 @@ namespace nanojit inline void Assembler::CMPi(R r, I32 i) { count_alu(); ALUi(0x3d, r, i); asm_output("cmp %s,%d", gpn(r), i); } inline void Assembler::LEA(R r, I32 d, R b) { count_alu(); ALUm(0x8d, REGNUM(r), d, b); asm_output("lea %s,%d(%s)", gpn(r), d, gpn(b)); } - // lea %r, d(%i*4) // This addressing mode is not supported by the MODRMsib function. inline void Assembler::LEAmi4(R r, I32 d, R i) { count_alu(); IMM32(int32_t(d)); - *(--_nIns) = uint8_t(2 << 6 | REGNUM(i) << 3 | 5); - *(--_nIns) = uint8_t(0 << 6 | REGNUM(r) << 3 | 4); + SIB(2, REGNUM(i), 5); + MODRM(0, REGNUM(r), 4); // amode == d(i*4) *(--_nIns) = 0x8d; asm_output("lea %s, %p(%s*4)", gpn(r), (void*)d, gpn(i)); } @@ -557,18 +552,13 @@ namespace nanojit *(--_nIns) = 0x6a; asm_output("push %d", i); } else { - PUSHi32(i); + underrunProtect(5); + IMM32(i); + *(--_nIns) = 0x68; + asm_output("push %d", i); } } - inline void Assembler::PUSHi32(I32 i) { - count_push(); - underrunProtect(5); - IMM32(i); - *(--_nIns) = 0x68; - asm_output("push %d", i); - } - inline void Assembler::PUSHr(R r) { count_push(); underrunProtect(1); @@ -627,10 +617,10 @@ namespace nanojit inline void Assembler::JMP_indexed(Register x, I32 ss, NIns** addr) { underrunProtect(7); - IMM32(int32_t(addr)); - *(--_nIns) = uint8_t(ss << 6 | REGNUM(x) << 3 | 5); /* sib: x<> 8) & 0xff); *(--_nIns) = uint8_t((c >> 16) & 0xff); @@ -691,10 +681,11 @@ namespace nanojit count_ldq(); underrunProtect(8); IMM32(int32_t(addr)); - *(--_nIns) = uint8_t((REGNUM(r) & 7) << 3 | 5); + MODRM(0, REGNUM(r) & 7, 5); // amode == addr(r) *(--_nIns) = 0x10; *(--_nIns) = 0x0f; *(--_nIns) = 0xf2; + // *addr is a constant, so we can print it here. asm_output("movsd %s,(%p) // =%f", gpn(r), (void*)addr, *addr); } @@ -705,14 +696,14 @@ namespace nanojit { count_ldq(); SSEsib(0xf30f7e, rr, d, rb, ri, scale); - asm_output("movq %s,%d(%s+%s*%d)", gpn(rr), d, gpn(rb), gpn(ri), SIBIDX(scale)); + asm_output("movq %s,%d(%s+%s*%c)", gpn(rr), d, gpn(rb), gpn(ri), SIBIDX(scale)); } inline void Assembler::SSE_LDSSsib(R rr, I32 d, R rb, R ri, I32 scale) { count_ld(); SSEsib(0xf30f10, rr, d, rb, ri, scale); - asm_output("movss %s,%d(%s+%s*%d)", gpn(rr), d, gpn(rb), gpn(ri), SIBIDX(scale)); + asm_output("movss %s,%d(%s+%s*%c)", gpn(rr), d, gpn(rb), gpn(ri), SIBIDX(scale)); } inline void Assembler::SSE_STSD(I32 d, R b, R r) { count_stq(); SSEm(0xf20f11, r, d, b); asm_output("movsd %d(%s),%s", d, gpn(b), gpn(r)); } @@ -722,7 +713,7 @@ namespace nanojit inline void Assembler::SSE_STQsib(I32 d, R rb, R ri, I32 scale, R rv) { count_stq(); SSEsib(0x660fd6, rv, d, rb, ri, scale); - asm_output("movq %d(%s+%s*%d),%s", d, gpn(rb), gpn(ri), scale, gpn(rv)); + asm_output("movq %d(%s+%s*%c),%s", d, gpn(rb), gpn(ri), SIBIDX(scale), gpn(rv)); } inline void Assembler::SSE_CVTSI2SD(R xr, R gr) { count_fpu(); SSE(0xf20f2a, xr, gr); asm_output("cvtsi2sd %s,%s", gpn(xr), gpn(gr)); } @@ -765,11 +756,12 @@ namespace nanojit NanoAssert(IsXmmReg(r)); const double* daddr = addr; IMM32(int32_t(daddr)); - *(--_nIns) = uint8_t((REGNUM(r) & 7) << 3 | 5); + MODRM(0, REGNUM(r) & 7, 5); // amode == daddr(r) *(--_nIns) = 0x58; *(--_nIns) = 0x0f; *(--_nIns) = 0xf2; - asm_output("addsd %s,%p // =%f", gpn(r), (void*)daddr, *daddr); + // *daddr is a constant, so we can print it here. + asm_output("addsd %s,(%p) // =%f", gpn(r), (void*)daddr, *daddr); } inline void Assembler::SSE_SUBSD(R rd, R rs) { @@ -804,11 +796,11 @@ namespace nanojit count_fpuld(); underrunProtect(8); IMM32(int32_t(maskaddr)); - *(--_nIns) = uint8_t((REGNUM(r) & 7) << 3 | 5); + MODRM(0, REGNUM(r) & 7, 5); // amode == maskaddr(r) *(--_nIns) = 0x57; *(--_nIns) = 0x0f; *(--_nIns) = 0x66; - asm_output("xorpd %s,[%p]", gpn(r), (void*)maskaddr); + asm_output("xorpd %s,(%p)", gpn(r), (void*)maskaddr); } inline void Assembler::SSE_XORPDr(R rd, R rs) { diff --git a/js/src/nanojit/Nativei386.h b/js/src/nanojit/Nativei386.h index 20d231d1ff9..a0686fe7dd6 100644 --- a/js/src/nanojit/Nativei386.h +++ b/js/src/nanojit/Nativei386.h @@ -204,26 +204,37 @@ namespace nanojit void asm_div_mod(LIns *cond); \ void asm_load(int d, Register r); \ void asm_immd(Register r, uint64_t q, double d, bool canClobberCCs); \ - void IMM8(int32_t i) { \ + \ + /* These function generate fragments of instructions. */ \ + void IMM8(int32_t i) { /* Length: 1 byte. */ \ _nIns -= 1; \ *((int8_t*)_nIns) = int8_t(i); \ }; \ - void IMM16(int32_t i) { \ + void IMM16(int32_t i) { /* Length: 2 bytes. */ \ _nIns -= 2; \ *((int16_t*)_nIns) = int16_t(i); \ }; \ - void IMM32(int32_t i) { \ + void IMM32(int32_t i) { /* Length: 4 bytes. */ \ _nIns -= 4; \ *((int32_t*)_nIns) = int32_t(i); \ }; \ + void MODRM(int32_t mod, int32_t ro, int32_t rm) { /* Length: 1 byte. */ \ + NanoAssert(unsigned(mod) < 4 && unsigned(ro) < 8 && unsigned(rm) < 8); \ + *(--_nIns) = uint8_t(mod << 6 | ro << 3 | rm); \ + } \ + void SIB(int32_t s, int32_t i, int32_t b) { /* Length: 1 byte. */ \ + NanoAssert(unsigned(s) < 4 && unsigned(i) < 8 && unsigned(b) < 8); \ + *(--_nIns) = uint8_t(s << 6 | i << 3 | b); \ + } \ + void MODRMr(int32_t d, int32_t s) { /* Length: 1 byte. */ \ + NanoAssert(unsigned(d) < 8 && unsigned(s) < 8); \ + MODRM(3, d, s); \ + }; \ void MODRMm(int32_t r, int32_t d, Register b); \ void MODRMsib(int32_t r, Register b, Register i, int32_t s, int32_t d); \ void MODRMdm(int32_t r, int32_t addr); \ - /* d may be a register number or something else */ \ - void MODRM(int32_t d, int32_t s) { \ - NanoAssert(unsigned(d) < 8 && unsigned(s) < 8); \ - *(--_nIns) = uint8_t(3 << 6 | d << 3 | s); \ - }; \ + \ + /* These functions generate entire instructions. */ \ void ALU0(int32_t o); \ void ALUm(int32_t c, int32_t r, int32_t d, Register b); \ void ALUdm(int32_t c, Register r, int32_t addr); \ @@ -233,10 +244,9 @@ namespace nanojit void ALU2dm(int32_t c, Register r, int32_t addr); \ void ALU2m(int32_t c, Register r, int32_t d, Register b); \ void ALU2sib(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \ - /* d may be a register number or something else */ \ void ALU(int32_t c, int32_t d, Register s) { \ underrunProtect(2); \ - MODRM(d, REGNUM(s)); \ + MODRMr(d, REGNUM(s)); \ *(--_nIns) = uint8_t(c); \ }; \ void ALUi(int32_t c, Register r, int32_t i); \ @@ -334,7 +344,6 @@ namespace nanojit void NOP(); \ void INT3(); \ void PUSHi(int32_t i); \ - void PUSHi32(int32_t i); \ void PUSHr(Register r); \ void PUSHm(int32_t d, Register b); \ void POPr(Register r); \ From 03a06266f2dd1386a6bae89635b097a01bc54066 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Oct 2010 15:44:27 -0700 Subject: [PATCH 110/263] Update nanojit-import-rev stamp. --- js/src/nanojit-import-rev | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index ba24b773b8f..7c8c0d74e8f 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -8cb17c62aaa615416ac901106292b69f691c51cf +5012f8eb917c654d4756025fd90f1f98a1f07626 From 1802eb481ebf16f878342c1b757c4c949ebe8226 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 26 Oct 2010 23:57:31 -0700 Subject: [PATCH 111/263] Bug 606585 - Make the compartment map use principals properly. r=peterv/bz --HG-- extra : rebase_source : b4585beb4aa5f9f44cb02beb3f0f91212345f1f8 --- .../base/src/nsInProcessTabChildGlobal.cpp | 2 +- content/xbl/src/nsXBLDocumentInfo.cpp | 4 +- .../document/src/nsXULPrototypeDocument.cpp | 4 +- dom/base/nsJSEnvironment.cpp | 2 +- dom/ipc/TabChild.cpp | 2 +- dom/src/threads/nsDOMWorker.cpp | 7 +- extensions/jssh/nsJSSh.cpp | 2 +- ipc/testshell/XPCShellEnvironment.cpp | 2 +- js/src/xpconnect/idl/nsIXPConnect.idl | 14 +- .../xpconnect/loader/mozJSComponentLoader.cpp | 2 +- js/src/xpconnect/shell/xpcshell.cpp | 2 +- js/src/xpconnect/src/XPCWrapper.h | 4 +- js/src/xpconnect/src/nsXPConnect.cpp | 159 +++++++++++------- js/src/xpconnect/src/xpccomponents.cpp | 26 ++- js/src/xpconnect/src/xpcinlines.h | 13 ++ js/src/xpconnect/src/xpcjsruntime.cpp | 36 ++-- js/src/xpconnect/src/xpcprivate.h | 95 ++++++++++- js/src/xpconnect/src/xpcpublic.h | 12 +- js/src/xpconnect/src/xpcthreadcontext.cpp | 12 +- 19 files changed, 269 insertions(+), 131 deletions(-) diff --git a/content/base/src/nsInProcessTabChildGlobal.cpp b/content/base/src/nsInProcessTabChildGlobal.cpp index ac4b590b471..608799bb364 100644 --- a/content/base/src/nsInProcessTabChildGlobal.cpp +++ b/content/base/src/nsInProcessTabChildGlobal.cpp @@ -315,7 +315,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal() nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports, NS_GET_IID(nsISupports), - GetPrincipal(), EmptyCString(), + GetPrincipal(), nsnull, flags, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index 846a061b4bd..84f3af36008 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -327,11 +327,9 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID) JS_SetErrorReporter(cx, XBL_ProtoErrorReporter); nsIPrincipal *principal = GetPrincipal(); - nsCString origin; JSCompartment *compartment; - principal->GetOrigin(getter_Copies(origin)); - rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal, + rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull, false, &mJSObject, &compartment); NS_ENSURE_SUCCESS(rv, nsnull); diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 6ddcfe5f32e..5981d819a5a 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -732,12 +732,10 @@ nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id) JSAutoRequest ar(cx); nsIPrincipal *principal = GetPrincipal(); - nsCString origin; JSObject *newGlob; JSCompartment *compartment; - principal->GetOrigin(getter_Copies(origin)); - rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal, + rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull, false, &newGlob, &compartment); NS_ENSURE_SUCCESS(rv, nsnull); diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 9b262b88ab8..5653fb9d31f 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2537,7 +2537,7 @@ nsJSContext::CreateNativeGlobalForInner( InitClassesWithNewWrappedGlobal(mContext, aNewInner, NS_GET_IID(nsISupports), aIsChrome ? systemPrincipal.get() : aPrincipal, - EmptyCString(), flags, + nsnull, flags, getter_AddRefs(jsholder)); if (NS_FAILED(rv)) return rv; diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index d9446d9e66c..cb9eba61da3 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -973,7 +973,7 @@ TabChild::InitTabChildGlobal() nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports, NS_GET_IID(nsISupports), - scope->GetPrincipal(), EmptyCString(), + scope->GetPrincipal(), nsnull, flags, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/dom/src/threads/nsDOMWorker.cpp b/dom/src/threads/nsDOMWorker.cpp index ec1a5b5e6c8..21fcc03a1e4 100644 --- a/dom/src/threads/nsDOMWorker.cpp +++ b/dom/src/threads/nsDOMWorker.cpp @@ -1641,15 +1641,12 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES | nsIXPConnect::OMIT_COMPONENTS_OBJECT; - nsCAutoString origin("DOM worker: "); - origin.AppendInt((PRUint64)this); - nsCOMPtr globalWrapper; nsresult rv = xpc->InitClassesWithNewWrappedGlobal(aCx, scopeSupports, NS_GET_IID(nsISupports), nsnull, - origin, flags, - getter_AddRefs(globalWrapper)); + NS_ISUPPORTS_CAST(nsIWorker*, this), + flags, getter_AddRefs(globalWrapper)); NS_ENSURE_SUCCESS(rv, PR_FALSE); JSObject* global; diff --git a/extensions/jssh/nsJSSh.cpp b/extensions/jssh/nsJSSh.cpp index 3170f93ea65..3614b0c87a3 100644 --- a/extensions/jssh/nsJSSh.cpp +++ b/extensions/jssh/nsJSSh.cpp @@ -618,7 +618,7 @@ NS_IMETHODIMP nsJSSh::Init() nsCOMPtr holder; xpc->InitClassesWithNewWrappedGlobal(mJSContext, (nsIJSSh*)this, NS_GET_IID(nsISupports), - PR_TRUE, + mPrincipal, nsnull, PR_TRUE, getter_AddRefs(holder)); if (!holder) { NS_ERROR("global initialization failed"); diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 716c0fce70b..57774cd31bc 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -1164,7 +1164,7 @@ XPCShellEnvironment::Init() rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), principal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl index 31e2323d98a..eb44d356091 100644 --- a/js/src/xpconnect/idl/nsIXPConnect.idl +++ b/js/src/xpconnect/idl/nsIXPConnect.idl @@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(74b5811e-92d1-468a-a59a-47760200370f)] +[uuid(fb780ace-dced-432b-bb82-8df7d4f919c8)] interface nsIXPConnect : nsISupports { %{ C++ @@ -424,12 +424,10 @@ interface nsIXPConnect : nsISupports * @param aCOMObj the native object that represents the global object. * @param aIID the IID used to wrap the global object. * @param aPrincipal the principal of the code that will run in this - * compartment. Can be null. If no specific origin is - * passed, will be used to compute the origin. - * @param aOrigin must be passed if aPrincipal is null. If non-empty, - * overrides aPrincipal's origin. (can be used to separate - * code from the same principals into different - * comartments, like sandboxes). + * compartment. Can be null if not on the main thread. + * @param aExtraPtr must be passed if aPrincipal is null. Used to separate + * code from the same principal into different + * compartments, as for sandboxes. * @param aFlags one of the flags below specifying what options this * global object wants. */ @@ -439,7 +437,7 @@ interface nsIXPConnect : nsISupports in nsISupports aCOMObj, in nsIIDRef aIID, in nsIPrincipal aPrincipal, - in ACString aOrigin, + in nsISupports aExtraPtr, in PRUint32 aFlags); const PRUint32 INIT_JS_STANDARD_CLASSES = 1 << 0; diff --git a/js/src/xpconnect/loader/mozJSComponentLoader.cpp b/js/src/xpconnect/loader/mozJSComponentLoader.cpp index 2f1bc6f188e..3e99f247ae1 100644 --- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp @@ -976,7 +976,7 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), mSystemPrincipal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/shell/xpcshell.cpp b/js/src/xpconnect/shell/xpcshell.cpp index 49e06b0a2fa..fc85b25c881 100644 --- a/js/src/xpconnect/shell/xpcshell.cpp +++ b/js/src/xpconnect/shell/xpcshell.cpp @@ -1957,7 +1957,7 @@ main(int argc, char **argv) rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), systemprincipal, - EmptyCString(), + nsnull, nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); diff --git a/js/src/xpconnect/src/XPCWrapper.h b/js/src/xpconnect/src/XPCWrapper.h index 834e436c0c8..29dce8124b5 100644 --- a/js/src/xpconnect/src/XPCWrapper.h +++ b/js/src/xpconnect/src/XPCWrapper.h @@ -60,8 +60,6 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject); } // namespace XPCNativeWrapper -extern nsIScriptSecurityManager *gScriptSecurityManager; - // This namespace wraps some common functionality between the three existing // wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both // as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to @@ -75,7 +73,7 @@ namespace XPCWrapper { inline nsIScriptSecurityManager * GetSecurityManager() { - return ::gScriptSecurityManager; + return nsXPConnect::gScriptSecurityManager; } inline JSBool diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 28c443c404e..1711f54c8d0 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -75,7 +75,7 @@ PRUint32 nsXPConnect::gReportAllJSExceptions = 0; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) -nsIScriptSecurityManager *gScriptSecurityManager = nsnull; +nsIScriptSecurityManager *nsXPConnect::gScriptSecurityManager = nsnull; const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1"; const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1"; @@ -939,69 +939,105 @@ static JSClass xpcTempGlobalClass = { JSCLASS_NO_OPTIONAL_MEMBERS }; +static bool +CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, + xpc::CompartmentPrivate *priv, JSObject **global, + JSCompartment **compartment) +{ + // We take ownership of |priv|. Ensure that either we free it in the case + // of failure or give ownership to the compartment in case of success (in + // that case it will be free'd in CompartmentCallback during GC). + nsAutoPtr priv_holder(priv); + JSPrincipals *principals = nsnull; + if(principal) + principal->GetJSPrincipals(cx, &principals); + JSObject *tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals); + if(principals) + JSPRINCIPALS_DROP(cx, principals); + + if(!tempGlobal) + return false; + + *global = tempGlobal; + *compartment = tempGlobal->getCompartment(); + + js::SwitchToCompartment sc(cx, *compartment); + JS_SetCompartmentPrivate(cx, *compartment, priv_holder.forget()); + return true; +} + nsresult xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, - const nsACString &origin, nsIPrincipal *principal, + nsIPrincipal *principal, nsISupports *ptr, bool wantXrays, JSObject **global, JSCompartment **compartment) { + NS_ABORT_IF_FALSE(NS_IsMainThread(), "using a principal off the main thread?"); + NS_ABORT_IF_FALSE(principal, "bad key"); + + nsCOMPtr uri; + nsresult rv = principal->GetURI(getter_AddRefs(uri)); + if(NS_FAILED(rv)) + return UnexpectedFailure(rv); + XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap(); - nsCAutoString local_origin(origin); - if(local_origin.EqualsLiteral("file://") && principal) + xpc::PtrAndPrincipalHashKey key(ptr, uri); + if(!map.Get(&key, compartment)) { - nsCOMPtr uri; - principal->GetURI(getter_AddRefs(uri)); - uri->GetSpec(local_origin); - } - - JSObject *tempGlobal; - if(!map.Get(local_origin, compartment)) - { - JSPrincipals *principals = nsnull; - if(principal) - principal->GetJSPrincipals(cx, &principals); - tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals); - if(principals) - JSPRINCIPALS_DROP(cx, principals); - - if(!tempGlobal) - return UnexpectedFailure(NS_ERROR_FAILURE); - - *global = tempGlobal; - *compartment = tempGlobal->getCompartment(); - - js::SwitchToCompartment sc(cx, *compartment); - + xpc::PtrAndPrincipalHashKey *priv_key = + new xpc::PtrAndPrincipalHashKey(ptr, uri); xpc::CompartmentPrivate *priv = - new xpc::CompartmentPrivate(ToNewCString(local_origin), wantXrays); - JS_SetCompartmentPrivate(cx, *compartment, priv); - map.Put(local_origin, *compartment); + new xpc::CompartmentPrivate(priv_key, wantXrays); + if(!CreateNewCompartment(cx, clasp, principal, priv, + global, compartment)) + { + return UnexpectedFailure(NS_ERROR_FAILURE); + } + + map.Put(&key, *compartment); } else { js::SwitchToCompartment sc(cx, *compartment); -#ifdef DEBUG - if(principal) - { - nsIPrincipal *cprincipal = xpc::AccessCheck::getPrincipal(*compartment); - PRBool equals; - nsresult rv = cprincipal->Equals(principal, &equals); - NS_ASSERTION(NS_SUCCEEDED(rv), "bad Equals implementation"); - if(!equals) - { - nsCOMPtr domain; - cprincipal->GetDomain(getter_AddRefs(domain)); - if(!domain) - { - principal->GetDomain(getter_AddRefs(domain)); - NS_ASSERTION(!domain, "bad mixing"); - } - } - } -#endif - - tempGlobal = JS_NewGlobalObject(cx, clasp); + JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp); + if(!tempGlobal) + return UnexpectedFailure(NS_ERROR_FAILURE); + *global = tempGlobal; + } + + return NS_OK; +} + +nsresult +xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, + nsISupports *ptr, JSObject **global, + JSCompartment **compartment) +{ + // NB: We can be either on or off the main thread here. + XPCMTCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetMTCompartmentMap(); + if(!map.Get(ptr, compartment)) + { + // We allow the pointer to be a principal, in which case it becomes + // the principal for the newly created compartment. The caller is + // responsible for ensuring that doing this doesn't violate + // threadsafety assumptions. + nsCOMPtr principal(do_QueryInterface(ptr)); + xpc::CompartmentPrivate *priv = + new xpc::CompartmentPrivate(ptr, false); + if(!CreateNewCompartment(cx, clasp, principal, priv, global, + compartment)) + { + return UnexpectedFailure(NS_ERROR_UNEXPECTED); + } + + map.Put(ptr, *compartment); + } + else + { + js::SwitchToCompartment sc(cx, *compartment); + + JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp); if(!tempGlobal) return UnexpectedFailure(NS_ERROR_FAILURE); *global = tempGlobal; @@ -1010,20 +1046,19 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, return NS_OK; } -/* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */ NS_IMETHODIMP nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsISupports *aCOMObj, const nsIID & aIID, nsIPrincipal * aPrincipal, - const nsACString & aOrigin, + nsISupports * aExtraPtr, PRUint32 aFlags, nsIXPConnectJSObjectHolder **_retval) { NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aCOMObj, "bad param"); NS_ASSERTION(_retval, "bad param"); - NS_ASSERTION(!aOrigin.IsEmpty() || aPrincipal, "must be able to assign an origin"); + NS_ASSERTION(aExtraPtr || aPrincipal, "must be able to find a compartment"); // XXX This is not pretty. We make a temporary global object and // init it with all the Components object junk just so we have a @@ -1032,18 +1067,16 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, XPCCallContext ccx(NATIVE_CALLER, aJSContext); - nsCString origin; - if(aOrigin.IsEmpty()) - aPrincipal->GetOrigin(getter_Copies(origin)); - else - origin = aOrigin; - JSCompartment* compartment; JSObject* tempGlobal; - nsresult rv = xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, origin, - aPrincipal, false, &tempGlobal, - &compartment); + nsresult rv = aPrincipal + ? xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, aPrincipal, + aExtraPtr, false, &tempGlobal, + &compartment) + : xpc_CreateMTGlobalObject(ccx, &xpcTempGlobalClass, + aExtraPtr, &tempGlobal, + &compartment); NS_ENSURE_SUCCESS(rv, rv); JSAutoEnterCompartment ac; diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index dcc32d2edd4..08951e1f3f9 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -3174,6 +3174,15 @@ WrapForSandbox(JSContext *cx, bool wantXrays, jsval *vp) : xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp); } +// Needed to distinguish multiple compartments with the same origin from each +// other. The only thing we need out of identity objects are unique addresses. +class Identity : public nsISupports +{ + NS_DECL_ISUPPORTS +}; + +NS_IMPL_ISUPPORTS0(Identity) + nsresult xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto, bool wantXrays) @@ -3209,25 +3218,12 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSOb } nsIPrincipal *principal = sop->GetPrincipal(); - nsAdoptingCString principalorigin; - principal->GetOrigin(getter_Copies(principalorigin)); - - nsCAutoString origin("sandbox:"); - origin.Append(principalorigin); - - nsRefPtr nullPrincipal = new nsNullPrincipal(); - rv = nullPrincipal->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = nullPrincipal->GetOrigin(getter_Copies(principalorigin)); - NS_ENSURE_SUCCESS(rv, rv); - - origin.Append(principalorigin); JSCompartment *compartment; JSObject *sandbox; - rv = xpc_CreateGlobalObject(cx, &SandboxClass, origin, principal, + nsRefPtr identity = new Identity(); + rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identity, wantXrays, &sandbox, &compartment); NS_ENSURE_SUCCESS(rv, rv); diff --git a/js/src/xpconnect/src/xpcinlines.h b/js/src/xpconnect/src/xpcinlines.h index f55c05be478..d146e326720 100644 --- a/js/src/xpconnect/src/xpcinlines.h +++ b/js/src/xpconnect/src/xpcinlines.h @@ -44,6 +44,19 @@ #define xpcinlines_h___ /***************************************************************************/ +PRBool +xpc::PtrAndPrincipalHashKey::KeyEquals(const PtrAndPrincipalHashKey* aKey) const +{ + if(aKey->mPtr != mPtr) + return PR_FALSE; + + if(!mURI || !aKey->mURI) + return mURI == aKey->mURI; + + nsIScriptSecurityManager *ssm = nsXPConnect::gScriptSecurityManager; + return !ssm || NS_SUCCEEDED(ssm->CheckSameOriginURI(mURI, aKey->mURI, PR_FALSE)); +} + inline void XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant) { diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index e780a383916..e745826f8d0 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -246,24 +246,37 @@ CompartmentCallback(JSContext *cx, JSCompartment *compartment, uintN op) if(!self) return JS_TRUE; - XPCCompartmentMap& map = self->GetCompartmentMap(); nsAutoPtr priv( static_cast(JS_SetCompartmentPrivate(cx, compartment, nsnull))); - if (!priv) + if(!priv) return JS_TRUE; - nsAdoptingCString origin; - origin.Adopt(static_cast(priv->origin)); - -#ifdef DEBUG + if(xpc::PtrAndPrincipalHashKey *key = priv->key) { - JSCompartment *current; - NS_ASSERTION(map.Get(origin, ¤t), "no compartment?"); - NS_ASSERTION(current == compartment, "compartment mismatch"); - } + XPCCompartmentMap &map = self->GetCompartmentMap(); +#ifdef DEBUG + { + JSCompartment *current; + NS_ASSERTION(map.Get(key, ¤t), "no compartment?"); + NS_ASSERTION(current == compartment, "compartment mismatch"); + } #endif + map.Remove(key); + } + else + { + nsISupports *ptr = priv->ptr; + XPCMTCompartmentMap &map = self->GetMTCompartmentMap(); +#ifdef DEBUG + { + JSCompartment *current; + NS_ASSERTION(map.Get(ptr, ¤t), "no compartment?"); + NS_ASSERTION(current == compartment, "compartment mismatch"); + } +#endif + map.Remove(ptr); + } - map.Remove(origin); return JS_TRUE; } @@ -1168,6 +1181,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) mJSHolders.ops = nsnull; mCompartmentMap.Init(); + mMTCompartmentMap.Init(); // Install a JavaScript 'debugger' keyword handler in debug builds only #ifdef DEBUG diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index daa14be8756..e749c7de227 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -117,6 +117,9 @@ #include "nsWrapperCache.h" #include "nsStringBuffer.h" +#include "nsIScriptSecurityManager.h" +#include "nsNetUtil.h" + #include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated #ifndef XPCONNECT_STANDALONE @@ -242,7 +245,75 @@ extern const char XPC_SCRIPT_ERROR_CONTRACTID[]; extern const char XPC_ID_CONTRACTID[]; extern const char XPC_XPCONNECT_CONTRACTID[]; -typedef nsDataHashtableMT XPCCompartmentMap; +namespace xpc { + +class PtrAndPrincipalHashKey : public PLDHashEntryHdr +{ + public: + typedef PtrAndPrincipalHashKey *KeyType; + typedef const PtrAndPrincipalHashKey *KeyTypePointer; + + PtrAndPrincipalHashKey(const PtrAndPrincipalHashKey *aKey) + : mPtr(aKey->mPtr), mURI(aKey->mURI), mSavedHash(aKey->mSavedHash) + { + MOZ_COUNT_CTOR(PtrAndPrincipalHashKey); + } + + PtrAndPrincipalHashKey(nsISupports *aPtr, nsIURI *aURI) + : mPtr(aPtr), mURI(aURI) + { + MOZ_COUNT_CTOR(PtrAndPrincipalHashKey); + mSavedHash = mURI + ? NS_SecurityHashURI(mURI) + : (NS_PTR_TO_UINT32(mPtr.get()) >> 2); + } + + ~PtrAndPrincipalHashKey() + { + MOZ_COUNT_DTOR(PtrAndPrincipalHashKey); + } + + PtrAndPrincipalHashKey* GetKey() const + { + return const_cast(this); + } + const PtrAndPrincipalHashKey* GetKeyPointer() const { return this; } + + inline PRBool KeyEquals(const PtrAndPrincipalHashKey* aKey) const; + + static const PtrAndPrincipalHashKey* + KeyToPointer(PtrAndPrincipalHashKey* aKey) { return aKey; } + static PLDHashNumber HashKey(const PtrAndPrincipalHashKey* aKey) + { + return aKey->mSavedHash; + } + + enum { ALLOW_MEMMOVE = PR_TRUE }; + + protected: + nsCOMPtr mPtr; + nsCOMPtr mURI; + + // During shutdown, when we GC, we need to remove these keys from the hash + // table. However, computing the saved hash, NS_SecurityHashURI calls back + // into XPCOM (which is illegal during shutdown). In order to avoid this, + // we compute the hash up front, so when we're in GC during shutdown, we + // don't have to call into XPCOM. + PLDHashNumber mSavedHash; +}; + +} + +// NB: nsDataHashtableMT is usually not very useful as all it does is lock +// around each individual operation performed on it. That would imply, that +// the pattern: if(!map.Get(key)) map.Put(key, value); is not safe as another +// thread could race to insert key into map. However, in our case, only one +// thread at any time could attempt to insert |key| into |map|, so it works +// well enough for our uses. +typedef nsDataHashtableMT XPCMTCompartmentMap; + +// This map is only used on the main thread. +typedef nsDataHashtable XPCCompartmentMap; /***************************************************************************/ // useful macros... @@ -555,6 +626,9 @@ private: nsCOMPtr mBackstagePass; static PRUint32 gReportAllJSExceptions; + +public: + static nsIScriptSecurityManager *gScriptSecurityManager; }; /***************************************************************************/ @@ -631,6 +705,8 @@ public: XPCCompartmentMap& GetCompartmentMap() {return mCompartmentMap;} + XPCMTCompartmentMap& GetMTCompartmentMap() + {return mMTCompartmentMap;} XPCLock* GetMapLock() const {return mMapLock;} @@ -754,6 +830,7 @@ private: XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap; XPCNativeWrapperMap* mExplicitNativeWrapperMap; XPCCompartmentMap mCompartmentMap; + XPCMTCompartmentMap mMTCompartmentMap; XPCLock* mMapLock; PRThread* mThreadRunningGC; nsTArray mWrappedJSToReleaseArray; @@ -4431,12 +4508,22 @@ namespace xpc { struct CompartmentPrivate { - CompartmentPrivate(char *origin, bool wantXrays) - : origin(origin), + CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays) + : key(key), + ptr(nsnull), wantXrays(wantXrays) { } - char *origin; + CompartmentPrivate(nsISupports *ptr, bool wantXrays) + : key(nsnull), + ptr(ptr), + wantXrays(wantXrays) + { + } + + // NB: key and ptr are mutually exclusive. + nsAutoPtr key; + nsCOMPtr ptr; bool wantXrays; }; diff --git a/js/src/xpconnect/src/xpcpublic.h b/js/src/xpconnect/src/xpcpublic.h index 2f9d40f046c..3be157907f0 100644 --- a/js/src/xpconnect/src/xpcpublic.h +++ b/js/src/xpconnect/src/xpcpublic.h @@ -41,13 +41,19 @@ #define xpcpublic_h #include "jsapi.h" -#include "nsAString.h" -#include "nsIPrincipal.h" +#include "nsISupports.h" + +class nsIPrincipal; nsresult xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp, - const nsACString &origin, nsIPrincipal *principal, + nsIPrincipal *principal, nsISupports *ptr, bool wantXrays, JSObject **global, JSCompartment **compartment); +nsresult +xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp, + nsISupports *ptr, JSObject **global, + JSCompartment **compartment); + #endif diff --git a/js/src/xpconnect/src/xpcthreadcontext.cpp b/js/src/xpconnect/src/xpcthreadcontext.cpp index ec4e40c8e8c..9c2805b65e0 100644 --- a/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -259,16 +259,16 @@ XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext) mSafeJSContext = JS_NewContext(rt, 8192); if(mSafeJSContext) { - nsCString origin; - principal->GetOrigin(getter_Copies(origin)); - // scoped JS Request JSAutoRequest req(mSafeJSContext); + // Because we can run off the main thread, we create an MT + // global object. Our principal is the unique key. JSCompartment *compartment; - nsresult rv = xpc_CreateGlobalObject(mSafeJSContext, &global_class, - origin, principal, false, &glob, - &compartment); + nsresult rv = xpc_CreateMTGlobalObject(mSafeJSContext, + &global_class, + principal, &glob, + &compartment); if(NS_FAILED(rv)) glob = nsnull; From 6b5b74d5417edf065a1fb42b280d4df840f1fc4d Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 27 Oct 2010 10:18:24 +0300 Subject: [PATCH 112/263] Bug 604660 - Make XSLT-inserted script execute in the insertion order. r=jonas, a=blocking2.0-beta7. --HG-- extra : rebase_source : fde633f62de8b4ec5af5c85f21c01ed4781e06e3 --- content/base/public/FromParser.h | 3 +- content/base/public/nsIScriptElement.h | 5 +- content/base/src/nsScriptLoader.cpp | 53 ++++++++++++-- content/base/src/nsScriptLoader.h | 1 + content/base/test/Makefile.in | 7 ++ content/base/test/file_bug604660-1.xml | 3 + content/base/test/file_bug604660-2.xsl | 19 +++++ content/base/test/file_bug604660-3.js | 1 + content/base/test/file_bug604660-4.js | 1 + content/base/test/file_bug604660-5.xml | 2 + content/base/test/file_bug604660-6.xsl | 9 +++ content/base/test/test_bug604660.html | 77 ++++++++++++++++++++ content/xslt/src/xslt/txMozillaXMLOutput.cpp | 45 ++++++++++-- 13 files changed, 211 insertions(+), 15 deletions(-) create mode 100644 content/base/test/file_bug604660-1.xml create mode 100644 content/base/test/file_bug604660-2.xsl create mode 100644 content/base/test/file_bug604660-3.js create mode 100644 content/base/test/file_bug604660-4.js create mode 100644 content/base/test/file_bug604660-5.xml create mode 100644 content/base/test/file_bug604660-6.xsl create mode 100644 content/base/test/test_bug604660.html diff --git a/content/base/public/FromParser.h b/content/base/public/FromParser.h index 7650b2e1260..3a2d7d064e0 100644 --- a/content/base/public/FromParser.h +++ b/content/base/public/FromParser.h @@ -47,7 +47,8 @@ enum FromParser { NOT_FROM_PARSER = 0, FROM_PARSER_NETWORK = 1, FROM_PARSER_DOCUMENT_WRITE = 1 << 1, - FROM_PARSER_FRAGMENT = 1 << 2 + FROM_PARSER_FRAGMENT = 1 << 2, + FROM_PARSER_XSLT = 1 << 3 }; } // namespace dom diff --git a/content/base/public/nsIScriptElement.h b/content/base/public/nsIScriptElement.h index 7922d9abbe1..8669fa4e82b 100644 --- a/content/base/public/nsIScriptElement.h +++ b/content/base/public/nsIScriptElement.h @@ -66,7 +66,10 @@ public: mFrozen(PR_FALSE), mDefer(PR_FALSE), mAsync(PR_FALSE), - mParserCreated(aFromParser), + mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT ? + mozilla::dom::NOT_FROM_PARSER : aFromParser), + // Fragment parser-created scripts (if executable) + // behave like script-created scripts. mCreatorParser(nsnull) { } diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 1132056086f..13f84ee0adf 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -157,6 +157,10 @@ nsScriptLoader::~nsScriptLoader() mParserBlockingRequest->FireScriptAvailable(NS_ERROR_ABORT); } + for (PRUint32 i = 0; i < mXSLTRequests.Length(); i++) { + mXSLTRequests[i]->FireScriptAvailable(NS_ERROR_ABORT); + } + for (PRUint32 i = 0; i < mDeferRequests.Length(); i++) { mDeferRequests[i]->FireScriptAvailable(NS_ERROR_ABORT); } @@ -577,8 +581,9 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // a parser-inserted script is being run, we came here by the parser // running the script, which means the parser is still alive and the // parse is ongoing. - NS_ASSERTION(mDocument->GetCurrentContentSink(), - "Defer script on a document without an active parser; bug 592366."); + NS_ASSERTION(mDocument->GetCurrentContentSink() || + aElement->GetParserCreated() == FROM_PARSER_XSLT, + "Non-XSLT Defer script on a document without an active parser; bug 592366."); mDeferRequests.AppendElement(request); return NS_OK; } @@ -591,6 +596,19 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) } return NS_OK; } + + if (aElement->GetParserCreated() == FROM_PARSER_XSLT) { + // Need to maintain order for XSLT-inserted scripts + NS_ASSERTION(!mParserBlockingRequest, + "Parser-blocking scripts and XSLT scripts in the same doc!"); + mXSLTRequests.AppendElement(request); + if (!request->mLoading) { + // The script is available already. Run it ASAP when the event + // loop gets a chance to spin. + ProcessPendingRequestsAsync(); + } + return NS_ERROR_HTMLPARSER_BLOCK; + } if (!request->mLoading && ReadyToExecuteScripts()) { // The request has already been loaded and there are no pending style // sheets. If the script comes from the network stream, cheat for @@ -603,6 +621,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // Web page. NS_ASSERTION(!mParserBlockingRequest, "There can be only one parser-blocking script at a time"); + NS_ASSERTION(mXSLTRequests.IsEmpty(), + "Parser-blocking scripts and XSLT scripts in the same doc!"); mParserBlockingRequest = request; ProcessPendingRequestsAsync(); return NS_ERROR_HTMLPARSER_BLOCK; @@ -611,6 +631,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // The script will be run when it loads or the style sheet loads. NS_ASSERTION(!mParserBlockingRequest, "There can be only one parser-blocking script at a time"); + NS_ASSERTION(mXSLTRequests.IsEmpty(), + "Parser-blocking scripts and XSLT scripts in the same doc!"); mParserBlockingRequest = request; return NS_ERROR_HTMLPARSER_BLOCK; } @@ -641,6 +663,14 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) request->mURI = mDocument->GetDocumentURI(); request->mLineNo = aElement->GetScriptLineNumber(); + if (aElement->GetParserCreated() == FROM_PARSER_XSLT && + (!ReadyToExecuteScripts() || !mXSLTRequests.IsEmpty())) { + // Need to maintain order for XSLT-inserted scripts + NS_ASSERTION(!mParserBlockingRequest, + "Parser-blocking scripts and XSLT scripts in the same doc!"); + mXSLTRequests.AppendElement(request); + return NS_ERROR_HTMLPARSER_BLOCK; + } if (aElement->GetParserCreated() == NOT_FROM_PARSER) { NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), "A script-inserted script is inserted without an update batch?"); @@ -653,6 +683,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) NS_ASSERTION(!mParserBlockingRequest, "There can be only one parser-blocking script at a time"); mParserBlockingRequest = request; + NS_ASSERTION(mXSLTRequests.IsEmpty(), + "Parser-blocking scripts and XSLT scripts in the same doc!"); return NS_ERROR_HTMLPARSER_BLOCK; } // We now have a document.written inline script or we have an inline script @@ -856,6 +888,14 @@ nsScriptLoader::ProcessPendingRequests() ProcessRequest(request); } + while (ReadyToExecuteScripts() && + !mXSLTRequests.IsEmpty() && + !mXSLTRequests[0]->mLoading) { + request.swap(mXSLTRequests[0]); + mXSLTRequests.RemoveElementAt(0); + ProcessRequest(request); + } + PRUint32 i = 0; while (mEnabled && i < mAsyncRequests.Length()) { if (!mAsyncRequests[i]->mLoading) { @@ -867,7 +907,7 @@ nsScriptLoader::ProcessPendingRequests() ++i; } - if (mDocumentParsingDone) { + if (mDocumentParsingDone && mXSLTRequests.IsEmpty()) { while (!mDeferRequests.IsEmpty() && !mDeferRequests[0]->mLoading) { request.swap(mDeferRequests[0]); mDeferRequests.RemoveElementAt(0); @@ -883,7 +923,7 @@ nsScriptLoader::ProcessPendingRequests() if (mDocumentParsingDone && mDocument && !mParserBlockingRequest && mAsyncRequests.IsEmpty() && - mDeferRequests.IsEmpty()) { + mXSLTRequests.IsEmpty() && mDeferRequests.IsEmpty()) { // No more pending scripts; time to unblock onload. // OK to unblock onload synchronously here, since callers must be // prepared for the world changing anyway. @@ -1053,7 +1093,8 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader, aString); if (NS_FAILED(rv)) { if (mDeferRequests.RemoveElement(request) || - mAsyncRequests.RemoveElement(request)) { + mAsyncRequests.RemoveElement(request) || + mXSLTRequests.RemoveElement(request)) { FireScriptAvailable(rv, request); } else if (mParserBlockingRequest == request) { mParserBlockingRequest = nsnull; @@ -1131,6 +1172,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest, // wrong, especially if you see it more than once. NS_ASSERTION(mDeferRequests.IndexOf(aRequest) >= 0 || mAsyncRequests.IndexOf(aRequest) >= 0 || + mXSLTRequests.IndexOf(aRequest) >= 0 || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest, "aRequest should be pending!"); @@ -1183,6 +1225,7 @@ nsScriptLoader::ParsingComplete(PRBool aTerminated) if (aTerminated) { mDeferRequests.Clear(); mAsyncRequests.Clear(); + mXSLTRequests.Clear(); mParserBlockingRequest = nsnull; } diff --git a/content/base/src/nsScriptLoader.h b/content/base/src/nsScriptLoader.h index 06b3213d5c8..01bb588f7ba 100644 --- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -299,6 +299,7 @@ private: nsCOMArray mObservers; nsTArray > mAsyncRequests; nsTArray > mDeferRequests; + nsTArray > mXSLTRequests; nsRefPtr mParserBlockingRequest; // In mRequests, the additional information here is stored by the element. diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 76c2189b435..303d80ea736 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -431,6 +431,13 @@ _TEST_FILES2 = \ test_bug601803.html \ file_bug601803a.html \ file_bug601803b.html \ + test_bug604660.html \ + file_bug604660-1.xml \ + file_bug604660-2.xsl \ + file_bug604660-3.js \ + file_bug604660-4.js \ + file_bug604660-5.xml \ + file_bug604660-6.xsl \ test_bug605982.html \ $(NULL) diff --git a/content/base/test/file_bug604660-1.xml b/content/base/test/file_bug604660-1.xml new file mode 100644 index 00000000000..231b4357d60 --- /dev/null +++ b/content/base/test/file_bug604660-1.xml @@ -0,0 +1,3 @@ + + + diff --git a/content/base/test/file_bug604660-2.xsl b/content/base/test/file_bug604660-2.xsl new file mode 100644 index 00000000000..16611726ce4 --- /dev/null +++ b/content/base/test/file_bug604660-2.xsl @@ -0,0 +1,19 @@ + + + + + + XSLT script execution test + + + + + + + + + + + + + diff --git a/content/base/test/file_bug604660-3.js b/content/base/test/file_bug604660-3.js new file mode 100644 index 00000000000..c11ae68f281 --- /dev/null +++ b/content/base/test/file_bug604660-3.js @@ -0,0 +1 @@ +parent.scriptRan(2); diff --git a/content/base/test/file_bug604660-4.js b/content/base/test/file_bug604660-4.js new file mode 100644 index 00000000000..2bd5b43e5b9 --- /dev/null +++ b/content/base/test/file_bug604660-4.js @@ -0,0 +1 @@ +parent.scriptRan(4); diff --git a/content/base/test/file_bug604660-5.xml b/content/base/test/file_bug604660-5.xml new file mode 100644 index 00000000000..58c6382836f --- /dev/null +++ b/content/base/test/file_bug604660-5.xml @@ -0,0 +1,2 @@ + + diff --git a/content/base/test/file_bug604660-6.xsl b/content/base/test/file_bug604660-6.xsl new file mode 100644 index 00000000000..4a75777d90d --- /dev/null +++ b/content/base/test/file_bug604660-6.xsl @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/content/base/test/test_bug604660.html b/content/base/test/test_bug604660.html new file mode 100644 index 00000000000..0008c2dd568 --- /dev/null +++ b/content/base/test/test_bug604660.html @@ -0,0 +1,77 @@ + + + + + Test for Bug 604660 + + + + + +Mozilla Bug 604660 + +

+ +
+
+
+ + + diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.cpp b/content/xslt/src/xslt/txMozillaXMLOutput.cpp index b117ec4bd14..b2f8a38a897 100644 --- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -259,8 +259,15 @@ txMozillaXMLOutput::endDocument(nsresult aResult) return rv; } - // This should really be handled by nsIDocument::EndLoad - mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE); + + if (mCreatingNewDocument) { + // This should really be handled by nsIDocument::EndLoad + mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE); + nsScriptLoader* loader = mDocument->ScriptLoader(); + if (loader) { + loader->ParsingComplete(PR_FALSE); + } + } if (!mRefreshString.IsEmpty()) { nsPIDOMWindow *win = mDocument->GetWindow(); @@ -312,10 +319,18 @@ txMozillaXMLOutput::endElement() NS_ENSURE_SUCCESS(rv, rv); } - // Handle script elements - if (element->Tag() == nsGkAtoms::script && - (element->IsHTML() || - element->GetNameSpaceID() == kNameSpaceID_SVG)) { + // Handle elements that are different when parser-created + PRInt32 ns = element->GetNameSpaceID(); + nsIAtom* localName = element->Tag(); + + if ((ns == kNameSpaceID_XHTML && (localName == nsGkAtoms::script || + localName == nsGkAtoms::title || + localName == nsGkAtoms::object || + localName == nsGkAtoms::applet || + localName == nsGkAtoms::select || + localName == nsGkAtoms::textarea)) || + (ns == kNameSpaceID_SVG && (localName == nsGkAtoms::script || + localName == nsGkAtoms::title))) { rv = element->DoneAddingChildren(PR_TRUE); @@ -326,6 +341,10 @@ txMozillaXMLOutput::endElement() rv = mNotifier->AddScriptElement(sele); NS_ENSURE_SUCCESS(rv, rv); } + } else if (ns == kNameSpaceID_XHTML && + (localName == nsGkAtoms::input || + localName == nsGkAtoms::button)) { + element->DoneCreatingElement(); } } @@ -433,6 +452,13 @@ txMozillaXMLOutput::startDocument() mNotifier->OnTransformStart(); } + if (mCreatingNewDocument) { + nsScriptLoader* loader = mDocument->ScriptLoader(); + if (loader) { + loader->BeginDeferringScripts(); + } + } + return NS_OK; } @@ -539,7 +565,8 @@ txMozillaXMLOutput::startElementInternal(nsIAtom* aPrefix, NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY); NS_NewElement(getter_AddRefs(mOpenedElement), aNsID, ni.forget(), - NOT_FROM_PARSER); + mCreatingNewDocument ? + FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT); // Set up the element and adjust state if (!mNoFixup) { @@ -950,7 +977,9 @@ txMozillaXMLOutput::createHTMLElement(nsIAtom* aName, kNameSpaceID_XHTML); NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY); - return NS_NewHTMLElement(aResult, ni.forget(), NOT_FROM_PARSER); + return NS_NewHTMLElement(aResult, ni.forget(), mCreatingNewDocument ? + FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT); + } txTransformNotifier::txTransformNotifier() From 7a6327ec8ae65ab52cd30d8ce4af62b1ec8ceeef Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 28 Oct 2010 17:11:15 +0300 Subject: [PATCH 113/263] Bug 606192 - After drag & drop any link/text/image to contents area, mouse click chrome elements does not work, r=enndeakin, a=beltzner --- content/base/src/nsGenericElement.cpp | 2 +- content/events/src/nsEventStateManager.cpp | 19 ++++--- content/events/src/nsEventStateManager.h | 8 +-- .../html/content/src/nsHTMLButtonElement.cpp | 2 +- layout/base/tests/test_bug603550.html | 49 ++++++++++++++++++- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 9914309f194..556e2fb40dd 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -5325,7 +5325,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor) nsIEventStateManager* esm = aVisitor.mPresContext->EventStateManager(); - nsEventStateManager::SetGlobalActiveContent( + nsEventStateManager::SetActiveManager( static_cast(esm), this); } } diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 84f440ab501..7bb2c4be10a 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2074,6 +2074,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext, PRBool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer, targetContent, isSelection); if (dragStarted) { + sActiveESM = nsnull; aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH; } } @@ -2935,7 +2936,6 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, if (par) activeContent = par; } - SetGlobalActiveContent(this, activeContent); } } else { @@ -2943,11 +2943,12 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, // any of our own processing of a drag. Workaround for bug 43258. StopTrackingDragGesture(); } + SetActiveManager(this, activeContent); } break; case NS_MOUSE_BUTTON_UP: { - ClearGlobalActiveContent(); + ClearGlobalActiveContent(this); if (IsMouseEventReal(aEvent)) { if (!mCurrentTarget) { nsIFrame* targ; @@ -3206,6 +3207,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext, targetContent, &status); } } + ClearGlobalActiveContent(this); break; } case NS_DRAGDROP_EXIT: @@ -4706,22 +4708,25 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent) } void -nsEventStateManager::SetGlobalActiveContent(nsEventStateManager* aNewESM, - nsIContent* aContent) +nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM, + nsIContent* aContent) { if (sActiveESM && aNewESM != sActiveESM) { sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE); } sActiveESM = aNewESM; - if (sActiveESM) { + if (sActiveESM && aContent) { sActiveESM->SetContentState(aContent, NS_EVENT_STATE_ACTIVE); } } void -nsEventStateManager::ClearGlobalActiveContent() +nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer) { - if (sActiveESM) { + if (aClearer) { + aClearer->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE); + } + if (sActiveESM && aClearer != sActiveESM) { sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE); } sActiveESM = nsnull; diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index af1c64e61f0..4a7d85ba7cd 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -159,8 +159,10 @@ public: static nsIEventStateManager* GetActiveEventStateManager() { return sActiveESM; } - static void SetGlobalActiveContent(nsEventStateManager* aNewESM, - nsIContent* aContent); + // Sets aNewESM to be the active event state manager, and + // if aContent is non-null, marks the object as active. + static void SetActiveManager(nsEventStateManager* aNewESM, + nsIContent* aContent); protected: void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus); /** @@ -415,7 +417,7 @@ protected: static nsEventStateManager* sActiveESM; - static void ClearGlobalActiveContent(); + static void ClearGlobalActiveContent(nsEventStateManager* aClearer); // Functions used for click hold context menus PRBool mClickHoldContextMenu; diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index 091230e4aab..2420d21242a 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -439,7 +439,7 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) { nsIEventStateManager* esm = aVisitor.mPresContext->EventStateManager(); - nsEventStateManager::SetGlobalActiveContent( + nsEventStateManager::SetActiveManager( static_cast(esm), this); } nsIFocusManager* fm = nsFocusManager::GetFocusManager(); diff --git a/layout/base/tests/test_bug603550.html b/layout/base/tests/test_bug603550.html index daeb46c710c..e639035d1e5 100644 --- a/layout/base/tests/test_bug603550.html +++ b/layout/base/tests/test_bug603550.html @@ -54,6 +54,33 @@ function sendMouseUp(el) { utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0); } +function fireEvent(target, event) { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + var utils = + window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). + getInterface(Components.interfaces.nsIDOMWindowUtils); + utils.dispatchDOMEventViaPresShell(target, event, true); +} + +function fireDrop(element) { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + var ds = Components.classes["@mozilla.org/widget/dragservice;1"]. + getService(Components.interfaces.nsIDragService); + + ds.startDragSession(); + + var event = document.createEvent("DragEvents"); + event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null); + fireEvent(element, event); + + event = document.createEvent("DragEvents"); + event.initDragEvent("drop", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null); + fireEvent(element, event); + + ds.endDragSession(false); + ok(!ds.getCurrentSession(), "There shouldn't be a drag session anymore!"); +} + function runTest() { var d1 = document.getElementById("d1"); var didGetMouseMove = false; @@ -65,7 +92,27 @@ function runTest() { true); sendMouseMoveFaraway(d1); ok(didGetMouseMove, "Should have got mousemove!"); - sendMouseUp(d1) + sendMouseUp(d1); + + didGetMouseMove = false; + document.addEventListener("mousedown", + function (e) { + e.preventDefault(); + }, + true); + sendMouseDown(d1); + sendMouseMoveFaraway(d1); + ok(didGetMouseMove, "Should have got mousemove! (2)"); + sendMouseUp(d1); + + didGetMouseMove = false; + sendMouseDown(d1); + fireDrop(d1); + sendMouseMoveFaraway(d1); + ok(!didGetMouseMove, "Shouldn't have got mousemove!"); + + + SimpleTest.finish(); } From 1d9f2bbd55b52451cd77dd7c07e859fecfc1ee09 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Wed, 27 Oct 2010 14:35:00 -0400 Subject: [PATCH 114/263] Bug 566478 - Invalid SSL cert error is not mobile-friendly [r=kaie a=blocking-fennecb2] --- .../http/HttpChannelParentListener.cpp | 6 + security/manager/ssl/src/Makefile.in | 1 + security/manager/ssl/src/NSSErrorsService.cpp | 189 ++++++++++++++++++ security/manager/ssl/src/NSSErrorsService.h | 68 +++++++ security/manager/ssl/src/nsNSSComponent.cpp | 111 +--------- security/manager/ssl/src/nsNSSComponent.h | 4 +- security/manager/ssl/src/nsNSSIOLayer.cpp | 91 +++++---- security/manager/ssl/src/nsNSSModule.cpp | 8 +- 8 files changed, 324 insertions(+), 154 deletions(-) create mode 100644 security/manager/ssl/src/NSSErrorsService.cpp create mode 100644 security/manager/ssl/src/NSSErrorsService.h diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp index 8eaeee8c822..74fe14c70e4 100644 --- a/netwerk/protocol/http/HttpChannelParentListener.cpp +++ b/netwerk/protocol/http/HttpChannelParentListener.cpp @@ -143,6 +143,12 @@ HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result) return mActiveChannel->mTabParent->QueryInterface(aIID, result); } + if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) { + if (!mActiveChannel && !mActiveChannel->mTabParent) + return NS_NOINTERFACE; + return mActiveChannel->mTabParent->QueryInterface(aIID, result); + } + if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) { if (!mActiveChannel) return NS_NOINTERFACE; diff --git a/security/manager/ssl/src/Makefile.in b/security/manager/ssl/src/Makefile.in index 021aaf9841a..3709bf2ab87 100644 --- a/security/manager/ssl/src/Makefile.in +++ b/security/manager/ssl/src/Makefile.in @@ -102,6 +102,7 @@ CPPSRCS = \ nsIdentityChecking.cpp \ nsDataSignatureVerifier.cpp \ nsRandomGenerator.cpp \ + NSSErrorsService.cpp \ $(NULL) ifdef MOZ_XUL diff --git a/security/manager/ssl/src/NSSErrorsService.cpp b/security/manager/ssl/src/NSSErrorsService.cpp new file mode 100644 index 00000000000..1133012c7eb --- /dev/null +++ b/security/manager/ssl/src/NSSErrorsService.cpp @@ -0,0 +1,189 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Personal Security Manager. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Hubbie Shaw + * Doug Turner + * Mitch Stoltz + * Brian Ryner + * Kai Engert + * Vipul Gupta + * Douglas Stebila + * Kai Engert + * honzab.moz@firemni.cz + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "NSSErrorsService.h" + +#include "nsNSSComponent.h" +#include "nsServiceManagerUtils.h" +#include "secerr.h" +#include "sslerr.h" + +#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties" +#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties" + +namespace mozilla { +namespace psm { + +NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService) + +nsresult +NSSErrorsService::Init() +{ + nsresult rv; + nsCOMPtr bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); + if (NS_FAILED(rv) || !bundleService) + return NS_ERROR_FAILURE; + + bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL, + getter_AddRefs(mPIPNSSBundle)); + if (!mPIPNSSBundle) + rv = NS_ERROR_FAILURE; + + bundleService->CreateBundle(NSSERR_STRBUNDLE_URL, + getter_AddRefs(mNSSErrorsBundle)); + if (!mNSSErrorsBundle) + rv = NS_ERROR_FAILURE; + + return rv; +} + +#define EXPECTED_SEC_ERROR_BASE (-0x2000) +#define EXPECTED_SSL_ERROR_BASE (-0x3000) + +#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE +#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" +/* + * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 + * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. + * The current code also assumes that NSS library error codes are negative. + */ +#endif + +NS_IMETHODIMP +NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) +{ + if (!_retval) + return NS_ERROR_FAILURE; + + *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) +{ + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + if (!aXPCOMErrorCode) + return NS_ERROR_INVALID_ARG; + + // The error codes within each module may be a 16 bit value. + // For simplicity let's use the positive value of the NSS code. + + *aXPCOMErrorCode = + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, + -1 * aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) +{ + NS_ENSURE_ARG(aErrorClass); + + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + switch (aNSPRCode) + { + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_UNTRUSTED_ISSUER: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_UNTRUSTED_CERT: + case SEC_ERROR_INADEQUATE_KEY_USAGE: + case SSL_ERROR_BAD_CERT_DOMAIN: + case SEC_ERROR_EXPIRED_CERTIFICATE: + *aErrorClass = ERROR_CLASS_BAD_CERT; + break; + default: + *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; + break; + } + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) +{ + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + nsCOMPtr theBundle = mPIPNSSBundle; + const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); + + if (!id_str) { + id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); + theBundle = mNSSErrorsBundle; + } + + if (!id_str || !theBundle) + return NS_ERROR_FAILURE; + + nsAutoString msg; + nsresult rv = + theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), + getter_Copies(msg)); + if (NS_SUCCEEDED(rv)) { + aErrorMessage = msg; + } + return rv; +} + +} // psm +} // mozilla diff --git a/security/manager/ssl/src/NSSErrorsService.h b/security/manager/ssl/src/NSSErrorsService.h new file mode 100644 index 00000000000..c87d9b79a81 --- /dev/null +++ b/security/manager/ssl/src/NSSErrorsService.h @@ -0,0 +1,68 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Personal Security Manager. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Hubbie Shaw + * Doug Turner + * Brian Ryner + * Kai Engert + * Kai Engert + * honzab.moz@firemni.cz + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsINSSErrorsService.h" + +#include "nsIStringBundle.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace psm { + +class NSSErrorsService : public nsINSSErrorsService +{ + NS_DECL_ISUPPORTS + NS_DECL_NSINSSERRORSSERVICE + +public: + nsresult Init(); + +private: + nsCOMPtr mPIPNSSBundle; + nsCOMPtr mNSSErrorsBundle; +}; + +} // psm +} // mozilla + +#define NS_NSSERRORSSERVICE_CID \ + { 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } } diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 487dc513bd3..e2340c9dff6 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1953,14 +1953,13 @@ nsNSSComponent::Init() } /* nsISupports Implementation for the class */ -NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent, +NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent, nsISignatureVerifier, nsIEntropyCollector, nsINSSComponent, nsIObserver, nsISupportsWeakReference, - nsITimerCallback, - nsINSSErrorsService) + nsITimerCallback) /* Callback functions for decoder. For now, use empty/default functions. */ @@ -2453,112 +2452,6 @@ nsNSSComponent::RememberCert(CERTCertificate *cert) return NS_OK; } -#define EXPECTED_SEC_ERROR_BASE (-0x2000) -#define EXPECTED_SSL_ERROR_BASE (-0x3000) - -#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE -#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" -/* - * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 - * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. - * The current code also assumes that NSS library error codes are negative. - */ -#endif - -NS_IMETHODIMP -nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) -{ - if (!_retval) - return NS_ERROR_FAILURE; - - *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) -{ - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - if (!aXPCOMErrorCode) - return NS_ERROR_INVALID_ARG; - - // The error codes within each module may be a 16 bit value. - // For simplicity let's use the positive value of the NSS code. - - *aXPCOMErrorCode = - NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, - -1 * aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) -{ - NS_ENSURE_ARG(aErrorClass); - - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - switch (aNSPRCode) - { - case SEC_ERROR_UNKNOWN_ISSUER: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_UNTRUSTED_ISSUER: - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - case SEC_ERROR_UNTRUSTED_CERT: - case SEC_ERROR_INADEQUATE_KEY_USAGE: - case SSL_ERROR_BAD_CERT_DOMAIN: - case SEC_ERROR_EXPIRED_CERTIFICATE: - *aErrorClass = ERROR_CLASS_BAD_CERT; - break; - default: - *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; - break; - } - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) -{ - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - nsCOMPtr theBundle = mPIPNSSBundle; - const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); - - if (!id_str) { - id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); - theBundle = mNSSErrorsBundle; - } - - if (!id_str || !theBundle) - return NS_ERROR_FAILURE; - - nsAutoString msg; - nsresult rv = - theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), - getter_Copies(msg)); - if (NS_SUCCEEDED(rv)) { - aErrorMessage = msg; - } - return rv; -} - void nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject) { diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index 2066ef59a47..7f255e5a309 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -239,8 +239,7 @@ class nsNSSComponent : public nsISignatureVerifier, public nsINSSComponent, public nsIObserver, public nsSupportsWeakReference, - public nsITimerCallback, - public nsINSSErrorsService + public nsITimerCallback { public: NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID ) @@ -253,7 +252,6 @@ public: NS_DECL_NSIENTROPYCOLLECTOR NS_DECL_NSIOBSERVER NS_DECL_NSITIMERCALLBACK - NS_DECL_NSINSSERRORSSERVICE NS_METHOD Init(); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 80a5a398d20..5b8bcd1dfd7 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -379,54 +379,63 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown() // with a socket close, and the socket transport might detach the callbacks // instance prior to our error reporting. - nsCOMPtr docshell; + nsISecureBrowserUI* secureUI = nsnull; +#ifdef MOZ_IPC + CallGetInterface(proxiedCallbacks.get(), &secureUI); +#endif - nsCOMPtr item(do_GetInterface(proxiedCallbacks)); - if (item) + if (!secureUI) { - nsCOMPtr proxiedItem; - nsCOMPtr rootItem; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIDocShellTreeItem), - item.get(), - NS_PROXY_SYNC, - getter_AddRefs(proxiedItem)); + nsCOMPtr docshell; - proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem)); - docshell = do_QueryInterface(rootItem); - NS_ASSERTION(docshell, "rootItem do_QI is null"); + nsCOMPtr item(do_GetInterface(proxiedCallbacks)); + if (item) + { + nsCOMPtr proxiedItem; + nsCOMPtr rootItem; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIDocShellTreeItem), + item.get(), + NS_PROXY_SYNC, + getter_AddRefs(proxiedItem)); + + proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem)); + docshell = do_QueryInterface(rootItem); + NS_ASSERTION(docshell, "rootItem do_QI is null"); + } + + if (docshell) + { + nsCOMPtr proxiedDocShell; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIDocShell), + docshell.get(), + NS_PROXY_SYNC, + getter_AddRefs(proxiedDocShell)); + nsISecureBrowserUI* secureUI = nsnull; + if (proxiedDocShell) + proxiedDocShell->GetSecurityUI(&secureUI); + } } - if (docshell) + if (secureUI) { - nsCOMPtr proxiedDocShell; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIDocShell), - docshell.get(), - NS_PROXY_SYNC, - getter_AddRefs(proxiedDocShell)); - nsISecureBrowserUI* secureUI = nsnull; - if (proxiedDocShell) - proxiedDocShell->GetSecurityUI(&secureUI); - if (secureUI) - { - nsCOMPtr mainThread(do_GetMainThread()); - NS_ProxyRelease(mainThread, secureUI, PR_FALSE); - mExternalErrorReporting = PR_TRUE; + nsCOMPtr mainThread(do_GetMainThread()); + NS_ProxyRelease(mainThread, secureUI, PR_FALSE); + mExternalErrorReporting = PR_TRUE; - // If this socket is associated to a docshell, let's try to remember - // the currently used cert. If this socket gets a notification from NSS - // having the same raw socket, we can keep the PSM wrapper object - // and all the data it has cached (like verification results). - nsCOMPtr statprov = do_QueryInterface(secureUI); - if (statprov) { - nsCOMPtr isup_stat; - statprov->GetSSLStatus(getter_AddRefs(isup_stat)); - if (isup_stat) { - nsCOMPtr sslstat = do_QueryInterface(isup_stat); - if (sslstat) { - sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); - } + // If this socket is associated to a docshell, let's try to remember + // the currently used cert. If this socket gets a notification from NSS + // having the same raw socket, we can keep the PSM wrapper object + // and all the data it has cached (like verification results). + nsCOMPtr statprov = do_QueryInterface(secureUI); + if (statprov) { + nsCOMPtr isup_stat; + statprov->GetSSLStatus(getter_AddRefs(isup_stat)); + if (isup_stat) { + nsCOMPtr sslstat = do_QueryInterface(isup_stat); + if (sslstat) { + sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); } } } diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index e6ec05c8e3b..178dc7424fb 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -78,6 +78,7 @@ #include "nsRecentBadCerts.h" #include "nsSSLStatus.h" #include "nsNSSIOLayer.h" +#include "NSSErrorsService.h" #ifdef MOZ_IPC #include "nsXULAppAPI.h" @@ -261,6 +262,9 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsNSSSocketInfo) +typedef mozilla::psm::NSSErrorsService NSSErrorsService; +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init) + NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID); NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID); @@ -296,6 +300,7 @@ NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID); NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID); NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID); NS_DEFINE_NAMED_CID(NS_NSSSOCKETINFO_CID); +NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID); static const mozilla::Module::CIDEntry kNSSCIDs[] = { @@ -334,12 +339,13 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { { &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor }, { &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor }, { &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor }, + { &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor }, { NULL } }; static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID }, - { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID }, + { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID }, { NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID }, { NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID }, { NS_SDR_CONTRACTID, &kNS_SDR_CID }, From d15be2e952eedb19f1953f41bc9918318d500651 Mon Sep 17 00:00:00 2001 From: Kai Engert Date: Thu, 28 Oct 2010 11:46:00 -0400 Subject: [PATCH 115/263] Bug 566478 - Invalid SSL cert error is not mobile-friendly [r=mayhemer a=blocking-fennecb2] --- .../http/HttpChannelParentListener.cpp | 6 + security/manager/ssl/src/Makefile.in | 1 + security/manager/ssl/src/NSSErrorsService.cpp | 189 ++++++++++++++++++ security/manager/ssl/src/NSSErrorsService.h | 68 +++++++ security/manager/ssl/src/nsNSSComponent.cpp | 111 +--------- security/manager/ssl/src/nsNSSComponent.h | 4 +- security/manager/ssl/src/nsNSSIOLayer.cpp | 45 +++-- security/manager/ssl/src/nsNSSModule.cpp | 8 +- 8 files changed, 299 insertions(+), 133 deletions(-) create mode 100644 security/manager/ssl/src/NSSErrorsService.cpp create mode 100644 security/manager/ssl/src/NSSErrorsService.h diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp index 8eaeee8c822..74fe14c70e4 100644 --- a/netwerk/protocol/http/HttpChannelParentListener.cpp +++ b/netwerk/protocol/http/HttpChannelParentListener.cpp @@ -143,6 +143,12 @@ HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result) return mActiveChannel->mTabParent->QueryInterface(aIID, result); } + if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) { + if (!mActiveChannel && !mActiveChannel->mTabParent) + return NS_NOINTERFACE; + return mActiveChannel->mTabParent->QueryInterface(aIID, result); + } + if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) { if (!mActiveChannel) return NS_NOINTERFACE; diff --git a/security/manager/ssl/src/Makefile.in b/security/manager/ssl/src/Makefile.in index 021aaf9841a..3709bf2ab87 100644 --- a/security/manager/ssl/src/Makefile.in +++ b/security/manager/ssl/src/Makefile.in @@ -102,6 +102,7 @@ CPPSRCS = \ nsIdentityChecking.cpp \ nsDataSignatureVerifier.cpp \ nsRandomGenerator.cpp \ + NSSErrorsService.cpp \ $(NULL) ifdef MOZ_XUL diff --git a/security/manager/ssl/src/NSSErrorsService.cpp b/security/manager/ssl/src/NSSErrorsService.cpp new file mode 100644 index 00000000000..1133012c7eb --- /dev/null +++ b/security/manager/ssl/src/NSSErrorsService.cpp @@ -0,0 +1,189 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Personal Security Manager. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Hubbie Shaw + * Doug Turner + * Mitch Stoltz + * Brian Ryner + * Kai Engert + * Vipul Gupta + * Douglas Stebila + * Kai Engert + * honzab.moz@firemni.cz + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "NSSErrorsService.h" + +#include "nsNSSComponent.h" +#include "nsServiceManagerUtils.h" +#include "secerr.h" +#include "sslerr.h" + +#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties" +#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties" + +namespace mozilla { +namespace psm { + +NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService) + +nsresult +NSSErrorsService::Init() +{ + nsresult rv; + nsCOMPtr bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); + if (NS_FAILED(rv) || !bundleService) + return NS_ERROR_FAILURE; + + bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL, + getter_AddRefs(mPIPNSSBundle)); + if (!mPIPNSSBundle) + rv = NS_ERROR_FAILURE; + + bundleService->CreateBundle(NSSERR_STRBUNDLE_URL, + getter_AddRefs(mNSSErrorsBundle)); + if (!mNSSErrorsBundle) + rv = NS_ERROR_FAILURE; + + return rv; +} + +#define EXPECTED_SEC_ERROR_BASE (-0x2000) +#define EXPECTED_SSL_ERROR_BASE (-0x3000) + +#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE +#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" +/* + * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 + * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. + * The current code also assumes that NSS library error codes are negative. + */ +#endif + +NS_IMETHODIMP +NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) +{ + if (!_retval) + return NS_ERROR_FAILURE; + + *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) +{ + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + if (!aXPCOMErrorCode) + return NS_ERROR_INVALID_ARG; + + // The error codes within each module may be a 16 bit value. + // For simplicity let's use the positive value of the NSS code. + + *aXPCOMErrorCode = + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, + -1 * aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) +{ + NS_ENSURE_ARG(aErrorClass); + + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + switch (aNSPRCode) + { + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_UNTRUSTED_ISSUER: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_UNTRUSTED_CERT: + case SEC_ERROR_INADEQUATE_KEY_USAGE: + case SSL_ERROR_BAD_CERT_DOMAIN: + case SEC_ERROR_EXPIRED_CERTIFICATE: + *aErrorClass = ERROR_CLASS_BAD_CERT; + break; + default: + *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; + break; + } + return NS_OK; +} + +NS_IMETHODIMP +NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) +{ + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + nsCOMPtr theBundle = mPIPNSSBundle; + const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); + + if (!id_str) { + id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); + theBundle = mNSSErrorsBundle; + } + + if (!id_str || !theBundle) + return NS_ERROR_FAILURE; + + nsAutoString msg; + nsresult rv = + theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), + getter_Copies(msg)); + if (NS_SUCCEEDED(rv)) { + aErrorMessage = msg; + } + return rv; +} + +} // psm +} // mozilla diff --git a/security/manager/ssl/src/NSSErrorsService.h b/security/manager/ssl/src/NSSErrorsService.h new file mode 100644 index 00000000000..c87d9b79a81 --- /dev/null +++ b/security/manager/ssl/src/NSSErrorsService.h @@ -0,0 +1,68 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Personal Security Manager. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Hubbie Shaw + * Doug Turner + * Brian Ryner + * Kai Engert + * Kai Engert + * honzab.moz@firemni.cz + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsINSSErrorsService.h" + +#include "nsIStringBundle.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace psm { + +class NSSErrorsService : public nsINSSErrorsService +{ + NS_DECL_ISUPPORTS + NS_DECL_NSINSSERRORSSERVICE + +public: + nsresult Init(); + +private: + nsCOMPtr mPIPNSSBundle; + nsCOMPtr mNSSErrorsBundle; +}; + +} // psm +} // mozilla + +#define NS_NSSERRORSSERVICE_CID \ + { 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } } diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 487dc513bd3..e2340c9dff6 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1953,14 +1953,13 @@ nsNSSComponent::Init() } /* nsISupports Implementation for the class */ -NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent, +NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent, nsISignatureVerifier, nsIEntropyCollector, nsINSSComponent, nsIObserver, nsISupportsWeakReference, - nsITimerCallback, - nsINSSErrorsService) + nsITimerCallback) /* Callback functions for decoder. For now, use empty/default functions. */ @@ -2453,112 +2452,6 @@ nsNSSComponent::RememberCert(CERTCertificate *cert) return NS_OK; } -#define EXPECTED_SEC_ERROR_BASE (-0x2000) -#define EXPECTED_SSL_ERROR_BASE (-0x3000) - -#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE -#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" -/* - * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 - * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. - * The current code also assumes that NSS library error codes are negative. - */ -#endif - -NS_IMETHODIMP -nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) -{ - if (!_retval) - return NS_ERROR_FAILURE; - - *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) -{ - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - if (!aXPCOMErrorCode) - return NS_ERROR_INVALID_ARG; - - // The error codes within each module may be a 16 bit value. - // For simplicity let's use the positive value of the NSS code. - - *aXPCOMErrorCode = - NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, - -1 * aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) -{ - NS_ENSURE_ARG(aErrorClass); - - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - switch (aNSPRCode) - { - case SEC_ERROR_UNKNOWN_ISSUER: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_UNTRUSTED_ISSUER: - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - case SEC_ERROR_UNTRUSTED_CERT: - case SEC_ERROR_INADEQUATE_KEY_USAGE: - case SSL_ERROR_BAD_CERT_DOMAIN: - case SEC_ERROR_EXPIRED_CERTIFICATE: - *aErrorClass = ERROR_CLASS_BAD_CERT; - break; - default: - *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; - break; - } - return NS_OK; -} - -NS_IMETHODIMP -nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) -{ - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - nsCOMPtr theBundle = mPIPNSSBundle; - const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); - - if (!id_str) { - id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); - theBundle = mNSSErrorsBundle; - } - - if (!id_str || !theBundle) - return NS_ERROR_FAILURE; - - nsAutoString msg; - nsresult rv = - theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), - getter_Copies(msg)); - if (NS_SUCCEEDED(rv)) { - aErrorMessage = msg; - } - return rv; -} - void nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject) { diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index 2066ef59a47..7f255e5a309 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -239,8 +239,7 @@ class nsNSSComponent : public nsISignatureVerifier, public nsINSSComponent, public nsIObserver, public nsSupportsWeakReference, - public nsITimerCallback, - public nsINSSErrorsService + public nsITimerCallback { public: NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID ) @@ -253,7 +252,6 @@ public: NS_DECL_NSIENTROPYCOLLECTOR NS_DECL_NSIOBSERVER NS_DECL_NSITIMERCALLBACK - NS_DECL_NSINSSERRORSSERVICE NS_METHOD Init(); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 80a5a398d20..88f0c98531a 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -379,6 +379,11 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown() // with a socket close, and the socket transport might detach the callbacks // instance prior to our error reporting. + nsISecureBrowserUI* secureUI = nsnull; +#ifdef MOZ_IPC + CallGetInterface(proxiedCallbacks.get(), &secureUI); +#endif + nsCOMPtr docshell; nsCOMPtr item(do_GetInterface(proxiedCallbacks)); @@ -397,7 +402,7 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown() NS_ASSERTION(docshell, "rootItem do_QI is null"); } - if (docshell) + if (docshell && !secureUI) { nsCOMPtr proxiedDocShell; NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, @@ -405,28 +410,28 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown() docshell.get(), NS_PROXY_SYNC, getter_AddRefs(proxiedDocShell)); - nsISecureBrowserUI* secureUI = nsnull; if (proxiedDocShell) proxiedDocShell->GetSecurityUI(&secureUI); - if (secureUI) - { - nsCOMPtr mainThread(do_GetMainThread()); - NS_ProxyRelease(mainThread, secureUI, PR_FALSE); - mExternalErrorReporting = PR_TRUE; + } - // If this socket is associated to a docshell, let's try to remember - // the currently used cert. If this socket gets a notification from NSS - // having the same raw socket, we can keep the PSM wrapper object - // and all the data it has cached (like verification results). - nsCOMPtr statprov = do_QueryInterface(secureUI); - if (statprov) { - nsCOMPtr isup_stat; - statprov->GetSSLStatus(getter_AddRefs(isup_stat)); - if (isup_stat) { - nsCOMPtr sslstat = do_QueryInterface(isup_stat); - if (sslstat) { - sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); - } + if (secureUI) + { + nsCOMPtr mainThread(do_GetMainThread()); + NS_ProxyRelease(mainThread, secureUI, PR_FALSE); + mExternalErrorReporting = PR_TRUE; + + // If this socket is associated to a docshell, let's try to remember + // the currently used cert. If this socket gets a notification from NSS + // having the same raw socket, we can keep the PSM wrapper object + // and all the data it has cached (like verification results). + nsCOMPtr statprov = do_QueryInterface(secureUI); + if (statprov) { + nsCOMPtr isup_stat; + statprov->GetSSLStatus(getter_AddRefs(isup_stat)); + if (isup_stat) { + nsCOMPtr sslstat = do_QueryInterface(isup_stat); + if (sslstat) { + sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); } } } diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index e6ec05c8e3b..178dc7424fb 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -78,6 +78,7 @@ #include "nsRecentBadCerts.h" #include "nsSSLStatus.h" #include "nsNSSIOLayer.h" +#include "NSSErrorsService.h" #ifdef MOZ_IPC #include "nsXULAppAPI.h" @@ -261,6 +262,9 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsNSSSocketInfo) +typedef mozilla::psm::NSSErrorsService NSSErrorsService; +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init) + NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID); NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID); @@ -296,6 +300,7 @@ NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID); NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID); NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID); NS_DEFINE_NAMED_CID(NS_NSSSOCKETINFO_CID); +NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID); static const mozilla::Module::CIDEntry kNSSCIDs[] = { @@ -334,12 +339,13 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { { &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor }, { &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor }, { &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor }, + { &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor }, { NULL } }; static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID }, - { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID }, + { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID }, { NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID }, { NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID }, { NS_SDR_CONTRACTID, &kNS_SDR_CID }, From fec6468b6cb3f7ca452b38947706aed90e64941a Mon Sep 17 00:00:00 2001 From: Rob Campbell Date: Thu, 28 Oct 2010 13:01:36 -0300 Subject: [PATCH 116/263] Bug 599940 - Web Console fails to get results of instanceof correctly, r=mossop, a=beltzner --- .../console/hudservice/HUDService.jsm | 307 +++++++++--------- .../browser/browser_webconsole_jsterm.js | 16 + 2 files changed, 165 insertions(+), 158 deletions(-) diff --git a/toolkit/components/console/hudservice/HUDService.jsm b/toolkit/components/console/hudservice/HUDService.jsm index 83daefef8cf..f9c0385cad1 100644 --- a/toolkit/components/console/hudservice/HUDService.jsm +++ b/toolkit/components/console/hudservice/HUDService.jsm @@ -3907,159 +3907,152 @@ function JSPropertyProvider(aScope, aInputValue) */ function JSTermHelper(aJSTerm) { - return { - /** - * Returns the result of document.getElementById(aId). - * - * @param string aId - * A string that is passed to window.document.getElementById. - * @returns nsIDOMNode or null - */ - $: function JSTH_$(aId) - { - try { - return aJSTerm._window.document.getElementById(aId); - } - catch (ex) { - aJSTerm.console.error(ex.message); - } - }, - - /** - * Returns the result of document.querySelectorAll(aSelector). - * - * @param string aSelector - * A string that is passed to window.document.querySelectorAll. - * @returns array of nsIDOMNode - */ - $$: function JSTH_$$(aSelector) - { - try { - return aJSTerm._window.document.querySelectorAll(aSelector); - } - catch (ex) { - aJSTerm.console.error(ex.message); - } - }, - - /** - * Runs a xPath query and returns all matched nodes. - * - * @param string aXPath - * xPath search query to execute. - * @param [optional] nsIDOMNode aContext - * Context to run the xPath query on. Uses window.document if not set. - * @returns array of nsIDOMNode - */ - $x: function JSTH_$x(aXPath, aContext) - { - let nodes = []; - let doc = aJSTerm._window.wrappedJSObject.document; - let aContext = aContext || doc; - - try { - let results = doc.evaluate(aXPath, aContext, null, - Ci.nsIDOMXPathResult.ANY_TYPE, null); - - let node; - while (node = results.iterateNext()) { - nodes.push(node); - } - } - catch (ex) { - aJSTerm.console.error(ex.message); - } - - return nodes; - }, - - /** - * Clears the output of the JSTerm. - */ - clear: function JSTH_clear() - { - aJSTerm.clearOutput(); - }, - - /** - * Returns the result of Object.keys(aObject). - * - * @param object aObject - * Object to return the property names from. - * @returns array of string - */ - keys: function JSTH_keys(aObject) - { - try { - return Object.keys(XPCNativeWrapper.unwrap(aObject)); - } - catch (ex) { - aJSTerm.console.error(ex.message); - } - }, - - /** - * Returns the values of all properties on aObject. - * - * @param object aObject - * Object to display the values from. - * @returns array of string - */ - values: function JSTH_values(aObject) - { - let arrValues = []; - let obj = XPCNativeWrapper.unwrap(aObject); - - try { - for (let prop in obj) { - arrValues.push(obj[prop]); - } - } - catch (ex) { - aJSTerm.console.error(ex.message); - } - return arrValues; - }, - - /** - * Inspects the passed aObject. This is done by opening the PropertyPanel. - * - * @param object aObject - * Object to inspect. - * @returns void - */ - inspect: function JSTH_inspect(aObject) - { - let obj = XPCNativeWrapper.unwrap(aObject); - aJSTerm.openPropertyPanel(null, obj); - }, - - /** - * Prints aObject to the output. - * - * @param object aObject - * Object to print to the output. - * @returns void - */ - pprint: function JSTH_pprint(aObject) - { - if (aObject === null || aObject === undefined || aObject === true || aObject === false) { - aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError")); - return; - } - let output = []; - if (typeof aObject != "string") { - aObject = XPCNativeWrapper.unwrap(aObject); - } - let pairs = namesAndValuesOf(aObject); - - pairs.forEach(function(pair) { - output.push(" " + pair.display); - }); - - aJSTerm.writeOutput(output.join("\n")); + /** + * Returns the result of document.getElementById(aId). + * + * @param string aId + * A string that is passed to window.document.getElementById. + * @returns nsIDOMNode or null + */ + aJSTerm.sandbox.$ = function JSTH_$(aId) + { + try { + return aJSTerm._window.document.getElementById(aId); } - } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }; + + /** + * Returns the result of document.querySelectorAll(aSelector). + * + * @param string aSelector + * A string that is passed to window.document.querySelectorAll. + * @returns array of nsIDOMNode + */ + aJSTerm.sandbox.$$ = function JSTH_$$(aSelector) + { + try { + return aJSTerm._window.document.querySelectorAll(aSelector); + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }; + + /** + * Runs a xPath query and returns all matched nodes. + * + * @param string aXPath + * xPath search query to execute. + * @param [optional] nsIDOMNode aContext + * Context to run the xPath query on. Uses window.document if not set. + * @returns array of nsIDOMNode + */ + aJSTerm.sandbox.$x = function JSTH_$x(aXPath, aContext) + { + let nodes = []; + let doc = aJSTerm._window.document; + let aContext = aContext || doc; + + try { + let results = doc.evaluate(aXPath, aContext, null, + Ci.nsIDOMXPathResult.ANY_TYPE, null); + + let node; + while (node = results.iterateNext()) { + nodes.push(node); + } + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + + return nodes; + }; + + /** + * Clears the output of the JSTerm. + */ + aJSTerm.sandbox.clear = function JSTH_clear() + { + aJSTerm.clearOutput(); + }; + + /** + * Returns the result of Object.keys(aObject). + * + * @param object aObject + * Object to return the property names from. + * @returns array of string + */ + aJSTerm.sandbox.keys = function JSTH_keys(aObject) + { + try { + return Object.keys(aObject); + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + }; + + /** + * Returns the values of all properties on aObject. + * + * @param object aObject + * Object to display the values from. + * @returns array of string + */ + aJSTerm.sandbox.values = function JSTH_values(aObject) + { + let arrValues = []; + + try { + for (let prop in aObject) { + arrValues.push(aObject[prop]); + } + } + catch (ex) { + aJSTerm.console.error(ex.message); + } + return arrValues; + }; + + /** + * Inspects the passed aObject. This is done by opening the PropertyPanel. + * + * @param object aObject + * Object to inspect. + * @returns void + */ + aJSTerm.sandbox.inspect = function JSTH_inspect(aObject) + { + aJSTerm.openPropertyPanel(null, aObject); + }; + + /** + * Prints aObject to the output. + * + * @param object aObject + * Object to print to the output. + * @returns void + */ + aJSTerm.sandbox.pprint = function JSTH_pprint(aObject) + { + if (aObject === null || aObject === undefined || aObject === true || aObject === false) { + aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError")); + return; + } + let output = []; + let pairs = namesAndValuesOf(aObject); + + pairs.forEach(function(pair) { + output.push(" " + pair.display); + }); + + aJSTerm.writeOutput(output.join("\n")); + }; } /** @@ -4146,11 +4139,10 @@ JSTerm.prototype = { createSandbox: function JST_setupSandbox() { // create a JS Sandbox out of this.context - this.sandbox = new Cu.Sandbox(this._window); - this.sandbox.window = this._window; + this.sandbox = new Cu.Sandbox(this._window, + { sandboxPrototype: this._window, wantXrays: false }); this.sandbox.console = this.console; - this.sandbox.__helperFunctions__ = JSTermHelper(this); - this.sandbox.__proto__ = this._window.wrappedJSObject; + JSTermHelper(this); }, get _window() @@ -4168,8 +4160,7 @@ JSTerm.prototype = { */ evalInSandbox: function JST_evalInSandbox(aString) { - let execStr = "with(__helperFunctions__) { with(window) {" + aString + "} }"; - return Cu.evalInSandbox(execStr, this.sandbox, "default", "HUD Console", 1); + return Cu.evalInSandbox(aString, this.sandbox, "1.8", "HUD Console", 1); }, diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js index bd309296d72..051676055c2 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_jsterm.js @@ -98,5 +98,21 @@ function testJSTerm() let label = jsterm.outputNode.querySelector(".jsterm-output-line"); is(label.textContent.trim(), "a: 1\n b: 2", "pprint() worked"); + // check instanceof correctness, bug 599940 + jsterm.clearOutput(); + jsterm.execute("[] instanceof Array"); + checkResult("true", "[] instanceof Array == true", 1); + + jsterm.clearOutput(); + jsterm.execute("({}) instanceof Object"); + checkResult("true", "({}) instanceof Object == true", 1); + + // check for occurrences of Object XRayWrapper, bug 604430 + jsterm.clearOutput(); + jsterm.execute("document"); + let label = jsterm.outputNode.querySelector(".jsterm-output-line"); + is(label.textContent.trim().search(/\[object XrayWrapper/), -1, + "check for non-existence of [object XrayWrapper "); + finishTest(); } From a8cd49d408aa1ee98b767fb7f3a381b79bb3ef5f Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Thu, 28 Oct 2010 13:01:37 -0300 Subject: [PATCH 117/263] Bug 601352 - Console does not scroll expression result into view, r+a=roc --- accessible/src/base/nsAccessNode.cpp | 3 +- accessible/src/base/nsAccessible.cpp | 3 +- .../html/content/src/nsGenericHTMLElement.cpp | 3 +- dom/base/nsFocusManager.cpp | 3 +- layout/base/nsDocumentViewer.cpp | 3 +- layout/base/nsIPresShell.h | 15 ++- layout/base/nsPresShell.cpp | 32 +++-- layout/inspector/src/inFlasher.cpp | 3 +- layout/xul/base/src/nsScrollBoxObject.cpp | 120 +++--------------- .../hudservice/tests/browser/Makefile.in | 1 + .../browser_webconsole_bug_601352_scroll.js | 62 +++++++++ .../satchel/src/nsFormFillController.cpp | 3 +- 12 files changed, 126 insertions(+), 125 deletions(-) create mode 100644 toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_601352_scroll.js diff --git a/accessible/src/base/nsAccessNode.cpp b/accessible/src/base/nsAccessNode.cpp index a8a5908f6c7..27338cd6199 100644 --- a/accessible/src/base/nsAccessNode.cpp +++ b/accessible/src/base/nsAccessNode.cpp @@ -382,7 +382,8 @@ nsAccessNode::ScrollTo(PRUint32 aScrollType) PRInt16 vPercent, hPercent; nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent); - return shell->ScrollContentIntoView(content, vPercent, hPercent); + return shell->ScrollContentIntoView(content, vPercent, hPercent, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); } NS_IMETHODIMP diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index ba85647ea2f..5f40a401bcd 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -2368,7 +2368,8 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex) // Scroll into view. presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE, - NS_PRESSHELL_SCROLL_ANYWHERE); + NS_PRESSHELL_SCROLL_ANYWHERE, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); // Fire mouse down and mouse up events. PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell, diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 2a169e30eb1..8ffe0c2a15a 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -808,7 +808,8 @@ nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc) NS_PRESSHELL_SCROLL_BOTTOM; presShell->ScrollContentIntoView(this, vpercent, - NS_PRESSHELL_SCROLL_ANYWHERE); + NS_PRESSHELL_SCROLL_ANYWHERE, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); return NS_OK; } diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index cc3f7fe7cd7..f252ba6bfab 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1800,7 +1800,8 @@ nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell, if (!(aFlags & FLAG_NOSCROLL)) aPresShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, - NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE); + NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); } diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 9907a5bc899..8d9e5c9d7d7 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -2681,7 +2681,8 @@ NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode) // Tell the PresShell to scroll to the primary frame of the content. NS_ENSURE_SUCCESS(presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP, - NS_PRESSHELL_SCROLL_ANYWHERE), + NS_PRESSHELL_SCROLL_ANYWHERE, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN), NS_ERROR_FAILURE); return NS_OK; } diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 6df24965c69..f032fbdd8b2 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -22,6 +22,7 @@ * Contributor(s): * Steve Clark * Dan Rosen + * Mihai Șucan * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -139,8 +140,8 @@ typedef struct CapturingContentInfo { } CapturingContentInfo; #define NS_IPRESSHELL_IID \ - { 0xb79574cd, 0x2555, 0x4b57, \ - { 0xb3, 0xf8, 0x27, 0x57, 0x3e, 0x60, 0x74, 0x01 } } + { 0xd1978bee, 0x43b9, 0x40de, \ + { 0x95, 0x47, 0x85, 0x06, 0x5e, 0x02, 0xec, 0xb4 } } // Constants for ScrollContentIntoView() function #define NS_PRESSHELL_SCROLL_TOP 0 @@ -544,10 +545,18 @@ public: * horizontally . A value of NS_PRESSHELL_SCROLL_ANYWHERE means move * the frame the minimum amount necessary in order for the entire * frame to be visible horizontally (if possible) + * @param aFlags If SCROLL_FIRST_ANCESTOR_ONLY is set, only the nearest + * scrollable ancestor is scrolled, otherwise all + * scrollable ancestors may be scrolled if necessary. + * If SCROLL_OVERFLOW_HIDDEN is set then we may scroll in a + * direction even if overflow:hidden is specified in that + * direction; otherwise we will not scroll in that direction + * when overflow:hidden is set for that direction. */ virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent) = 0; + PRIntn aHPercent, + PRUint32 aFlags) = 0; enum { SCROLL_FIRST_ANCESTOR_ONLY = 0x01, diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 4734b5d8edc..657718cf579 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -26,6 +26,7 @@ * Dan Rosen * Daniel Glazman * Mats Palmgren + * Mihai Șucan * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -773,7 +774,8 @@ public: virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent); + PRIntn aHPercent, + PRUint32 aFlags); virtual PRBool ScrollFrameRectIntoView(nsIFrame* aFrame, const nsRect& aRect, PRIntn aVPercent, @@ -1005,7 +1007,8 @@ protected: // Helper for ScrollContentIntoView void DoScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent); + PRIntn aHPercent, + PRUint32 aFlags); friend struct AutoRenderingStateSaveRestore; friend struct RenderingState; @@ -3906,7 +3909,8 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll) if (content) { if (aScroll) { rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP, - NS_PRESSHELL_SCROLL_ANYWHERE); + NS_PRESSHELL_SCROLL_ANYWHERE, + SCROLL_OVERFLOW_HIDDEN); NS_ENSURE_SUCCESS(rv, rv); nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable(); @@ -4013,7 +4017,8 @@ PresShell::ScrollToAnchor() return NS_OK; nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo, NS_PRESSHELL_SCROLL_TOP, - NS_PRESSHELL_SCROLL_ANYWHERE); + NS_PRESSHELL_SCROLL_ANYWHERE, + SCROLL_OVERFLOW_HIDDEN); mLastAnchorScrolledTo = nsnull; return rv; } @@ -4196,7 +4201,8 @@ static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame, nsresult PresShell::ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent) + PRIntn aHPercent, + PRUint32 aFlags) { nsCOMPtr content = aContent; // Keep content alive while flushing. NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); @@ -4221,7 +4227,7 @@ PresShell::ScrollContentIntoView(nsIContent* aContent, // than a single best-effort scroll followed by one final scroll on the first // completed reflow. if (mContentToScrollTo) { - DoScrollContentIntoView(content, aVPercent, aHPercent); + DoScrollContentIntoView(content, aVPercent, aHPercent, aFlags); } return NS_OK; } @@ -4229,7 +4235,8 @@ PresShell::ScrollContentIntoView(nsIContent* aContent, void PresShell::DoScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent) + PRIntn aHPercent, + PRUint32 aFlags) { NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now"); @@ -4272,7 +4279,7 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent, } while ((frame = frame->GetNextContinuation())); ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent, - SCROLL_OVERFLOW_HIDDEN); + aFlags); } PRBool @@ -4873,7 +4880,8 @@ PresShell::FlushPendingNotifications(mozFlushType aType) if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) { // We didn't get interrupted. Go ahead and scroll to our content DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition, - mContentScrollHPosition); + mContentScrollHPosition, + SCROLL_OVERFLOW_HIDDEN); mContentToScrollTo = nsnull; } } @@ -7161,7 +7169,8 @@ PresShell::PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTarge // an edit box below the current view, you'll get the edit box aligned with // the top of the window. This is arguably better behavior anyway. rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, - NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE); + NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, + SCROLL_OVERFLOW_HIDDEN); NS_ENSURE_SUCCESS(rv, PR_FALSE); frame = content->GetPrimaryFrame(); NS_WARN_IF_FALSE(frame, "No frame for focused content?"); @@ -7224,7 +7233,8 @@ PresShell::GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl, { nsCOMPtr focusedContent(do_QueryInterface(aCurrentEl)); ScrollContentIntoView(focusedContent, NS_PRESSHELL_SCROLL_ANYWHERE, - NS_PRESSHELL_SCROLL_ANYWHERE); + NS_PRESSHELL_SCROLL_ANYWHERE, + SCROLL_OVERFLOW_HIDDEN); nsPresContext* presContext = GetPresContext(); diff --git a/layout/inspector/src/inFlasher.cpp b/layout/inspector/src/inFlasher.cpp index 79499ca4228..75c3603b127 100644 --- a/layout/inspector/src/inFlasher.cpp +++ b/layout/inspector/src/inFlasher.cpp @@ -196,7 +196,8 @@ inFlasher::ScrollElementIntoView(nsIDOMElement *aElement) nsCOMPtr content = do_QueryInterface(aElement); presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */, - NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */); + NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); return NS_OK; } diff --git a/layout/xul/base/src/nsScrollBoxObject.cpp b/layout/xul/base/src/nsScrollBoxObject.cpp index 17877956faa..46783ac3bf1 100644 --- a/layout/xul/base/src/nsScrollBoxObject.cpp +++ b/layout/xul/base/src/nsScrollBoxObject.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Original Author: David W. Hyatt (hyatt@netscape.com) + * Mihai Șucan * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -254,56 +255,18 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollToLine(PRInt32 line) NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child) { NS_ENSURE_ARG_POINTER(child); - nsIScrollableFrame* sf = GetScrollFrame(); - if (!sf) - return NS_ERROR_FAILURE; nsCOMPtr shell = GetPresShell(PR_FALSE); if (!shell) { return NS_ERROR_UNEXPECTED; } - nsIFrame* scrolledBox = GetScrolledBox(this); - if (!scrolledBox) - return NS_ERROR_FAILURE; - - nsRect rect, crect; - nsCOMPtr doc; - child->GetOwnerDocument(getter_AddRefs(doc)); - nsCOMPtr nsDoc(do_QueryInterface(doc)); - if(!nsDoc) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr childBoxObject; - nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject)); - if(!childBoxObject) - return NS_ERROR_UNEXPECTED; - - PRInt32 x,y; - childBoxObject->GetX(&x); - childBoxObject->GetY(&y); - // get the twips rectangle from the boxobject (which has pixels) - rect.x = nsPresContext::CSSPixelsToAppUnits(x); - rect.y = nsPresContext::CSSPixelsToAppUnits(y); - - // TODO: make sure the child is inside the box - - // get our current info - nsPoint cp = sf->GetScrollPosition(); - nsIntRect prect; - GetOffsetRect(prect); - crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel()); - nscoord newx=cp.x, newy=cp.y; - - // we only scroll in the direction of the scrollbox orientation - // always scroll to left or top edge of child element - if (scrolledBox->IsHorizontal()) { - newx = rect.x - crect.x; - } else { - newy = rect.y - crect.y; - } - // scroll away - sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT); + nsCOMPtr content = do_QueryInterface(child); + shell->ScrollContentIntoView(content, + NS_PRESSHELL_SCROLL_TOP, + NS_PRESSHELL_SCROLL_LEFT, + nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY | + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); return NS_OK; } @@ -347,68 +310,17 @@ NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child) { NS_ENSURE_ARG_POINTER(child); - // Start with getting info about the child, since that will flush - // layout and possibly destroy scrollable views, presshells, etc. - nsCOMPtr doc; - // XXXbz sXBL/XBL2 issue -- which document? - child->GetOwnerDocument(getter_AddRefs(doc)); - nsCOMPtr nsDoc(do_QueryInterface(doc)); - if(!nsDoc) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr childBoxObject; - nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject)); - if(!childBoxObject) + nsCOMPtr shell = GetPresShell(PR_FALSE); + if (!shell) { return NS_ERROR_UNEXPECTED; - - PRInt32 x, y, width, height; - childBoxObject->GetX(&x); - childBoxObject->GetY(&y); - childBoxObject->GetWidth(&width); - childBoxObject->GetHeight(&height); - - nsIScrollableFrame* sf = GetScrollFrame(); - if (!sf) - return NS_ERROR_FAILURE; - - nsIFrame* scrolledBox = GetScrolledBox(this); - if (!scrolledBox) - return NS_ERROR_FAILURE; - - nsRect rect, crect; - // get the twips rectangle from the boxobject (which has pixels) - rect.x = nsPresContext::CSSPixelsToAppUnits(x); - rect.y = nsPresContext::CSSPixelsToAppUnits(y); - rect.width = nsPresContext::CSSPixelsToAppUnits(width); - rect.height = nsPresContext::CSSPixelsToAppUnits(height); - - // TODO: make sure the child is inside the box - - // get our current info - nsPoint cp = sf->GetScrollPosition(); - nsIntRect prect; - GetOffsetRect(prect); - crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel()); - - nscoord newx=cp.x, newy=cp.y; - - // we only scroll in the direction of the scrollbox orientation - if (scrolledBox->IsHorizontal()) { - if ((rect.x - crect.x) + rect.width > cp.x + crect.width) { - newx = cp.x + (((rect.x - crect.x) + rect.width)-(cp.x + crect.width)); - } else if (rect.x - crect.x < cp.x) { - newx = rect.x - crect.x; - } - } else { - if ((rect.y - crect.y) + rect.height > cp.y + crect.height) { - newy = cp.y + (((rect.y - crect.y) + rect.height)-(cp.y + crect.height)); - } else if (rect.y - crect.y < cp.y) { - newy = rect.y - crect.y; - } } - - // scroll away - sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT); + + nsCOMPtr content = do_QueryInterface(child); + shell->ScrollContentIntoView(content, + NS_PRESSHELL_SCROLL_ANYWHERE, + NS_PRESSHELL_SCROLL_ANYWHERE, + nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY | + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); return NS_OK; } diff --git a/toolkit/components/console/hudservice/tests/browser/Makefile.in b/toolkit/components/console/hudservice/tests/browser/Makefile.in index a0c7ac3b07b..113f1901085 100644 --- a/toolkit/components/console/hudservice/tests/browser/Makefile.in +++ b/toolkit/components/console/hudservice/tests/browser/Makefile.in @@ -98,6 +98,7 @@ _BROWSER_TEST_FILES = \ browser_webconsole_bug_594497_history_arrow_keys.js \ browser_webconsole_bug_588342_document_focus.js \ browser_webconsole_bug_595934_message_categories.js \ + browser_webconsole_bug_601352_scroll.js \ head.js \ $(NULL) diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_601352_scroll.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_601352_scroll.js new file mode 100644 index 00000000000..c3994d7b413 --- /dev/null +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_601352_scroll.js @@ -0,0 +1,62 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + * + * Contributor(s): + * Mihai Șucan + * + * ***** END LICENSE BLOCK ***** */ + +function tabLoad(aEvent) { + browser.removeEventListener(aEvent.type, arguments.callee, true); + + openConsole(); + + let hudId = HUDService.getHudIdByWindow(content); + let HUD = HUDService.hudWeakReferences[hudId].get(); + + let longMessage = ""; + for (let i = 0; i < 20; i++) { + longMessage += "LongNonwrappingMessage"; + } + + for (let i = 0; i < 100; i++) { + HUD.console.log("test message " + i); + } + + HUD.console.log(longMessage); + + for (let i = 0; i < 100; i++) { + HUD.console.log("test message " + i); + } + + HUD.jsterm.execute("1+1"); + + executeSoon(function() { + isnot(HUD.outputNode.scrollTop, 0, "scroll location is not at the top"); + + let node = HUD.outputNode.querySelector(".hud-group > *:last-child"); + let rectNode = node.getBoundingClientRect(); + let rectOutput = HUD.outputNode.getBoundingClientRect(); + + // Visible scroll viewport. + let height = HUD.outputNode.scrollHeight - HUD.outputNode.scrollTop; + + // Top position of the last message node, relative to the outputNode. + let top = rectNode.top - rectOutput.top; + + // Bottom position of the last message node, relative to the outputNode. + let bottom = rectNode.bottom - rectOutput.top; + + ok(top >= 0 && bottom <= height, "last message is visible"); + + finishTest(); + }); +} + +function test() { + addTab("data:text/html,Web Console test for bug 601352"); + browser.addEventListener("load", tabLoad, true); +} + diff --git a/toolkit/components/satchel/src/nsFormFillController.cpp b/toolkit/components/satchel/src/nsFormFillController.cpp index 5cb5b035c40..ccd6d953993 100644 --- a/toolkit/components/satchel/src/nsFormFillController.cpp +++ b/toolkit/components/satchel/src/nsFormFillController.cpp @@ -294,7 +294,8 @@ nsFormFillController::SetPopupOpen(PRBool aPopupOpen) NS_ENSURE_STATE(presShell); presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, - NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE); + NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, + nsIPresShell::SCROLL_OVERFLOW_HIDDEN); // mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089 if (mFocusedPopup) mFocusedPopup->OpenAutocompletePopup(this, mFocusedInput); From e0a3cc5dd74d5798e2996f14fe83657832daabcf Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 28 Oct 2010 12:17:01 -0400 Subject: [PATCH 118/263] Backout bug 566478 due to test orange a=orangehurts --- .../http/HttpChannelParentListener.cpp | 6 - security/manager/ssl/src/Makefile.in | 1 - security/manager/ssl/src/NSSErrorsService.cpp | 189 ------------------ security/manager/ssl/src/NSSErrorsService.h | 68 ------- security/manager/ssl/src/nsNSSComponent.cpp | 111 +++++++++- security/manager/ssl/src/nsNSSComponent.h | 4 +- security/manager/ssl/src/nsNSSIOLayer.cpp | 91 ++++----- security/manager/ssl/src/nsNSSModule.cpp | 8 +- 8 files changed, 154 insertions(+), 324 deletions(-) delete mode 100644 security/manager/ssl/src/NSSErrorsService.cpp delete mode 100644 security/manager/ssl/src/NSSErrorsService.h diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp index 74fe14c70e4..8eaeee8c822 100644 --- a/netwerk/protocol/http/HttpChannelParentListener.cpp +++ b/netwerk/protocol/http/HttpChannelParentListener.cpp @@ -143,12 +143,6 @@ HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result) return mActiveChannel->mTabParent->QueryInterface(aIID, result); } - if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) { - if (!mActiveChannel && !mActiveChannel->mTabParent) - return NS_NOINTERFACE; - return mActiveChannel->mTabParent->QueryInterface(aIID, result); - } - if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) { if (!mActiveChannel) return NS_NOINTERFACE; diff --git a/security/manager/ssl/src/Makefile.in b/security/manager/ssl/src/Makefile.in index 3709bf2ab87..021aaf9841a 100644 --- a/security/manager/ssl/src/Makefile.in +++ b/security/manager/ssl/src/Makefile.in @@ -102,7 +102,6 @@ CPPSRCS = \ nsIdentityChecking.cpp \ nsDataSignatureVerifier.cpp \ nsRandomGenerator.cpp \ - NSSErrorsService.cpp \ $(NULL) ifdef MOZ_XUL diff --git a/security/manager/ssl/src/NSSErrorsService.cpp b/security/manager/ssl/src/NSSErrorsService.cpp deleted file mode 100644 index 1133012c7eb..00000000000 --- a/security/manager/ssl/src/NSSErrorsService.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Personal Security Manager. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Hubbie Shaw - * Doug Turner - * Mitch Stoltz - * Brian Ryner - * Kai Engert - * Vipul Gupta - * Douglas Stebila - * Kai Engert - * honzab.moz@firemni.cz - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "NSSErrorsService.h" - -#include "nsNSSComponent.h" -#include "nsServiceManagerUtils.h" -#include "secerr.h" -#include "sslerr.h" - -#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties" -#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties" - -namespace mozilla { -namespace psm { - -NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService) - -nsresult -NSSErrorsService::Init() -{ - nsresult rv; - nsCOMPtr bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); - if (NS_FAILED(rv) || !bundleService) - return NS_ERROR_FAILURE; - - bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL, - getter_AddRefs(mPIPNSSBundle)); - if (!mPIPNSSBundle) - rv = NS_ERROR_FAILURE; - - bundleService->CreateBundle(NSSERR_STRBUNDLE_URL, - getter_AddRefs(mNSSErrorsBundle)); - if (!mNSSErrorsBundle) - rv = NS_ERROR_FAILURE; - - return rv; -} - -#define EXPECTED_SEC_ERROR_BASE (-0x2000) -#define EXPECTED_SSL_ERROR_BASE (-0x3000) - -#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE -#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" -/* - * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 - * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. - * The current code also assumes that NSS library error codes are negative. - */ -#endif - -NS_IMETHODIMP -NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) -{ - if (!_retval) - return NS_ERROR_FAILURE; - - *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) -{ - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - if (!aXPCOMErrorCode) - return NS_ERROR_INVALID_ARG; - - // The error codes within each module may be a 16 bit value. - // For simplicity let's use the positive value of the NSS code. - - *aXPCOMErrorCode = - NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, - -1 * aNSPRCode); - return NS_OK; -} - -NS_IMETHODIMP -NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) -{ - NS_ENSURE_ARG(aErrorClass); - - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - switch (aNSPRCode) - { - case SEC_ERROR_UNKNOWN_ISSUER: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_UNTRUSTED_ISSUER: - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - case SEC_ERROR_UNTRUSTED_CERT: - case SEC_ERROR_INADEQUATE_KEY_USAGE: - case SSL_ERROR_BAD_CERT_DOMAIN: - case SEC_ERROR_EXPIRED_CERTIFICATE: - *aErrorClass = ERROR_CLASS_BAD_CERT; - break; - default: - *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; - break; - } - return NS_OK; -} - -NS_IMETHODIMP -NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) -{ - if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY - || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) - return NS_ERROR_FAILURE; - - PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); - - if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) - return NS_ERROR_FAILURE; - - nsCOMPtr theBundle = mPIPNSSBundle; - const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); - - if (!id_str) { - id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); - theBundle = mNSSErrorsBundle; - } - - if (!id_str || !theBundle) - return NS_ERROR_FAILURE; - - nsAutoString msg; - nsresult rv = - theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), - getter_Copies(msg)); - if (NS_SUCCEEDED(rv)) { - aErrorMessage = msg; - } - return rv; -} - -} // psm -} // mozilla diff --git a/security/manager/ssl/src/NSSErrorsService.h b/security/manager/ssl/src/NSSErrorsService.h deleted file mode 100644 index c87d9b79a81..00000000000 --- a/security/manager/ssl/src/NSSErrorsService.h +++ /dev/null @@ -1,68 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Personal Security Manager. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Hubbie Shaw - * Doug Turner - * Brian Ryner - * Kai Engert - * Kai Engert - * honzab.moz@firemni.cz - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsINSSErrorsService.h" - -#include "nsIStringBundle.h" -#include "nsCOMPtr.h" - -namespace mozilla { -namespace psm { - -class NSSErrorsService : public nsINSSErrorsService -{ - NS_DECL_ISUPPORTS - NS_DECL_NSINSSERRORSSERVICE - -public: - nsresult Init(); - -private: - nsCOMPtr mPIPNSSBundle; - nsCOMPtr mNSSErrorsBundle; -}; - -} // psm -} // mozilla - -#define NS_NSSERRORSSERVICE_CID \ - { 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } } diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index e2340c9dff6..487dc513bd3 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1953,13 +1953,14 @@ nsNSSComponent::Init() } /* nsISupports Implementation for the class */ -NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent, +NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent, nsISignatureVerifier, nsIEntropyCollector, nsINSSComponent, nsIObserver, nsISupportsWeakReference, - nsITimerCallback) + nsITimerCallback, + nsINSSErrorsService) /* Callback functions for decoder. For now, use empty/default functions. */ @@ -2452,6 +2453,112 @@ nsNSSComponent::RememberCert(CERTCertificate *cert) return NS_OK; } +#define EXPECTED_SEC_ERROR_BASE (-0x2000) +#define EXPECTED_SSL_ERROR_BASE (-0x3000) + +#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE +#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code" +/* + * Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000 + * Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts. + * The current code also assumes that NSS library error codes are negative. + */ +#endif + +NS_IMETHODIMP +nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval) +{ + if (!_retval) + return NS_ERROR_FAILURE; + + *_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode) +{ + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + if (!aXPCOMErrorCode) + return NS_ERROR_INVALID_ARG; + + // The error codes within each module may be a 16 bit value. + // For simplicity let's use the positive value of the NSS code. + + *aXPCOMErrorCode = + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, + -1 * aNSPRCode); + return NS_OK; +} + +NS_IMETHODIMP +nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) +{ + NS_ENSURE_ARG(aErrorClass); + + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + switch (aNSPRCode) + { + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_UNTRUSTED_ISSUER: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_UNTRUSTED_CERT: + case SEC_ERROR_INADEQUATE_KEY_USAGE: + case SSL_ERROR_BAD_CERT_DOMAIN: + case SEC_ERROR_EXPIRED_CERTIFICATE: + *aErrorClass = ERROR_CLASS_BAD_CERT; + break; + default: + *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; + break; + } + return NS_OK; +} + +NS_IMETHODIMP +nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) +{ + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + nsCOMPtr theBundle = mPIPNSSBundle; + const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode); + + if (!id_str) { + id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode); + theBundle = mNSSErrorsBundle; + } + + if (!id_str || !theBundle) + return NS_ERROR_FAILURE; + + nsAutoString msg; + nsresult rv = + theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(), + getter_Copies(msg)); + if (NS_SUCCEEDED(rv)) { + aErrorMessage = msg; + } + return rv; +} + void nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject) { diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index 7f255e5a309..2066ef59a47 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -239,7 +239,8 @@ class nsNSSComponent : public nsISignatureVerifier, public nsINSSComponent, public nsIObserver, public nsSupportsWeakReference, - public nsITimerCallback + public nsITimerCallback, + public nsINSSErrorsService { public: NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID ) @@ -252,6 +253,7 @@ public: NS_DECL_NSIENTROPYCOLLECTOR NS_DECL_NSIOBSERVER NS_DECL_NSITIMERCALLBACK + NS_DECL_NSINSSERRORSSERVICE NS_METHOD Init(); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 5b8bcd1dfd7..80a5a398d20 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -379,63 +379,54 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown() // with a socket close, and the socket transport might detach the callbacks // instance prior to our error reporting. - nsISecureBrowserUI* secureUI = nsnull; -#ifdef MOZ_IPC - CallGetInterface(proxiedCallbacks.get(), &secureUI); -#endif + nsCOMPtr docshell; - if (!secureUI) + nsCOMPtr item(do_GetInterface(proxiedCallbacks)); + if (item) { - nsCOMPtr docshell; + nsCOMPtr proxiedItem; + nsCOMPtr rootItem; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIDocShellTreeItem), + item.get(), + NS_PROXY_SYNC, + getter_AddRefs(proxiedItem)); - nsCOMPtr item(do_GetInterface(proxiedCallbacks)); - if (item) - { - nsCOMPtr proxiedItem; - nsCOMPtr rootItem; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIDocShellTreeItem), - item.get(), - NS_PROXY_SYNC, - getter_AddRefs(proxiedItem)); - - proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem)); - docshell = do_QueryInterface(rootItem); - NS_ASSERTION(docshell, "rootItem do_QI is null"); - } - - if (docshell) - { - nsCOMPtr proxiedDocShell; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIDocShell), - docshell.get(), - NS_PROXY_SYNC, - getter_AddRefs(proxiedDocShell)); - nsISecureBrowserUI* secureUI = nsnull; - if (proxiedDocShell) - proxiedDocShell->GetSecurityUI(&secureUI); - } + proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem)); + docshell = do_QueryInterface(rootItem); + NS_ASSERTION(docshell, "rootItem do_QI is null"); } - if (secureUI) + if (docshell) { - nsCOMPtr mainThread(do_GetMainThread()); - NS_ProxyRelease(mainThread, secureUI, PR_FALSE); - mExternalErrorReporting = PR_TRUE; + nsCOMPtr proxiedDocShell; + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIDocShell), + docshell.get(), + NS_PROXY_SYNC, + getter_AddRefs(proxiedDocShell)); + nsISecureBrowserUI* secureUI = nsnull; + if (proxiedDocShell) + proxiedDocShell->GetSecurityUI(&secureUI); + if (secureUI) + { + nsCOMPtr mainThread(do_GetMainThread()); + NS_ProxyRelease(mainThread, secureUI, PR_FALSE); + mExternalErrorReporting = PR_TRUE; - // If this socket is associated to a docshell, let's try to remember - // the currently used cert. If this socket gets a notification from NSS - // having the same raw socket, we can keep the PSM wrapper object - // and all the data it has cached (like verification results). - nsCOMPtr statprov = do_QueryInterface(secureUI); - if (statprov) { - nsCOMPtr isup_stat; - statprov->GetSSLStatus(getter_AddRefs(isup_stat)); - if (isup_stat) { - nsCOMPtr sslstat = do_QueryInterface(isup_stat); - if (sslstat) { - sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); + // If this socket is associated to a docshell, let's try to remember + // the currently used cert. If this socket gets a notification from NSS + // having the same raw socket, we can keep the PSM wrapper object + // and all the data it has cached (like verification results). + nsCOMPtr statprov = do_QueryInterface(secureUI); + if (statprov) { + nsCOMPtr isup_stat; + statprov->GetSSLStatus(getter_AddRefs(isup_stat)); + if (isup_stat) { + nsCOMPtr sslstat = do_QueryInterface(isup_stat); + if (sslstat) { + sslstat->GetServerCert(getter_AddRefs(mPreviousCert)); + } } } } diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index 178dc7424fb..e6ec05c8e3b 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -78,7 +78,6 @@ #include "nsRecentBadCerts.h" #include "nsSSLStatus.h" #include "nsNSSIOLayer.h" -#include "NSSErrorsService.h" #ifdef MOZ_IPC #include "nsXULAppAPI.h" @@ -262,9 +261,6 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsNSSSocketInfo) -typedef mozilla::psm::NSSErrorsService NSSErrorsService; -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init) - NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID); NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID); NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID); @@ -300,7 +296,6 @@ NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID); NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID); NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID); NS_DEFINE_NAMED_CID(NS_NSSSOCKETINFO_CID); -NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID); static const mozilla::Module::CIDEntry kNSSCIDs[] = { @@ -339,13 +334,12 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = { { &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor }, { &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor }, { &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor }, - { &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor }, { NULL } }; static const mozilla::Module::ContractIDEntry kNSSContracts[] = { { PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID }, - { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID }, + { NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID }, { NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID }, { NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID }, { NS_SDR_CONTRACTID, &kNS_SDR_CID }, From 26fd38c103b1c029eaab0a8dd5d36a686895075e Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Thu, 28 Oct 2010 10:09:08 -0700 Subject: [PATCH 119/263] Bug 606719 - Browser stalls with connections left hanging in TCP close wait state. Part 1: rename LOG to SOCKET_LOG. r=mcmanus, a=b7+ --- netwerk/base/src/nsServerSocket.cpp | 4 +- netwerk/base/src/nsSocketTransport2.cpp | 114 +++++++++--------- .../base/src/nsSocketTransportService2.cpp | 54 ++++----- netwerk/base/src/nsSocketTransportService2.h | 4 +- 4 files changed, 88 insertions(+), 88 deletions(-) diff --git a/netwerk/base/src/nsServerSocket.cpp b/netwerk/base/src/nsServerSocket.cpp index f0fd3a49776..82f3e909036 100644 --- a/netwerk/base/src/nsServerSocket.cpp +++ b/netwerk/base/src/nsServerSocket.cpp @@ -99,7 +99,7 @@ nsServerSocket::~nsServerSocket() void nsServerSocket::OnMsgClose() { - LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this)); + SOCKET_LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this)); if (NS_FAILED(mCondition)) return; @@ -116,7 +116,7 @@ nsServerSocket::OnMsgClose() void nsServerSocket::OnMsgAttach() { - LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this)); + SOCKET_LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this)); if (NS_FAILED(mCondition)) return; diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index c8f7e925dc6..da79e43e0df 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -140,7 +140,7 @@ static PRErrorCode RandomizeConnectError(PRErrorCode code) }; n = n % (sizeof(errors)/sizeof(errors[0])); code = errors[n].err_code; - LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name)); + SOCKET_LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name)); } return code; } @@ -202,7 +202,7 @@ ErrorAccordingToNSPR(PRErrorCode errorCode) rv = GetXPCOMFromNSSError(errorCode); break; } - LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv)); + SOCKET_LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv)); return rv; } @@ -230,7 +230,7 @@ nsSocketInputStream::~nsSocketInputStream() void nsSocketInputStream::OnSocketReady(nsresult condition) { - LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n", + SOCKET_LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n", this, condition)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -284,7 +284,7 @@ nsSocketInputStream::Close() NS_IMETHODIMP nsSocketInputStream::Available(PRUint32 *avail) { - LOG(("nsSocketInputStream::Available [this=%x]\n", this)); + SOCKET_LOG(("nsSocketInputStream::Available [this=%x]\n", this)); *avail = 0; @@ -329,7 +329,7 @@ nsSocketInputStream::Available(PRUint32 *avail) NS_IMETHODIMP nsSocketInputStream::Read(char *buf, PRUint32 count, PRUint32 *countRead) { - LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count)); + SOCKET_LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count)); *countRead = 0; @@ -345,14 +345,14 @@ nsSocketInputStream::Read(char *buf, PRUint32 count, PRUint32 *countRead) return NS_BASE_STREAM_WOULD_BLOCK; } - LOG((" calling PR_Read [count=%u]\n", count)); + SOCKET_LOG((" calling PR_Read [count=%u]\n", count)); // cannot hold lock while calling NSPR. (worried about the fact that PSM // synchronously proxies notifications over to the UI thread, which could // mistakenly try to re-enter this code.) PRInt32 n = PR_Read(fd, buf, count); - LOG((" PR_Read returned [n=%d]\n", n)); + SOCKET_LOG((" PR_Read returned [n=%d]\n", n)); nsresult rv; { @@ -403,7 +403,7 @@ nsSocketInputStream::IsNonBlocking(PRBool *nonblocking) NS_IMETHODIMP nsSocketInputStream::CloseWithStatus(nsresult reason) { - LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason)); + SOCKET_LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason)); // may be called from any thread @@ -427,7 +427,7 @@ nsSocketInputStream::AsyncWait(nsIInputStreamCallback *callback, PRUint32 amount, nsIEventTarget *target) { - LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this)); + SOCKET_LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this)); // This variable will be non-null when we want to call the callback // directly from this function, but outside the lock. @@ -489,7 +489,7 @@ nsSocketOutputStream::~nsSocketOutputStream() void nsSocketOutputStream::OnSocketReady(nsresult condition) { - LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n", + SOCKET_LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n", this, condition)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -549,7 +549,7 @@ nsSocketOutputStream::Flush() NS_IMETHODIMP nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWritten) { - LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count)); + SOCKET_LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count)); *countWritten = 0; @@ -568,14 +568,14 @@ nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWrit return NS_BASE_STREAM_WOULD_BLOCK; } - LOG((" calling PR_Write [count=%u]\n", count)); + SOCKET_LOG((" calling PR_Write [count=%u]\n", count)); // cannot hold lock while calling NSPR. (worried about the fact that PSM // synchronously proxies notifications over to the UI thread, which could // mistakenly try to re-enter this code.) PRInt32 n = PR_Write(fd, buf, count); - LOG((" PR_Write returned [n=%d]\n", n)); + SOCKET_LOG((" PR_Write returned [n=%d]\n", n)); NS_ASSERTION(n != 0, "unexpected return value"); nsresult rv; @@ -645,7 +645,7 @@ nsSocketOutputStream::IsNonBlocking(PRBool *nonblocking) NS_IMETHODIMP nsSocketOutputStream::CloseWithStatus(nsresult reason) { - LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason)); + SOCKET_LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason)); // may be called from any thread @@ -669,7 +669,7 @@ nsSocketOutputStream::AsyncWait(nsIOutputStreamCallback *callback, PRUint32 amount, nsIEventTarget *target) { - LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this)); + SOCKET_LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this)); { nsAutoLock lock(mTransport->mLock); @@ -721,7 +721,7 @@ nsSocketTransport::nsSocketTransport() , mOutput(this) , mQoSBits(0x00) { - LOG(("creating nsSocketTransport @%x\n", this)); + SOCKET_LOG(("creating nsSocketTransport @%x\n", this)); NS_ADDREF(gSocketTransportService); @@ -731,7 +731,7 @@ nsSocketTransport::nsSocketTransport() nsSocketTransport::~nsSocketTransport() { - LOG(("destroying nsSocketTransport @%x\n", this)); + SOCKET_LOG(("destroying nsSocketTransport @%x\n", this)); // cleanup socket type info if (mTypes) { @@ -779,7 +779,7 @@ nsSocketTransport::Init(const char **types, PRUint32 typeCount, proxyType = nsnull; } - LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n", + SOCKET_LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n", this, mHost.get(), mPort, mProxyHost.get(), mProxyPort)); // include proxy type as a socket type if proxy type is not "http" @@ -869,7 +869,7 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const PRNetAddr *addr opt.value.non_blocking = PR_TRUE; PR_SetSocketOption(mFD, &opt); - LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n", + SOCKET_LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n", this, mHost.get(), mPort)); // jump to InitiateSocket to get ourselves attached to the STS poll list. @@ -879,7 +879,7 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const PRNetAddr *addr nsresult nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param) { - LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n", + SOCKET_LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n", this, type, status, param)); nsCOMPtr event = new nsSocketEvent(this, type, status, param); @@ -892,7 +892,7 @@ nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param) void nsSocketTransport::SendStatus(nsresult status) { - LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status)); + SOCKET_LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status)); nsCOMPtr sink; PRUint64 progress; @@ -918,7 +918,7 @@ nsSocketTransport::SendStatus(nsresult status) nsresult nsSocketTransport::ResolveHost() { - LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this)); + SOCKET_LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this)); nsresult rv; @@ -955,7 +955,7 @@ nsSocketTransport::ResolveHost() rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nsnull, getter_AddRefs(mDNSRequest)); if (NS_SUCCEEDED(rv)) { - LOG((" advancing to STATE_RESOLVING\n")); + SOCKET_LOG((" advancing to STATE_RESOLVING\n")); mState = STATE_RESOLVING; // only report that we are resolving if we are still resolving... if (mResolving) @@ -967,7 +967,7 @@ nsSocketTransport::ResolveHost() nsresult nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool &usingSSL) { - LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this)); + SOCKET_LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this)); nsresult rv; @@ -995,7 +995,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool for (i=0; i provider; - LOG((" pushing io layer [%u:%s]\n", i, mTypes[i])); + SOCKET_LOG((" pushing io layer [%u:%s]\n", i, mTypes[i])); rv = spserv->GetSocketProvider(mTypes[i], getter_AddRefs(provider)); if (NS_FAILED(rv)) @@ -1043,7 +1043,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool nsAutoLock lock(mLock); mSecInfo = secinfo; callbacks = mCallbacks; - LOG((" [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get())); + SOCKET_LOG((" [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get())); } // don't call into PSM while holding mLock!! nsCOMPtr secCtrl(do_QueryInterface(secinfo)); @@ -1063,7 +1063,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool } if (NS_FAILED(rv)) { - LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv)); + SOCKET_LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv)); if (fd) PR_Close(fd); } @@ -1075,7 +1075,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool nsresult nsSocketTransport::InitiateSocket() { - LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this)); + SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this)); nsresult rv; @@ -1118,7 +1118,7 @@ nsSocketTransport::InitiateSocket() rv = BuildSocket(fd, proxyTransparent, usingSSL); if (NS_FAILED(rv)) { - LOG((" BuildSocket failed [rv=%x]\n", rv)); + SOCKET_LOG((" BuildSocket failed [rv=%x]\n", rv)); return rv; } @@ -1165,16 +1165,16 @@ nsSocketTransport::InitiateSocket() mFDconnected = PR_FALSE; } - LOG((" advancing to STATE_CONNECTING\n")); + SOCKET_LOG((" advancing to STATE_CONNECTING\n")); mState = STATE_CONNECTING; mPollTimeout = mTimeouts[TIMEOUT_CONNECT]; SendStatus(STATUS_CONNECTING_TO); #if defined(PR_LOGGING) - if (LOG_ENABLED()) { + if (SOCKET_LOG_ENABLED()) { char buf[64]; PR_NetAddrToString(&mNetAddr, buf, sizeof(buf)); - LOG((" trying address: %s\n", buf)); + SOCKET_LOG((" trying address: %s\n", buf)); } #endif @@ -1215,7 +1215,7 @@ nsSocketTransport::InitiateSocket() nsCOMPtr secCtrl = do_QueryInterface(mSecInfo); if (secCtrl) { - LOG((" calling ProxyStartSSL()\n")); + SOCKET_LOG((" calling ProxyStartSSL()\n")); secCtrl->ProxyStartSSL(); } // XXX what if we were forced to poll on the socket for a successful @@ -1243,7 +1243,7 @@ nsSocketTransport::RecoverFromError() { NS_ASSERTION(NS_FAILED(mCondition), "there should be something wrong"); - LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n", + SOCKET_LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n", this, mState, mCondition)); // can only recover from errors in these states @@ -1267,7 +1267,7 @@ nsSocketTransport::RecoverFromError() if (mState == STATE_CONNECTING && mDNSRecord) { nsresult rv = mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr); if (NS_SUCCEEDED(rv)) { - LOG((" trying again with next ip address\n")); + SOCKET_LOG((" trying again with next ip address\n")); tryAgain = PR_TRUE; } } @@ -1311,7 +1311,7 @@ nsSocketTransport::RecoverFromError() void nsSocketTransport::OnMsgInputClosed(nsresult reason) { - LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n", + SOCKET_LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n", this, reason)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -1333,7 +1333,7 @@ nsSocketTransport::OnMsgInputClosed(nsresult reason) void nsSocketTransport::OnMsgOutputClosed(nsresult reason) { - LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n", + SOCKET_LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n", this, reason)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -1354,7 +1354,7 @@ nsSocketTransport::OnMsgOutputClosed(nsresult reason) void nsSocketTransport::OnSocketConnected() { - LOG((" advancing to STATE_TRANSFERRING\n")); + SOCKET_LOG((" advancing to STATE_TRANSFERRING\n")); mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT); mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE]; @@ -1391,7 +1391,7 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd) NS_ASSERTION(mFD == fd, "wrong fd"); if (--mFDref == 0) { - LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this)); + SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this)); PR_Close(mFD); mFD = nsnull; } @@ -1403,12 +1403,12 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd) void nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *param) { - LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n", + SOCKET_LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n", this, type, status, param)); if (NS_FAILED(mCondition)) { // block event since we're apparently already dead. - LOG((" blocking event [condition=%x]\n", mCondition)); + SOCKET_LOG((" blocking event [condition=%x]\n", mCondition)); // // notify input/output streams in case either has a pending notify. // @@ -1419,7 +1419,7 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa switch (type) { case MSG_ENSURE_CONNECT: - LOG((" MSG_ENSURE_CONNECT\n")); + SOCKET_LOG((" MSG_ENSURE_CONNECT\n")); // // ensure that we have created a socket, attached it, and have a // connection. @@ -1427,11 +1427,11 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa if (mState == STATE_CLOSED) mCondition = ResolveHost(); else - LOG((" ignoring redundant event\n")); + SOCKET_LOG((" ignoring redundant event\n")); break; case MSG_DNS_LOOKUP_COMPLETE: - LOG((" MSG_DNS_LOOKUP_COMPLETE\n")); + SOCKET_LOG((" MSG_DNS_LOOKUP_COMPLETE\n")); mDNSRequest = 0; if (param) { mDNSRecord = static_cast(param); @@ -1459,35 +1459,35 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa break; case MSG_INPUT_CLOSED: - LOG((" MSG_INPUT_CLOSED\n")); + SOCKET_LOG((" MSG_INPUT_CLOSED\n")); OnMsgInputClosed(status); break; case MSG_INPUT_PENDING: - LOG((" MSG_INPUT_PENDING\n")); + SOCKET_LOG((" MSG_INPUT_PENDING\n")); OnMsgInputPending(); break; case MSG_OUTPUT_CLOSED: - LOG((" MSG_OUTPUT_CLOSED\n")); + SOCKET_LOG((" MSG_OUTPUT_CLOSED\n")); OnMsgOutputClosed(status); break; case MSG_OUTPUT_PENDING: - LOG((" MSG_OUTPUT_PENDING\n")); + SOCKET_LOG((" MSG_OUTPUT_PENDING\n")); OnMsgOutputPending(); break; case MSG_TIMEOUT_CHANGED: - LOG((" MSG_TIMEOUT_CHANGED\n")); + SOCKET_LOG((" MSG_TIMEOUT_CHANGED\n")); mPollTimeout = mTimeouts[(mState == STATE_TRANSFERRING) ? TIMEOUT_READ_WRITE : TIMEOUT_CONNECT]; break; default: - LOG((" unhandled event!\n")); + SOCKET_LOG((" unhandled event!\n")); } if (NS_FAILED(mCondition)) { - LOG((" after event [this=%x cond=%x]\n", this, mCondition)); + SOCKET_LOG((" after event [this=%x cond=%x]\n", this, mCondition)); if (!mAttached) // need to process this error ourselves... OnSocketDetached(nsnull); } @@ -1501,11 +1501,11 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa void nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags) { - LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n", + SOCKET_LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n", this, outFlags)); if (outFlags == -1) { - LOG(("socket timeout expired\n")); + SOCKET_LOG(("socket timeout expired\n")); mCondition = NS_ERROR_NET_TIMEOUT; return; } @@ -1557,7 +1557,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags) mCondition = ErrorAccordingToNSPR(code); if ((mCondition == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty()) mCondition = NS_ERROR_PROXY_CONNECTION_REFUSED; - LOG((" connection failed! [reason=%x]\n", mCondition)); + SOCKET_LOG((" connection failed! [reason=%x]\n", mCondition)); } } } @@ -1574,7 +1574,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags) void nsSocketTransport::OnSocketDetached(PRFileDesc *fd) { - LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n", + SOCKET_LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n", this, mCondition)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -1651,7 +1651,7 @@ nsSocketTransport::OpenInputStream(PRUint32 flags, PRUint32 segcount, nsIInputStream **result) { - LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n", + SOCKET_LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n", this, flags)); NS_ENSURE_TRUE(!mInput.IsReferenced(), NS_ERROR_UNEXPECTED); @@ -1699,7 +1699,7 @@ nsSocketTransport::OpenOutputStream(PRUint32 flags, PRUint32 segcount, nsIOutputStream **result) { - LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n", + SOCKET_LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n", this, flags)); NS_ENSURE_TRUE(!mOutput.IsReferenced(), NS_ERROR_UNEXPECTED); diff --git a/netwerk/base/src/nsSocketTransportService2.cpp b/netwerk/base/src/nsSocketTransportService2.cpp index ac372674c02..7d21140f287 100644 --- a/netwerk/base/src/nsSocketTransportService2.cpp +++ b/netwerk/base/src/nsSocketTransportService2.cpp @@ -117,7 +117,7 @@ nsSocketTransportService::GetThreadSafely() NS_IMETHODIMP nsSocketTransportService::Dispatch(nsIRunnable *event, PRUint32 flags) { - LOG(("STS dispatch [%p]\n", event)); + SOCKET_LOG(("STS dispatch [%p]\n", event)); nsCOMPtr thread = GetThreadSafely(); NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED); @@ -144,7 +144,7 @@ nsSocketTransportService::IsOnCurrentThread(PRBool *result) NS_IMETHODIMP nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event) { - LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n")); + SOCKET_LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n")); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -159,7 +159,7 @@ nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event) NS_IMETHODIMP nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler) { - LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler)); + SOCKET_LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); @@ -181,7 +181,7 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler nsresult nsSocketTransportService::DetachSocket(SocketContext *sock) { - LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler)); + SOCKET_LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler)); // inform the handler that this socket is going away sock->mHandler->OnSocketDetached(sock->mFD); @@ -213,7 +213,7 @@ nsSocketTransportService::DetachSocket(SocketContext *sock) nsresult nsSocketTransportService::AddToPollList(SocketContext *sock) { - LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler)); + SOCKET_LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler)); if (mActiveCount == NS_SOCKET_MAX_COUNT) { NS_ERROR("too many active sockets"); @@ -227,19 +227,19 @@ nsSocketTransportService::AddToPollList(SocketContext *sock) mPollList[mActiveCount].in_flags = sock->mHandler->mPollFlags; mPollList[mActiveCount].out_flags = 0; - LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); + SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); return NS_OK; } void nsSocketTransportService::RemoveFromPollList(SocketContext *sock) { - LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler)); + SOCKET_LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler)); PRUint32 index = sock - mActiveList; NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index"); - LOG((" index=%u mActiveCount=%u\n", index, mActiveCount)); + SOCKET_LOG((" index=%u mActiveCount=%u\n", index, mActiveCount)); if (index != mActiveCount-1) { mActiveList[index] = mActiveList[mActiveCount-1]; @@ -247,13 +247,13 @@ nsSocketTransportService::RemoveFromPollList(SocketContext *sock) } mActiveCount--; - LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); + SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); } nsresult nsSocketTransportService::AddToIdleList(SocketContext *sock) { - LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler)); + SOCKET_LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler)); if (mIdleCount == NS_SOCKET_MAX_COUNT) { NS_ERROR("too many idle sockets"); @@ -263,14 +263,14 @@ nsSocketTransportService::AddToIdleList(SocketContext *sock) mIdleList[mIdleCount] = *sock; mIdleCount++; - LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); + SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); return NS_OK; } void nsSocketTransportService::RemoveFromIdleList(SocketContext *sock) { - LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler)); + SOCKET_LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler)); PRUint32 index = sock - &mIdleList[0]; NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index"); @@ -279,7 +279,7 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock) mIdleList[index] = mIdleList[mIdleCount-1]; mIdleCount--; - LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); + SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); } void @@ -320,7 +320,7 @@ nsSocketTransportService::PollTimeout() if (r < minR) minR = r; } - LOG(("poll timeout: %lu\n", minR)); + SOCKET_LOG(("poll timeout: %lu\n", minR)); return PR_SecondsToInterval(minR); } @@ -352,13 +352,13 @@ nsSocketTransportService::Poll(PRBool wait, PRUint32 *interval) PRIntervalTime ts = PR_IntervalNow(); - LOG((" timeout = %i milliseconds\n", + SOCKET_LOG((" timeout = %i milliseconds\n", PR_IntervalToMilliseconds(pollTimeout))); PRInt32 rv = PR_Poll(pollList, pollCount, pollTimeout); PRIntervalTime passedInterval = PR_IntervalNow() - ts; - LOG((" ...returned after %i milliseconds\n", + SOCKET_LOG((" ...returned after %i milliseconds\n", PR_IntervalToMilliseconds(passedInterval))); *interval = PR_IntervalToSeconds(passedInterval); @@ -409,7 +409,7 @@ nsSocketTransportService::Init() // if (!mThreadEvent) { NS_WARNING("running socket transport thread without a pollable event"); - LOG(("running socket transport thread without a pollable event")); + SOCKET_LOG(("running socket transport thread without a pollable event")); } } @@ -440,7 +440,7 @@ nsSocketTransportService::Init() NS_IMETHODIMP nsSocketTransportService::Shutdown() { - LOG(("nsSocketTransportService::Shutdown\n")); + SOCKET_LOG(("nsSocketTransportService::Shutdown\n")); NS_ENSURE_STATE(NS_IsMainThread()); @@ -559,7 +559,7 @@ nsSocketTransportService::AfterProcessNextEvent(nsIThreadInternal* thread, NS_IMETHODIMP nsSocketTransportService::Run() { - LOG(("STS thread init\n")); + SOCKET_LOG(("STS thread init\n")); gSocketThread = PR_GetCurrentThread(); @@ -589,7 +589,7 @@ nsSocketTransportService::Run() NS_ProcessNextEvent(thread); } - LOG(("STS shutting down thread\n")); + SOCKET_LOG(("STS shutting down thread\n")); // detach any sockets PRInt32 i; @@ -604,14 +604,14 @@ nsSocketTransportService::Run() gSocketThread = nsnull; - LOG(("STS thread exit\n")); + SOCKET_LOG(("STS thread exit\n")); return NS_OK; } nsresult nsSocketTransportService::DoPollIteration(PRBool wait) { - LOG(("STS poll iter [%d]\n", wait)); + SOCKET_LOG(("STS poll iter [%d]\n", wait)); PRInt32 i, count; @@ -629,7 +629,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait) count = mIdleCount; for (i=mActiveCount-1; i>=0; --i) { //--- - LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i, + SOCKET_LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i, mActiveList[i].mHandler, mActiveList[i].mHandler->mCondition, mActiveList[i].mHandler->mPollFlags)); @@ -649,7 +649,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait) } for (i=count-1; i>=0; --i) { //--- - LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i, + SOCKET_LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i, mIdleList[i].mHandler, mIdleList[i].mHandler->mCondition, mIdleList[i].mHandler->mPollFlags)); @@ -660,14 +660,14 @@ nsSocketTransportService::DoPollIteration(PRBool wait) MoveToPollList(&mIdleList[i]); } - LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); + SOCKET_LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); // Measures seconds spent while blocked on PR_Poll PRUint32 pollInterval; PRInt32 n = Poll(wait, &pollInterval); if (n < 0) { - LOG((" PR_Poll error [%d]\n", PR_GetError())); + SOCKET_LOG((" PR_Poll error [%d]\n", PR_GetError())); pollError = PR_TRUE; } else { @@ -722,7 +722,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait) if (!mThreadEvent) { NS_WARNING("running socket transport thread without " "a pollable event"); - LOG(("running socket transport thread without " + SOCKET_LOG(("running socket transport thread without " "a pollable event")); } mPollList[0].fd = mThreadEvent; diff --git a/netwerk/base/src/nsSocketTransportService2.h b/netwerk/base/src/nsSocketTransportService2.h index 727a0fb2b2f..b21c1bd240f 100644 --- a/netwerk/base/src/nsSocketTransportService2.h +++ b/netwerk/base/src/nsSocketTransportService2.h @@ -59,8 +59,8 @@ // extern PRLogModuleInfo *gSocketTransportLog; #endif -#define LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args) -#define LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG) +#define SOCKET_LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args) +#define SOCKET_LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG) //----------------------------------------------------------------------------- From eff99966309315b8a0a3e62eac54c3f46ed5c664 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Thu, 28 Oct 2010 10:10:03 -0700 Subject: [PATCH 120/263] Bug 606719 - Browser stalls with connections left hanging in TCP close wait state. Part 2: fix it. r=dwitte, a=b7+ --- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 49 +++++++++++-------- netwerk/protocol/http/nsHttpHandler.cpp | 3 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 3768d396a5f..0ffe6b8a306 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -206,6 +206,8 @@ nsHttpConnectionMgr::StopPruneDeadConnectionsTimer() { LOG(("nsHttpConnectionMgr::StopPruneDeadConnectionsTimer\n")); + // Reset mTimeOfNextWakeUp so that we can find a new shortest value. + mTimeOfNextWakeUp = LL_MAXUINT; if (mTimer) { mTimer->Cancel(); mTimer = NULL; @@ -412,8 +414,8 @@ nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *cl // If time to next expire found is shorter than time to next wake-up, we need to // change the time for next wake-up. + PRUint32 now = NowInSeconds(); if (0 < ent->mIdleConns.Length()) { - PRUint32 now = NowInSeconds(); PRUint64 timeOfNextExpire = now + timeToNextExpire; // If pruning of dead connections is not already scheduled to happen // or time found for next connection to expire is is before @@ -556,7 +558,8 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n", ci->HashKey().get(), caps)); - // use >= just to be safe + // If we have more active connections than the limit, then we're done -- + // purging idle connections won't get us below it. if (mNumActiveConns >= mMaxConns) { LOG((" num active conns == max conns\n")); return PR_TRUE; @@ -602,11 +605,6 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps, *result = nsnull; - if (AtActiveConnectionLimit(ent, caps)) { - LOG((" at active connection limit!\n")); - return; - } - nsHttpConnection *conn = nsnull; if (caps & NS_HTTP_ALLOW_KEEPALIVE) { @@ -624,15 +622,31 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps, LOG((" reusing connection [conn=%x]\n", conn)); ent->mIdleConns.RemoveElementAt(0); mNumIdleConns--; + + // If there are no idle connections left at all, we need to make + // sure that we are not pruning dead connections anymore. + if (0 == mNumIdleConns) + StopPruneDeadConnectionsTimer(); } } if (!conn) { - // No reusable idle connection found for this entry. If there are no - // idle connections left at all, we need to make sure that we are not - // pruning dead connections anymore. - if (0 == mNumIdleConns) - StopPruneDeadConnectionsTimer(); + // Check if we need to purge an idle connection. Note that we may have + // removed one above; if so, this will be a no-op. We do this before + // checking the active connection limit to catch the case where we do + // have an idle connection, but the purge timer hasn't fired yet. + // XXX this just purges a random idle connection. we should instead + // enumerate the entire hash table to find the eldest idle connection. + if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns) + mCT.Enumerate(PurgeOneIdleConnectionCB, this); + + // Need to make a new TCP connection. First, we check if we've hit + // either the maximum connection limit globally or for this particular + // host or proxy. If we have, we're done. + if (AtActiveConnectionLimit(ent, caps)) { + LOG((" at active connection limit!\n")); + return; + } conn = new nsHttpConnection(); if (!conn) @@ -644,15 +658,6 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps, NS_RELEASE(conn); return; } - - // We created a new connection that will become active, purge the - // oldest idle connection if we've reached the upper limit. - // This only needs to be done if there is a idle connection. - if (0 < mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 > mMaxConns) - mCT.Enumerate(PurgeOneIdleConnectionCB, this); - - // XXX this just purges a random idle connection. we should instead - // enumerate the entire hash table to find the eldest idle connection. } *result = conn; @@ -932,6 +937,8 @@ nsHttpConnectionMgr::OnMsgPruneDeadConnections(PRInt32, void *) { LOG(("nsHttpConnectionMgr::OnMsgPruneDeadConnections\n")); + // Reset mTimeOfNextWakeUp so that we can find a new shortest value. + mTimeOfNextWakeUp = LL_MAXUINT; if (mNumIdleConns > 0) mCT.Enumerate(PruneDeadConnectionsCB, this); } diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index 84ca43b6acc..96b0a8ab4fb 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -76,6 +76,7 @@ #include "nsNetUtil.h" #include "nsIOService.h" #include "nsAsyncRedirectVerifyHelper.h" +#include "nsSocketTransportService2.h" #include "nsIXULAppInfo.h" @@ -854,7 +855,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) if (PREF_CHANGED(HTTP_PREF("max-connections"))) { rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val); if (NS_SUCCEEDED(rv)) { - mMaxConnections = (PRUint16) NS_CLAMP(val, 1, 0xffff); + mMaxConnections = (PRUint16) NS_CLAMP(val, 1, NS_SOCKET_MAX_COUNT); if (mConnMgr) mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS, mMaxConnections); From e7d2253efb2667195d733d029fdb5b4948d8cecf Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Thu, 28 Oct 2010 12:21:04 -0700 Subject: [PATCH 121/263] Bug 606076: XUL fastload is not cleared when new extensions are installed. r=bsmedberg, a=blocks-beta7 --- .../xul/document/src/nsXULPrototypeCache.cpp | 42 ++++++++++++------- .../test/xpcshell/test_bug594058.js | 20 ++++++++- .../extensions/test/xpcshell/test_startup.js | 31 ++++++++++++++ 3 files changed, 77 insertions(+), 16 deletions(-) diff --git a/content/xul/document/src/nsXULPrototypeCache.cpp b/content/xul/document/src/nsXULPrototypeCache.cpp index 9639526ede4..b71fdd2518e 100644 --- a/content/xul/document/src/nsXULPrototypeCache.cpp +++ b/content/xul/document/src/nsXULPrototypeCache.cpp @@ -145,6 +145,7 @@ NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult) nsXULPrototypeCache *p = result; obsSvc->AddObserver(p, "chrome-flush-skin-caches", PR_FALSE); obsSvc->AddObserver(p, "chrome-flush-caches", PR_FALSE); + obsSvc->AddObserver(p, "startupcache-invalidate", PR_FALSE); } return rv; @@ -410,10 +411,6 @@ nsXULPrototypeCache::AbortFastLoads() NS_BREAK(); #endif - // Save a strong ref to the FastLoad file, so we can remove it after we - // close open streams to it. - nsCOMPtr file = gFastLoadFile; - // Flush the XUL cache for good measure, in case we cached a bogus/downrev // script, somehow. Flush(); @@ -421,29 +418,42 @@ nsXULPrototypeCache::AbortFastLoads() // Clear the FastLoad set mFastLoadURITable.Clear(); - if (! gFastLoadService) - return; + nsCOMPtr fastLoadService = gFastLoadService; + nsCOMPtr file = gFastLoadFile; + + nsresult rv; + + if (! fastLoadService) { + fastLoadService = do_GetFastLoadService(); + if (! fastLoadService) + return; + + rv = fastLoadService->NewFastLoadFile(XUL_FASTLOAD_FILE_BASENAME, + getter_AddRefs(file)); + if (NS_FAILED(rv)) + return; + } // Fetch the current input (if FastLoad file existed) or output (if we're // creating the FastLoad file during this app startup) stream. nsCOMPtr objectInput; nsCOMPtr objectOutput; - gFastLoadService->GetInputStream(getter_AddRefs(objectInput)); - gFastLoadService->GetOutputStream(getter_AddRefs(objectOutput)); + fastLoadService->GetInputStream(getter_AddRefs(objectInput)); + fastLoadService->GetOutputStream(getter_AddRefs(objectOutput)); if (objectOutput) { - gFastLoadService->SetOutputStream(nsnull); + fastLoadService->SetOutputStream(nsnull); if (NS_SUCCEEDED(objectOutput->Close()) && gChecksumXULFastLoadFile) - gFastLoadService->CacheChecksum(gFastLoadFile, - objectOutput); + fastLoadService->CacheChecksum(file, + objectOutput); } if (objectInput) { // If this is the last of one or more XUL master documents loaded // together at app startup, close the FastLoad service's singleton // input stream now. - gFastLoadService->SetInputStream(nsnull); + fastLoadService->SetInputStream(nsnull); objectInput->Close(); } @@ -462,13 +472,15 @@ nsXULPrototypeCache::AbortFastLoads() } file->MoveToNative(nsnull, NS_LITERAL_CSTRING("Aborted.mfasl")); #else - file->Remove(PR_FALSE); + rv = file->Remove(PR_FALSE); + if (NS_FAILED(rv)) + NS_WARNING("Failed to remove fastload file, fastload data may be outdated"); #endif } // If the list is empty now, the FastLoad process is done. - NS_RELEASE(gFastLoadService); - NS_RELEASE(gFastLoadFile); + NS_IF_RELEASE(gFastLoadService); + NS_IF_RELEASE(gFastLoadFile); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js index 3f8f4801582..1ed8a3638a8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug594058.js @@ -12,6 +12,10 @@ const Ci = Components.interfaces; const extDir = gProfD.clone(); extDir.append("extensions"); +var gFastLoadService = AM_Cc["@mozilla.org/fast-load-service;1"]. + getService(AM_Ci.nsIFastLoadService); +var gFastLoadFile = null; + /** * Start the test by installing extensions. */ @@ -27,10 +31,19 @@ function run_test() { } }, "startupcache-invalidate", false); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + + gFastLoadFile = gFastLoadService.newFastLoadFile("XUL"); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + startupManager(); + // nsAppRunner takes care of clearing this when a new app is installed + do_check_true(gFastLoadFile.exists()); installAllFiles([do_get_addon("test_bug594058")], function() { restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); do_check_true(cachePurged); cachePurged = false; @@ -47,15 +60,20 @@ function run_test() { otherFile.lastModifiedTime = pastTime; restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); cachePurged = false; otherFile.lastModifiedTime = pastTime + 5000; restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); do_check_true(cachePurged); cachePurged = false; restartManager(); - do_check_true(!cachePurged); + do_check_true(gFastLoadFile.exists()); + do_check_false(cachePurged); do_test_finished(); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js index d9d9a0c0d5c..e3a4d87d2d8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js @@ -85,11 +85,19 @@ registerDirectory("XREUSysExt", userDir.parent); const profileDir = gProfD.clone(); profileDir.append("extensions"); +var gFastLoadService = AM_Cc["@mozilla.org/fast-load-service;1"]. + getService(AM_Ci.nsIFastLoadService); +var gFastLoadFile = null; + // Set up the profile function run_test() { do_test_pending(); startupManager(); + gFastLoadFile = gFastLoadService.newFastLoadFile("XUL"); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", @@ -127,6 +135,9 @@ function run_test_1() { writeInstallRDFForExtension(addon5, profileDir); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", @@ -203,6 +214,8 @@ function run_test_2() { dest.remove(true); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -257,6 +270,8 @@ function run_test_3() { writeInstallRDFForExtension(addon3, profileDir, "addon4@tests.mozilla.org"); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -308,6 +323,8 @@ function run_test_4() { Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_SYSTEM); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -340,6 +357,8 @@ function run_test_5() { Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_USER); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -378,6 +397,8 @@ function run_test_6() { Services.prefs.clearUserPref("extensions.enabledScopes"); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -420,6 +441,8 @@ function run_test_7() { dest.remove(true); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -467,6 +490,8 @@ function run_test_8() { Services.prefs.setIntPref("extensions.enabledScopes", 0); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -508,6 +533,8 @@ function run_test_9() { writeInstallRDFForExtension(addon2, profileDir); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -558,6 +585,8 @@ function run_test_10() { writeInstallRDFForExtension(addon1, userDir); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", @@ -608,6 +637,8 @@ function run_test_11() { dest.remove(true); restartManager(); + do_check_false(gFastLoadFile.exists()); + gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", From 8f52e9d7f56f1f4bec609bc03e934c3d7388b12a Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 28 Oct 2010 22:27:52 +0200 Subject: [PATCH 122/263] Delay hiding the plugin window when a delayed stop is requested (eg. during frame destruction). b=604734 r=roc a=blocking2.0:beta7 --- layout/generic/nsObjectFrame.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 839c47913d1..59b639b8f7c 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -365,6 +365,7 @@ public: static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance); void SetupCARefresh(); void* FixUpPluginWindow(PRInt32 inPaintState); + void HidePluginWindow(); // Set a flag that (if true) indicates the plugin port info has changed and // SetWindow() needs to be called. void SetPluginPortChanged(PRBool aState) { mPluginPortChanged = aState; } @@ -1102,8 +1103,6 @@ nsObjectFrame::CallSetWindow() if (IsHidden()) return; - PRBool windowless = (window->type == NPWindowTypeDrawable); - // refresh the plugin port as well window->window = mInstanceOwner->GetPluginPortFromWidget(); @@ -2463,7 +2462,11 @@ DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop) if (DoDelayedStop(aInstanceOwner, aDelayedStop)) return; - + +#if defined(XP_MACOSX) + aInstanceOwner->HidePluginWindow(); +#endif + inst->Stop(); nsCOMPtr pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID); @@ -2554,7 +2557,6 @@ nsObjectFrame::StopPluginInternal(PRBool aDelayedStop) nsTArray configurations; GetEmptyClipConfiguration(&configurations); parent->ConfigureChildren(configurations); - DidSetWidgetGeometry(); } } else { @@ -6429,6 +6431,19 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState) return nsnull; } +void +nsPluginInstanceOwner::HidePluginWindow() +{ + if (!mPluginWindow || !mInstance) { + return; + } + + mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top; + mPluginWindow->clipRect.right = mPluginWindow->clipRect.left; + mWidgetVisible = PR_FALSE; + mInstance->SetWindow(mPluginWindow); +} + #endif // XP_MACOSX // Little helper function to resolve relative URL in From 3b0915cde5c80a5b53004489813f1d3dc8647c75 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 28 Oct 2010 22:48:06 +0200 Subject: [PATCH 123/263] Bug 607974 - Write tests for bug 297761. r=bz a=tests --- content/html/content/test/Makefile.in | 2 + content/html/content/test/file_bug297761.html | 13 ++++ content/html/content/test/test_bug297761.html | 78 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 content/html/content/test/file_bug297761.html create mode 100644 content/html/content/test/test_bug297761.html diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index 53e49ff5975..7170818b06c 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -236,6 +236,8 @@ _TEST_FILES = \ test_bug600155.html \ test_bug556007.html \ test_bug606817.html \ + test_bug297761.html \ + file_bug297761.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/file_bug297761.html b/content/html/content/test/file_bug297761.html new file mode 100644 index 00000000000..5e861a00fd3 --- /dev/null +++ b/content/html/content/test/file_bug297761.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/content/html/content/test/test_bug297761.html b/content/html/content/test/test_bug297761.html new file mode 100644 index 00000000000..4869c8bd4c9 --- /dev/null +++ b/content/html/content/test/test_bug297761.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 297761 + + + + + +Mozilla Bug 297761 +

+
+ + + + +
+
+
+
+ + From cb87c2bda90beae00c0e89b13308436021a34fe1 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 28 Oct 2010 22:48:24 +0200 Subject: [PATCH 124/263] Bug 607957 - Fix test_bug392567.html. r=bz a=tests --- content/html/content/test/test_bug392567.html | 101 ++++++++++-------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/content/html/content/test/test_bug392567.html b/content/html/content/test/test_bug392567.html index a059dc8144c..e7e76d8d081 100644 --- a/content/html/content/test/test_bug392567.html +++ b/content/html/content/test/test_bug392567.html @@ -22,57 +22,68 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392567 /** Test for Bug 392567 **/ -var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar"; -var jarUrl = "jar:" + dataUrl + "!/index.html"; -var httpUrl = location.href.replace(/\.html.*/, "_404"); -var previousDir = location.href.replace(/test\/[^\/]*$/, ""); +SimpleTest.waitForExplicitFinish(); -var form = document.forms.testForm; -var frame = frames.testFrame; -document.getElementById("testFrame").onload = processTestResult; - -// List of tests to run, each test consists of form action URL and expected result URL -var tests = [ - [jarUrl, jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null], - ["data:text/html,", "data:text/html,?$PARAMS", null], - ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS", null], - [httpUrl, httpUrl + "?$PARAMS", null], - [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ], - [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null], - ["", jarUrl + "?key=value0", null], - [" ", jarUrl + "?key=value0", document.location], - ["../", previousDir + "?$PARAMS", previousDir], -]; - -var currentTest = -1; - -SimpleTest.waitForExplicitFinish(); -runNextTest(); - -function runNextTest() { - currentTest++; - if (currentTest >= tests.length) { - SimpleTest.finish(); +function runTests() +{ + if (window.location.search.match(/\?key=value/)) { return; } - form.setAttribute("action", tests[currentTest][0]); - is(form.action, tests[currentTest][0], - "action IDL attribute should reflect the action content attribute"); - is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0], - "mozActionUri IDL attribute should resolve the action URI"); - form.key.value = "value" + currentTest; - form.submit(); + var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar"; + var jarUrl = "jar:" + dataUrl + "!/index.html"; + var httpUrl = location.href.replace(/\.html.*/, "_404"); + var previousDir = location.href.replace(/test\/[^\/]*$/, ""); + var documentURL = location.href.replace(/\.html.*/, "\.html"); + + var form = document.forms.testForm; + var frame = frames.testFrame; + document.getElementById("testFrame").onload = processTestResult; + + // List of tests to run, each test consists of form action URL and expected result URL + var tests = [ + [jarUrl, jarUrl + "?$PARAMS", null], + [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null], + [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null], + ["data:text/html,", "data:text/html,?$PARAMS", null], + ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS", null], + [httpUrl, httpUrl + "?$PARAMS", null], + [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ], + [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null], + ["", documentURL + "?$PARAMS", null], + [" ", documentURL + "?$PARAMS", document.location], + ["../", previousDir + "?$PARAMS", previousDir], + ]; + + var currentTest = -1; + + runNextTest(); + + function runNextTest() { + currentTest++; + if (currentTest >= tests.length) { + SimpleTest.finish(); + return; + } + + form.setAttribute("action", tests[currentTest][0]); + is(form.action, tests[currentTest][0], + "action IDL attribute should reflect the action content attribute"); + is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0], + "mozActionUri IDL attribute should resolve the action URI"); + form.key.value = "value" + currentTest; + form.submit(); + } + + function processTestResult() { + var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest); + is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]); + + setTimeout(runNextTest, 0); + } } -function processTestResult() { - var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest); - is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]); - - setTimeout(runNextTest, 0); -} +addLoadEvent(runTests); From 00c432bb8cc2e120e3005adf238bf7ee64961e3e Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 28 Oct 2010 22:49:14 +0200 Subject: [PATCH 125/263] Bug 607145 - form.action, button.formAction and input.formAction should be reflected as URL. r=bz a=blocking-b7 --- .../html/content/src/nsGenericHTMLElement.cpp | 12 ++- .../html/content/src/nsHTMLButtonElement.cpp | 2 +- .../html/content/src/nsHTMLFormElement.cpp | 22 ++---- .../html/content/src/nsHTMLInputElement.cpp | 2 +- content/html/content/test/Makefile.in | 1 + content/html/content/test/test_bug392567.html | 26 +++---- content/html/content/test/test_bug566160.html | 33 --------- content/html/content/test/test_bug607145.html | 74 +++++++++++++++++++ dom/interfaces/html/nsIDOMHTMLFormElement.idl | 5 +- .../passwordmgr/src/nsLoginManager.js | 7 +- 10 files changed, 106 insertions(+), 78 deletions(-) create mode 100644 content/html/content/test/test_bug607145.html diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 8ffe0c2a15a..3f4f67f2f90 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2131,14 +2131,12 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& { nsCOMPtr uri; PRBool hadAttr = GetURIAttr(aAttr, aBaseAttr, PR_FALSE, getter_AddRefs(uri)); - if (!hadAttr) { - aResult.Truncate(); - return NS_OK; - } - if (!uri) { - // Just return the attr value - GetAttr(kNameSpaceID_None, aAttr, aResult); + // If the content attribute isn't set or the URL is invalid, the default value + // should be returned. The default default value is the empty string and it + // looks like no attribute have a specified default value. + if (!hadAttr || !uri) { + aResult.Truncate(); return NS_OK; } diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index 2420d21242a..e9cb26fc35c 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -218,7 +218,7 @@ nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Autofocus, autofocus) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled) -NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormAction, formaction) +NS_IMPL_URI_ATTR(nsHTMLButtonElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormMethod, formmethod, diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index bb62ab3ac2c..ffca7972054 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -375,7 +375,7 @@ nsHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, } NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset) -NS_IMPL_STRING_ATTR(nsHTMLFormElement, Action, action) +NS_IMPL_URI_ATTR(nsHTMLFormElement, Action, action) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Autocomplete, autocomplete, kFormDefaultAutocomplete->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Enctype, enctype, @@ -386,17 +386,6 @@ NS_IMPL_BOOL_ATTR(nsHTMLFormElement, NoValidate, novalidate) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Name, name) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target) -NS_IMETHODIMP -nsHTMLFormElement::GetMozActionUri(nsAString& aValue) -{ - GetAttr(kNameSpaceID_None, nsGkAtoms::action, aValue); - if (aValue.IsEmpty()) { - // Avoid resolving action="" to the base uri, bug 297761. - return NS_OK; - } - return GetURIAttr(nsGkAtoms::action, nsnull, aValue); -} - NS_IMETHODIMP nsHTMLFormElement::Submit() { @@ -1430,18 +1419,23 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL, // attribute specified, it should be used. Otherwise, the action attribute // from the form element should be used. // + // In addition, if action="" or formaction="", we need to make sure we don't + // try to resolve the URL but we should submit to the current document. + // nsAutoString action; nsCOMPtr formControl = do_QueryInterface(aOriginatingElement); if (formControl && formControl->IsSubmitControl() && aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formaction, action)) { - // Avoid resolving action="" to the base uri, bug 297761. if (!action.IsEmpty()) { static_cast(aOriginatingElement)-> GetURIAttr(nsGkAtoms::formaction, nsnull, action); } } else { - GetMozActionUri(action); + GetAttr(kNameSpaceID_None, nsGkAtoms::action, action); + if (!action.IsEmpty()) { + GetAction(action); + } } // diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index f56251136a4..cce840d6d78 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -962,7 +962,7 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete, NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus) //NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked) NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled) -NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormAction, formaction) +NS_IMPL_URI_ATTR(nsHTMLInputElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod, diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index 7170818b06c..e84f741f722 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -238,6 +238,7 @@ _TEST_FILES = \ test_bug606817.html \ test_bug297761.html \ file_bug297761.html \ + test_bug607145.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/test_bug392567.html b/content/html/content/test/test_bug392567.html index e7e76d8d081..766c8e7b870 100644 --- a/content/html/content/test/test_bug392567.html +++ b/content/html/content/test/test_bug392567.html @@ -42,17 +42,17 @@ function runTests() // List of tests to run, each test consists of form action URL and expected result URL var tests = [ - [jarUrl, jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null], - [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null], - ["data:text/html,", "data:text/html,?$PARAMS", null], - ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS", null], - [httpUrl, httpUrl + "?$PARAMS", null], - [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ], - [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null], - ["", documentURL + "?$PARAMS", null], - [" ", documentURL + "?$PARAMS", document.location], - ["../", previousDir + "?$PARAMS", previousDir], + [jarUrl, jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"], + ["data:text/html,", "data:text/html,?$PARAMS"], + ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS"], + [httpUrl, httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"], + ["", documentURL + "?$PARAMS"], + [" ", documentURL + "?$PARAMS"], + ["../", previousDir + "?$PARAMS"], ]; var currentTest = -1; @@ -67,10 +67,6 @@ function runTests() } form.setAttribute("action", tests[currentTest][0]); - is(form.action, tests[currentTest][0], - "action IDL attribute should reflect the action content attribute"); - is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0], - "mozActionUri IDL attribute should resolve the action URI"); form.key.value = "value" + currentTest; form.submit(); } diff --git a/content/html/content/test/test_bug566160.html b/content/html/content/test/test_bug566160.html index cd258ce0b14..c11faaef65d 100644 --- a/content/html/content/test/test_bug566160.html +++ b/content/html/content/test/test_bug566160.html @@ -83,41 +83,8 @@ var gTestResults = { var gPendingLoad = 0; // Has to be set after depending on the frames number. -function checkFormActionAttribute(aElement) -{ - ok("formAction" in aElement, "formAction IDL attribute should be available in " - + aElement); - - is(aElement.formAction, "", "formAction IDL attribute should be " + - "undefined by default"); - is(aElement.getAttribute('formaction'), null, "formaction content attribute " + - "should be the empty string by default"); - - aElement.formAction = "foo"; - is(aElement.getAttribute('formaction'), "foo", "formaction content attribute " + - "should be 'foo'."); - is(aElement.formAction, "foo", "formAction IDL attribute should reflect " + - "the content attribute"); - - aElement.setAttribute('formaction', 'bar'); - is(aElement.getAttribute('formaction'), "bar", "formaction content attribute " + - "should be 'foo'."); - is(aElement.formAction, "bar", "formAction IDL attribute should reflect " + - "the content attribute"); - - aElement.removeAttribute('formaction'); - is(aElement.formAction, "", "formAction IDL attribute should be " + - "undefined by default"); - is(aElement.getAttribute('formaction'), null, "formaction content attribute " + - "should be the empty string by default"); -} - function runTests() { - // First of all, let's check if .formAction and @formaction work correctly. - checkFormActionAttribute(document.createElement('input')); - checkFormActionAttribute(document.createElement('button')); - // We add a load event for the frames which will be called when the forms // will be submitted. var frames = [ document.getElementById('frame1'), diff --git a/content/html/content/test/test_bug607145.html b/content/html/content/test/test_bug607145.html new file mode 100644 index 00000000000..dd72371de88 --- /dev/null +++ b/content/html/content/test/test_bug607145.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 607145 + + + + + +Mozilla Bug 607145 +

+
+
+
+ + diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index 96da5649277..7d78a2d0035 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -47,7 +47,7 @@ * http://www.w3.org/TR/DOM-Level-2-HTML/ */ -[scriptable, uuid(653dc482-d6db-4e85-bdd9-151fd110e7b1)] +[scriptable, uuid(0884ce23-e069-499e-a13c-a91c8ae0fc98)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString name; @@ -65,7 +65,4 @@ interface nsIDOMHTMLFormElement : nsIDOMHTMLElement void submit(); void reset(); - - // This property returns the resolved action URI. - readonly attribute DOMString mozActionUri; }; diff --git a/toolkit/components/passwordmgr/src/nsLoginManager.js b/toolkit/components/passwordmgr/src/nsLoginManager.js index 25140729414..4b7cfb7cfcc 100644 --- a/toolkit/components/passwordmgr/src/nsLoginManager.js +++ b/toolkit/components/passwordmgr/src/nsLoginManager.js @@ -978,11 +978,12 @@ LoginManager.prototype = { }, _getActionOrigin : function (form) { - var uriString = form.mozActionUri; + var uriString = form.action; - // A blank or mission action submits to where it came from. + // If uriString equals the empty string that means actian attribute is + // missing or invalid and it will submit to the baseURI. if (uriString == "") - uriString = form.baseURI; // ala bug 297761 + uriString = form.baseURI; return this._getPasswordOrigin(uriString, true); }, From d57f78da96d1ea810bc40737e1dd94ab07d11c8a Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Thu, 28 Oct 2010 14:03:26 -0700 Subject: [PATCH 126/263] test fix and some cleanup - Bug 607545 - Intermittent browser_bug562797.js | Test timed out *followed* by other errors. r=dtownsend, a=test fix --- .../test/browser/browser_bug557943.js | 155 +++++++++--------- .../test/browser/browser_bug557956.js | 3 +- .../test/browser/browser_bug562797.js | 4 +- 3 files changed, 83 insertions(+), 79 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557943.js b/toolkit/mozapps/extensions/test/browser/browser_bug557943.js index 34bb5ba00eb..e7f60741fa7 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557943.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557943.js @@ -1,77 +1,78 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Bug 557943 - Searching for addons can result in wrong results - -var gManagerWindow; - -function test() { - waitForExplicitFinish(); - - gProvider = new MockProvider(); - - gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "Microsoft .NET Framework Assistant", - description: "", - version: "6.66" - }, { - id: "addon2@tests.mozilla.org", - name: "AwesomeNet Addon", - description: "" - }, { - id: "addon3@tests.mozilla.org", - name: "Dictionnaire MySpell en Francais (réforme 1990)", - description: "" - }]); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - run_next_test(); - }); -} - -function end_test() { - close_manager(gManagerWindow, function() { - finish(); - }); -} - - -function perform_search(aQuery, aCallback) { - var searchBox = gManagerWindow.document.getElementById("header-search"); - searchBox.value = aQuery; - - EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow); - EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); - wait_for_view_load(gManagerWindow, function() { - var list = gManagerWindow.document.getElementById("search-list"); - var rows = list.getElementsByTagName("richlistitem"); - aCallback(rows); - }); -} - - -add_test(function() { - perform_search(".net", function(aRows) { - is(aRows.length, 1, "Should only get one result"); - is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result"); - run_next_test(); - }); -}); - -add_test(function() { - perform_search("réf", function(aRows) { - is(aRows.length, 1, "Should only get one result"); - is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result"); - run_next_test(); - }); -}); - -add_test(function() { - perform_search("javascript:void()", function(aRows) { - is(aRows.length, 0, "Should not get any results"); - run_next_test(); - }); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 557943 - Searching for addons can result in wrong results + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "Microsoft .NET Framework Assistant", + description: "", + version: "6.66" + }, { + id: "addon2@tests.mozilla.org", + name: "AwesomeNet Addon", + description: "" + }, { + id: "addon3@tests.mozilla.org", + name: "Dictionnaire MySpell en Francais (réforme 1990)", + description: "" + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +function perform_search(aQuery, aCallback) { + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + aCallback(rows); + }); +} + + +add_test(function() { + perform_search(".net", function(aRows) { + is(aRows.length, 1, "Should only get one result"); + is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result"); + run_next_test(); + }); +}); + +add_test(function() { + perform_search("réf", function(aRows) { + is(aRows.length, 1, "Should only get one result"); + is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result"); + run_next_test(); + }); +}); + +add_test(function() { + perform_search("javascript:void()", function(aRows) { + is(aRows.length, 0, "Should not get any results"); + run_next_test(); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js index 3575dc5a5f4..8f172f6a22f 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js @@ -119,7 +119,8 @@ function open_compatibility_window(aInactiveAddonIds, aCallback) { info("Compatibility dialog opened"); function page_shown(aEvent) { - info("Page " + aEvent.target.id + " shown"); + if (aEvent.target.pageid) + info("Page " + aEvent.target.pageid + " shown"); } win.addEventListener("pageshow", page_shown, false); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js index a54302445c5..e2f8f87f8ae 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js @@ -7,7 +7,9 @@ */ function test() { - requestLongerTimeout(2); + // Set the timeout to 300 seconds since this test can easily take 220 seconds + // to run on a Windows debug build when it runs in a tab. + requestLongerTimeout(10); waitForExplicitFinish(); From 78ab2ebe44f086f6adbe9d657b724c9b7599e219 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Thu, 28 Oct 2010 14:03:52 -0700 Subject: [PATCH 127/263] test cleanup - Bug 607545 - Intermittent browser_bug562797.js | Test timed out *followed* by other errors. r=dtownsend, a=test fix --- .../extensions/test/browser/addon_prefs.xul | 10 +- .../test/browser/browser_bug567127.js | 318 ++++---- .../test/browser/browser_bug581076.js | 258 +++---- .../test/browser/browser_bug587970.js | 304 ++++---- .../test/browser/browser_bug591465.js | 702 +++++++++--------- .../test/browser/browser_details.js | 1 + .../test/browser/browser_globalwarnings.js | 130 ++-- .../test/browser/browser_manualupdates.js | 376 +++++----- .../test/browser/browser_recentupdates.js | 172 ++--- .../mozapps/extensions/test/browser/head.js | 4 +- .../test/browser/releaseNotes.xhtml | 30 +- .../test/xpinstall/browser_auth4.js | 2 + .../test/xpinstall/browser_cancel.js | 3 +- .../test/xpinstall/browser_multipackage.js | 1 + .../test/xpinstall/browser_signed_multiple.js | 1 + .../test/xpinstall/browser_signed_naming.js | 1 + .../mozapps/extensions/test/xpinstall/head.js | 6 +- 17 files changed, 1163 insertions(+), 1156 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul index 713ea86a2b9..d058af2c5cd 100644 --- a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul +++ b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul @@ -1,5 +1,5 @@ - - - + + + diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js index a9dfa8b12df..bed62f04f23 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js @@ -1,159 +1,159 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests bug 567127 - Add install button to the add-ons manager - - -var gFilePickerFiles = []; -var gMockFilePickerFactory; -var gMockFilePickerFactoryCID; -var gManagerWindow; - -function MockFilePicker() { } - -MockFilePicker.prototype = { - QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]), - init: function(aParent, aTitle, aMode) { }, - appendFilters: function(aFilterMask) { }, - appendFilter: function(aTitle, aFilter) { }, - defaultString: "", - defaultExtension: "", - filterIndex: 0, - displayDirectory: null, - file: null, - fileURL: null, - get files() { - var i = 0; - return { - getNext: function() gFilePickerFiles[i++], - hasMoreElements: function() gFilePickerFiles.length > i - }; - }, - show: function() { - return gFilePickerFiles.length == 0 ? - Components.interfaces.nsIFilePicker.returnCancel : - Components.interfaces.nsIFilePicker.returnOK; - } -}; - -// This listens for the next opened window and checks it is of the right url. -// opencallback is called when the new window is fully loaded -// closecallback is called when the window is closed -function WindowOpenListener(url, opencallback, closecallback) { - this.url = url; - this.opencallback = opencallback; - this.closecallback = closecallback; - - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.addListener(this); -} - -WindowOpenListener.prototype = { - url: null, - opencallback: null, - closecallback: null, - window: null, - domwindow: null, - - handleEvent: function(event) { - is(this.domwindow.document.location.href, this.url, "Should have opened the correct window"); - - this.domwindow.removeEventListener("load", this, false); - // Allow any other load handlers to execute - var self = this; - executeSoon(function() { self.opencallback(self.domwindow); } ); - }, - - onWindowTitleChange: function(window, title) { - }, - - onOpenWindow: function(window) { - if (this.window) - return; - - this.window = window; - this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIDOMWindowInternal); - this.domwindow.addEventListener("load", this, false); - }, - - onCloseWindow: function(window) { - if (this.window != window) - return; - - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.removeListener(this); - this.opencallback = null; - this.window = null; - this.domwindow = null; - - // Let the window close complete - executeSoon(this.closecallback); - this.closecallback = null; - } -}; - - -function test_confirmation(aWindow, aExpectedURLs) { - var list = aWindow.document.getElementById("itemList"); - is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs"); - - aExpectedURLs.forEach(function(aURL) { - var node = list.firstChild; - while (node) { - if (node.url == aURL) { - ok(true, "Should have seen " + aURL + " in the list"); - return; - } - node = node.nextSibling; - } - ok(false, "Should have seen " + aURL + " in the list"); - }); - - aWindow.document.documentElement.cancelDialog(); -} - - -function test() { - waitForExplicitFinish(); - - gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}"); - gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker); - var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); - compReg.registerFactory(gMockFilePickerFactoryCID, - "Mock FilePicker", - "@mozilla.org/filepicker;1", - gMockFilePickerFactory); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - run_next_test(); - }); -} - -function end_test() { - var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); - compReg.unregisterFactory(gMockFilePickerFactoryCID, - gMockFilePickerFactory); - close_manager(gManagerWindow, function() { - finish(); - }); -} - - -add_test(function() { - var filePaths = [ - get_addon_file_url("browser_bug567127_1.xpi"), - get_addon_file_url("browser_bug567127_2.xpi") - ]; - gFilePickerFiles = filePaths.map(function(aPath) aPath.file); - - new WindowOpenListener(INSTALL_URI, function(aWindow) { - test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec)); - }, run_next_test); - - gManagerWindow.gViewController.doCommand("cmd_installFromFile"); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests bug 567127 - Add install button to the add-ons manager + + +var gFilePickerFiles = []; +var gMockFilePickerFactory; +var gMockFilePickerFactoryCID; +var gManagerWindow; + +function MockFilePicker() { } + +MockFilePicker.prototype = { + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]), + init: function(aParent, aTitle, aMode) { }, + appendFilters: function(aFilterMask) { }, + appendFilter: function(aTitle, aFilter) { }, + defaultString: "", + defaultExtension: "", + filterIndex: 0, + displayDirectory: null, + file: null, + fileURL: null, + get files() { + var i = 0; + return { + getNext: function() gFilePickerFiles[i++], + hasMoreElements: function() gFilePickerFiles.length > i + }; + }, + show: function() { + return gFilePickerFiles.length == 0 ? + Components.interfaces.nsIFilePicker.returnCancel : + Components.interfaces.nsIFilePicker.returnOK; + } +}; + +// This listens for the next opened window and checks it is of the right url. +// opencallback is called when the new window is fully loaded +// closecallback is called when the window is closed +function WindowOpenListener(url, opencallback, closecallback) { + this.url = url; + this.opencallback = opencallback; + this.closecallback = closecallback; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.addListener(this); +} + +WindowOpenListener.prototype = { + url: null, + opencallback: null, + closecallback: null, + window: null, + domwindow: null, + + handleEvent: function(event) { + is(this.domwindow.document.location.href, this.url, "Should have opened the correct window"); + + this.domwindow.removeEventListener("load", this, false); + // Allow any other load handlers to execute + var self = this; + executeSoon(function() { self.opencallback(self.domwindow); } ); + }, + + onWindowTitleChange: function(window, title) { + }, + + onOpenWindow: function(window) { + if (this.window) + return; + + this.window = window; + this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowInternal); + this.domwindow.addEventListener("load", this, false); + }, + + onCloseWindow: function(window) { + if (this.window != window) + return; + + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + wm.removeListener(this); + this.opencallback = null; + this.window = null; + this.domwindow = null; + + // Let the window close complete + executeSoon(this.closecallback); + this.closecallback = null; + } +}; + + +function test_confirmation(aWindow, aExpectedURLs) { + var list = aWindow.document.getElementById("itemList"); + is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs"); + + aExpectedURLs.forEach(function(aURL) { + var node = list.firstChild; + while (node) { + if (node.url == aURL) { + ok(true, "Should have seen " + aURL + " in the list"); + return; + } + node = node.nextSibling; + } + ok(false, "Should have seen " + aURL + " in the list"); + }); + + aWindow.document.documentElement.cancelDialog(); +} + + +function test() { + waitForExplicitFinish(); + + gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}"); + gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker); + var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); + compReg.registerFactory(gMockFilePickerFactoryCID, + "Mock FilePicker", + "@mozilla.org/filepicker;1", + gMockFilePickerFactory); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); + compReg.unregisterFactory(gMockFilePickerFactoryCID, + gMockFilePickerFactory); + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +add_test(function() { + var filePaths = [ + get_addon_file_url("browser_bug567127_1.xpi"), + get_addon_file_url("browser_bug567127_2.xpi") + ]; + gFilePickerFiles = filePaths.map(function(aPath) aPath.file); + + new WindowOpenListener(INSTALL_URI, function(aWindow) { + test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec)); + }, run_next_test); + + gManagerWindow.gViewController.doCommand("cmd_installFromFile"); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js index 63928f1ac1a..ea78b0a73f3 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug581076.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug581076.js @@ -1,129 +1,129 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults) - -const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; -const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; -const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; -const SEARCH_URL = TESTROOT + "browser_searching.xml"; -const SEARCH_EXPECTED_TOTAL = 100; -const SEARCH_QUERY = "search"; - -var gManagerWindow; - - -function test() { - Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); - Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); - - waitForExplicitFinish(); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - run_next_test(); - }); -} - -function end_test() { - Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS); - - // Test generates a lot of available installs so just cancel them all - AddonManager.getAllInstalls(function(aInstalls) { - aInstalls.forEach(function(aInstall) { - aInstall.cancel(); - }); - - close_manager(gManagerWindow, finish); - }); -} - -function search(aRemoteSearch, aCallback) { - var searchBox = gManagerWindow.document.getElementById("header-search"); - searchBox.value = SEARCH_QUERY; - - EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); - EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); - - wait_for_view_load(gManagerWindow, function() { - if (aRemoteSearch) - var filter = gManagerWindow.document.getElementById("search-filter-remote"); - else - var filter = gManagerWindow.document.getElementById("search-filter-local"); - EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); - - executeSoon(aCallback); - }); -} - -function check_allresultslink(aShouldShow) { - var list = gManagerWindow.document.getElementById("search-list"); - var link = gManagerWindow.document.getElementById("search-allresults-link"); - is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox"); - if (aShouldShow) { - is_element_visible(link, "All Results link should be visible"); - is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message"); - var scope = {}; - Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope); - is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href"); - } else { - is_element_hidden(link, "All Results link should be hidden"); - } -} - -add_test(function() { - info("Searching locally"); - search(false, function() { - check_allresultslink(false); - restart_manager(gManagerWindow, null, function(aManager) { - gManagerWindow = aManager; - run_next_test(); - }); - }); -}); - -add_test(function() { - info("Searching remotely - more results than cap"); - Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); - search(true, function() { - check_allresultslink(true); - restart_manager(gManagerWindow, null, function(aManager) { - gManagerWindow = aManager; - run_next_test(); - }); - }); -}); - -add_test(function() { - info("Searching remotely - less results than cap"); - Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200); - search(true, function() { - check_allresultslink(false); - restart_manager(gManagerWindow, null, function(aManager) { - gManagerWindow = aManager; - run_next_test(); - }); - }); -}); - -add_test(function() { - info("Searching remotely - more results than cap"); - Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); - search(true, function() { - check_allresultslink(true); - run_next_test(); - }); -}); - -add_test(function() { - info("Switching views"); - gManagerWindow.loadView("addons://list/extension"); - wait_for_view_load(gManagerWindow, function() { - info("Re-loading previous search"); - search(true, function() { - check_allresultslink(true); - run_next_test(); - }); - }); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults) + +const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; +const SEARCH_URL = TESTROOT + "browser_searching.xml"; +const SEARCH_EXPECTED_TOTAL = 100; +const SEARCH_QUERY = "search"; + +var gManagerWindow; + + +function test() { + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + waitForExplicitFinish(); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + +function end_test() { + Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS); + + // Test generates a lot of available installs so just cancel them all + AddonManager.getAllInstalls(function(aInstalls) { + aInstalls.forEach(function(aInstall) { + aInstall.cancel(); + }); + + close_manager(gManagerWindow, finish); + }); +} + +function search(aRemoteSearch, aCallback) { + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = SEARCH_QUERY; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + if (aRemoteSearch) + var filter = gManagerWindow.document.getElementById("search-filter-remote"); + else + var filter = gManagerWindow.document.getElementById("search-filter-local"); + EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); + + executeSoon(aCallback); + }); +} + +function check_allresultslink(aShouldShow) { + var list = gManagerWindow.document.getElementById("search-list"); + var link = gManagerWindow.document.getElementById("search-allresults-link"); + is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox"); + if (aShouldShow) { + is_element_visible(link, "All Results link should be visible"); + is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message"); + var scope = {}; + Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope); + is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href"); + } else { + is_element_hidden(link, "All Results link should be hidden"); + } +} + +add_test(function() { + info("Searching locally"); + search(false, function() { + check_allresultslink(false); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - more results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); + search(true, function() { + check_allresultslink(true); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - less results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200); + search(true, function() { + check_allresultslink(false); + restart_manager(gManagerWindow, null, function(aManager) { + gManagerWindow = aManager; + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Searching remotely - more results than cap"); + Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3); + search(true, function() { + check_allresultslink(true); + run_next_test(); + }); +}); + +add_test(function() { + info("Switching views"); + gManagerWindow.loadView("addons://list/extension"); + wait_for_view_load(gManagerWindow, function() { + info("Re-loading previous search"); + search(true, function() { + check_allresultslink(true); + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js index ce44979fe3b..d48f0037c2d 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug587970.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug587970.js @@ -1,152 +1,152 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen - -var gManagerWindow; -var gProvider; - -function test() { - waitForExplicitFinish(); - - gProvider = new MockProvider(); - - gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "addon 1", - version: "1.0", - applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE - }, { - id: "addon2@tests.mozilla.org", - name: "addon 2", - version: "2.0", - applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE - }]); - - - open_manager("addons://updates/available", function(aWindow) { - gManagerWindow = aWindow; - run_next_test(); - }); -} - - -function end_test() { - close_manager(gManagerWindow, finish); -} - - -add_test(function() { - var list = gManagerWindow.document.getElementById("updates-list"); - is(list.childNodes.length, 0, "Available updates list should be empty"); - - var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); - is_element_visible(emptyNotice, "Empty notice should be visible"); - - var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); - is_element_hidden(updateSelected, "Update Selected button should be hidden"); - - info("Adding updates"); - gProvider.createInstalls([{ - name: "addon 1", - version: "1.1", - existingAddon: gProvider.addons[0] - }, { - name: "addon 2", - version: "2.1", - existingAddon: gProvider.addons[1] - }]); - - function wait_for_refresh() { - if (list.childNodes.length == 2 && - list.childNodes[0].mManualUpdate && - list.childNodes[1].mManualUpdate) { - run_next_test(); - } else { - info("Waiting for pane to refresh"); - setTimeout(wait_for_refresh, 10); - } - } - info("Waiting for pane to refresh"); - setTimeout(wait_for_refresh, 10); -}); - - -add_test(function() { - var list = gManagerWindow.document.getElementById("updates-list"); - is(list.childNodes.length, 2, "Available updates list should have 2 items"); - - var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); - isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); - var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list"); - - var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); - is_element_hidden(emptyNotice, "Empty notice should be hidden"); - - var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); - is_element_visible(updateSelected, "Update Selected button should be visible"); - is(updateSelected.disabled, false, "Update Selected button should be enabled by default"); - - is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); - is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2"); - - info("Unchecking Include Update checkbox for addon1"); - EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); - is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); - is(updateSelected.disabled, false, "Update Selected button should still be enabled"); - - info("Unchecking Include Update checkbox for addon2"); - EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); - is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2"); - is(updateSelected.disabled, true, "Update Selected button should now be disabled"); - - info("Checking Include Update checkbox for addon2"); - EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); - is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2"); - is(updateSelected.disabled, false, "Update Selected button should now be enabled"); - - var listener = { - onInstallEnded: function() { - gProvider.installs[1].removeTestListener(listener); - - is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded"); - is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded"); - } - } - gProvider.installs[1].addTestListener(listener); - info("Clicking Update Selected button"); - EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow); - - wait_for_view_load(gManagerWindow, function() { - function wait_for_refresh() { - var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); - if (item.mManualUpdate) { - run_next_test(); - } else { - info("Waiting for pane to refresh"); - setTimeout(wait_for_refresh, 10); - } - } - info("Waiting for pane to refresh"); - setTimeout(wait_for_refresh, 10); - }, true); -}); - - -add_test(function() { - var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); - is(updateSelected.disabled, false, "Update Selected button should now be enabled"); - - var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); - isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); - is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); - - info("Unchecking Include Update checkbox for addon1"); - EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); - is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); - is(updateSelected.disabled, true, "Update Selected button should now be disabled"); - - run_next_test(); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen + +var gManagerWindow; +var gProvider; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }, { + id: "addon2@tests.mozilla.org", + name: "addon 2", + version: "2.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + + open_manager("addons://updates/available", function(aWindow) { + gManagerWindow = aWindow; + run_next_test(); + }); +} + + +function end_test() { + close_manager(gManagerWindow, finish); +} + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.childNodes.length, 0, "Available updates list should be empty"); + + var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); + is_element_visible(emptyNotice, "Empty notice should be visible"); + + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is_element_hidden(updateSelected, "Update Selected button should be hidden"); + + info("Adding updates"); + gProvider.createInstalls([{ + name: "addon 1", + version: "1.1", + existingAddon: gProvider.addons[0] + }, { + name: "addon 2", + version: "2.1", + existingAddon: gProvider.addons[1] + }]); + + function wait_for_refresh() { + if (list.childNodes.length == 2 && + list.childNodes[0].mManualUpdate && + list.childNodes[1].mManualUpdate) { + run_next_test(); + } else { + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); + } + } + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); +}); + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.childNodes.length, 2, "Available updates list should have 2 items"); + + var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); + var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list"); + + var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg"); + is_element_hidden(emptyNotice, "Empty notice should be hidden"); + + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is_element_visible(updateSelected, "Update Selected button should be visible"); + is(updateSelected.disabled, false, "Update Selected button should be enabled by default"); + + is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); + is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2"); + + info("Unchecking Include Update checkbox for addon1"); + EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); + is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); + is(updateSelected.disabled, false, "Update Selected button should still be enabled"); + + info("Unchecking Include Update checkbox for addon2"); + EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); + is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2"); + is(updateSelected.disabled, true, "Update Selected button should now be disabled"); + + info("Checking Include Update checkbox for addon2"); + EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow); + is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2"); + is(updateSelected.disabled, false, "Update Selected button should now be enabled"); + + var listener = { + onInstallEnded: function() { + gProvider.installs[1].removeTestListener(listener); + + is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded"); + is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded"); + } + } + gProvider.installs[1].addTestListener(listener); + info("Clicking Update Selected button"); + EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + function wait_for_refresh() { + var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + if (item.mManualUpdate) { + run_next_test(); + } else { + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); + } + } + info("Waiting for pane to refresh"); + setTimeout(wait_for_refresh, 10); + }, true); +}); + + +add_test(function() { + var updateSelected = gManagerWindow.document.getElementById("update-selected-btn"); + is(updateSelected.disabled, false, "Update Selected button should now be enabled"); + + var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list"); + is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1"); + + info("Unchecking Include Update checkbox for addon1"); + EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow); + is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1"); + is(updateSelected.disabled, true, "Update Selected button should now be disabled"); + + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js index 0531d6eabe9..8e3bfadb60d 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug591465.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug591465.js @@ -1,351 +1,351 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Bug 591465 - Context menu of add-ons miss context related state change entries - -const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; -const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; -const SEARCH_URL = TESTROOT + "browser_bug591465.xml"; -const SEARCH_QUERY = "SEARCH"; - -var gManagerWindow; -var gProvider; -var gContextMenu; - - -function test() { - waitForExplicitFinish(); - - gProvider = new MockProvider(); - - gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "addon 1", - version: "1.0" - }, { - id: "addon2@tests.mozilla.org", - name: "addon 2", - version: "1.0", - _userDisabled: true - }, { - id: "theme1@tests.mozilla.org", - name: "theme 1", - version: "1.0", - type: "theme" - }, { - id: "theme2@tests.mozilla.org", - name: "theme 2", - version: "1.0", - type: "theme", - _userDisabled: true - }, { - id: "theme3@tests.mozilla.org", - name: "theme 3", - version: "1.0", - type: "theme", - permissions: 0 - }]); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - gContextMenu = aWindow.document.getElementById("addonitem-popup"); - run_next_test(); - }); -} - - -function end_test() { - Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS); - close_manager(gManagerWindow, finish); -} - - -function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) { - if (aIsTheme || aIsEnabled || aIsRemote) - is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"), - "'Enable' should be hidden"); - else - is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"), - "'Enable' should be visible"); - - if (aIsTheme || !aIsEnabled || aIsRemote) - is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"), - "'Disable' should be hidden"); - else - is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"), - "'Disable' should be visible"); - - if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase) - is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"), - "'Wear Theme' should be hidden"); - else - is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"), - "'Wear Theme' should be visible"); - - if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase) - is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"), - "'Stop Wearing Theme' should be hidden"); - else - is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"), - "'Stop Wearing Theme' should be visible"); - - if (aIsRemote) - is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"), - "'Install' should be visible"); - else - is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"), - "'Install' should be hidden"); - - if (aIsDetails) - is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"), - "'Show More Information' should be hidden in details view"); - else - is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"), - "'Show More Information' should be visible in list view"); - - if (aIsSingleItemCase) - is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"), - "Menu separator should be hidden with only one menu item"); - else - is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"), - "Menu separator should be visible with multiple menu items"); - -} - - -add_test(function() { - var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); - isnot(el, null, "Should have found addon element"); - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, true, false, false, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on enabled extension item"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); -}); - - -add_test(function() { - var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, false, false, false, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on disabled extension item"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://list/theme"); - wait_for_view_load(gManagerWindow, function() { - var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org"); - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(true, true, false, false, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on enabled theme item"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - - -add_test(function() { - var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org"); - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(true, false, false, false, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on disabled theme item"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, true, false, true, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on enabled extension, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, false, false, true, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on disabled extension, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(true, true, false, true, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on enabled theme, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(true, false, false, true, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on disabled theme, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - -add_test(function() { - gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(true, true, false, true, true); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu with single menu item on enabled theme, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); - -add_test(function() { - info("Searching for remote addons"); - - Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); - Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); - - var searchBox = gManagerWindow.document.getElementById("header-search"); - searchBox.value = SEARCH_QUERY; - - EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); - EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); - - wait_for_view_load(gManagerWindow, function() { - var filter = gManagerWindow.document.getElementById("search-filter-remote"); - EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); - executeSoon(function() { - - var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org"); - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, false, true, false, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on remote extension item"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - - }); - }); -}); - - -add_test(function() { - gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org"); - wait_for_view_load(gManagerWindow, function() { - - gContextMenu.addEventListener("popupshown", function() { - gContextMenu.removeEventListener("popupshown", arguments.callee, false); - - check_contextmenu(false, false, true, true, false); - - gContextMenu.hidePopup(); - run_next_test(); - }, false); - - info("Opening context menu on remote extension, in detail view"); - var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); - EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); - EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); - }); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 591465 - Context menu of add-ons miss context related state change entries + +const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const SEARCH_URL = TESTROOT + "browser_bug591465.xml"; +const SEARCH_QUERY = "SEARCH"; + +var gManagerWindow; +var gProvider; +var gContextMenu; + + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "addon 1", + version: "1.0" + }, { + id: "addon2@tests.mozilla.org", + name: "addon 2", + version: "1.0", + _userDisabled: true + }, { + id: "theme1@tests.mozilla.org", + name: "theme 1", + version: "1.0", + type: "theme" + }, { + id: "theme2@tests.mozilla.org", + name: "theme 2", + version: "1.0", + type: "theme", + _userDisabled: true + }, { + id: "theme3@tests.mozilla.org", + name: "theme 3", + version: "1.0", + type: "theme", + permissions: 0 + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gContextMenu = aWindow.document.getElementById("addonitem-popup"); + run_next_test(); + }); +} + + +function end_test() { + Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS); + close_manager(gManagerWindow, finish); +} + + +function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) { + if (aIsTheme || aIsEnabled || aIsRemote) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"), + "'Enable' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"), + "'Enable' should be visible"); + + if (aIsTheme || !aIsEnabled || aIsRemote) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"), + "'Disable' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"), + "'Disable' should be visible"); + + if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"), + "'Wear Theme' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"), + "'Wear Theme' should be visible"); + + if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"), + "'Stop Wearing Theme' should be hidden"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"), + "'Stop Wearing Theme' should be visible"); + + if (aIsRemote) + is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"), + "'Install' should be visible"); + else + is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"), + "'Install' should be hidden"); + + if (aIsDetails) + is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"), + "'Show More Information' should be hidden in details view"); + else + is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"), + "'Show More Information' should be visible in list view"); + + if (aIsSingleItemCase) + is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"), + "Menu separator should be hidden with only one menu item"); + else + is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"), + "Menu separator should be visible with multiple menu items"); + +} + + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + isnot(el, null, "Should have found addon element"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled extension item"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled extension item"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://list/theme"); + wait_for_view_load(gManagerWindow, function() { + var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled theme item"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled theme item"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, true, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on enabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, false, false, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on disabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + +add_test(function() { + gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(true, true, false, true, true); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu with single menu item on enabled theme, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); + +add_test(function() { + info("Searching for remote addons"); + + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL); + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = SEARCH_QUERY; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + wait_for_view_load(gManagerWindow, function() { + var filter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow); + executeSoon(function() { + + var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org"); + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, true, false, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on remote extension item"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + + }); + }); +}); + + +add_test(function() { + gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org"); + wait_for_view_load(gManagerWindow, function() { + + gContextMenu.addEventListener("popupshown", function() { + gContextMenu.removeEventListener("popupshown", arguments.callee, false); + + check_contextmenu(false, false, true, true, false); + + gContextMenu.hidePopup(); + run_next_test(); + }, false); + + info("Opening context menu on remote extension, in detail view"); + var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container"); + EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow); + EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_details.js b/toolkit/mozapps/extensions/test/browser/browser_details.js index 57642fab871..36c59512d07 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_details.js +++ b/toolkit/mozapps/extensions/test/browser/browser_details.js @@ -10,6 +10,7 @@ const SEARCH_URL = TESTROOT + "browser_details.xml"; var gManagerWindow; var gCategoryUtilities; +var gProvider; var gApp = document.getElementById("bundle_brand").getString("brandShortName"); var gVersion = Services.appinfo.version; diff --git a/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js index a90d173e4e1..4c9b852dad9 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js +++ b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js @@ -1,65 +1,65 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI - -function test() { - waitForExplicitFinish(); - run_next_test(); -} - -function end_test() { - finish(); -} - -add_test(function() { - info("Testing compatibility checking warning"); - - var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); - var pref = "extensions.checkCompatibility." + version; - info("Setting " + pref + " pref to false") - Services.prefs.setBoolPref(pref, false); - - open_manager("addons://list/extension", function(aWindow) { - var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility"); - is_element_visible(label, "Check Compatibility warning label should be visible"); - var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility"); - is_element_visible(button, "Check Compatibility warning button should be visible"); - - info("Clicking 'Enable' button"); - EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); - is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared"); - is_element_hidden(label, "Check Compatibility warning label should be hidden"); - is_element_hidden(button, "Check Compatibility warning button should be hidden"); - - close_manager(aWindow, function() { - run_next_test(); - }); - }); -}); - -add_test(function() { - info("Testing update security checking warning"); - - var pref = "extensions.checkUpdateSecurity"; - info("Setting " + pref + " pref to false") - Services.prefs.setBoolPref(pref, false); - - open_manager(null, function(aWindow) { - var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity"); - is_element_visible(label, "Check Update Security warning label should be visible"); - var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity"); - is_element_visible(button, "Check Update Security warning button should be visible"); - - info("Clicking 'Enable' button"); - EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); - is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared"); - is_element_hidden(label, "Check Update Security warning label should be hidden"); - is_element_hidden(button, "Check Update Security warning button should be hidden"); - - close_manager(aWindow, function() { - run_next_test(); - }); - }); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI + +function test() { + waitForExplicitFinish(); + run_next_test(); +} + +function end_test() { + finish(); +} + +add_test(function() { + info("Testing compatibility checking warning"); + + var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); + var pref = "extensions.checkCompatibility." + version; + info("Setting " + pref + " pref to false") + Services.prefs.setBoolPref(pref, false); + + open_manager("addons://list/extension", function(aWindow) { + var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility"); + is_element_visible(label, "Check Compatibility warning label should be visible"); + var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility"); + is_element_visible(button, "Check Compatibility warning button should be visible"); + + info("Clicking 'Enable' button"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared"); + is_element_hidden(label, "Check Compatibility warning label should be hidden"); + is_element_hidden(button, "Check Compatibility warning button should be hidden"); + + close_manager(aWindow, function() { + run_next_test(); + }); + }); +}); + +add_test(function() { + info("Testing update security checking warning"); + + var pref = "extensions.checkUpdateSecurity"; + info("Setting " + pref + " pref to false") + Services.prefs.setBoolPref(pref, false); + + open_manager(null, function(aWindow) { + var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity"); + is_element_visible(label, "Check Update Security warning label should be visible"); + var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity"); + is_element_visible(button, "Check Update Security warning button should be visible"); + + info("Clicking 'Enable' button"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared"); + is_element_hidden(label, "Check Update Security warning label should be hidden"); + is_element_hidden(button, "Check Update Security warning button should be hidden"); + + close_manager(aWindow, function() { + run_next_test(); + }); + }); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js index 8801255204c..ed73fe2299f 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js +++ b/toolkit/mozapps/extensions/test/browser/browser_manualupdates.js @@ -1,188 +1,188 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests manual updates, including the Available Updates pane - -var gProvider; -var gManagerWindow; -var gCategoryUtilities; -var gAvailableCategory; - -function test() { - waitForExplicitFinish(); - - gProvider = new MockProvider(); - - gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "auto updating addon", - version: "1.0", - applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE - }]); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - run_next_test(); - }); -} - -function end_test() { - close_manager(gManagerWindow, function() { - finish(); - }); -} - - -add_test(function() { - gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available"); - is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden"); - - gProvider.createAddons([{ - id: "addon2@tests.mozilla.org", - name: "manually updating addon", - version: "1.0", - isCompatible: false, - blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, - applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE - }]); - - is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible"); - - gAvailableCategory.addEventListener("CategoryVisible", function() { - gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false); - is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible"); - gAvailableCategory.addEventListener("CategoryVisible", function() { - gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false); - is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible"); - run_next_test(); - }, false); - gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; - }, false); - gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; -}); - - -add_test(function() { - gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { - gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); - is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1"); - run_next_test(); - }, false); - - gCategoryUtilities.openType("extension", function() { - gProvider.createInstalls([{ - name: "manually updating addon (new and improved!)", - existingAddon: gProvider.addons[1], - version: "1.1", - releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null) - }]); - - var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); - is(item._version.value, "1.0", "Should still show the old version in the normal list"); - }); -}); - - -add_test(function() { - wait_for_view_load(gManagerWindow, function() { - is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected"); - is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view"); - run_next_test(); - }, true); - EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow); -}); - - -add_test(function() { - var list = gManagerWindow.document.getElementById("updates-list"); - is(list.itemCount, 1, "Should be 1 available update listed"); - var item = list.firstChild; - is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon"); - - // for manual update items, update-related properties are updated asynchronously, - // so we poll for one of the expected changes to know when its done - function waitForAsyncInit() { - if (item._version.value == "1.1") { - run_next_test(); - return; - } - info("Update item not initialized yet, checking again in 100ms"); - setTimeout(waitForAsyncInit, 100); - } - waitForAsyncInit(); -}); - -add_test(function() { - var list = gManagerWindow.document.getElementById("updates-list"); - var item = list.firstChild; - is(item._version.value, "1.1", "Update item should have version number of the update"); - var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix"); - is_element_visible(postfix, "'Update' postfix should be visible"); - is_element_visible(item._updateAvailable, ""); - is_element_visible(item._relNotesToggle, "Release notes toggle should be visible"); - is_element_hidden(item._warning, "Incompatible warning should be hidden"); - is_element_hidden(item._error, "Blocklist error should be hidden"); - - info("Opening release notes"); - item.addEventListener("RelNotesToggle", function() { - item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now open"); - - is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); - is_element_visible(item._relNotesError, "Release notes error message should be visible"); - is(item._relNotes.childElementCount, 0, "Release notes should be empty"); - - info("Closing release notes"); - item.addEventListener("RelNotesToggle", function() { - item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now closed"); - info("Setting Release notes URI to something that should load"); - gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) - - info("Re-opening release notes"); - item.addEventListener("RelNotesToggle", function() { - item.removeEventListener("RelNotesToggle", arguments.callee, false); - info("Release notes now open"); - - is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); - is_element_hidden(item._relNotesError, "Release notes error message should be hidden"); - isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container"); - run_next_test(); - - }, false); - EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); - is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); - - }, false); - EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); - - }, false); - EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); - is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); -}); - - -add_test(function() { - var list = gManagerWindow.document.getElementById("updates-list"); - var item = list.firstChild; - var updateBtn = item._updateBtn; - is_element_visible(updateBtn, "Update button should be visible"); - - var install = gProvider.installs[0]; - var listener = { - onInstallStarted: function() { - info("Install started"); - is_element_visible(item._installStatus, "Install progress widget should be visible"); - }, - onInstallEnded: function() { - install.removeTestListener(this); - info("install ended"); - is_element_hidden(item._installStatus, "Install progress widget should be hidden"); - run_next_test(); - } - }; - install.addTestListener(listener); - EventUtils.synthesizeMouseAtCenter(updateBtn, { }, gManagerWindow); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests manual updates, including the Available Updates pane + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; +var gAvailableCategory; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "auto updating addon", + version: "1.0", + applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +add_test(function() { + gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available"); + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden"); + + gProvider.createAddons([{ + id: "addon2@tests.mozilla.org", + name: "manually updating addon", + version: "1.0", + isCompatible: false, + blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED, + applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE + }]); + + is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible"); + + gAvailableCategory.addEventListener("CategoryVisible", function() { + gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false); + is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible"); + gAvailableCategory.addEventListener("CategoryVisible", function() { + gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false); + is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible"); + run_next_test(); + }, false); + gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE; + }, false); + gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE; +}); + + +add_test(function() { + gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() { + gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false); + is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1"); + run_next_test(); + }, false); + + gCategoryUtilities.openType("extension", function() { + gProvider.createInstalls([{ + name: "manually updating addon (new and improved!)", + existingAddon: gProvider.addons[1], + version: "1.1", + releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null) + }]); + + var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org"); + is(item._version.value, "1.0", "Should still show the old version in the normal list"); + }); +}); + + +add_test(function() { + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected"); + is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view"); + run_next_test(); + }, true); + EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow); +}); + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + is(list.itemCount, 1, "Should be 1 available update listed"); + var item = list.firstChild; + is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon"); + + // for manual update items, update-related properties are updated asynchronously, + // so we poll for one of the expected changes to know when its done + function waitForAsyncInit() { + if (item._version.value == "1.1") { + run_next_test(); + return; + } + info("Update item not initialized yet, checking again in 100ms"); + setTimeout(waitForAsyncInit, 100); + } + waitForAsyncInit(); +}); + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + var item = list.firstChild; + is(item._version.value, "1.1", "Update item should have version number of the update"); + var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix"); + is_element_visible(postfix, "'Update' postfix should be visible"); + is_element_visible(item._updateAvailable, ""); + is_element_visible(item._relNotesToggle, "Release notes toggle should be visible"); + is_element_hidden(item._warning, "Incompatible warning should be hidden"); + is_element_hidden(item._error, "Blocklist error should be hidden"); + + info("Opening release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now open"); + + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_visible(item._relNotesError, "Release notes error message should be visible"); + is(item._relNotes.childElementCount, 0, "Release notes should be empty"); + + info("Closing release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now closed"); + info("Setting Release notes URI to something that should load"); + gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) + + info("Re-opening release notes"); + item.addEventListener("RelNotesToggle", function() { + item.removeEventListener("RelNotesToggle", arguments.callee, false); + info("Release notes now open"); + + is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden"); + is_element_hidden(item._relNotesError, "Release notes error message should be hidden"); + isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container"); + run_next_test(); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + + }, false); + EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow); + is_element_visible(item._relNotesLoading, "Release notes loading message should be visible"); +}); + + +add_test(function() { + var list = gManagerWindow.document.getElementById("updates-list"); + var item = list.firstChild; + var updateBtn = item._updateBtn; + is_element_visible(updateBtn, "Update button should be visible"); + + var install = gProvider.installs[0]; + var listener = { + onInstallStarted: function() { + info("Install started"); + is_element_visible(item._installStatus, "Install progress widget should be visible"); + }, + onInstallEnded: function() { + install.removeTestListener(this); + info("install ended"); + is_element_hidden(item._installStatus, "Install progress widget should be hidden"); + run_next_test(); + } + }; + install.addTestListener(listener); + EventUtils.synthesizeMouseAtCenter(updateBtn, { }, gManagerWindow); +}); diff --git a/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js index 34ac241b585..1a29732e280 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js +++ b/toolkit/mozapps/extensions/test/browser/browser_recentupdates.js @@ -1,86 +1,86 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Tests the recent updates pane - -var gProvider; -var gManagerWindow; -var gCategoryUtilities; - -function test() { - waitForExplicitFinish(); - - gProvider = new MockProvider(); - - gProvider.createAddons([{ - id: "addon1@tests.mozilla.org", - name: "updated 6 hours ago", - version: "1.0", - updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)), - releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) - }, { - id: "addon2@tests.mozilla.org", - name: "updated 5 seconds ago", - version: "1.0", - updateDate: new Date(Date.now() - (1000 * 5)) - }, { - id: "addon3@tests.mozilla.org", - name: "updated 1 month ago", - version: "1.0", - updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30)) - }]); - - open_manager("addons://list/extension", function(aWindow) { - gManagerWindow = aWindow; - gCategoryUtilities = new CategoryUtilities(gManagerWindow); - run_next_test(); - }); -} - -function end_test() { - close_manager(gManagerWindow, function() { - finish(); - }); -} - - -add_test(function() { - info("Checking menuitem for Recent Updates opens that pane"); - var recentCat = gManagerWindow.gCategories.get("addons://updates/recent"); - is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden"); - - var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn"); - utilsBtn.addEventListener("popupshown", function() { - wait_for_view_load(gManagerWindow, function() { - is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible"); - is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected"); - is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view"); - run_next_test(); - }, true); - var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates"); - EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow); - }, false); - EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow); -}); - - -add_test(function() { - var updatesList = gManagerWindow.document.getElementById("updates-list"); - var items = updatesList.getElementsByTagName("richlistitem"); - var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon2@tests.mozilla.org"]; - var expected = ["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"]; - for (let i = 0; i < items.length; i++) { - let item = items[i]; - let itemId = item.mAddon.id; - if (possible.indexOf(itemId) == -1) - continue; // skip over any other addons, such as shipped addons that would update on every build - isnot(expected.length, 0, "Should be expecting more items"); - is(itemId, expected.shift(), "Should get expected item based on recenty of update"); - if (itemId == "addon1@tests.mozilla.org") - is_element_visible(item._relNotesToggle, "Release notes toggle should be visible for addon with release notes"); - else - is_element_hidden(item._relNotesToggle, "Release notes toggle should be hidden for addon with no release notes"); - } - run_next_test(); -}); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests the recent updates pane + +var gProvider; +var gManagerWindow; +var gCategoryUtilities; + +function test() { + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "addon1@tests.mozilla.org", + name: "updated 6 hours ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)), + releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null) + }, { + id: "addon2@tests.mozilla.org", + name: "updated 5 seconds ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 5)) + }, { + id: "addon3@tests.mozilla.org", + name: "updated 1 month ago", + version: "1.0", + updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30)) + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, function() { + finish(); + }); +} + + +add_test(function() { + info("Checking menuitem for Recent Updates opens that pane"); + var recentCat = gManagerWindow.gCategories.get("addons://updates/recent"); + is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden"); + + var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn"); + utilsBtn.addEventListener("popupshown", function() { + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible"); + is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected"); + is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view"); + run_next_test(); + }, true); + var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates"); + EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow); + }, false); + EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow); +}); + + +add_test(function() { + var updatesList = gManagerWindow.document.getElementById("updates-list"); + var items = updatesList.getElementsByTagName("richlistitem"); + var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon2@tests.mozilla.org"]; + var expected = ["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"]; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + let itemId = item.mAddon.id; + if (possible.indexOf(itemId) == -1) + continue; // skip over any other addons, such as shipped addons that would update on every build + isnot(expected.length, 0, "Should be expecting more items"); + is(itemId, expected.shift(), "Should get expected item based on recenty of update"); + if (itemId == "addon1@tests.mozilla.org") + is_element_visible(item._relNotesToggle, "Release notes toggle should be visible for addon with release notes"); + else + is_element_hidden(item._relNotesToggle, "Release notes toggle should be hidden for addon with no release notes"); + } + run_next_test(); +}); diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js index 7208d31f7e8..e6354ce5053 100644 --- a/toolkit/mozapps/extensions/test/browser/head.js +++ b/toolkit/mozapps/extensions/test/browser/head.js @@ -393,8 +393,8 @@ CertOverrideListener.prototype = { }, notifyCertProblem: function (socketInfo, sslStatus, targetHost) { - cert = sslStatus.QueryInterface(Components.interfaces.nsISSLStatus) - .serverCert; + var cert = sslStatus.QueryInterface(Components.interfaces.nsISSLStatus) + .serverCert; var cos = Cc["@mozilla.org/security/certoverride;1"]. getService(Ci.nsICertOverrideService); cos.rememberValidityOverride(this.host, -1, cert, this.bits, false); diff --git a/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml b/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml index 60a66d58b29..63ae07901cf 100644 --- a/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml +++ b/toolkit/mozapps/extensions/test/browser/releaseNotes.xhtml @@ -1,15 +1,15 @@ - - - - - - - - -

OMG, an update!!!!

-
    -
  • Made everything more awesome
  • -
  • Added hot sauce
  • -
- - + + + + + + + + +

OMG, an update!!!!

+
    +
  • Made everything more awesome
  • +
  • Added hot sauce
  • +
+ + diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js index 81c3779d115..135d679454e 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js @@ -1,5 +1,7 @@ // ---------------------------------------------------------------------------- // Test whether a request for auth for an XPI switches to the appropriate tab +var gNewTab; + function test() { Harness.authenticationCallback = get_auth_info; Harness.downloadFailedCallback = download_failed; diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js index 8e5b5a2651b..1e75b51b065 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cancel.js @@ -27,10 +27,11 @@ function get_item(items, url) { return items[i]; } ok(false, "Item for " + url + " was not listed"); + return null; } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + let items = window.document.getElementById("itemList").childNodes; is(items.length, 2, "Should be 2 items listed in the confirmation dialog"); let item = get_item(items, TESTROOT + "signed.xpi"); if (item) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js index 8c1703d4dba..2ab893bf88c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_multipackage.js @@ -16,6 +16,7 @@ function get_item(items, name) { return items[i]; } ok(false, "Item for " + name + " was not listed"); + return null; } function confirm_install(window) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js index 0db723fea60..63e7a7966e8 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_multiple.js @@ -27,6 +27,7 @@ function get_item(items, url) { return items[i]; } ok(false, "Item for " + url + " was not listed"); + return null; } function confirm_install(window) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js index 0479d304203..6c0d60ebc95 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js @@ -26,6 +26,7 @@ function get_item(items, url) { return items[i]; } ok(false, "Item for " + url + " was not listed"); + return null; } function confirm_install(window) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/head.js b/toolkit/mozapps/extensions/test/xpinstall/head.js index a7923a8cf80..f313a7a4f96 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/head.js +++ b/toolkit/mozapps/extensions/test/xpinstall/head.js @@ -17,13 +17,13 @@ function getChromeRoot(path) { } function extractChromeRoot(path) { - var path = getChromeRoot(path); - var jar = getJar(path); + var chromeRootPath = getChromeRoot(path); + var jar = getJar(chromeRootPath); if (jar) { var tmpdir = extractJarToTmp(jar); return "file://" + tmpdir.path + "/"; } - return path; + return chromeRootPath; } Components.utils.import("resource://gre/modules/AddonManager.jsm"); From 236ad5b5883ac24ec35f1393543a6bb6cc79ad1c Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Thu, 28 Oct 2010 23:48:48 +0200 Subject: [PATCH 128/263] Backed out changeset 81326ef16ae1. a=oranges --- .../html/content/src/nsGenericHTMLElement.cpp | 12 +-- .../html/content/src/nsHTMLButtonElement.cpp | 2 +- .../html/content/src/nsHTMLFormElement.cpp | 22 ++++-- .../html/content/src/nsHTMLInputElement.cpp | 2 +- content/html/content/test/Makefile.in | 1 - content/html/content/test/test_bug392567.html | 26 ++++--- content/html/content/test/test_bug566160.html | 33 +++++++++ content/html/content/test/test_bug607145.html | 74 ------------------- dom/interfaces/html/nsIDOMHTMLFormElement.idl | 5 +- .../passwordmgr/src/nsLoginManager.js | 7 +- 10 files changed, 78 insertions(+), 106 deletions(-) delete mode 100644 content/html/content/test/test_bug607145.html diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 3f4f67f2f90..8ffe0c2a15a 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2131,15 +2131,17 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& { nsCOMPtr uri; PRBool hadAttr = GetURIAttr(aAttr, aBaseAttr, PR_FALSE, getter_AddRefs(uri)); - - // If the content attribute isn't set or the URL is invalid, the default value - // should be returned. The default default value is the empty string and it - // looks like no attribute have a specified default value. - if (!hadAttr || !uri) { + if (!hadAttr) { aResult.Truncate(); return NS_OK; } + if (!uri) { + // Just return the attr value + GetAttr(kNameSpaceID_None, aAttr, aResult); + return NS_OK; + } + nsCAutoString spec; uri->GetSpec(spec); CopyUTF8toUTF16(spec, aResult); diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index e9cb26fc35c..2420d21242a 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -218,7 +218,7 @@ nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Autofocus, autofocus) NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled) -NS_IMPL_URI_ATTR(nsHTMLButtonElement, FormAction, formaction) +NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormMethod, formmethod, diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index ffca7972054..bb62ab3ac2c 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -375,7 +375,7 @@ nsHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, } NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset) -NS_IMPL_URI_ATTR(nsHTMLFormElement, Action, action) +NS_IMPL_STRING_ATTR(nsHTMLFormElement, Action, action) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Autocomplete, autocomplete, kFormDefaultAutocomplete->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Enctype, enctype, @@ -386,6 +386,17 @@ NS_IMPL_BOOL_ATTR(nsHTMLFormElement, NoValidate, novalidate) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Name, name) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target) +NS_IMETHODIMP +nsHTMLFormElement::GetMozActionUri(nsAString& aValue) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::action, aValue); + if (aValue.IsEmpty()) { + // Avoid resolving action="" to the base uri, bug 297761. + return NS_OK; + } + return GetURIAttr(nsGkAtoms::action, nsnull, aValue); +} + NS_IMETHODIMP nsHTMLFormElement::Submit() { @@ -1419,23 +1430,18 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL, // attribute specified, it should be used. Otherwise, the action attribute // from the form element should be used. // - // In addition, if action="" or formaction="", we need to make sure we don't - // try to resolve the URL but we should submit to the current document. - // nsAutoString action; nsCOMPtr formControl = do_QueryInterface(aOriginatingElement); if (formControl && formControl->IsSubmitControl() && aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formaction, action)) { + // Avoid resolving action="" to the base uri, bug 297761. if (!action.IsEmpty()) { static_cast(aOriginatingElement)-> GetURIAttr(nsGkAtoms::formaction, nsnull, action); } } else { - GetAttr(kNameSpaceID_None, nsGkAtoms::action, action); - if (!action.IsEmpty()) { - GetAction(action); - } + GetMozActionUri(action); } // diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index cce840d6d78..f56251136a4 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -962,7 +962,7 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete, NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus) //NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked) NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled) -NS_IMPL_URI_ATTR(nsHTMLInputElement, FormAction, formaction) +NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormAction, formaction) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype, kFormDefaultEnctype->tag) NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod, diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index e84f741f722..7170818b06c 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -238,7 +238,6 @@ _TEST_FILES = \ test_bug606817.html \ test_bug297761.html \ file_bug297761.html \ - test_bug607145.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/test_bug392567.html b/content/html/content/test/test_bug392567.html index 766c8e7b870..e7e76d8d081 100644 --- a/content/html/content/test/test_bug392567.html +++ b/content/html/content/test/test_bug392567.html @@ -42,17 +42,17 @@ function runTests() // List of tests to run, each test consists of form action URL and expected result URL var tests = [ - [jarUrl, jarUrl + "?$PARAMS"], - [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"], - [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"], - ["data:text/html,", "data:text/html,?$PARAMS"], - ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS"], - [httpUrl, httpUrl + "?$PARAMS"], - [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"], - [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"], - ["", documentURL + "?$PARAMS"], - [" ", documentURL + "?$PARAMS"], - ["../", previousDir + "?$PARAMS"], + [jarUrl, jarUrl + "?$PARAMS", null], + [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null], + [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null], + ["data:text/html,", "data:text/html,?$PARAMS", null], + ["data:text/html,How%20about%20this?", "data:text/html,How%20about%20this?$PARAMS", null], + [httpUrl, httpUrl + "?$PARAMS", null], + [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ], + [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null], + ["", documentURL + "?$PARAMS", null], + [" ", documentURL + "?$PARAMS", document.location], + ["../", previousDir + "?$PARAMS", previousDir], ]; var currentTest = -1; @@ -67,6 +67,10 @@ function runTests() } form.setAttribute("action", tests[currentTest][0]); + is(form.action, tests[currentTest][0], + "action IDL attribute should reflect the action content attribute"); + is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0], + "mozActionUri IDL attribute should resolve the action URI"); form.key.value = "value" + currentTest; form.submit(); } diff --git a/content/html/content/test/test_bug566160.html b/content/html/content/test/test_bug566160.html index c11faaef65d..cd258ce0b14 100644 --- a/content/html/content/test/test_bug566160.html +++ b/content/html/content/test/test_bug566160.html @@ -83,8 +83,41 @@ var gTestResults = { var gPendingLoad = 0; // Has to be set after depending on the frames number. +function checkFormActionAttribute(aElement) +{ + ok("formAction" in aElement, "formAction IDL attribute should be available in " + + aElement); + + is(aElement.formAction, "", "formAction IDL attribute should be " + + "undefined by default"); + is(aElement.getAttribute('formaction'), null, "formaction content attribute " + + "should be the empty string by default"); + + aElement.formAction = "foo"; + is(aElement.getAttribute('formaction'), "foo", "formaction content attribute " + + "should be 'foo'."); + is(aElement.formAction, "foo", "formAction IDL attribute should reflect " + + "the content attribute"); + + aElement.setAttribute('formaction', 'bar'); + is(aElement.getAttribute('formaction'), "bar", "formaction content attribute " + + "should be 'foo'."); + is(aElement.formAction, "bar", "formAction IDL attribute should reflect " + + "the content attribute"); + + aElement.removeAttribute('formaction'); + is(aElement.formAction, "", "formAction IDL attribute should be " + + "undefined by default"); + is(aElement.getAttribute('formaction'), null, "formaction content attribute " + + "should be the empty string by default"); +} + function runTests() { + // First of all, let's check if .formAction and @formaction work correctly. + checkFormActionAttribute(document.createElement('input')); + checkFormActionAttribute(document.createElement('button')); + // We add a load event for the frames which will be called when the forms // will be submitted. var frames = [ document.getElementById('frame1'), diff --git a/content/html/content/test/test_bug607145.html b/content/html/content/test/test_bug607145.html deleted file mode 100644 index dd72371de88..00000000000 --- a/content/html/content/test/test_bug607145.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - Test for Bug 607145 - - - - - -Mozilla Bug 607145 -

-
-
-
- - diff --git a/dom/interfaces/html/nsIDOMHTMLFormElement.idl b/dom/interfaces/html/nsIDOMHTMLFormElement.idl index 7d78a2d0035..96da5649277 100644 --- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl @@ -47,7 +47,7 @@ * http://www.w3.org/TR/DOM-Level-2-HTML/ */ -[scriptable, uuid(0884ce23-e069-499e-a13c-a91c8ae0fc98)] +[scriptable, uuid(653dc482-d6db-4e85-bdd9-151fd110e7b1)] interface nsIDOMHTMLFormElement : nsIDOMHTMLElement { attribute DOMString name; @@ -65,4 +65,7 @@ interface nsIDOMHTMLFormElement : nsIDOMHTMLElement void submit(); void reset(); + + // This property returns the resolved action URI. + readonly attribute DOMString mozActionUri; }; diff --git a/toolkit/components/passwordmgr/src/nsLoginManager.js b/toolkit/components/passwordmgr/src/nsLoginManager.js index 4b7cfb7cfcc..25140729414 100644 --- a/toolkit/components/passwordmgr/src/nsLoginManager.js +++ b/toolkit/components/passwordmgr/src/nsLoginManager.js @@ -978,12 +978,11 @@ LoginManager.prototype = { }, _getActionOrigin : function (form) { - var uriString = form.action; + var uriString = form.mozActionUri; - // If uriString equals the empty string that means actian attribute is - // missing or invalid and it will submit to the baseURI. + // A blank or mission action submits to where it came from. if (uriString == "") - uriString = form.baseURI; + uriString = form.baseURI; // ala bug 297761 return this._getPasswordOrigin(uriString, true); }, From f74adedb2c917ca3864e5c554dee48261d94aa96 Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Thu, 28 Oct 2010 15:00:31 -0700 Subject: [PATCH 129/263] Bug 575561 - External links from within app tabs should always open in new tabs instead of replacing the app tab's page. r=gavin+bz, a=blocking-beta7 --- browser/base/content/browser.js | 21 ++++++ browser/base/content/tabbrowser.xml | 4 ++ docshell/base/nsDocShell.cpp | 33 +++++++++- docshell/base/nsDocShell.h | 1 + docshell/base/nsIDocShell.idl | 10 ++- embedding/browser/webBrowser/Makefile.in | 1 + .../webBrowser/nsIWebBrowserChrome3.idl | 65 +++++++++++++++++++ toolkit/components/help/content/help.js | 3 +- toolkit/content/Services.jsm | 4 ++ .../content/tests/chrome/findbar_window.xul | 4 +- xpfe/appshell/public/nsIXULBrowserWindow.idl | 10 +++ xpfe/appshell/src/nsContentTreeOwner.cpp | 24 +++++++ xpfe/appshell/src/nsContentTreeOwner.h | 5 +- 13 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 embedding/browser/webBrowser/nsIWebBrowserChrome3.idl diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 006eec5f90c..65310db8558 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3985,6 +3985,27 @@ var XULBrowserWindow = { encodeURIComponent); gURLBar.setOverLink(link); }, + + // Called before links are navigated to to allow us to retarget them if needed. + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { + // Don't modify non-default targets or targets that aren't in top-level app + // tab docshells (isAppTab will be false for app tab subframes). + if (originalTarget != "" || !isAppTab) + return originalTarget; + + let docURI = linkNode.ownerDocument.documentURIObject; + try { + let docURIDomain = Services.eTLD.getBaseDomain(docURI, 0); + let linkURIDomain = Services.eTLD.getBaseDomain(linkURI, 0); + // External links from within app tabs should always open in new tabs + // instead of replacing the app tab's page (Bug 575561) + if (docURIDomain != linkURIDomain) + return "_blank"; + } catch(e) { + // If getBaseDomain fails, we return originalTarget below. + } + return originalTarget; + }, onLinkIconAvailable: function (aIconURL) { if (gProxyFavIcon && gBrowser.userTypedValue === null) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index a11bde11f22..fdb9bb62fc8 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -191,6 +191,8 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = true; + let event = document.createEvent("Events"); event.initEvent("TabPinned", true, false); aTab.dispatchEvent(event); @@ -210,6 +212,8 @@ this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = false; + let event = document.createEvent("Events"); event.initEvent("TabUnpinned", true, false); aTab.dispatchEvent(event); diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 8257979f25d..42ffaec9270 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -159,7 +159,7 @@ #include "nsIController.h" #include "nsPICommandUpdater.h" #include "nsIDOMHTMLAnchorElement.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsITabChild.h" #include "nsIStrictTransportSecurityService.h" @@ -711,6 +711,7 @@ nsDocShell::nsDocShell(): mAllowKeywordFixup(PR_FALSE), mIsOffScreenBrowser(PR_FALSE), mIsActive(PR_TRUE), + mIsAppTab(PR_FALSE), mFiredUnloadEvent(PR_FALSE), mEODForCurrentDocument(PR_FALSE), mURIResultedInDocument(PR_FALSE), @@ -4802,6 +4803,20 @@ nsDocShell::GetIsActive(PRBool *aIsActive) return NS_OK; } +NS_IMETHODIMP +nsDocShell::SetIsAppTab(PRBool aIsAppTab) +{ + mIsAppTab = aIsAppTab; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShell::GetIsAppTab(PRBool *aIsAppTab) +{ + *aIsAppTab = mIsAppTab; + return NS_OK; +} + NS_IMETHODIMP nsDocShell::SetVisibility(PRBool aVisibility) { @@ -11311,8 +11326,22 @@ nsDocShell::OnLinkClick(nsIContent* aContent, return NS_OK; } + nsresult rv = NS_ERROR_FAILURE; + nsAutoString target; + + nsCOMPtr browserChrome3 = do_GetInterface(mTreeOwner); + if (browserChrome3) { + nsCOMPtr linkNode = do_QueryInterface(aContent); + nsAutoString oldTarget(aTargetSpec); + rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI, + linkNode, mIsAppTab, target); + } + + if (NS_FAILED(rv)) + target = aTargetSpec; + nsCOMPtr ev = - new OnLinkClickEvent(this, aContent, aURI, aTargetSpec, + new OnLinkClickEvent(this, aContent, aURI, target.get(), aPostDataStream, aHeadersDataStream); return NS_DispatchToCurrentThread(ev); } diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index a6c33f149c1..317f766a48a 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -790,6 +790,7 @@ protected: PRPackedBool mAllowKeywordFixup; PRPackedBool mIsOffScreenBrowser; PRPackedBool mIsActive; + PRPackedBool mIsAppTab; // This boolean is set to true right before we fire pagehide and generally // unset when we embed a new content viewer. While it's true no navigation diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 788be5c5ef2..e5a72e5813e 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -71,7 +71,7 @@ interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; -[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)] +[scriptable, uuid(98cdbcc4-2d81-4191-a63f-b6c52085edbc)] interface nsIDocShell : nsISupports { /** @@ -529,11 +529,17 @@ interface nsIDocShell : nsISupports */ attribute boolean isActive; - /** * The ID of the docshell in the session history. */ readonly attribute unsigned long long historyID; + + /** + * Sets whether a docshell is an app tab. An app tab docshell may behave + * differently than a non-app tab docshell in some cases, such as when + * handling link clicks. Docshells are not app tabs unless told otherwise. + */ + attribute boolean isAppTab; }; [uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)] diff --git a/embedding/browser/webBrowser/Makefile.in b/embedding/browser/webBrowser/Makefile.in index b068d4c210d..10a56f9671c 100644 --- a/embedding/browser/webBrowser/Makefile.in +++ b/embedding/browser/webBrowser/Makefile.in @@ -78,6 +78,7 @@ XPIDLSRCS = \ nsIEmbeddingSiteWindow2.idl \ nsIContextMenuListener2.idl \ nsIWebBrowserChrome2.idl \ + nsIWebBrowserChrome3.idl \ $(NULL) CPPSRCS = \ diff --git a/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl new file mode 100644 index 00000000000..b15bf12335e --- /dev/null +++ b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl @@ -0,0 +1,65 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Margaret Leibovic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "nsIWebBrowserChrome2.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" + +/** + * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2. + */ +[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)] +interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 +{ + /** + * Determines the appropriate target for a link. + * + * @param originalTarget + * The original link target. + * @param linkURI + * Link destination URI. + * @param aDOMNode + * Link DOM node. + * @param isAppTab + * Whether or not the link is in an app tab. + * @returns A new link target, if appropriate. + * Otherwise returns originalTarget. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); +}; diff --git a/toolkit/components/help/content/help.js b/toolkit/components/help/content/help.js index f17403b17bd..4a49bfb9b7c 100644 --- a/toolkit/components/help/content/help.js +++ b/toolkit/components/help/content/help.js @@ -562,7 +562,8 @@ nsHelpStatusHandler.prototype = { setJSStatus : function(status) {}, setJSDefaultStatus : function(status) {}, - setOverLink : function(link, context) {} + setOverLink : function(link, context) {}, + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {} } function UpdateBackForwardButtons() { diff --git a/toolkit/content/Services.jsm b/toolkit/content/Services.jsm index 4d6a82866bf..86ad255edd2 100644 --- a/toolkit/content/Services.jsm +++ b/toolkit/content/Services.jsm @@ -130,3 +130,7 @@ XPCOMUtils.defineLazyServiceGetter(Services, "strings", XPCOMUtils.defineLazyServiceGetter(Services, "urlFormatter", "@mozilla.org/toolkit/URLFormatterService;1", "nsIURLFormatter"); + +XPCOMUtils.defineLazyServiceGetter(Services, "eTLD", + "@mozilla.org/network/effective-tld-service;1", + "nsIEffectiveTLDService"); diff --git a/toolkit/content/tests/chrome/findbar_window.xul b/toolkit/content/tests/chrome/findbar_window.xul index 33729245b7e..911b3e9cf85 100644 --- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -76,7 +76,9 @@ setOverLink: function(aStatusText, aLink) { gStatusText = aStatusText; - } + }, + + onBeforeLinkTraversal: function() { } }; function ok(condition, message) { diff --git a/xpfe/appshell/public/nsIXULBrowserWindow.idl b/xpfe/appshell/public/nsIXULBrowserWindow.idl index 37a8676aa99..d787d9405a0 100644 --- a/xpfe/appshell/public/nsIXULBrowserWindow.idl +++ b/xpfe/appshell/public/nsIXULBrowserWindow.idl @@ -38,6 +38,8 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" interface nsIRequest; interface nsIDOMElement; @@ -65,5 +67,13 @@ interface nsIXULBrowserWindow : nsISupports * over. */ void setOverLink(in AString link, in nsIDOMElement element); + + /** + * Determines the appropriate target for a link. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); }; diff --git a/xpfe/appshell/src/nsContentTreeOwner.cpp b/xpfe/appshell/src/nsContentTreeOwner.cpp index 3794e06d4b9..f6c21a0a86d 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -124,6 +124,7 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) // NOTE: This is using aggregation because there are some properties and @@ -430,6 +431,29 @@ nsContentTreeOwner::GetPersistence(PRBool* aPersistPosition, return NS_OK; } +//***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome3 +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget, + nsIURI *linkURI, + nsIDOMNode *linkNode, + PRBool isAppTab, + nsAString &_retval) +{ + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI, + linkNode, isAppTab, _retval); + + _retval = originalTarget; + return NS_OK; +} + //***************************************************************************** // nsContentTreeOwner::nsIWebBrowserChrome2 //***************************************************************************** diff --git a/xpfe/appshell/src/nsContentTreeOwner.h b/xpfe/appshell/src/nsContentTreeOwner.h index efc4e54b339..31d462a52e5 100644 --- a/xpfe/appshell/src/nsContentTreeOwner.h +++ b/xpfe/appshell/src/nsContentTreeOwner.h @@ -49,7 +49,7 @@ #include "nsIDocShellTreeOwner.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsIWindowProvider.h" class nsXULWindow; @@ -58,7 +58,7 @@ class nsSiteWindow2; class nsContentTreeOwner : public nsIDocShellTreeOwner, public nsIBaseWindow, public nsIInterfaceRequestor, - public nsIWebBrowserChrome2, + public nsIWebBrowserChrome3, public nsIWindowProvider { friend class nsXULWindow; @@ -72,6 +72,7 @@ public: NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 + NS_DECL_NSIWEBBROWSERCHROME3 NS_DECL_NSIWINDOWPROVIDER protected: From 3400fbf5cbb51ca9536c679d1b40a5e6a8cad9aa Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Thu, 28 Oct 2010 15:00:50 -0700 Subject: [PATCH 130/263] Bug 575561 - External links from within app tabs should always open in new tabs instead of replacing the app tab's page (Tests). r=gavin, a=blocking-beta7 --- browser/base/content/test/Makefile.in | 3 + browser/base/content/test/app_bug575561.html | 16 ++++ .../content/test/app_subframe_bug575561.html | 12 +++ .../base/content/test/browser_bug575561.js | 73 +++++++++++++++++++ .../content/tests/browser/browser_Services.js | 3 + 5 files changed, 107 insertions(+) create mode 100644 browser/base/content/test/app_bug575561.html create mode 100644 browser/base/content/test/app_subframe_bug575561.html create mode 100644 browser/base/content/test/browser_bug575561.js diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 6022529c7ac..3492d16576f 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -145,6 +145,7 @@ _BROWSER_FILES = \ browser_bug561636.js \ browser_bug562649.js \ browser_bug563588.js \ + browser_bug575561.js \ browser_bug577121.js \ browser_bug579872.js \ browser_bug580956.js \ @@ -218,6 +219,8 @@ _BROWSER_FILES = \ file_bug550565_favicon.ico \ browser_overLinkInLocationBar.js \ browser_aboutHome.js \ + app_bug575561.html \ + app_subframe_bug575561.html \ $(NULL) # compartment-disabled diff --git a/browser/base/content/test/app_bug575561.html b/browser/base/content/test/app_bug575561.html new file mode 100644 index 00000000000..60511f5dedd --- /dev/null +++ b/browser/base/content/test/app_bug575561.html @@ -0,0 +1,16 @@ + + + + + Test for links in app tabs + + + same domain + same domain (different subdomain) + different domain + different domain (with target) + + + diff --git a/browser/base/content/test/app_subframe_bug575561.html b/browser/base/content/test/app_subframe_bug575561.html new file mode 100644 index 00000000000..754f3806e15 --- /dev/null +++ b/browser/base/content/test/app_subframe_bug575561.html @@ -0,0 +1,12 @@ + + + + + Test for links in app tab subframes + + + different domain + + diff --git a/browser/base/content/test/browser_bug575561.js b/browser/base/content/test/browser_bug575561.js new file mode 100644 index 00000000000..131c06a47dd --- /dev/null +++ b/browser/base/content/test/browser_bug575561.js @@ -0,0 +1,73 @@ +function test() { + waitForExplicitFinish(); + + // Pinned: Link to the same domain should not open a new tab + // Tests link to http://example.com/browser/browser/base/content/test/dummy_page.html + testLink(0, true, false, function() { + // Pinned: Link to the same domain should not open a new tab + // Tests link to http://test1.example.com/browser/browser/base/content/test/dummy_page.html + testLink(1, true, false, function() { + // Pinned: Link to a different domain should open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html + testLink(2, true, true, function() { + // Not Pinned: Link to a different domain should not open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html + testLink(2, false, false, function() { + // Pinned: Targetted link should open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html with target="foo" + testLink(3, true, true, function() { + // Pinned: Link in a subframe should not open a new tab + // Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html in subframe + testLink(0, true, false, finish, true); + }); + }); + }); + }); + }); +} + +function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) { + let appTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/app_bug575561.html", {skipAnimation: true}); + if (pinTab) + gBrowser.pinTab(appTab); + gBrowser.selectedTab = appTab; + appTab.linkedBrowser.addEventListener("load", onLoad, true); + + let loadCount = 0; + function onLoad() { + loadCount++; + if (loadCount < 2) + return; + + appTab.linkedBrowser.removeEventListener("load", onLoad, true); + + let browser = gBrowser.getBrowserForTab(appTab); + if (testSubFrame) + browser = browser.contentDocument.getElementsByTagName("iframe")[0]; + + let links = browser.contentDocument.getElementsByTagName("a"); + + if (expectNewTab) + gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true); + else + browser.addEventListener("load", onPageLoad, true); + + info("Clicking " + links[aLinkIndex].textContent); + EventUtils.sendMouseEvent({type:"click"}, links[aLinkIndex], browser.contentWindow); + + function onPageLoad() { + browser.removeEventListener("load", onPageLoad, true); + is(browser.contentDocument.location.href, links[aLinkIndex].href, "Link should not open in a new tab"); + gBrowser.removeTab(appTab); + nextTest(); + } + + function onTabOpen(event) { + gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true); + ok(true, "Link should open a new tab"); + gBrowser.removeTab(appTab); + gBrowser.removeCurrentTab(); + nextTest(); + } + } +} diff --git a/toolkit/content/tests/browser/browser_Services.js b/toolkit/content/tests/browser/browser_Services.js index 311de6a2e5a..635e06d68aa 100644 --- a/toolkit/content/tests/browser/browser_Services.js +++ b/toolkit/content/tests/browser/browser_Services.js @@ -50,6 +50,7 @@ function checkServices() { checkService("prefs", Ci.nsIPrefService); checkService("contentPrefs", Ci.nsIContentPrefService); checkService("wm", Ci.nsIWindowMediator); + checkService("obs", Ci.nsIObserverService); checkService("perms", Ci.nsIPermissionManager); checkService("io", Ci.nsIIOService); checkService("io", Ci.nsIIOService2); @@ -66,6 +67,8 @@ function checkServices() { checkService("scriptloader", Ci.mozIJSSubScriptLoader); checkService("ww", Ci.nsIWindowWatcher); checkService("tm", Ci.nsIThreadManager); + checkService("droppedLinkHandler", Ci.nsIDroppedLinkHandler); checkService("strings", Ci.nsIStringBundleService); checkService("urlFormatter", Ci.nsIURLFormatter); + checkService("eTLD", Ci.nsIEffectiveTLDService); } From b30c4361a1c71ec76b830a104ada98bbbd4cb8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Wed, 27 Oct 2010 17:32:14 -0400 Subject: [PATCH 131/263] Bug 593823: put tabs on top by default for Linux, r=gavin, a=beltzner for b7 --- browser/base/content/browser.xul | 5 ----- 1 file changed, 5 deletions(-) diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 53858613f3b..d629ad790fc 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -826,12 +826,7 @@ #ifdef WINCE defaulticonsize="small" iconsize="small" #endif -#ifdef XP_WIN tabsontop="true" -#endif -#ifdef XP_MACOSX - tabsontop="true" -#endif persist="tabsontop"> Date: Thu, 28 Oct 2010 15:59:30 -0700 Subject: [PATCH 132/263] Bug 548949 - make CSP parse hostless schemes properly, r=dveditz, a=jst --- content/base/src/CSPUtils.jsm | 47 +++++++++++++++---------- content/base/test/unit/test_csputils.js | 12 +++++++ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/content/base/src/CSPUtils.jsm b/content/base/src/CSPUtils.jsm index 3722c7d7476..0afb96d240a 100644 --- a/content/base/src/CSPUtils.jsm +++ b/content/base/src/CSPUtils.jsm @@ -380,8 +380,7 @@ CSPRep.prototype = { }, /** - * Generates string representation of the policy. Should be fairly similar - * to the original. + * Generates canonical string representation of the policy. */ toString: function csp_toString() { @@ -607,8 +606,7 @@ CSPSourceList.prototype = { }, /** - * Generates string representation of the Source List. - * Should be fairly similar to the original. + * Generates canonical string representation of the Source List. */ toString: function() { @@ -639,7 +637,7 @@ CSPSourceList.prototype = { }, /** - * Makes a new instance that resembles this object. + * Makes a new deep copy of this object. * @returns * a new CSPSourceList */ @@ -951,7 +949,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) { // Allow scheme-only sources! These default to wildcard host/port, // especially since host and port don't always matter. // Example: "javascript:" and "data:" - if (!sObj._host) sObj._host = "*"; + if (!sObj._host) sObj._host = CSPHost.fromString("*"); if (!sObj._port) sObj._port = "*"; } else { // some host was defined. @@ -1050,8 +1048,7 @@ CSPSource.prototype = { }, /** - * Generates string representation of the Source. - * Should be fairly similar to the original. + * Generates canonical string representation of the Source. */ toString: function() { @@ -1069,7 +1066,7 @@ CSPSource.prototype = { }, /** - * Makes a new instance that resembles this object. + * Makes a new deep copy of this object. * @returns * a new CSPSource */ @@ -1172,13 +1169,28 @@ CSPSource.prototype = { return null; } + // NOTE: Both sources must have a host, if they don't, something funny is + // going on. The fromString() factory method should have set the host to + // * if there's no host specified in the input. Regardless, if a host is + // not present either the scheme is hostless or any host should be allowed. + // This means we can use the other source's host as the more restrictive + // host expression, or if neither are present, we can use "*", but the + // error should still be reported. + // host - if (!this._host) - newSource._host = that._host; - else if (!that._host) - newSource._host = this._host; - else // both this and that have hosts + if (this._host && that._host) { newSource._host = this._host.intersectWith(that._host); + } else if (this._host) { + CSPError("intersecting source with undefined host: " + that.toString()); + newSource._host = this._host.clone(); + } else if (that._host) { + CSPError("intersecting source with undefined host: " + this.toString()); + newSource._host = that._host.clone(); + } else { + CSPError("intersecting two sources with undefined hosts: " + + this.toString() + " and " + that.toString()); + newSource._host = CSPHost.fromString("*"); + } return newSource; }, @@ -1266,8 +1278,7 @@ CSPHost.fromString = function(aStr) { CSPHost.prototype = { /** - * Generates string representation of the Source. - * Should be fairly similar to the original. + * Generates canonical string representation of the Host. */ toString: function() { @@ -1275,7 +1286,7 @@ CSPHost.prototype = { }, /** - * Makes a new instance that resembles this object. + * Makes a new deep copy of this object. * @returns * a new CSPHost */ @@ -1297,7 +1308,7 @@ CSPHost.prototype = { */ permits: function(aHost) { - if (!aHost) return false; + if (!aHost) aHost = CSPHost.fromString("*"); if (!(aHost instanceof CSPHost)) { // -- compare CSPHost to String diff --git a/content/base/test/unit/test_csputils.js b/content/base/test/unit/test_csputils.js index 2a9a8755755..75683b8977c 100644 --- a/content/base/test/unit/test_csputils.js +++ b/content/base/test/unit/test_csputils.js @@ -35,6 +35,7 @@ //load('CSPUtils.jsm'); Components.utils.import('resource://gre/modules/CSPUtils.jsm'); +Components.utils.import('resource://gre/modules/NetUtil.jsm'); // load the HTTP server do_load_httpd_js(); @@ -190,6 +191,7 @@ test( //"funny characters (#) should not work for host."); do_check_eq(null, CSPSource.fromString("a#2-c.com")); + //print(" --- Stop ignoring errors that print ---\n"); //"failed to parse host with port."); @@ -229,6 +231,16 @@ test( do_check_true(src.permits("https://foobar.com")); //"src should reject other hosts" do_check_false(src.permits("https://a.com")); + + src = CSPSource.create("javascript:", "https://foobar.com:443"); + //"hostless schemes should be parseable." + var aUri = NetUtil.newURI("javascript:alert('foo');"); + do_check_true(src.permits(aUri)); + //"src should reject other hosts" + do_check_false(src.permits("https://a.com")); + //"nothing else should be allowed" + do_check_false(src.permits("https://foobar.com")); + }); ///////////////////// Test the source list ////////////////////// From f60e694777a254387def39427f5ca3de6a59d312 Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 28 Oct 2010 17:05:53 -0700 Subject: [PATCH 133/263] Backed out changeset fb506072dca8 due to crashes Bug 570619 - Move crypto off the main thread --- services/crypto/modules/WeaveCrypto.js | 92 +++++------ services/crypto/modules/threaded.js | 150 ------------------ services/crypto/tests/unit/head_helpers.js | 2 - .../crypto/tests/unit/test_crypto_crypt.js | 4 +- .../crypto/tests/unit/test_crypto_keypair.js | 4 +- .../crypto/tests/unit/test_crypto_random.js | 4 +- .../crypto/tests/unit/test_crypto_rewrap.js | 4 +- .../crypto/tests/unit/test_crypto_verify.js | 4 +- services/sync/modules/util.js | 4 +- 9 files changed, 55 insertions(+), 213 deletions(-) delete mode 100644 services/crypto/modules/threaded.js diff --git a/services/crypto/modules/WeaveCrypto.js b/services/crypto/modules/WeaveCrypto.js index ae7dbf819f8..55d3b7d279d 100644 --- a/services/crypto/modules/WeaveCrypto.js +++ b/services/crypto/modules/WeaveCrypto.js @@ -71,12 +71,6 @@ WeaveCrypto.prototype = { } }, - // This is its own method so that it can be overridden. - // (Components.Exception isn't thread-safe for instance) - makeException : function makeException(message, result) { - return Components.Exception(message, result); - }, - init : function() { try { // Preferences. Add observer so we get notified of changes. @@ -130,7 +124,7 @@ WeaveCrypto.prototype = { nssfile.append("libnss3.so"); break; default: - throw this.makeException("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED); + throw Components.Exception("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED); } this.log("Using NSS library " + nssfile.path); @@ -530,31 +524,31 @@ WeaveCrypto.prototype = { let mechanism = this.nss.PK11_AlgtagToMechanism(this.algorithm); mechanism = this.nss.PK11_GetPadMechanism(mechanism); if (mechanism == this.nss.CKM_INVALID_MECHANISM) - throw this.makeException("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE); + throw Components.Exception("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE); let ctx, symKey, slot, ivParam; try { ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem.address()); if (ivParam.isNull()) - throw this.makeException("can't convert IV to param", Cr.NS_ERROR_FAILURE); + throw Components.Exception("can't convert IV to param", Cr.NS_ERROR_FAILURE); slot = this.nss.PK11_GetInternalKeySlot(); if (slot.isNull()) - throw this.makeException("can't get internal key slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("can't get internal key slot", Cr.NS_ERROR_FAILURE); symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem.address(), null); if (symKey.isNull()) - throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE); ctx = this.nss.PK11_CreateContextBySymKey(mechanism, operation, symKey, ivParam); if (ctx.isNull()) - throw this.makeException("couldn't create context for symkey", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't create context for symkey", Cr.NS_ERROR_FAILURE); let maxOutputSize = output.length; let tmpOutputSize = new ctypes.int(); // Note 1: NSS uses a signed int here... if (this.nss.PK11_CipherOp(ctx, output, tmpOutputSize.address(), maxOutputSize, input, input.length)) - throw this.makeException("cipher operation failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("cipher operation failed", Cr.NS_ERROR_FAILURE); let actualOutputSize = tmpOutputSize.value; let finalOutput = output.addressOfElement(actualOutputSize); @@ -565,7 +559,7 @@ WeaveCrypto.prototype = { // cipher operation. You'd think it would be called PK11_CipherOpFinal... let tmpOutputSize2 = new ctypes.unsigned_int(); // Note 2: ...but an unsigned here! if (this.nss.PK11_DigestFinal(ctx, finalOutput, tmpOutputSize2.address(), maxOutputSize)) - throw this.makeException("cipher finalize failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("cipher finalize failed", Cr.NS_ERROR_FAILURE); actualOutputSize += tmpOutputSize2.value; let newOutput = ctypes.cast(output, ctypes.unsigned_char.array(actualOutputSize)); @@ -604,7 +598,7 @@ WeaveCrypto.prototype = { slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); // Generate the keypair. privKey = this.nss.PK11_GenerateKeyPairWithFlags(slot, @@ -613,18 +607,18 @@ WeaveCrypto.prototype = { pubKey.address(), attrFlags, null); if (privKey.isNull()) - throw this.makeException("keypair generation failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("keypair generation failed", Cr.NS_ERROR_FAILURE); let s = this.nss.PK11_SetPrivateKeyNickname(privKey, "Weave User PrivKey"); if (s) - throw this.makeException("key nickname failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("key nickname failed", Cr.NS_ERROR_FAILURE); let wrappedPrivateKey = this._wrapPrivateKey(privKey, passphrase, salt, iv); out_wrappedPrivateKey.value = wrappedPrivateKey; // outparam let derKey = this.nss.SECKEY_EncodeDERSubjectPublicKeyInfo(pubKey); if (derKey.isNull()) - throw this.makeException("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE); let encodedPublicKey = this.encodeBase64(derKey.contents.data, derKey.contents.len); out_encodedPublicKey.value = encodedPublicKey; // outparam @@ -664,27 +658,27 @@ WeaveCrypto.prototype = { break; default: - throw this.makeException("unknown algorithm", Cr.NS_ERROR_FAILURE); + throw Components.Exception("unknown algorithm", Cr.NS_ERROR_FAILURE); } let slot, randKey, keydata; try { slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); randKey = this.nss.PK11_KeyGen(slot, keygenMech, null, keySize, null); if (randKey.isNull()) - throw this.makeException("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE); // Slightly odd API, this call just prepares the key value for // extraction, we get the actual bits from the call to PK11_GetKeyData(). if (this.nss.PK11_ExtractKeyValue(randKey)) - throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE); keydata = this.nss.PK11_GetKeyData(randKey); if (keydata.isNull()) - throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE); return this.encodeBase64(keydata.contents.data, keydata.contents.len); } catch (e) { @@ -715,7 +709,7 @@ WeaveCrypto.prototype = { // Temporary buffer to hold the generated data. let scratch = new ctypes.ArrayType(ctypes.unsigned_char, byteCount)(); if (this.nss.PK11_GenerateRandom(scratch, byteCount)) - throw this.makeException("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE); return this.encodeBase64(scratch.address(), scratch.length); }, @@ -738,7 +732,7 @@ WeaveCrypto.prototype = { try { slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); // ImportSymKey wants a mechanism, from which it derives the key type. let keyMech = this.nss.PK11_AlgtagToMechanism(this.algorithm); @@ -747,7 +741,7 @@ WeaveCrypto.prototype = { // really matter because we're just going to wrap it up and not use it. symKey = this.nss.PK11_ImportSymKey(slot, keyMech, this.nss.PK11_OriginUnwrap, this.nss.CKA_ENCRYPT, symKeyData.address(), null); if (symKey.isNull()) - throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE); // Step 3. Put the public key bits into a P11 key object. @@ -755,11 +749,11 @@ WeaveCrypto.prototype = { // pubKey = SECKEY_ImportDERPublicKey(&pubKeyData, CKK_RSA); pubKeyInfo = this.nss.SECKEY_DecodeDERSubjectPublicKeyInfo(pubKeyData.address()); if (pubKeyInfo.isNull()) - throw this.makeException("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE); pubKey = this.nss.SECKEY_ExtractPublicKey(pubKeyInfo); if (pubKey.isNull()) - throw this.makeException("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE); // Step 4. Wrap the symmetric key with the public key. @@ -767,7 +761,7 @@ WeaveCrypto.prototype = { let s = this.nss.PK11_PubWrapSymKey(wrapMech, pubKey, symKey, wrappedKey.address()); if (s) - throw this.makeException("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE); // Step 5. Base64 encode the wrapped key, cleanup, and return to caller. return this.encodeBase64(wrappedKey.data, wrappedKey.len); @@ -807,16 +801,16 @@ WeaveCrypto.prototype = { let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm); wrapMech = this.nss.PK11_GetPadMechanism(wrapMech); if (wrapMech == this.nss.CKM_INVALID_MECHANISM) - throw this.makeException("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); + throw Components.Exception("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address()); if (ivParam.isNull()) - throw this.makeException("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); // Step 3. Unwrap the private key with the key from the passphrase. slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); // Normally, one wants to associate a private key with a public key. // P11_UnwrapPrivKey() passes its keyID arg to PK11_MakeIDFromPubKey(), @@ -837,7 +831,7 @@ WeaveCrypto.prototype = { privKeyUsage.addressOfElement(0), privKeyUsageLength, null); // wincx if (privKey.isNull()) - throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE); // Step 4. Unwrap the symmetric key with the user's private key. @@ -846,15 +840,15 @@ WeaveCrypto.prototype = { symKey = this.nss.PK11_PubUnwrapSymKey(privKey, wrappedSymKey.address(), wrapMech, this.nss.CKA_DECRYPT, 0); if (symKey.isNull()) - throw this.makeException("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE); // Step 5. Base64 encode the unwrapped key, cleanup, and return to caller. if (this.nss.PK11_ExtractKeyValue(symKey)) - throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE); symKeyData = this.nss.PK11_GetKeyData(symKey); if (symKeyData.isNull()) - throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE); return this.encodeBase64(symKeyData.contents.data, symKeyData.contents.len); } catch (e) { @@ -894,16 +888,16 @@ WeaveCrypto.prototype = { let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm); wrapMech = this.nss.PK11_GetPadMechanism(wrapMech); if (wrapMech == this.nss.CKM_INVALID_MECHANISM) - throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); + throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address()); if (ivParam.isNull()) - throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); // Step 3. Unwrap the private key with the key from the passphrase. slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); let keyID = ivItem.address(); @@ -917,7 +911,7 @@ WeaveCrypto.prototype = { privKeyUsage.addressOfElement(0), privKeyUsageLength, null); // wincx if (privKey.isNull()) - throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE); // Step 4. Rewrap the private key with the new passphrase. return this._wrapPrivateKey(privKey, newPassphrase, salt, iv); @@ -956,16 +950,16 @@ WeaveCrypto.prototype = { let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm); wrapMech = this.nss.PK11_GetPadMechanism(wrapMech); if (wrapMech == this.nss.CKM_INVALID_MECHANISM) - throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); + throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE); ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address()); if (ivParam.isNull()) - throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); // Step 3. Unwrap the private key with the key from the passphrase. slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); let keyID = ivItem.address(); @@ -1059,15 +1053,15 @@ WeaveCrypto.prototype = { algid = this.nss.PK11_CreatePBEV2AlgorithmID(pbeAlg, cipherAlg, prfAlg, keyLength, iterations, saltItem.address()); if (algid.isNull()) - throw this.makeException("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE); slot = this.nss.PK11_GetInternalSlot(); if (slot.isNull()) - throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE); + throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE); symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem.address(), false, null); if (symKey.isNull()) - throw this.makeException("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE); } catch (e) { this.log("_deriveKeyFromPassphrase: failed: " + e); throw e; @@ -1095,11 +1089,11 @@ WeaveCrypto.prototype = { let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm); wrapMech = this.nss.PK11_GetPadMechanism(wrapMech); if (wrapMech == this.nss.CKM_INVALID_MECHANISM) - throw this.makeException("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE); + throw Components.Exception("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE); let ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address()); if (ivParam.isNull()) - throw this.makeException("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE); // Use a buffer to hold the wrapped key. NSS says about 1200 bytes for // a 2048-bit RSA key, so a 4096 byte buffer should be plenty. @@ -1111,7 +1105,7 @@ WeaveCrypto.prototype = { wrapMech, ivParam, wrappedKey.address(), null); if (s) - throw this.makeException("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE); + throw Components.Exception("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE); return this.encodeBase64(wrappedKey.data, wrappedKey.len); } catch (e) { diff --git a/services/crypto/modules/threaded.js b/services/crypto/modules/threaded.js deleted file mode 100644 index 691f2d3408a..00000000000 --- a/services/crypto/modules/threaded.js +++ /dev/null @@ -1,150 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Firefox Sync. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Philipp von Weitershausen - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const EXPORTED_SYMBOLS = ["ThreadedCrypto"]; - -const Cu = Components.utils; -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://services-sync/ext/Sync.js"); -Cu.import("resource://services-crypto/WeaveCrypto.js"); - -/* - * Execute a function in a thread. - */ -function Runner(func, thisObj, returnval, error) { - this.func = func; - this.thisObj = thisObj; - this.returnval = returnval; - this.error = error; -} -Runner.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]), - - run: function run() { - let ex = this.error; - if (ex) { - this.func.throw(ex); - } else { - this.func.call(this.thisObj, this.returnval); - } - } -}; - -/* - * Execute a function in a thread and notify a callback on another thread - * afterward. - */ -function CallbackRunner(func, thisObj, args, callback, cbThread) { - this.func = func; - this.thisObj = thisObj; - this.args = args; - this.callback = callback; - this.cbThread = cbThread; -} -CallbackRunner.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]), - - run: function run() { - let returnval, error; - try { - returnval = this.func.apply(this.thisObj, this.args); - } catch(ex) { - error = ex; - } - this.cbThread.dispatch(new Runner(this.callback, this.thisObj, - returnval, error), - Ci.nsIThread.DISPATCH_NORMAL); - } -}; - -/* - * Implementation of IWeaveCrypto that defers method calls to another thread - * but keeps the synchronous API. (Don't ask...) - */ -function ThreadedCrypto() { - this.backgroundThread = Services.tm.newThread(0); - this.crypto = new WeaveCrypto(); - - // Components.Exception isn't thread-safe. - this.crypto.makeException = function makeException(message, result) { - return result; - }; - - // Make sure to kill the thread before XPCOM shuts down. - Services.obs.addObserver(this, "profile-before-change", true); -} -ThreadedCrypto.deferToThread = function deferToThread(methodname) { - return function threadMethod() { - // Dispatch method call to background thread. - let args = Array.slice(arguments); - return Sync(function(callback) { - let runner = new CallbackRunner(this.crypto[methodname], this.crypto, - args, callback, Services.tm.mainThread); - this.backgroundThread.dispatch(runner, Ci.nsIThread.DISPATCH_NORMAL); - }, this)(); - }; -}; -ThreadedCrypto.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.IWeaveCrypto, - Ci.nsISupportsWeakReference]), - - observe: function observe() { - this.backgroundThread.shutdown(); - }, - - get algorithm() this.crypto.algorithm, - set algorithm(value) this.crypto.algorithm = value, - - get keypairBits() this.crypto.keypairBits, - set keypairBits(value) this.crypto.keypairBits = value, - - encrypt: ThreadedCrypto.deferToThread("encrypt"), - decrypt: ThreadedCrypto.deferToThread("decrypt"), - generateKeypair: ThreadedCrypto.deferToThread("generateKeypair"), - generateRandomKey: ThreadedCrypto.deferToThread("generateRandomKey"), - generateRandomIV: ThreadedCrypto.deferToThread("generateRandomIV"), - generateRandomBytes: ThreadedCrypto.deferToThread("generateRandomBytes"), - wrapSymmetricKey: ThreadedCrypto.deferToThread("wrapSymmetricKey"), - unwrapSymmetricKey: ThreadedCrypto.deferToThread("unwrapSymmetricKey"), - rewrapPrivateKey: ThreadedCrypto.deferToThread("rewrapPrivateKey"), - verifyPassphrase: ThreadedCrypto.deferToThread("verifyPassphrase") -}; diff --git a/services/crypto/tests/unit/head_helpers.js b/services/crypto/tests/unit/head_helpers.js index 86e12ab7eac..61155489200 100644 --- a/services/crypto/tests/unit/head_helpers.js +++ b/services/crypto/tests/unit/head_helpers.js @@ -11,8 +11,6 @@ try { } catch(ex) { -do_get_profile(); - // Make sure to provide the right OS so crypto loads the right binaries let OS = "XPCShell"; if ("@mozilla.org/windows-registry-key;1" in Cc) diff --git a/services/crypto/tests/unit/test_crypto_crypt.js b/services/crypto/tests/unit/test_crypto_crypt.js index d8104cbee16..dc53002dab7 100644 --- a/services/crypto/tests/unit/test_crypto_crypt.js +++ b/services/crypto/tests/unit/test_crypto_crypt.js @@ -1,7 +1,7 @@ let cryptoSvc; try { - Components.utils.import("resource://services-crypto/threaded.js"); - cryptoSvc = new ThreadedCrypto(); + Components.utils.import("resource://services-crypto/WeaveCrypto.js"); + cryptoSvc = new WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"] diff --git a/services/crypto/tests/unit/test_crypto_keypair.js b/services/crypto/tests/unit/test_crypto_keypair.js index 258f473319a..8ea7907f637 100644 --- a/services/crypto/tests/unit/test_crypto_keypair.js +++ b/services/crypto/tests/unit/test_crypto_keypair.js @@ -1,7 +1,7 @@ let cryptoSvc; try { - Components.utils.import("resource://services-crypto/threaded.js"); - cryptoSvc = new ThreadedCrypto(); + Components.utils.import("resource://services-crypto/WeaveCrypto.js"); + cryptoSvc = new WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"] diff --git a/services/crypto/tests/unit/test_crypto_random.js b/services/crypto/tests/unit/test_crypto_random.js index 105c743f644..ab85169be6b 100644 --- a/services/crypto/tests/unit/test_crypto_random.js +++ b/services/crypto/tests/unit/test_crypto_random.js @@ -1,7 +1,7 @@ let cryptoSvc; try { - Components.utils.import("resource://services-crypto/threaded.js"); - cryptoSvc = new ThreadedCrypto(); + Components.utils.import("resource://services-crypto/WeaveCrypto.js"); + cryptoSvc = new WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"] diff --git a/services/crypto/tests/unit/test_crypto_rewrap.js b/services/crypto/tests/unit/test_crypto_rewrap.js index 67fb6ccf020..d9568d6e66a 100644 --- a/services/crypto/tests/unit/test_crypto_rewrap.js +++ b/services/crypto/tests/unit/test_crypto_rewrap.js @@ -1,7 +1,7 @@ let cryptoSvc; try { - Components.utils.import("resource://services-crypto/threaded.js"); - cryptoSvc = new ThreadedCrypto(); + Components.utils.import("resource://services-crypto/WeaveCrypto.js"); + cryptoSvc = new WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"] diff --git a/services/crypto/tests/unit/test_crypto_verify.js b/services/crypto/tests/unit/test_crypto_verify.js index 6acdaff8dea..5475503e69d 100644 --- a/services/crypto/tests/unit/test_crypto_verify.js +++ b/services/crypto/tests/unit/test_crypto_verify.js @@ -1,7 +1,7 @@ let cryptoSvc; try { - Components.utils.import("resource://services-crypto/threaded.js"); - cryptoSvc = new ThreadedCrypto(); + Components.utils.import("resource://services-crypto/WeaveCrypto.js"); + cryptoSvc = new WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"] diff --git a/services/sync/modules/util.js b/services/sync/modules/util.js index 5e24fb4f26e..78af94fd654 100644 --- a/services/sync/modules/util.js +++ b/services/sync/modules/util.js @@ -1039,8 +1039,8 @@ Svc.__defineGetter__("Crypto", function() { let cryptoSvc; try { let ns = {}; - Cu.import("resource://services-crypto/threaded.js", ns); - cryptoSvc = new ns.ThreadedCrypto(); + Cu.import("resource://services-crypto/WeaveCrypto.js", ns); + cryptoSvc = new ns.WeaveCrypto(); } catch (ex) { // Fallback to binary WeaveCrypto cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]. From aebb292d450815b700c2bdefddd0611cb2541d5e Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Thu, 28 Oct 2010 17:19:28 -0700 Subject: [PATCH 134/263] Bug 604565 - Disable another intermittently failing xpcshell tests on OSX debug build [r=mconnor] --- services/sync/tests/unit/test_service_sync_remoteSetup.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/sync/tests/unit/test_service_sync_remoteSetup.js b/services/sync/tests/unit/test_service_sync_remoteSetup.js index 9e73b550b4f..a4035935702 100644 --- a/services/sync/tests/unit/test_service_sync_remoteSetup.js +++ b/services/sync/tests/unit/test_service_sync_remoteSetup.js @@ -3,6 +3,9 @@ Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/log4moz.js"); function run_test() { + if (DISABLE_TESTS_BUG_604565) + return; + let logger = Log4Moz.repository.rootLogger; Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender()); From 036c4f53772d641ba44a2df1776f5b74d02d3011 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 28 Oct 2010 17:26:19 -0700 Subject: [PATCH 135/263] Bug 606138 - Gatling gun should guard against clobbered callee/this (r=waldo) --- js/src/jit-test/tests/basic/testBug606138.js | 3 +++ js/src/jsinterp.cpp | 12 +++++------- js/src/jsinterpinlines.h | 10 ++++++---- 3 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 js/src/jit-test/tests/basic/testBug606138.js diff --git a/js/src/jit-test/tests/basic/testBug606138.js b/js/src/jit-test/tests/basic/testBug606138.js new file mode 100644 index 00000000000..155a19f5b45 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug606138.js @@ -0,0 +1,3 @@ +// The proxy is going to mutate thisv in place. InvokeSessionGuard should be +// cool with that +with(evalcx(''))[7, 8].map(Int16Array, []) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b8d1dcb25c8..b283cf1b7ad 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -788,6 +788,10 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this if (!stack.pushInvokeArgs(cx, argc, &args_)) return false; + /* Callees may clobber 'this' or 'callee'. */ + savedCallee_ = args_.callee() = calleev; + savedThis_ = args_.thisv() = thisv; + do { /* Hoist dynamic checks from scripted Invoke. */ if (!calleev.isObject()) @@ -802,10 +806,6 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this if (fun->isHeavyweight() || script_->isEmpty() || cx->compartment->debugMode) break; - /* Set (callee, this) once for the session (before args are duped). */ - args_.callee().setObject(callee); - args_.thisv() = thisv; - /* Push the stack frame once for the session. */ uint32 flags = 0; if (!stack.getInvokeFrame(cx, args_, fun, script_, &flags, &frame_)) @@ -820,7 +820,7 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this if (!thisp) return false; JS_ASSERT(IsSaneThisObject(*thisp)); - fp->functionThis().setObject(*thisp); + savedThis_.setObject(*thisp); } #ifdef JS_METHODJIT @@ -859,8 +859,6 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this */ if (frame_.pushed()) frame_.pop(); - args_.thisv() = thisv; - savedCallee_ = calleev; formals_ = actuals_ = args_.argv(); nformals_ = (unsigned)-1; return true; diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 164e71f85d1..6628e06f90f 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -511,7 +511,7 @@ class InvokeSessionGuard { InvokeArgsGuard args_; InvokeFrameGuard frame_; - Value savedCallee_; + Value savedCallee_, savedThis_; Value *formals_, *actuals_; unsigned nformals_; JSScript *script_; @@ -554,10 +554,12 @@ InvokeSessionGuard::invoke(JSContext *cx) const { /* N.B. Must be kept in sync with Invoke */ - if (!optimized()) { - args_.callee() = savedCallee_; + /* Refer to canonical (callee, this) for optimized() sessions. */ + formals_[-2] = savedCallee_; + formals_[-1] = savedThis_; + + if (!optimized()) return Invoke(cx, args_, 0); - } /* Clear any garbage left from the last Invoke. */ JSStackFrame *fp = frame_.fp(); From 35fc61d36ce34210edf48b2fd0aaf0647a17e2ad Mon Sep 17 00:00:00 2001 From: David Mandelin Date: Thu, 28 Oct 2010 17:44:24 -0700 Subject: [PATCH 136/263] Backed out changeset c133d3c084c0: now we want to measure if not doing sync stuff on background thread reduces crashes. --- js/src/jsstr.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index b3beae68ffd..925bf319fe6 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -104,18 +104,6 @@ js_GetStringChars(JSContext *cx, JSString *str) void JSString::flatten() { - // Diagnostic: serialize all calls to this function to see - // if concurrent calls are crashing us. - JS_LOCK_RUNTIME(asCell()->compartment()->rt); - // The main body of this function can be executed only if - // the string is a rope. With multiple threads, it's possible - // we waited while another one ran, and the string has - // already been flattened for us. - if (!isRope()) { - JS_UNLOCK_RUNTIME(asCell()->compartment()->rt); - return; - } - JSString *topNode; jschar *chars; size_t capacity; @@ -193,8 +181,6 @@ JSString::flatten() /* Set null terminator. */ chars[pos] = 0; topNode->initFlatMutable(chars, pos, capacity); - - JS_UNLOCK_RUNTIME(asCell()->compartment()->rt); } #ifdef JS_TRACER From 505e8ac40a73a67f20f30086a8f907546d48c8d2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Oct 2010 18:28:36 -0700 Subject: [PATCH 137/263] Bug 602703 - TM: create a layer over Nanojit's LIR creation API. r=lw. --- js/src/Makefile.in | 12 +- js/src/jsarray.cpp | 4 +- js/src/jsbuiltins.h | 91 -- js/src/jsiter.h | 1 + js/src/jstl.h | 9 + js/src/jstracer.cpp | 2745 ++++++++++++------------------------ js/src/jstracer.h | 132 +- js/src/tracejit/Writer.cpp | 548 +++++++ js/src/tracejit/Writer.h | 1185 ++++++++++++++++ 9 files changed, 2666 insertions(+), 2061 deletions(-) create mode 100644 js/src/tracejit/Writer.cpp create mode 100644 js/src/tracejit/Writer.h diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 3721a9378d2..674d5ffeae8 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -254,7 +254,9 @@ INSTALLED_HEADERS = \ $(NULL) ifdef ENABLE_TRACEJIT -VPATH += $(srcdir)/nanojit +VPATH += \ + $(srcdir)/tracejit \ + $(srcdir)/nanojit \ INSTALLED_HEADERS += \ jsbuiltins.h \ @@ -263,15 +265,18 @@ INSTALLED_HEADERS += \ CodeAlloc.h \ Containers.h \ LIR.h \ + LIRopcode.tbl \ avmplus.h \ Fragmento.h \ Native.h \ NativeCommon.h \ Native$(NANOJIT_ARCH).h \ - njconfig.h \ + njconfig.h \ + njcpudetect.h \ RegAlloc.h \ nanojit.h \ VMPI.h \ + Writer.h \ $(NULL) CPPSRCS += \ @@ -286,8 +291,9 @@ CPPSRCS += \ RegAlloc.cpp \ avmplus.cpp \ Native$(NANOJIT_ARCH).cpp \ - jsbuiltins.cpp \ + jsbuiltins.cpp \ VMPI.cpp \ + Writer.cpp \ $(NULL) ifdef WINCE diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index c95e6499386..cd21b609143 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -451,7 +451,7 @@ js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i) } /* This function and its callees do not touch any object's .clasp field. */ JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32, - 0, nanojit::ACCSET_STORE_ANY & ~ACCSET_OBJ_CLASP) + 0, nanojit::ACCSET_STORE_ANY & ~tjit::ACCSET_OBJ_CLASP) #endif static JSBool @@ -828,7 +828,7 @@ js_Array_dense_setelem_hole(JSContext* cx, JSObject* obj, jsint i) } /* storeAccSet == ACCSET_OBJ_PRIVATE: because it can set 'length'. */ JS_DEFINE_CALLINFO_3(extern, BOOL, js_Array_dense_setelem_hole, CONTEXT, OBJECT, INT32, - 0, ACCSET_OBJ_PRIVATE) + 0, tjit::ACCSET_OBJ_PRIVATE) #endif static JSBool diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index 89913a27953..a7701af2644 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -49,97 +49,6 @@ #undef THIS #endif -namespace js { - -/* - * See ValidateWriter::checkAccSet() for what each of these access regions - * mean. - * - * *** WARNING WARNING WARNING *** - * - * Any incorrect access region annotations on loads/stores/calls could lead to - * subtle bugs that manifest rarely, eg. when two loads are CSE'd that - * shouldn't be. - * - * If you add a new access region you will need to add some sanity checking to - * ValidateWriter::checkAccSet(). Do not skimp on this checking! Make it as - * strong as you can. Look at the existing cases for inspiration. This - * checking helps prevent these subtle bugs. - * - * Furthermore, do not add a "catch-all" region such as "ACCSET_OTHER". There - * are two reasons for this. First, no checking could be done on loads/stores - * bearing it. Second, it would be too easy for someone in the future who - * doesn't understand how AccSets work to use it inappropriately. Only - * ACCSET_ALL (the union of all access regions) should be used as a catch-all, - * it can always be used safely, but it reduces optimization possibilities. - * - * Most of the access regions are type-based, ie. all structs of a particular - * type combined together form a region. This is less precise than - * considering each struct separately, but also much simpler. - * - * - ACCSET_STATE: The TracerState struct. - * - ACCSET_STACK: The stack. - * - ACCSET_RSTACK: The return stack. - * - ACCSET_CX: All JSContext structs. - * - ACCSET_EOS: The globals area. - * - ACCSET_ALLOC: All memory blocks allocated with LIR_allocp (in - * other words, this region is the AR space). - * - ACCSET_FRAMEREGS: All JSFrameRegs structs. - * - ACCSET_STACKFRAME: All JSStackFrame objects. - * - ACCSET_RUNTIME: The JSRuntime object. - * - ACCSET_OBJ_CLASP: The 'clasp' field of all JSObjects. - * - ACCSET_OBJ_FLAGS: The 'flags' field of all JSObjects. - * - ACCSET_OBJ_SHAPE: The 'shape' field of all JSObjects. - * - ACCSET_OBJ_PROTO: The 'proto' field of all JSObjects. - * - ACCSET_OBJ_PARENT: The 'parent' field of all JSObjects. - * - ACCSET_OBJ_PRIVATE: The 'private' field of all JSObjects. - * - ACCSET_OBJ_CAPACITY: The 'capacity' field of all JSObjects. - * - ACCSET_OBJ_SLOTS: The 'slots' field of all JSObjects. - * - ACCSET_SLOTS: The slots (be they fixed or dynamic) of all JSObjects. - * - ACCSET_TARRAY: All TypedArray structs. - * - ACCSET_TARRAY_DATA: All TypedArray data arrays. - * - ACCSET_ITER: All NativeIterator structs. - * - ACCSET_ITER_PROPS: The props_arrays of all NativeIterator structs. - * - ACCSET_STRING: All JSString structs. - * - ACCSET_STRING_MCHARS: All JSString mchars arrays. - * - ACCSET_TYPEMAP: All typemaps form a single region. - * - ACCSET_FCSLOTS: All fcslots arrays form a single region. - * - ACCSET_ARGS_DATA: All Arguments data arrays form a single region. - */ -static const nanojit::AccSet ACCSET_STATE = (1 << 0); -static const nanojit::AccSet ACCSET_STACK = (1 << 1); -static const nanojit::AccSet ACCSET_RSTACK = (1 << 2); -static const nanojit::AccSet ACCSET_CX = (1 << 3); -static const nanojit::AccSet ACCSET_EOS = (1 << 4); -static const nanojit::AccSet ACCSET_ALLOC = (1 << 5); -static const nanojit::AccSet ACCSET_FRAMEREGS = (1 << 6); -static const nanojit::AccSet ACCSET_STACKFRAME = (1 << 7); -static const nanojit::AccSet ACCSET_RUNTIME = (1 << 8); - -// Nb: JSObject::{lastProp,map} don't have an AccSet because they are never accessed on trace -static const nanojit::AccSet ACCSET_OBJ_CLASP = (1 << 9); -static const nanojit::AccSet ACCSET_OBJ_FLAGS = (1 << 10); -static const nanojit::AccSet ACCSET_OBJ_SHAPE = (1 << 11); -static const nanojit::AccSet ACCSET_OBJ_PROTO = (1 << 12); -static const nanojit::AccSet ACCSET_OBJ_PARENT = (1 << 13); -static const nanojit::AccSet ACCSET_OBJ_PRIVATE = (1 << 14); -static const nanojit::AccSet ACCSET_OBJ_CAPACITY = (1 << 15); -static const nanojit::AccSet ACCSET_OBJ_SLOTS = (1 << 16); // the pointer to the slots - -static const nanojit::AccSet ACCSET_SLOTS = (1 << 17); // the slots themselves -static const nanojit::AccSet ACCSET_TARRAY = (1 << 18); -static const nanojit::AccSet ACCSET_TARRAY_DATA = (1 << 19); -static const nanojit::AccSet ACCSET_ITER = (1 << 20); -static const nanojit::AccSet ACCSET_ITER_PROPS = (1 << 21); -static const nanojit::AccSet ACCSET_STRING = (1 << 22); -static const nanojit::AccSet ACCSET_STRING_MCHARS = (1 << 23); -static const nanojit::AccSet ACCSET_TYPEMAP = (1 << 24); -static const nanojit::AccSet ACCSET_FCSLOTS = (1 << 25); -static const nanojit::AccSet ACCSET_ARGS_DATA = (1 << 26); -} - -static const uint8_t TM_NUM_USED_ACCS = 27; // number of access regions used by TraceMonkey - enum JSTNErrType { INFALLIBLE, FAIL_STATUS, FAIL_NULL, FAIL_NEG, FAIL_NEITHER }; enum { JSTN_ERRTYPE_MASK = 0x07, diff --git a/js/src/jsiter.h b/js/src/jsiter.h index 2cfee0cf052..5198c9eb751 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -43,6 +43,7 @@ /* * JavaScript iterators. */ +#include "jscntxt.h" #include "jsprvtd.h" #include "jspubtd.h" #include "jsversion.h" diff --git a/js/src/jstl.h b/js/src/jstl.h index d05914289b1..1c837b85fcb 100644 --- a/js/src/jstl.h +++ b/js/src/jstl.h @@ -48,6 +48,7 @@ #endif #include "jsbit.h" +#include "jsstaticcheck.h" #include #include @@ -456,6 +457,14 @@ Max(T t1, T t2) return t1 > t2 ? t1 : t2; } +/* Allows a const variable to be initialized after its declaration. */ +template +static T& +InitConst(const T &t) +{ + return const_cast(t); +} + } /* namespace js */ #endif /* jstl_h_ */ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index f880ade7d06..7b516112f2a 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -73,6 +73,7 @@ #include "jsscope.h" #include "jsscript.h" #include "jsstaticcheck.h" +#include "jstl.h" #include "jstracer.h" #include "jsxml.h" #include "jstypedarray.h" @@ -109,6 +110,7 @@ namespace nanojit { using namespace js; using namespace js::gc; +using namespace js::tjit; /* Implement embedder-specific nanojit members. */ @@ -457,33 +459,6 @@ InitJITStatsClass(JSContext *cx, JSObject *glob) #define AUDIT(x) ((void)0) #endif /* JS_JIT_SPEW */ -/* - * INS_CONSTPTR can be used to embed arbitrary pointers into the native code. It should not - * be used directly to embed GC thing pointers. Instead, use the INS_CONSTOBJ/FUN/STR/SHAPE - * variants which ensure that the embedded pointer will be kept alive across GCs. - */ - -#define INS_CONST(c) addName(lir->insImmI(c), #c) -#define INS_CONSTU(c) addName(lir->insImmI((uint32_t)c), #c) -#define INS_CONSTPTR(p) addName(lir->insImmP(p), #p) -#define INS_CONSTWORD(v) addName(lir->insImmP((void *) (v)), #v) -#define INS_CONSTQWORD(c) addName(lir->insImmQ(c), #c) -#define INS_CONSTOBJ(obj) addName(insImmObj(obj), #obj) -#define INS_CONSTFUN(fun) addName(insImmFun(fun), #fun) -#define INS_CONSTSTR(str) addName(insImmStr(str), #str) -#define INS_CONSTSHAPE(shape) addName(insImmShape(shape), #shape) -#define INS_CONSTID(id) addName(insImmId(id), #id) -#define INS_ATOM(atom) INS_CONSTSTR(ATOM_TO_STRING(atom)) -#define INS_NULL() INS_CONSTPTR(NULL) -#define INS_UNDEFINED() INS_CONST(0) -#define INS_MAGIC_WHY(why) INS_CONSTWORD((size_t)why) -#define INS_MAGIC_NULL() INS_NULL() - -static const size_t sPayloadOffset = offsetof(jsval_layout, s.payload); -#if JS_BITS_PER_WORD == 32 -static const size_t sTagOffset = offsetof(jsval_layout, s.tag); -#endif - static avmplus::AvmCore s_core = avmplus::AvmCore(); static avmplus::AvmCore* core = &s_core; @@ -584,7 +559,6 @@ InitJITLogController() if (strstr(tmf, "recorder") || strstr(tmf, "full")) bits |= LC_TMRecorder; if (strstr(tmf, "abort") || strstr(tmf, "full")) bits |= LC_TMAbort; if (strstr(tmf, "stats") || strstr(tmf, "full")) bits |= LC_TMStats; - if (strstr(tmf, "regexp") || strstr(tmf, "full")) bits |= LC_TMRegexp; if (strstr(tmf, "profiler") || strstr(tmf, "full")) bits |= LC_TMProfiler; if (strstr(tmf, "treevis")) bits |= LC_TMTreeVis; @@ -960,15 +934,13 @@ TraceRecorder::tprint(const char *format, int count, nanojit::LIns *insa[]) memcpy(data, format, size); double *args = (double*) traceMonitor->traceAlloc->alloc(count * sizeof(double)); - for (int i = 0; i < count; ++i) { - JS_ASSERT(insa[i]); - // The AccSet doesn't matter much here, this isn't perf-critical code. - lir->insStore(insa[i], INS_CONSTPTR(args), sizeof(double) * i, ACCSET_STORE_ANY); - } + LIns* argsp_ins = w.nameImmpNonGC(args); + for (int i = 0; i < count; ++i) + w.stTprintArg(insa, argsp_ins, i); - LIns* args_ins[] = { INS_CONSTPTR(args), INS_CONST(count), INS_CONSTPTR(data) }; - LIns* call_ins = lir->insCall(&PrintOnTrace_ci, args_ins); - guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT); + LIns* args_ins[] = { w.nameImmpNonGC(args), w.nameImmi(count), w.nameImmpNonGC(data) }; + LIns* call_ins = w.call(&PrintOnTrace_ci, args_ins); + guard(false, w.eqi0(call_ins), MISMATCH_EXIT); } // Generate a 'printf'-type call from trace for debugging. @@ -1656,112 +1628,10 @@ AttemptCompilation(JSContext *cx, JSObject* globalObj, } } - -static bool -isfop(LIns* i, LOpcode op) -{ - if (i->isop(op)) - return true; -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float && - i->isop(LIR_ii2d) && - i->oprnd1()->isop(LIR_calli) && - i->oprnd2()->isop(LIR_hcalli)) { - return i->oprnd1()->callInfo() == softFloatOps.opmap[op]; - } -#endif - return false; -} - static const CallInfo * -fcallinfo(LIns *i) +fcallinfo(LIns *ins) { -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float) { - if (!i->isop(LIR_ii2d)) - return NULL; - i = i->oprnd1(); - return i->isop(LIR_calli) ? i->callInfo() : NULL; - } -#endif - return i->isop(LIR_calld) ? i->callInfo() : NULL; -} - -static LIns* -fcallarg(LIns* i, int n) -{ -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float) { - NanoAssert(i->isop(LIR_ii2d)); - return i->oprnd1()->callArgN(n); - } -#endif - NanoAssert(i->isop(LIR_calld)); - return i->callArgN(n); -} - -static LIns* -foprnd1(LIns* i) -{ -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float) - return fcallarg(i, 0); -#endif - return i->oprnd1(); -} - -static LIns* -foprnd2(LIns* i) -{ -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float) - return fcallarg(i, 1); -#endif - return i->oprnd2(); -} - -static LIns* -demote(LirWriter *out, LIns* ins) -{ - JS_ASSERT(ins->isD()); - if (ins->isCall()) - return ins->callArgN(0); - if (isfop(ins, LIR_i2d) || isfop(ins, LIR_ui2d)) - return foprnd1(ins); - JS_ASSERT(ins->isImmD()); - double cf = ins->immD(); - int32_t ci = cf > 0x7fffffff ? uint32_t(cf) : int32_t(cf); - return out->insImmI(ci); -} - -static bool -isPromoteInt(LIns* ins) -{ - if (isfop(ins, LIR_i2d)) - return true; - if (ins->isImmD()) { - jsdouble d = ins->immD(); - return d == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d); - } - return false; -} - -static bool -isPromoteUint(LIns* ins) -{ - if (isfop(ins, LIR_ui2d)) - return true; - if (ins->isImmD()) { - jsdouble d = ins->immD(); - return d == jsdouble(jsuint(d)) && !JSDOUBLE_IS_NEGZERO(d); - } - return false; -} - -static bool -isPromote(LIns* ins) -{ - return isPromoteInt(ins) || isPromoteUint(ins); + return ins->isop(LIR_calld) ? ins->callInfo() : NULL; } /* @@ -1809,44 +1679,6 @@ ChecksRequired(LOpcode op, LIns* op1, LIns* op2, *needsOverflowCheck = z.hasOverflowed; } -class FuncFilter: public LirWriter -{ -public: - FuncFilter(LirWriter* out): - LirWriter(out) - { - } - - LIns* ins2(LOpcode v, LIns* s0, LIns* s1) - { - if (s0 == s1 && v == LIR_eqd) { - if (isPromote(s0)) { - // double(int) and double(uint) cannot be nan - return insImmI(1); - } - if (s0->isop(LIR_muld) || s0->isop(LIR_subd) || s0->isop(LIR_addd)) { - LIns* lhs = s0->oprnd1(); - LIns* rhs = s0->oprnd2(); - if (isPromote(lhs) && isPromote(rhs)) { - // add/sub/mul promoted ints can't be nan - return insImmI(1); - } - } - } else if (isCmpDOpcode(v)) { - if (isPromoteInt(s0) && isPromoteInt(s1)) { - // demote fcmp to cmp - v = cmpOpcodeD2I(v); - return out->ins2(v, demote(out, s0), demote(out, s1)); - } else if (isPromoteUint(s0) && isPromoteUint(s1)) { - // uint compare - v = cmpOpcodeD2UI(v); - return out->ins2(v, demote(out, s0), demote(out, s1)); - } - } - return out->ins2(v, s0, s1); - } -}; - /* * JSStackFrame::numActualArgs is only defined for function frames. Since the * actual arguments of the entry frame are kept on trace, argc is included in @@ -2341,20 +2173,6 @@ FlushJITCache(JSContext *cx) static void TrashTree(TreeFragment* f); -template -static T& -InitConst(const T &t) -{ - return const_cast(t); -} - -/* These must be macros because 'field' is a field name. */ -#define loadFromState(op, field) \ - lir->insLoad(op, lirbuf->state, offsetof(TracerState, field), ACCSET_STATE) - -#define storeToState(value, field) \ - lir->insStore(value, lirbuf->state, offsetof(TracerState, field), ACCSET_STATE) - JS_REQUIRES_STACK TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* fragment, unsigned stackSlots, unsigned ngslots, JSValueType* typeMap, @@ -2370,8 +2188,6 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag outerPC(outerPC), outerArgc(outerArgc), anchor(anchor), - lir(NULL), - cse_filter(NULL), cx_ins(NULL), eos_ins(NULL), eor_ins(NULL), @@ -2401,13 +2217,13 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag pendingGuardCondition(NULL), pendingLoop(true), generatedSpecializedNative(), - tempTypeMap(cx) + tempTypeMap(cx), + w(&tempAlloc(), lirbuf) { JS_ASSERT(globalObj == cx->fp()->scopeChain().getGlobal()); JS_ASSERT(globalObj->hasOwnShape()); JS_ASSERT(cx->regs->pc == (jsbytecode*)fragment->ip); - fragment->lirbuf = lirbuf; #ifdef DEBUG lirbuf->printer = new (tempAlloc()) LInsPrinter(tempAlloc(), TM_NUM_USED_ACCS); #endif @@ -2448,50 +2264,25 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag (void*)anchor); #endif - nanojit::LirWriter*& lir = InitConst(this->lir); - nanojit::CseFilter*& cse_filter = InitConst(this->cse_filter); - lir = new (tempAlloc()) LirBufWriter(lirbuf, nanojit::AvmCore::config); -#ifdef DEBUG - ValidateWriter* validate2; - lir = validate2 = - new (tempAlloc()) ValidateWriter(lir, lirbuf->printer, "end of writer pipeline"); -#endif - debug_only_stmt( - if (LogController.lcbits & LC_TMRecorder) { - lir = new (tempAlloc()) VerboseWriter(tempAlloc(), lir, lirbuf->printer, - &LogController); - } - ) - // CseFilter must be downstream of SoftFloatFilter (see bug 527754 for why). - if (avmplus::AvmCore::config.cseopt) - lir = cse_filter = new (tempAlloc()) CseFilter(lir, TM_NUM_USED_ACCS, tempAlloc()); -#if NJ_SOFTFLOAT_SUPPORTED - if (nanojit::AvmCore::config.soft_float) - lir = new (tempAlloc()) SoftFloatFilter(lir); -#endif - lir = new (tempAlloc()) ExprFilter(lir); - lir = new (tempAlloc()) FuncFilter(lir); -#ifdef DEBUG - ValidateWriter* validate1; - lir = validate1 = - new (tempAlloc()) ValidateWriter(lir, lirbuf->printer, "start of writer pipeline"); -#endif - lir->ins0(LIR_start); + /* This creates the LIR writer pipeline. */ + w.init(&LogController); + + w.start(); for (int i = 0; i < NumSavedRegs; ++i) - lir->insParam(i, 1); + w.paramp(i, 1); #ifdef DEBUG for (int i = 0; i < NumSavedRegs; ++i) - addName(lirbuf->savedRegs[i], regNames[REGNUM(Assembler::savedRegs[i])]); + w.name(lirbuf->savedRegs[i], regNames[REGNUM(Assembler::savedRegs[i])]); #endif - lirbuf->state = addName(lir->insParam(0, 0), "state"); + lirbuf->state = w.name(w.paramp(0, 0), "state"); if (fragment == fragment->root) { - insComment("begin-loop"); - InitConst(loopLabel) = lir->ins0(LIR_label); + w.comment("begin-loop"); + InitConst(loopLabel) = w.label(); } - insComment("begin-setup"); + w.comment("begin-setup"); // if profiling, drop a label, so the assembler knows to put a // frag-entry-counter increment at this point. If there's a @@ -2502,20 +2293,20 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag if (fragment == fragment->root) { entryLabel = loopLabel; } else { - entryLabel = lir->ins0(LIR_label); + entryLabel = w.label(); } NanoAssert(entryLabel); NanoAssert(!fragment->loopLabel); fragment->loopLabel = entryLabel; }) - lirbuf->sp = addName(loadFromState(LIR_ldp, sp), "sp"); - lirbuf->rp = addName(loadFromState(LIR_ldp, rp), "rp"); - InitConst(cx_ins) = addName(loadFromState(LIR_ldp, cx), "cx"); - InitConst(eos_ins) = addName(loadFromState(LIR_ldp, eos), "eos"); - InitConst(eor_ins) = addName(loadFromState(LIR_ldp, eor), "eor"); + lirbuf->sp = w.name(w.ldpStateField(sp), "sp"); + lirbuf->rp = w.name(w.ldpStateField(rp), "rp"); + InitConst(cx_ins) = w.name(w.ldpStateField(cx), "cx"); + InitConst(eos_ins) = w.name(w.ldpStateField(eos), "eos"); + InitConst(eor_ins) = w.name(w.ldpStateField(eor), "eor"); - strictModeCode_ins = addName(lir->insImmI(cx->fp()->script()->strictModeCode), "strict"); + strictModeCode_ins = w.name(w.immi(cx->fp()->script()->strictModeCode), "strict"); /* If we came from exit, we might not have enough global types. */ if (tree->globalSlots->length() > tree->nGlobalTypes()) @@ -2527,14 +2318,14 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag if (fragment == fragment->root) { /* * We poll the operation callback request flag. It is updated asynchronously whenever - * the callback is to be invoked. We can use INS_CONSTPTR here as JIT-ed code is per + * the callback is to be invoked. We can use w.nameImmpNonGC here as JIT-ed code is per * thread and cannot outlive the corresponding JSThreadData. */ - insComment("begin-interruptFlags-check"); - LIns* flagptr = INS_CONSTPTR((void *) &JS_THREAD_DATA(cx)->interruptFlags); - LIns* x = lir->insLoad(LIR_ldi, flagptr, 0, ACCSET_LOAD_ANY, LOAD_VOLATILE); - guard(true, lir->insEqI_0(x), snapshot(TIMEOUT_EXIT)); - insComment("end-interruptFlags-check"); + w.comment("begin-interruptFlags-check"); + LIns* flagptr = w.nameImmpNonGC((void *) &JS_THREAD_DATA(cx)->interruptFlags); + LIns* x = w.ldiVolatile(flagptr); + guard(true, w.eqi0(x), TIMEOUT_EXIT); + w.comment("end-interruptFlags-check"); /* * Count the number of iterations run by a trace, so that we can blacklist if @@ -2543,20 +2334,18 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag */ #ifdef JS_METHODJIT if (cx->methodJitEnabled) { - insComment("begin-count-loop-iterations"); - LIns* counterPtr = INS_CONSTPTR((void *) &JS_THREAD_DATA(cx)->iterationCounter); - LIns* counterValue = lir->insLoad(LIR_ldi, counterPtr, 0, ACCSET_LOAD_ANY, - LOAD_VOLATILE); - LIns* test = lir->ins2ImmI(LIR_lti, counterValue, LOOP_COUNT_MAX); - LIns *branch = unoptimizableCondBranch(LIR_jf, test); - counterValue = lir->ins2(LIR_addi, counterValue, INS_CONST(1)); + w.comment("begin-count-loop-iterations"); + LIns* counterPtr = w.nameImmpNonGC((void *) &JS_THREAD_DATA(cx)->iterationCounter); + LIns* counterValue = w.ldiVolatile(counterPtr); + LIns* test = w.ltiN(counterValue, LOOP_COUNT_MAX); + LIns *branch = w.jfUnoptimizable(test); /* - * ACCSET_STORE_ANY doesn't matter right now. But if LICM is - * implemented (bug 545406) this counter will need its own region. + * stiVolatile() uses ACCSET_STORE_ANY; If LICM is implemented + * (bug 545406) this counter will need its own region. */ - lir->insStore(counterValue, counterPtr, 0, ACCSET_STORE_ANY); - labelForBranch(branch); - insComment("end-count-loop-iterations"); + w.stiVolatile(w.addi(counterValue, w.nameImmi(1)), counterPtr); + w.label(branch); + w.comment("end-count-loop-iterations"); } #endif } @@ -2566,12 +2355,12 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag * tree exited from is what we expect it to be. */ if (anchor && anchor->exitType == NESTED_EXIT) { - LIns* nested_ins = - addName(loadFromState(LIR_ldp, outermostTreeExitGuard), "outermostTreeExitGuard"); - guard(true, lir->ins2(LIR_eqp, nested_ins, INS_CONSTPTR(innermost)), NESTED_EXIT); + LIns* nested_ins = w.name(w.ldpStateField(outermostTreeExitGuard), + "outermostTreeExitGuard"); + guard(true, w.eqp(nested_ins, w.nameImmpNonGC(innermost)), NESTED_EXIT); } - insComment("end-setup"); + w.comment("end-setup"); } TraceRecorder::~TraceRecorder() @@ -2677,76 +2466,40 @@ TraceRecorder::finishAbort(const char* reason) return NORMAL_ABORT; } -/* Add debug information to a LIR instruction as we emit it. */ inline LIns* -TraceRecorder::addName(LIns* ins, const char* name) -{ -#ifdef JS_JIT_SPEW - /* - * We'll only ask for verbose Nanojit when .lcbits > 0, so there's no point - * in adding names otherwise. - */ - if (LogController.lcbits > 0) - lirbuf->printer->lirNameMap->addName(ins, name); -#endif - return ins; -} - -inline LIns* -TraceRecorder::insComment(const char* str) -{ -#ifdef JS_JIT_SPEW - return lir->insComment(str); -#else - return NULL; -#endif - -} - -inline LIns* -TraceRecorder::insImmObj(JSObject* obj) +TraceRecorder::w_immpObjGC(JSObject* obj) { tree->gcthings.addUnique(ObjectValue(*obj)); - return lir->insImmP((void*)obj); + return w.immpNonGC((void*)obj); } inline LIns* -TraceRecorder::insImmFun(JSFunction* fun) +TraceRecorder::w_immpFunGC(JSFunction* fun) { tree->gcthings.addUnique(ObjectValue(*fun)); - return lir->insImmP((void*)fun); + return w.immpNonGC((void*)fun); } inline LIns* -TraceRecorder::insImmStr(JSString* str) +TraceRecorder::w_immpStrGC(JSString* str) { tree->gcthings.addUnique(StringValue(str)); - return lir->insImmP((void*)str); + return w.immpNonGC((void*)str); } inline LIns* -TraceRecorder::insImmShape(const Shape* shape) +TraceRecorder::w_immpShapeGC(const Shape* shape) { tree->shapes.addUnique(shape); - return lir->insImmP((void*)shape); + return w.immpNonGC((void*)shape); } inline LIns* -TraceRecorder::insImmId(jsid id) +TraceRecorder::w_immpIdGC(jsid id) { if (JSID_IS_GCTHING(id)) tree->gcthings.addUnique(IdToValue(id)); - return lir->insImmP((void*)JSID_BITS(id)); -} - -inline LIns* -TraceRecorder::p2i(nanojit::LIns* ins) -{ -#ifdef NANOJIT_64BIT - return lir->ins1(LIR_q2i, ins); -#else - return ins; -#endif + return w.immpNonGC((void*)JSID_BITS(id)); } ptrdiff_t @@ -3623,8 +3376,8 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, const JSValueType* mp, /* Emit load instructions onto the trace that read the initial stack state. */ JS_REQUIRES_STACK void -TraceRecorder::importImpl(LIns* base, ptrdiff_t offset, AccSet accSet, const void* p, - JSValueType t, const char *prefix, uintN index, JSStackFrame *fp) +TraceRecorder::importImpl(Address addr, const void* p, JSValueType t, + const char *prefix, uintN index, JSStackFrame *fp) { LIns* ins; if (t == JSVAL_TYPE_INT32) { /* demoted */ @@ -3636,21 +3389,21 @@ TraceRecorder::importImpl(LIns* base, ptrdiff_t offset, AccSet accSet, const voi * to see doubles on entry. The first op to use this slot will emit a * d2i cast which will cancel out the i2d we insert here. */ - ins = lir->insLoad(LIR_ldi, base, offset, accSet); - ins = lir->ins1(LIR_i2d, ins); + ins = w.ldi(addr); + ins = w.i2d(ins); } else { JS_ASSERT_IF(t != JSVAL_TYPE_BOXED && !isFrameObjPtrTraceType(t), ((const Value *)p)->isNumber() == (t == JSVAL_TYPE_DOUBLE)); if (t == JSVAL_TYPE_DOUBLE) { - ins = lir->insLoad(LIR_ldd, base, offset, accSet); + ins = w.ldd(addr); } else if (t == JSVAL_TYPE_BOOLEAN) { - ins = lir->insLoad(LIR_ldi, base, offset, accSet); + ins = w.ldi(addr); } else if (t == JSVAL_TYPE_UNDEFINED) { - ins = INS_UNDEFINED(); + ins = w.immiUndefined(); } else if (t == JSVAL_TYPE_MAGIC) { - ins = lir->insLoad(LIR_ldi, base, offset, accSet); + ins = w.ldi(addr); } else { - ins = lir->insLoad(LIR_ldp, base, offset, accSet); + ins = w.ldp(addr); } } checkForGlobalObjectReallocation(); @@ -3686,7 +3439,7 @@ TraceRecorder::importImpl(LIns* base, ptrdiff_t offset, AccSet accSet, const voi if (mark) JS_ARENA_RELEASE(&cx->tempPool, mark); - addName(ins, name); + w.name(ins, name); debug_only_printf(LC_TMTracer, "import vp=%p name=%s type=%c\n", p, name, TypeToChar(t)); @@ -3694,10 +3447,10 @@ TraceRecorder::importImpl(LIns* base, ptrdiff_t offset, AccSet accSet, const voi } JS_REQUIRES_STACK void -TraceRecorder::import(LIns* base, ptrdiff_t offset, AccSet accSet, const Value* p, JSValueType t, +TraceRecorder::import(Address addr, const Value* p, JSValueType t, const char *prefix, uintN index, JSStackFrame *fp) { - return importImpl(base, offset, accSet, p, t, prefix, index, fp); + return importImpl(addr, p, t, prefix, index, fp); } class ImportBoxedStackSlotVisitor : public SlotVisitorBase @@ -3722,9 +3475,10 @@ public: visitStackSlots(Value *vp, size_t count, JSStackFrame* fp) { for (size_t i = 0; i < count; ++i) { if (*mTypemap == JSVAL_TYPE_BOXED) { - mRecorder.import(mBase, mStackOffset, ACCSET_STACK, vp, JSVAL_TYPE_BOXED, + mRecorder.import(StackAddress(mBase, mStackOffset), vp, JSVAL_TYPE_BOXED, "jsval", i, fp); - LIns *vp_ins = mRecorder.unbox_value(*vp, mBase, mStackOffset, ACCSET_STACK, + LIns *vp_ins = mRecorder.unbox_value(*vp, + StackAddress(mBase, mStackOffset), mRecorder.copy(mRecorder.anchor)); mRecorder.set(vp, vp_ins); } @@ -3843,7 +3597,7 @@ TraceRecorder::importGlobalSlot(unsigned slot) type = importTypeMap[importStackSlots + index]; JS_ASSERT(type != JSVAL_TYPE_UNINITIALIZED); } - import(eos_ins, slot * sizeof(double), ACCSET_EOS, vp, type, "global", index, NULL); + import(EosAddress(eos_ins, slot * sizeof(double)), vp, type, "global", index, NULL); } /* Lazily import a global slot if we don't already have it in the tracker. */ @@ -3867,7 +3621,7 @@ TraceRecorder::lazilyImportGlobalSlot(unsigned slot) /* Write back a value onto the stack or global frames. */ LIns* -TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset, bool shouldDemote) +TraceRecorder::writeBack(LIns* ins, LIns* base, ptrdiff_t offset, bool shouldDemote) { /* * Sink all type casts targeting the stack into the side exit by simply storing the original @@ -3875,9 +3629,12 @@ TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset, bool shouldDemot * last stores to every stack location, so it's safe to not perform them on-trace. */ JS_ASSERT(base == lirbuf->sp || base == eos_ins); - if (shouldDemote && isPromoteInt(i)) - i = demote(lir, i); - return lir->insStore(i, base, offset, (base == lirbuf->sp) ? ACCSET_STACK : ACCSET_EOS); + if (shouldDemote && IsPromoteInt(ins)) + ins = w.demote(ins); + Address addr = (base == lirbuf->sp) + ? (Address)StackAddress(base, offset) + : (Address)EosAddress(base, offset); + return w.st(ins, addr); } /* Update the tracker, then issue a write back store. */ @@ -3982,7 +3739,7 @@ TraceRecorder::getImpl(const void *p) unsigned slot = nativeStackSlotImpl(p); JSValueType type = importTypeMap[slot]; JS_ASSERT(type != JSVAL_TYPE_UNINITIALIZED); - importImpl(lirbuf->sp, -tree->nativeStackBase + slot * sizeof(jsdouble), ACCSET_STACK, + importImpl(StackAddress(lirbuf->sp, -tree->nativeStackBase + slot * sizeof(jsdouble)), p, type, "stack", slot, cx->fp()); } JS_ASSERT(knownImpl(p)); @@ -4019,8 +3776,8 @@ JS_REQUIRES_STACK LIns* TraceRecorder::addr(Value* p) { return isGlobal(p) - ? lir->ins2(LIR_addp, eos_ins, INS_CONSTWORD(nativeGlobalOffset(p))) - : lir->ins2(LIR_addp, lirbuf->sp, INS_CONSTWORD(nativespOffset(p))); + ? w.addp(eos_ins, w.nameImmw(nativeGlobalOffset(p))) + : w.addp(lirbuf->sp, w.nameImmw(nativespOffset(p))); } JS_REQUIRES_STACK inline bool @@ -4087,7 +3844,6 @@ class AdjustCallerGlobalTypesVisitor : public SlotVisitorBase TraceRecorder &mRecorder; JSContext *mCx; nanojit::LirBuffer *mLirbuf; - nanojit::LirWriter *mLir; JSValueType *mTypeMap; public: AdjustCallerGlobalTypesVisitor(TraceRecorder &recorder, @@ -4095,7 +3851,6 @@ public: mRecorder(recorder), mCx(mRecorder.cx), mLirbuf(mRecorder.lirbuf), - mLir(mRecorder.lir), mTypeMap(typeMap) {} @@ -4107,11 +3862,10 @@ public: JS_REQUIRES_STACK JS_ALWAYS_INLINE void visitGlobalSlot(Value *vp, unsigned n, unsigned slot) { LIns *ins = mRecorder.get(vp); - bool isPromote = isPromoteInt(ins); + bool isPromote = IsPromoteInt(ins); if (isPromote && *mTypeMap == JSVAL_TYPE_DOUBLE) { - mLir->insStore(mRecorder.get(vp), mRecorder.eos_ins, - mRecorder.nativeGlobalOffset(vp), ACCSET_EOS); - + mRecorder.w.st(mRecorder.get(vp), + EosAddress(mRecorder.eos_ins, mRecorder.nativeGlobalOffset(vp))); /* * Aggressively undo speculation so the inner tree will compile * if this fails. @@ -4128,7 +3882,6 @@ class AdjustCallerStackTypesVisitor : public SlotVisitorBase TraceRecorder &mRecorder; JSContext *mCx; nanojit::LirBuffer *mLirbuf; - nanojit::LirWriter *mLir; unsigned mSlotnum; JSValueType *mTypeMap; public: @@ -4137,7 +3890,6 @@ public: mRecorder(recorder), mCx(mRecorder.cx), mLirbuf(mRecorder.lirbuf), - mLir(mRecorder.lir), mSlotnum(0), mTypeMap(typeMap) {} @@ -4152,11 +3904,9 @@ public: /* N.B. vp may actually point to a JSObject*. */ for (size_t i = 0; i < count; ++i) { LIns *ins = mRecorder.get(vp); - bool isPromote = isPromoteInt(ins); + bool isPromote = IsPromoteInt(ins); if (isPromote && *mTypeMap == JSVAL_TYPE_DOUBLE) { - mLir->insStore(ins, mLirbuf->sp, - mRecorder.nativespOffset(vp), ACCSET_STACK); - + mRecorder.w.st(ins, StackAddress(mLirbuf->sp, mRecorder.nativespOffset(vp))); /* * Aggressively undo speculation so the inner tree will compile * if this fails. @@ -4204,7 +3954,7 @@ TraceRecorder::determineSlotType(Value* vp) LIns *i = getFromTracker(vp); JSValueType t; if (i) { - t = isPromoteInt(i) ? JSVAL_TYPE_INT32 : JSVAL_TYPE_DOUBLE; + t = IsPromoteInt(i) ? JSVAL_TYPE_INT32 : JSVAL_TYPE_DOUBLE; } else if (isGlobal(vp)) { int offset = tree->globalSlots->offsetOf(uint16(nativeGlobalSlot(vp))); JS_ASSERT(offset != -1); @@ -4460,7 +4210,7 @@ TraceRecorder::ensureCond(LIns** ins, bool* cond) { if (!isCond(*ins)) { *cond = !*cond; - *ins = (*ins)->isI() ? lir->insEqI_0(*ins) : lir->insEqP_0(*ins); + *ins = (*ins)->isI() ? w.eqi0(*ins) : w.eqp0(*ins); } } @@ -4519,8 +4269,9 @@ TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit, /* * Nb: if the guard is never taken, no instruction will be created and * insGuard() will return NULL. This is a good thing. - * */ - lir->insGuard(expected ? LIR_xf : LIR_xt, cond, createGuardRecord(exit)); + */ + GuardRecord* guardRec = createGuardRecord(exit); + expected ? w.xf(cond, guardRec) : w.xt(cond, guardRec); return RECORD_CONTINUE; } @@ -4543,32 +4294,21 @@ TraceRecorder::guard(bool expected, LIns* cond, ExitType exitType, JS_REQUIRES_STACK LIns* TraceRecorder::guard_xov(LOpcode op, LIns* d0, LIns* d1, VMSideExit* exit) { - debug_only_printf(LC_TMRecorder, - " About to try emitting guard_xov code for " - "SideExit=%p exitType=%s\n", - (void*)exit, getExitName(exit->exitType)); - - GuardRecord* guardRec = createGuardRecord(exit); JS_ASSERT(exit->exitType == OVERFLOW_EXIT); + GuardRecord* guardRec = createGuardRecord(exit); switch (op) { case LIR_addi: - op = LIR_addxovi; - break; + return w.addxovi(d0, d1, guardRec); case LIR_subi: - op = LIR_subxovi; - break; + return w.subxovi(d0, d1, guardRec); case LIR_muli: - op = LIR_mulxovi; - break; + return w.mulxovi(d0, d1, guardRec); default: - JS_NOT_REACHED("unexpected comparison op"); break; } - - LIns* guardIns = lir->insGuardXov(op, d0, d1, guardRec); - NanoAssert(guardIns); - return guardIns; + JS_NOT_REACHED("unexpected opcode"); + return NULL; } JS_REQUIRES_STACK VMSideExit* @@ -4820,7 +4560,7 @@ class SlotMap : public SlotVisitorBase bool promoteInt = false; if (vp->isNumber()) { if (LIns* i = mRecorder.getFromTracker(vp)) { - promoteInt = isPromoteInt(i); + promoteInt = IsPromoteInt(i); } else if (mRecorder.isGlobal(vp)) { int offset = mRecorder.tree->globalSlots->offsetOf(uint16(mRecorder.nativeGlobalSlot(vp))); JS_ASSERT(offset != -1); @@ -4876,7 +4616,7 @@ class SlotMap : public SlotVisitorBase JS_ASSERT(info.type == JSVAL_TYPE_INT32 || info.type == JSVAL_TYPE_DOUBLE); /* * This should only happen if the slot has a trivial conversion, i.e. - * isPromoteInt() is true. We check this. + * IsPromoteInt() is true. We check this. * * Note that getFromTracker() will return NULL if the slot was * never used, in which case we don't do the check. We could @@ -4885,7 +4625,7 @@ class SlotMap : public SlotVisitorBase * Not checking unused slots isn't so bad. */ LIns* ins = mRecorder.getFromTrackerImpl(info.vp); - JS_ASSERT_IF(ins, isPromoteInt(ins)); + JS_ASSERT_IF(ins, IsPromoteInt(ins)); } else #endif if (info.lastCheck == TypeCheck_Demote) { @@ -5086,7 +4826,7 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) slotMap.adjustTail(consensus); if (consensus != TypeConsensus_Okay || peer) { - fragment->lastIns = lir->insGuard(LIR_x, NULL, createGuardRecord(exit)); + fragment->lastIns = w.x(createGuardRecord(exit)); /* If there is a peer, there must have been an "Okay" consensus. */ JS_ASSERT_IF(peer, consensus == TypeConsensus_Okay); @@ -5122,9 +4862,9 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) JS_ASSERT((fragment == fragment->root) == !!loopLabel); if (loopLabel) { - lir->insBranch(LIR_j, NULL, loopLabel); - insComment("end-loop"); - lir->ins1(LIR_livep, lirbuf->state); + w.j(loopLabel); + w.comment("end-loop"); + w.livep(lirbuf->state); } exit->target = tree; @@ -5134,7 +4874,7 @@ TraceRecorder::closeLoop(SlotMap& slotMap, VMSideExit* exit) * remove some stack stores that it shouldn't. See bug 582766 comment * 19. */ - fragment->lastIns = lir->insGuard(LIR_x, NULL, createGuardRecord(exit)); + fragment->lastIns = w.x(createGuardRecord(exit)); } CHECK_STATUS_A(compile()); @@ -5298,8 +5038,7 @@ TraceRecorder::endLoop(VMSideExit* exit) return ARECORD_STOP; } - fragment->lastIns = - lir->insGuard(LIR_x, NULL, createGuardRecord(exit)); + fragment->lastIns = w.x(createGuardRecord(exit)); CHECK_STATUS_A(compile()); @@ -5378,21 +5117,21 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner) - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ + inner->maxNativeStackSlots * sizeof(double); /* plus the inner tree's stack */ - LIns* sp_top = lir->ins2(LIR_addp, lirbuf->sp, INS_CONSTWORD(sp_offset)); - guard(true, lir->ins2(LIR_ltp, sp_top, eos_ins), exit); + LIns* sp_top = w.addp(lirbuf->sp, w.nameImmw(sp_offset)); + guard(true, w.ltp(sp_top, eos_ins), exit); /* Guard that we have enough call stack space. */ ptrdiff_t rp_offset = rp_adj + inner->maxCallDepth * sizeof(FrameInfo*); - LIns* rp_top = lir->ins2(LIR_addp, lirbuf->rp, INS_CONSTWORD(rp_offset)); - guard(true, lir->ins2(LIR_ltp, rp_top, eor_ins), exit); + LIns* rp_top = w.addp(lirbuf->rp, w.nameImmw(rp_offset)); + guard(true, w.ltp(rp_top, eor_ins), exit); sp_offset = - tree->nativeStackBase /* rebase sp to beginning of outer tree's stack */ + sp_adj /* adjust for stack in outer frame inner tree can't see */ + inner->nativeStackBase; /* plus the inner tree's stack base */ /* We have enough space, so adjust sp and rp to their new level. */ - storeToState(lir->ins2(LIR_addp, lirbuf->sp, INS_CONSTWORD(sp_offset)), sp); - storeToState(lir->ins2(LIR_addp, lirbuf->rp, INS_CONSTWORD(rp_adj)), rp); + w.stStateField(w.addp(lirbuf->sp, w.nameImmw(sp_offset)), sp); + w.stStateField(w.addp(lirbuf->rp, w.nameImmw(rp_adj)), rp); } /* @@ -5401,8 +5140,7 @@ TraceRecorder::prepareTreeCall(TreeFragment* inner) * * (The ExitType of this snapshot is nugatory. The exit can't be taken.) */ - GuardRecord* guardRec = createGuardRecord(exit); - lir->insGuard(LIR_xbarrier, NULL, guardRec); + w.xbarrier(createGuardRecord(exit)); } static unsigned @@ -5442,53 +5180,37 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit) #ifdef DEBUG ci->_name = "fragment"; #endif - LIns* rec = lir->insCall(ci, args); - // We use ACCSET_LOAD_ANY for the GuardRecord and VMSideExit loads; - // they're immediately after a fragment call, and so won't be optimizable - // anyway. - LIns* lr = lir->insLoad(LIR_ldp, rec, offsetof(GuardRecord, exit), ACCSET_LOAD_ANY); - LIns* nested = - unoptimizableCondBranch(LIR_jt, - lir->ins2ImmI(LIR_eqi, - lir->insLoad(LIR_ldi, lr, - offsetof(VMSideExit, exitType), - ACCSET_LOAD_ANY), - NESTED_EXIT)); + LIns* rec = w.call(ci, args); + LIns* lr = w.ldpGuardRecordExit(rec); + LIns* nested = w.jtUnoptimizable(w.eqiN(w.ldiVMSideExitField(lr, exitType), NESTED_EXIT)); + /* * If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard * with that guard. If we mismatch on a tree call guard, this will contain the last * non-nested guard we encountered, which is the innermost loop or branch guard. */ - storeToState(lr, lastTreeExitGuard); - LIns* done1 = lir->insBranch(LIR_j, NULL, NULL); + w.stStateField(lr, lastTreeExitGuard); + LIns* done1 = w.j(NULL); /* * The tree exited on a nested guard. This only occurs once a tree call guard mismatches * and we unwind the tree call stack. We store the first (innermost) tree call guard in state * and we will try to grow the outer tree the failing call was in starting at that guard. */ - labelForBranch(nested); - LIns* done2 = - unoptimizableCondBranch(LIR_jf, - lir->insEqP_0(loadFromState(LIR_ldp, lastTreeCallGuard))); - storeToState(lr, lastTreeCallGuard); - storeToState(lir->ins2(LIR_addp, - loadFromState(LIR_ldp, rp), - lir->insI2P(lir->ins2ImmI(LIR_lshi, - // See the other VMSideExit load above for - // why ACCSET_LOAD_ANY is used here. - lir->insLoad(LIR_ldi, lr, - offsetof(VMSideExit, calldepth), - ACCSET_LOAD_ANY), - sizeof(void*) == 4 ? 2 : 3))), - rpAtLastTreeCall); - labelForBranches(done1, done2); + w.label(nested); + LIns* done2 = w.jfUnoptimizable(w.eqp0(w.ldpStateField(lastTreeCallGuard))); + w.stStateField(lr, lastTreeCallGuard); + w.stStateField(w.addp(w.ldpStateField(rp), + w.i2p(w.lshiN(w.ldiVMSideExitField(lr, calldepth), + sizeof(void*) == 4 ? 2 : 3))), + rpAtLastTreeCall); + w.label(done1, done2); /* * Keep updating outermostTreeExit so that TracerState always contains the most recent * side exit. */ - storeToState(lr, outermostTreeExitGuard); + w.stStateField(lr, outermostTreeExitGuard); /* Read back all registers, in case the called tree changed any of them. */ #ifdef DEBUG @@ -5558,8 +5280,8 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit) /* Restore sp and rp to their original values (we still have them in a register). */ if (callDepth > 0) { - storeToState(lirbuf->sp, sp); - storeToState(lirbuf->rp, rp); + w.stStateField(lirbuf->sp, sp); + w.stStateField(lirbuf->rp, rp); } /* @@ -5568,7 +5290,7 @@ TraceRecorder::emitTreeCall(TreeFragment* inner, VMSideExit* exit) */ VMSideExit* nestedExit = snapshot(NESTED_EXIT); JS_ASSERT(exit->exitType == LOOP_EXIT); - guard(true, lir->ins2(LIR_eqp, lr, INS_CONSTPTR(exit)), nestedExit); + guard(true, w.eqp(lr, w.nameImmpNonGC(exit)), nestedExit); debug_only_printf(LC_TMTreeVis, "TREEVIS TREECALL INNER=%p EXIT=%p GUARD=%p\n", (void*)inner, (void*)nestedExit, (void*)exit); @@ -6417,7 +6139,7 @@ public: debug_only_printf(LC_TMTracer, "global%d=", n); if (!IsEntryTypeCompatible(*vp, *mTypeMap)) { mOk = false; - } else if (!isPromoteInt(mRecorder.get(vp)) && *mTypeMap == JSVAL_TYPE_INT32) { + } else if (!IsPromoteInt(mRecorder.get(vp)) && *mTypeMap == JSVAL_TYPE_INT32) { mOracle->markGlobalSlotUndemotable(mCx, slot); mOk = false; } else if (vp->isInt32() && *mTypeMap == JSVAL_TYPE_DOUBLE) { @@ -6439,7 +6161,7 @@ public: debug_only_printf(LC_TMTracer, "%s%u=", stackSlotKind(), unsigned(i)); if (!IsEntryTypeCompatible(*vp, *mTypeMap)) { mOk = false; - } else if (!isPromoteInt(mRecorder.get(vp)) && *mTypeMap == JSVAL_TYPE_INT32) { + } else if (!IsPromoteInt(mRecorder.get(vp)) && *mTypeMap == JSVAL_TYPE_INT32) { mOracle->markStackSlotUndemotable(mCx, mStackSlotNum); mOk = false; } else if (vp->isInt32() && *mTypeMap == JSVAL_TYPE_DOUBLE) { @@ -7419,8 +7141,7 @@ TraceRecorder::monitorRecording(JSOp op) * pendingUnboxSlot to have this information. */ LIns* unboxed_ins = unbox_value(*pendingUnboxSlot, - val_ins->oprnd1(), val_ins->disp(), - ACCSET_LOAD_ANY, + AnyAddress(val_ins->oprnd1(), val_ins->disp()), snapshot(BRANCH_EXIT)); set(pendingUnboxSlot, unboxed_ins); pendingUnboxSlot = 0; @@ -7454,7 +7175,7 @@ TraceRecorder::monitorRecording(JSOp op) break; # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ case op: \ - insComment(#op); \ + w.comment(#op); \ status = this->record_##op(); \ break; # include "jsopcode.tbl" @@ -8124,7 +7845,7 @@ TraceRecorder::updateAtoms() consts = cx->fp()->hasImacropc() || script->constOffset == 0 ? 0 : script->consts()->vector; - strictModeCode_ins = addName(lir->insImmI(script->strictModeCode), "strict"); + strictModeCode_ins = w.name(w.immi(script->strictModeCode), "strict"); } JS_REQUIRES_STACK void @@ -8132,7 +7853,7 @@ TraceRecorder::updateAtoms(JSScript *script) { atoms = script->atomMap.vector; consts = script->constOffset == 0 ? 0 : script->consts()->vector; - strictModeCode_ins = addName(lir->insImmI(script->strictModeCode), "strict"); + strictModeCode_ins = w.name(w.immi(script->strictModeCode), "strict"); } /* @@ -8154,8 +7875,7 @@ TraceRecorder::scopeChain() JS_REQUIRES_STACK LIns* TraceRecorder::entryScopeChain() const { - return lir->insLoad(LIR_ldp, entryFrameIns(), - JSStackFrame::offsetOfScopeChain(), ACCSET_STACKFRAME); + return w.ldpStackFrameScopeChain(entryFrameIns()); } /* @@ -8164,8 +7884,7 @@ TraceRecorder::entryScopeChain() const JS_REQUIRES_STACK LIns* TraceRecorder::entryFrameIns() const { - LIns *regs_ins = lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, regs), ACCSET_CX); - return lir->insLoad(LIR_ldp, regs_ins, offsetof(JSFrameRegs, fp), ACCSET_FRAMEREGS); + return w.ldpFrameFp(w.ldpContextField(regs)); } /* @@ -8236,7 +7955,7 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameR // Call name the compiler resolves statically and we do not need // to match shapes of the Call objects. chainHead = cx->fp()->callee().getParent(); - head_ins = stobj_get_parent(get(&cx->fp()->calleeValue())); + head_ins = w.ldpObjParent(get(&cx->fp()->calleeValue())); } else { head_ins = scopeChain(); } @@ -8325,7 +8044,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, LIns* obj_ins; JSObject* parent = cx->fp()->callee().getParent(); - LIns* parent_ins = stobj_get_parent(get(&cx->fp()->calleeValue())); + LIns* parent_ins = w.ldpObjParent(get(&cx->fp()->calleeValue())); CHECK_STATUS(traverseScopeChain(parent, parent_ins, obj, obj_ins)); if (!cfp) { @@ -8360,13 +8079,13 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, // inner trace such that the target variable is defined in the outer trace // entry frame. For simplicity, we just fall off trace. guard(false, - lir->ins2(LIR_eqp, entryFrameIns(), stobj_get_private(obj_ins)), + w.eqp(entryFrameIns(), w.ldpObjPrivate(obj_ins)), MISMATCH_EXIT); - LIns* outp = lir->insAlloc(sizeof(double)); + LIns* outp = w.allocp(sizeof(double)); LIns* args[] = { outp, - INS_CONSTPTR(cv), + w.nameImmpNonGC(cv), obj_ins, cx_ins }; @@ -8383,14 +8102,13 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, // Now assert that our use of shape->shortid was in fact kosher. JS_ASSERT(shape->hasShortID()); - LIns* call_ins = lir->insCall(ci, args); + LIns* call_ins = w.call(ci, args); JSValueType type = getCoercedType(nr.v); guard(true, - addName(lir->ins2(LIR_eqi, call_ins, lir->insImmI(type)), - "guard(type-stable name access)"), + w.name(w.eqi(call_ins, w.immi(type)), "guard(type-stable name access)"), BRANCH_EXIT); - ins = stackLoad(outp, ACCSET_ALLOC, type); + ins = stackLoad(AllocSlotsAddress(outp), type); } nr.tracked = false; nr.obj = obj; @@ -8442,12 +8160,12 @@ TraceRecorder::guardNonNeg(LIns* d0, LIns* d1, VMSideExit* exit) if (d0->isImmI()) JS_ASSERT(d0->immI() >= 0); else - guard(false, lir->ins2ImmI(LIR_lti, d0, 0), exit); + guard(false, w.ltiN(d0, 0), exit); if (d1->isImmI()) JS_ASSERT(d1->immI() >= 0); else - guard(false, lir->ins2ImmI(LIR_lti, d1, 0), exit); + guard(false, w.ltiN(d1, 0), exit); } JS_REQUIRES_STACK LIns* @@ -8459,13 +8177,13 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) * instruction. */ if (!oracle || oracle->isInstructionUndemotable(cx->regs->pc) || - !isPromoteInt(s0) || !isPromoteInt(s1)) { + !IsPromoteInt(s0) || !IsPromoteInt(s1)) { out: if (v == LIR_modd) { LIns* args[] = { s1, s0 }; - return lir->insCall(&js_dmod_ci, args); + return w.call(&js_dmod_ci, args); } - LIns* result = lir->ins2(v, s0, s1); + LIns* result = w.ins2(v, s0, s1); JS_ASSERT_IF(s0->isImmD() && s1->isImmD(), result->isImmD()); return result; } @@ -8506,8 +8224,8 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) if (jsint(r) != r || JSDOUBLE_IS_NEGZERO(r)) goto out; - LIns* d0 = demote(lir, s0); - LIns* d1 = demote(lir, s1); + LIns* d0 = w.demote(s0); + LIns* d1 = w.demote(s1); /* * Speculatively emit an integer operation, betting that at runtime we @@ -8519,7 +8237,7 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) #if defined NANOJIT_IA32 || defined NANOJIT_X64 case LIR_divd: if (d0->isImmI() && d1->isImmI()) - return lir->ins1(LIR_i2d, lir->insImmI(jsint(r))); + return w.i2d(w.immi(jsint(r))); exit = snapshot(OVERFLOW_EXIT); @@ -8529,47 +8247,46 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) * into -2147483648 / -1, because it can raise an overflow exception. */ if (!d1->isImmI()) { - LIns* br; - if (condBranch(LIR_jt, lir->ins2ImmI(LIR_gti, d1, 0), &br)) { - guard(false, lir->insEqI_0(d1), exit); - guard(true, lir->insEqI_0(lir->ins2(LIR_andi, - lir->ins2ImmI(LIR_eqi, d0, 0x80000000), - lir->ins2ImmI(LIR_eqi, d1, -1))), exit); - labelForBranch(br); + if (MaybeBranch mbr = w.jt(w.gtiN(d1, 0))) { + guard(false, w.eqi0(d1), exit); + guard(true, w.eqi0(w.andi(w.eqiN(d0, 0x80000000), + w.eqiN(d1, -1))), exit); + w.label(mbr); } } else { if (d1->immI() == -1) - guard(false, lir->ins2ImmI(LIR_eqi, d0, 0x80000000), exit); + guard(false, w.eqiN(d0, 0x80000000), exit); } - result = lir->ins2(v = LIR_divi, d0, d1); + v = LIR_divi; + result = w.divi(d0, d1); /* As long as the modulus is zero, the result is an integer. */ - guard(true, lir->insEqI_0(lir->ins1(LIR_modi, result)), exit); + guard(true, w.eqi0(w.modi(result)), exit); /* Don't lose a -0. */ - guard(false, lir->insEqI_0(result), exit); + guard(false, w.eqi0(result), exit); break; case LIR_modd: { if (d0->isImmI() && d1->isImmI()) - return lir->ins1(LIR_i2d, lir->insImmI(jsint(r))); + return w.i2d(w.immi(jsint(r))); exit = snapshot(OVERFLOW_EXIT); /* Make sure we don't trigger division by zero at runtime. */ if (!d1->isImmI()) - guard(false, lir->insEqI_0(d1), exit); - result = lir->ins1(v = LIR_modi, lir->ins2(LIR_divi, d0, d1)); + guard(false, w.eqi0(d1), exit); + v = LIR_modi; + result = w.modi(w.divi(d0, d1)); /* If the result is not 0, it is always within the integer domain. */ - LIns* br; - if (condBranch(LIR_jf, lir->insEqI_0(result), &br)) { + if (MaybeBranch mbr = w.jf(w.eqi0(result))) { /* * If the result is zero, we must exit if the lhs is negative since * the result is -0 in this case, which is not in the integer domain. */ - guard(false, lir->ins2ImmI(LIR_lti, d0, 0), exit); - labelForBranch(br); + guard(false, w.ltiN(d0, 0), exit); + w.label(mbr); } break; } @@ -8592,11 +8309,10 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) exit = snapshot(OVERFLOW_EXIT); result = guard_xov(v, d0, d1, exit); } else { - result = lir->ins2(v, d0, d1); + result = w.ins2(v, d0, d1); } if (needsNegZeroCheck) { JS_ASSERT(v == LIR_muli); - /* * Make sure we don't lose a -0. We exit if the result is zero and if * either operand is negative. We start out using a weaker guard, checking @@ -8610,11 +8326,9 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) exit = snapshot(OVERFLOW_EXIT); guard(true, - lir->insEqI_0(lir->ins2(LIR_andi, - lir->insEqI_0(result), - lir->ins2(LIR_ori, - lir->ins2ImmI(LIR_lti, d0, 0), - lir->ins2ImmI(LIR_lti, d1, 0)))), + w.eqi0(w.andi(w.eqi0(result), + w.ori(w.ltiN(d0, 0), + w.ltiN(d1, 0)))), exit); } else { guardNonNeg(d0, d1, snapshot(MUL_ZERO_EXIT)); @@ -8622,137 +8336,65 @@ TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1) } break; } - JS_ASSERT_IF(d0->isImmI() && d1->isImmI(), - result->isImmI() && result->immI() == jsint(r)); - return lir->ins1(LIR_i2d, result); -} - -/* - * If the branch is always taken, return false; the code jumped over by the - * branch need not be generated. If the branch is never taken, return true - * and put NULL in *brOut. Otherwise, return true and put the branch in - * *brOut. - */ -bool -TraceRecorder::condBranch(LOpcode op, LIns* cond, LIns** brOut) -{ - JS_ASSERT(op == LIR_jt || op == LIR_jf); - *brOut = NULL; - if (cond->isImmI()) { - int32 condval = cond->immI(); - JS_ASSERT(condval == 0 || condval == 1); - if ((op == LIR_jt && condval == 1) || (op == LIR_jf && condval == 0)) - return false; /* branch is always taken */ - } - *brOut = lir->insBranch(op, cond, NULL); - return true; -} - -/* - * Like condBranch(), but for when we know the branch condition cannot be - * optimized to a constant, eg. because one of the operands is the result of a - * volatile load. - */ -LIns* -TraceRecorder::unoptimizableCondBranch(LOpcode op, LIns* cond) -{ - JS_ASSERT(op == LIR_jt || op == LIR_jf); - JS_ASSERT(!cond->isImmI()); - return lir->insBranch(op, cond, NULL); -} - -/* - * Inserts a label and updates 'branch' to branch to it, if 'branch' is non-NULL. - * ('branch' may be NULL if it was a conditional branch and its condition was - * a constant value that resulted in the branch never being taken.) - */ -void -TraceRecorder::labelForBranch(LIns* br) -{ - if (br) { - JS_ASSERT(br->isop(LIR_j) || br->isop(LIR_jt) || br->isop(LIR_jf)); - br->setTarget(lir->ins0(LIR_label)); - } -} - -/* Similar to the other labelForBranch(), but for two branches. */ -void -TraceRecorder::labelForBranches(LIns* br1, LIns* br2) -{ - if (br1 || br2) { - LIns* label = lir->ins0(LIR_label); - if (br1) { - JS_ASSERT(br1->isop(LIR_j) || br1->isop(LIR_jt) || br1->isop(LIR_jf)); - br1->setTarget(label); - } - if (br2) { - JS_ASSERT(br2->isop(LIR_j) || br2->isop(LIR_jt) || br2->isop(LIR_jf)); - br2->setTarget(label); - } - } + JS_ASSERT_IF(d0->isImmI() && d1->isImmI(), result->isImmI(jsint(r))); + return w.i2d(result); } LIns* -TraceRecorder::i2d(LIns* i) +TraceRecorder::d2i(LIns* d, bool resultCanBeImpreciseIfFractional) { - return lir->ins1(LIR_i2d, i); -} - -LIns* -TraceRecorder::d2i(LIns* f, bool resultCanBeImpreciseIfFractional) -{ - if (f->isImmD()) - return lir->insImmI(js_DoubleToECMAInt32(f->immD())); - if (isfop(f, LIR_i2d) || isfop(f, LIR_ui2d)) - return foprnd1(f); - if (isfop(f, LIR_addd) || isfop(f, LIR_subd)) { - LIns* lhs = foprnd1(f); - LIns* rhs = foprnd2(f); - if (isPromote(lhs) && isPromote(rhs)) { - LOpcode op = arithOpcodeD2I(f->opcode()); - return lir->ins2(op, demote(lir, lhs), demote(lir, rhs)); + if (d->isImmD()) + return w.immi(js_DoubleToECMAInt32(d->immD())); + if (d->isop(LIR_i2d) || d->isop(LIR_ui2d)) + return d->oprnd1(); + if (d->isop(LIR_addd) || d->isop(LIR_subd)) { + LIns* lhs = d->oprnd1(); + LIns* rhs = d->oprnd2(); + if (IsPromote(lhs) && IsPromote(rhs)) { + LOpcode op = arithOpcodeD2I(d->opcode()); + return w.ins2(op, w.demote(lhs), w.demote(rhs)); } } - if (f->isCall()) { - const CallInfo* ci = f->callInfo(); + if (d->isCall()) { + const CallInfo* ci = d->callInfo(); if (ci == &js_UnboxDouble_ci) { #if JS_BITS_PER_WORD == 32 - LIns *tag_ins = fcallarg(f, 0); - LIns *payload_ins = fcallarg(f, 1); + LIns *tag_ins = d->callArgN(0); + LIns *payload_ins = d->callArgN(1); LIns* args[] = { payload_ins, tag_ins }; - return lir->insCall(&js_UnboxInt32_ci, args); + return w.call(&js_UnboxInt32_ci, args); #else - LIns* val_ins = fcallarg(f, 0); + LIns* val_ins = d->callArgN(0); LIns* args[] = { val_ins }; - return lir->insCall(&js_UnboxInt32_ci, args); + return w.call(&js_UnboxInt32_ci, args); #endif } if (ci == &js_StringToNumber_ci) { - LIns* args[] = { fcallarg(f, 1), fcallarg(f, 0) }; - return lir->insCall(&js_StringToInt32_ci, args); + LIns* args[] = { d->callArgN(1), d->callArgN(0) }; + return w.call(&js_StringToInt32_ci, args); } } return resultCanBeImpreciseIfFractional - ? lir->ins1(LIR_d2i, f) - : lir->insCall(&js_DoubleToInt32_ci, &f); + ? w.rawD2i(d) + : w.call(&js_DoubleToInt32_ci, &d); } LIns* -TraceRecorder::f2u(LIns* f) +TraceRecorder::d2u(LIns* d) { - if (f->isImmD()) - return lir->insImmI(js_DoubleToECMAUint32(f->immD())); - if (isfop(f, LIR_i2d) || isfop(f, LIR_ui2d)) - return foprnd1(f); - return lir->insCall(&js_DoubleToUint32_ci, &f); + if (d->isImmD()) + return w.immi(js_DoubleToECMAUint32(d->immD())); + if (d->isop(LIR_i2d) || d->isop(LIR_ui2d)) + return d->oprnd1(); + return w.call(&js_DoubleToUint32_ci, &d); } JS_REQUIRES_STACK RecordingStatus TraceRecorder::makeNumberInt32(LIns* d, LIns** out) { JS_ASSERT(d->isD()); - if (isPromote(d)) { - *out = demote(lir, d); + if (IsPromote(d)) { + *out = w.demote(d); return RECORD_CONTINUE; } @@ -8761,8 +8403,7 @@ TraceRecorder::makeNumberInt32(LIns* d, LIns** out) // and exit if the two doubles don't match. If 'f' is a non-integral // immediate we'll end up aborting. *out = d2i(d, /* resultCanBeImpreciseIfFractional = */true); - return guard(true, lir->ins2(LIR_eqd, d, i2d(*out)), MISMATCH_EXIT, - /* abortIfAlwaysExits = */true); + return guard(true, w.eqd(d, w.i2d(*out)), MISMATCH_EXIT, /* abortIfAlwaysExits = */true); } JS_REQUIRES_STACK LIns* @@ -8777,7 +8418,7 @@ TraceRecorder::stringify(const Value& v) if (v.isNumber()) { ci = &js_NumberToString_ci; } else if (v.isUndefined()) { - return INS_ATOM(cx->runtime->atomState.booleanAtoms[2]); + return w.immpAtomGC(cx->runtime->atomState.booleanAtoms[2]); } else if (v.isBoolean()) { ci = &js_BooleanIntToString_ci; } else { @@ -8787,11 +8428,11 @@ TraceRecorder::stringify(const Value& v) * what valueOf hint, here. */ JS_ASSERT(v.isNull()); - return INS_ATOM(cx->runtime->atomState.nullAtom); + return w.immpAtomGC(cx->runtime->atomState.nullAtom); } - v_ins = lir->insCall(ci, args); - guard(false, lir->insEqP_0(v_ins), OOM_EXIT); + v_ins = w.call(ci, args); + guard(false, w.eqp0(v_ins), OOM_EXIT); return v_ins; } @@ -8830,23 +8471,21 @@ TraceRecorder::ifop() if (v.isNull() || v.isUndefined()) { cond = false; - x = lir->insImmI(0); + x = w.immi(0); } else if (!v.isPrimitive()) { cond = true; - x = lir->insImmI(1); + x = w.immi(1); } else if (v.isBoolean()) { /* Test for boolean is true, negate later if we are testing for false. */ cond = v.isTrue(); - x = lir->ins2ImmI(LIR_eqi, v_ins, 1); + x = w.eqiN(v_ins, 1); } else if (v.isNumber()) { jsdouble d = v.toNumber(); cond = !JSDOUBLE_IS_NaN(d) && d; - x = lir->ins2(LIR_andi, - lir->ins2(LIR_eqd, v_ins, v_ins), - lir->insEqI_0(lir->ins2(LIR_eqd, v_ins, lir->insImmD(0)))); + x = w.andi(w.eqd(v_ins, v_ins), w.eqi0(w.eqd0(v_ins))); } else if (v.isString()) { cond = v.toString()->length() != 0; - x = getStringLength(v_ins); + x = w.getStringLength(v_ins); } else { JS_NOT_REACHED("ifop"); return ARECORD_STOP; @@ -8918,15 +8557,15 @@ TraceRecorder::tableswitch() si->count = count; si->table = 0; si->index = (uint32) -1; - LIns* diff = lir->ins2(LIR_subi, v_ins, lir->insImmI(low)); - LIns* cmp = lir->ins2(LIR_ltui, diff, lir->insImmI(si->count)); - lir->insGuard(LIR_xf, cmp, createGuardRecord(snapshot(DEFAULT_EXIT))); - // We use ACCSET_STORE_ANY; it's imprecise but this case is rare and not - // worth its own access region. - lir->insStore(diff, lir->insImmP(&si->index), 0, ACCSET_STORE_ANY); + LIns* diff = w.subi(v_ins, w.immi(low)); + LIns* cmp = w.ltui(diff, w.immi(si->count)); + guard(true, cmp, DEFAULT_EXIT); + // We use AnyAddress; it's imprecise but this case is rare and not worth its + // own access region. + w.st(diff, AnyAddress(w.immpNonGC(&si->index))); VMSideExit* exit = snapshot(CASE_EXIT); exit->switchInfo = si; - LIns* guardIns = lir->insGuard(LIR_xtbl, diff, createGuardRecord(exit)); + LIns* guardIns = w.xtbl(diff, createGuardRecord(exit)); fragment->lastIns = guardIns; CHECK_STATUS_A(compile()); return finishSuccessfully(); @@ -8945,19 +8584,17 @@ TraceRecorder::switchop() if (v.isNumber()) { jsdouble d = v.toNumber(); guard(true, - addName(lir->ins2(LIR_eqd, v_ins, lir->insImmD(d)), - "guard(switch on numeric)"), + w.name(w.eqd(v_ins, w.immd(d)), "guard(switch on numeric)"), BRANCH_EXIT); } else if (v.isString()) { - LIns* args[] = { INS_CONSTSTR(v.toString()), v_ins }; + LIns* args[] = { w.immpStrGC(v.toString()), v_ins }; guard(true, - addName(lir->insEqI_0(lir->insEqI_0(lir->insCall(&js_EqualStrings_ci, args))), - "guard(switch on string)"), + w.name(w.eqi0(w.eqi0(w.call(&js_EqualStrings_ci, args))), + "guard(switch on string)"), BRANCH_EXIT); } else if (v.isBoolean()) { guard(true, - addName(lir->ins2(LIR_eqi, v_ins, lir->insImmI(v.isTrue())), - "guard(switch on boolean)"), + w.name(w.eqi(v_ins, w.immi(v.isTrue())), "guard(switch on boolean)"), BRANCH_EXIT); } else if (v.isUndefined()) { // This is a unit type, so no guard is needed. @@ -9001,7 +8638,7 @@ TraceRecorder::incHelper(const Value &v, LIns* v_ins, LIns*& v_after, jsint incr { if (!v.isNumber()) RETURN_STOP("can only inc numbers"); - v_after = alu(LIR_addd, v.toNumber(), incr, v_ins, lir->insImmD(incr)); + v_after = alu(LIR_addd, v.toNumber(), incr, v_ins, w.immd(incr)); return RECORD_CONTINUE; } @@ -9045,7 +8682,7 @@ TraceRecorder::incElem(jsint incr, bool pre) if (!addr_ins) // if we read a hole, abort return RECORD_STOP; CHECK_STATUS(inc(*vp, v_ins, incr, pre)); - box_value_into(*vp, v_ins, addr_ins, 0, ACCSET_SLOTS); + box_value_into(*vp, v_ins, DSlotsAddress(addr_ins)); return RECORD_CONTINUE; } @@ -9102,22 +8739,20 @@ TraceRecorder::strictEquality(bool equal, bool cmpCase) JSValueType ltag = getPromotedType(l); if (ltag != getPromotedType(r)) { cond = !equal; - x = lir->insImmI(cond); + x = w.immi(cond); } else if (ltag == JSVAL_TYPE_STRING) { LIns* args[] = { r_ins, l_ins }; - x = lir->ins2ImmI(LIR_eqi, lir->insCall(&js_EqualStrings_ci, args), equal); + x = w.eqiN(w.call(&js_EqualStrings_ci, args), equal); cond = !!js_EqualStrings(l.toString(), r.toString()); } else { - LOpcode op; if (ltag == JSVAL_TYPE_DOUBLE) - op = LIR_eqd; + x = w.eqd(l_ins, r_ins); else if (ltag == JSVAL_TYPE_NULL || ltag == JSVAL_TYPE_NONFUNOBJ || ltag == JSVAL_TYPE_FUNOBJ) - op = LIR_eqp; + x = w.eqp(l_ins, r_ins); else - op = LIR_eqi; - x = lir->ins2(op, l_ins, r_ins); + x = w.eqi(l_ins, r_ins); if (!equal) - x = lir->insEqI_0(x); + x = w.eqi0(x); cond = (ltag == JSVAL_TYPE_DOUBLE) ? l.toNumber() == r.toNumber() : l == r; @@ -9173,10 +8808,9 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins, } else if (l.isObject()) { if (l.toObject().getClass()->ext.equality) RETURN_STOP_A("Can't trace extended class equality operator"); - LIns* flags_ins = lir->insLoad(LIR_ldi, l_ins, offsetof(JSObject, flags), - ACCSET_OBJ_FLAGS); - LIns* flag_ins = lir->ins2(LIR_andi, flags_ins, INS_CONSTU(JSObject::HAS_EQUALITY)); - guard(true, lir->insEqI_0(flag_ins), BRANCH_EXIT); + LIns* flags_ins = w.ldiObjFlags(l_ins); + LIns* flag_ins = w.andi(flags_ins, w.nameImmui(JSObject::HAS_EQUALITY)); + guard(true, w.eqi0(flag_ins), BRANCH_EXIT); op = LIR_eqp; cond = (l == r); @@ -9188,17 +8822,15 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins, JSString *r_str = r.toString(); if (!l_str->isRope() && !r_str->isRope() && l_str->length() == 1 && r_str->length() == 1) { VMSideExit *exit = snapshot(BRANCH_EXIT); - LIns *c = INS_CONSTWORD(1); - guard(true, lir->ins2(LIR_eqp, getStringLength(l_ins), c), exit); - guard(true, lir->ins2(LIR_eqp, getStringLength(r_ins), c), exit); - l_ins = lir->insLoad(LIR_ldus2ui, getStringChars(l_ins), 0, ACCSET_STRING_MCHARS, - LOAD_CONST); - r_ins = lir->insLoad(LIR_ldus2ui, getStringChars(r_ins), 0, ACCSET_STRING_MCHARS, - LOAD_CONST); + LIns *c = w.nameImmw(1); + guard(true, w.eqp(w.getStringLength(l_ins), c), exit); + guard(true, w.eqp(w.getStringLength(r_ins), c), exit); + l_ins = w.getStringChar0(l_ins); + r_ins = w.getStringChar0(r_ins); } else { args[0] = r_ins, args[1] = l_ins; - l_ins = lir->insCall(&js_EqualStrings_ci, args); - r_ins = lir->insImmI(1); + l_ins = w.call(&js_EqualStrings_ci, args); + r_ins = w.immi(1); } cond = !!js_EqualStrings(l.toString(), r.toString()); } else { @@ -9207,33 +8839,33 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins, op = LIR_eqd; } } else if (l.isNull() && r.isUndefined()) { - l_ins = INS_UNDEFINED(); + l_ins = w.immiUndefined(); cond = true; } else if (l.isUndefined() && r.isNull()) { - r_ins = INS_UNDEFINED(); + r_ins = w.immiUndefined(); cond = true; } else if (l.isNumber() && r.isString()) { args[0] = r_ins, args[1] = cx_ins; - r_ins = lir->insCall(&js_StringToNumber_ci, args); + r_ins = w.call(&js_StringToNumber_ci, args); cond = (l.toNumber() == js_StringToNumber(cx, r.toString())); op = LIR_eqd; } else if (l.isString() && r.isNumber()) { args[0] = l_ins, args[1] = cx_ins; - l_ins = lir->insCall(&js_StringToNumber_ci, args); + l_ins = w.call(&js_StringToNumber_ci, args); cond = (js_StringToNumber(cx, l.toString()) == r.toNumber()); op = LIR_eqd; } else { // Below we may assign to l or r, which modifies the interpreter state. // This is fine as long as we also update the tracker. if (l.isBoolean()) { - l_ins = i2d(l_ins); + l_ins = w.i2d(l_ins); set(&l, l_ins); l.setInt32(l.isTrue()); return equalityHelper(l, r, l_ins, r_ins, negate, tryBranchAfterCond, rval); } if (r.isBoolean()) { - r_ins = i2d(r_ins); + r_ins = w.i2d(r_ins); set(&r, r_ins); r.setInt32(r.isTrue()); return equalityHelper(l, r, l_ins, r_ins, negate, @@ -9248,15 +8880,15 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins, return InjectStatus(callImacro(equality_imacros.obj_any)); } - l_ins = lir->insImmI(0); - r_ins = lir->insImmI(1); + l_ins = w.immi(0); + r_ins = w.immi(1); cond = false; } /* If the operands aren't numbers, compare them as integers. */ - LIns* x = lir->ins2(op, l_ins, r_ins); + LIns* x = w.ins2(op, l_ins, r_ins); if (negate) { - x = lir->insEqI_0(x); + x = w.eqi0(x); cond = !cond; } @@ -9321,8 +8953,8 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond) /* 11.8.5 steps 3, 16-21. */ if (l.isString() && r.isString()) { LIns* args[] = { r_ins, l_ins }; - l_ins = lir->insCall(&js_CompareStrings_ci, args); - r_ins = lir->insImmI(0); + l_ins = w.call(&js_CompareStrings_ci, args); + r_ins = w.immi(0); cond = EvalCmp(op, l.toString(), r.toString()); goto do_comparison; } @@ -9331,13 +8963,13 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond) if (!l.isNumber()) { LIns* args[] = { l_ins, cx_ins }; if (l.isBoolean()) { - l_ins = i2d(l_ins); + l_ins = w.i2d(l_ins); } else if (l.isUndefined()) { - l_ins = lir->insImmD(js_NaN); + l_ins = w.immd(js_NaN); } else if (l.isString()) { - l_ins = lir->insCall(&js_StringToNumber_ci, args); + l_ins = w.call(&js_StringToNumber_ci, args); } else if (l.isNull()) { - l_ins = lir->insImmD(0.0); + l_ins = w.immd(0.0); } else { JS_NOT_REACHED("JSVAL_IS_NUMBER if int/double, objects should " "have been handled at start of method"); @@ -9347,13 +8979,13 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond) if (!r.isNumber()) { LIns* args[] = { r_ins, cx_ins }; if (r.isBoolean()) { - r_ins = i2d(r_ins); + r_ins = w.i2d(r_ins); } else if (r.isUndefined()) { - r_ins = lir->insImmD(js_NaN); + r_ins = w.immd(js_NaN); } else if (r.isString()) { - r_ins = lir->insCall(&js_StringToNumber_ci, args); + r_ins = w.call(&js_StringToNumber_ci, args); } else if (r.isNull()) { - r_ins = lir->insImmD(0.0); + r_ins = w.immd(0.0); } else { JS_NOT_REACHED("JSVAL_IS_NUMBER if int/double, objects should " "have been handled at start of method"); @@ -9380,7 +9012,7 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond) JS_ASSERT(isCmpDOpcode(op)); op = cmpOpcodeD2I(op); } - x = lir->ins2(op, l_ins, r_ins); + x = w.ins2(op, l_ins, r_ins); jsbytecode* pc = cx->regs->pc; @@ -9419,9 +9051,9 @@ TraceRecorder::unary(LOpcode op) LIns* a = get(&v); if (intop) a = d2i(a); - a = lir->ins1(op, a); + a = w.ins1(op, a); if (intop) - a = lir->ins1(LIR_i2d, a); + a = w.i2d(a); set(&v, a); return RECORD_CONTINUE; } @@ -9460,43 +9092,43 @@ TraceRecorder::binary(LOpcode op) if (l.isString()) { NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD() LIns* args[] = { a, cx_ins }; - a = lir->insCall(&js_StringToNumber_ci, args); + a = w.call(&js_StringToNumber_ci, args); lnum = js_StringToNumber(cx, l.toString()); leftIsNumber = true; } if (r.isString()) { NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD() LIns* args[] = { b, cx_ins }; - b = lir->insCall(&js_StringToNumber_ci, args); + b = w.call(&js_StringToNumber_ci, args); rnum = js_StringToNumber(cx, r.toString()); rightIsNumber = true; } if (l.isBoolean()) { - a = i2d(a); + a = w.i2d(a); lnum = l.toBoolean(); leftIsNumber = true; } else if (l.isUndefined()) { - a = lir->insImmD(js_NaN); + a = w.immd(js_NaN); lnum = js_NaN; leftIsNumber = true; } if (r.isBoolean()) { - b = i2d(b); + b = w.i2d(b); rnum = r.toBoolean(); rightIsNumber = true; } else if (r.isUndefined()) { - b = lir->insImmD(js_NaN); + b = w.immd(js_NaN); rnum = js_NaN; rightIsNumber = true; } if (leftIsNumber && rightIsNumber) { if (intop) { - a = (op == LIR_rshui) ? f2u(a) : d2i(a); + a = (op == LIR_rshui) ? d2u(a) : d2i(a); b = d2i(b); } a = alu(op, lnum, rnum, a, b); if (intop) - a = lir->ins1(op == LIR_rshui ? LIR_ui2d : LIR_i2d, a); + a = (op == LIR_rshui) ? w.ui2d(a) : w.i2d(a); set(&l, a); return RECORD_CONTINUE; } @@ -9557,7 +9189,7 @@ TraceRecorder::guardShape(LIns* obj_ins, JSObject* obj, uint32 shape, const char if (obj == globalObj) { // In this case checking object identity is equivalent and faster. guard(true, - addName(lir->ins2(LIR_eqp, obj_ins, INS_CONSTOBJ(globalObj)), "guard_global"), + w.name(w.eqp(obj_ins, w.immpObjGC(globalObj)), "guard_global"), exit); return RECORD_CONTINUE; } @@ -9568,7 +9200,7 @@ TraceRecorder::guardShape(LIns* obj_ins, JSObject* obj, uint32 shape, const char #endif // Finally, emit the shape guard. - guard(true, addName(lir->ins2ImmI(LIR_eqi, shape_ins(obj_ins), shape), guardName), exit); + guard(true, w.name(w.eqiN(w.ldiObjShape(obj_ins), shape), guardName), exit); return RECORD_CONTINUE; } @@ -9594,20 +9226,6 @@ TraceRecorder::forgetGuardedShapes() guardedShapeTable.clear(); } -inline LIns* -TraceRecorder::shape_ins(LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldi, obj_ins, offsetof(JSObject, objShape), ACCSET_OBJ_SHAPE), - "objShape"); -} - -inline LIns* -TraceRecorder::slots(LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS), - "slots"); -} - JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, PCVal& pcval) { @@ -9622,7 +9240,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 if (obj->isDenseArray()) { guardDenseArray(obj_ins, BRANCH_EXIT); aobj = obj->getProto(); - obj_ins = stobj_get_proto(obj_ins); + obj_ins = w.ldpObjProto(obj_ins); } if (!aobj->isNative()) @@ -9727,7 +9345,7 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, JSOp op = js_GetOpcode(cx, cx->fp()->script(), cx->regs->pc); if (JOF_OPMODE(op) != JOF_NAME) { guard(true, - addName(lir->ins2(LIR_eqp, obj_ins, INS_CONSTOBJ(globalObj)), "guard_global"), + w.name(w.eqp(obj_ins, w.immpObjGC(globalObj)), "guard_global"), exit); } } else { @@ -9735,16 +9353,11 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, } if (entry->adding()) { - LIns *vshape_ins = addName( - lir->insLoad(LIR_ldi, - addName(lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime), - ACCSET_CX, LOAD_CONST), - "runtime"), - offsetof(JSRuntime, protoHazardShape), ACCSET_RUNTIME), - "protoHazardShape"); + LIns *vshape_ins = + w.ldiRuntimeProtoHazardShape(w.name(w.ldpConstContextField(runtime), "runtime")); guard(true, - addName(lir->ins2ImmI(LIR_eqi, vshape_ins, vshape), "guard_protoHazardShape"), + w.name(w.eqiN(vshape_ins, vshape), "guard_protoHazardShape"), MISMATCH_EXIT); } @@ -9758,10 +9371,10 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, LIns* obj2_ins; if (entry->vcapTag() == 1) { // Duplicate the special case in PropertyCache::test. - obj2_ins = addName(stobj_get_proto(obj_ins), "proto"); - guard(false, lir->insEqP_0(obj2_ins), exit); + obj2_ins = w.ldpObjProto(obj_ins); + guard(false, w.eqp0(obj2_ins), exit); } else { - obj2_ins = INS_CONSTOBJ(obj2); + obj2_ins = w.immpObjGC(obj2); } CHECK_STATUS(guardShape(obj2_ins, obj2, vshape, "guard_vshape", exit)); } @@ -9773,7 +9386,7 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins, void TraceRecorder::stobj_set_fslot(LIns *obj_ins, unsigned slot, const Value &v, LIns* v_ins) { - box_value_into(v, v_ins, obj_ins, JSObject::getFixedSlotOffset(slot), ACCSET_SLOTS); + box_value_into(v, v_ins, FSlotsAddress(obj_ins, slot)); } void @@ -9781,8 +9394,8 @@ TraceRecorder::stobj_set_dslot(LIns *obj_ins, unsigned slot, LIns*& slots_ins, const Value &v, LIns* v_ins) { if (!slots_ins) - slots_ins = slots(obj_ins); - box_value_into(v, v_ins, slots_ins, slot * sizeof(Value), ACCSET_SLOTS); + slots_ins = w.name(w.ldpObjSlots(obj_ins), "slots"); + box_value_into(v, v_ins, DSlotsAddress(slots_ins, slot)); } void @@ -9801,94 +9414,68 @@ TraceRecorder::stobj_set_slot(JSObject *obj, LIns* obj_ins, unsigned slot, LIns* } } -#if JS_BITS_PER_WORD == 32 || JS_BITS_PER_WORD == 64 -LIns* -TraceRecorder::stobj_get_slot_uint32(LIns* obj_ins, unsigned slot) -{ - LIns *vaddr_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS); - return lir->insLoad(LIR_ldi, vaddr_ins, slot * sizeof(Value) + sPayloadOffset, ACCSET_SLOTS); -} -#endif - LIns* TraceRecorder::unbox_slot(JSObject *obj, LIns *obj_ins, uint32 slot, VMSideExit *exit) { - LIns *vaddr_ins; - ptrdiff_t offset; - /* Same guarantee about fixed slots as stobj_set_slot. */ - if (!obj->hasSlotsArray()) { - vaddr_ins = obj_ins; - offset = JSObject::getFixedSlotOffset(slot); - } else { - vaddr_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS); - offset = slot * sizeof(Value); - } + Address addr = (!obj->hasSlotsArray()) + ? (Address)FSlotsAddress(obj_ins, slot) + : (Address)DSlotsAddress(w.ldpObjSlots(obj_ins), slot); - return unbox_value(obj->getSlot(slot), vaddr_ins, offset, ACCSET_SLOTS, exit); + return unbox_value(obj->getSlot(slot), addr, exit); } #if JS_BITS_PER_WORD == 32 -LIns* -TraceRecorder::stobj_get_const_private_ptr(LIns *obj_ins, unsigned slot) +void +TraceRecorder::box_undefined_into(Address addr) { - LIns *vaddr_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS); - return lir->insLoad(LIR_ldi, vaddr_ins, - slot * sizeof(Value) + sPayloadOffset, ACCSET_SLOTS, LOAD_CONST); + w.stiValueTag(w.nameImmui(JSVAL_TAG_UNDEFINED), addr); + w.stiValuePayload(w.nameImmi(0), addr); } void -TraceRecorder::box_undefined_into(LIns *vaddr_ins, ptrdiff_t offset, AccSet accSet) +TraceRecorder::box_null_into(Address addr) { - lir->insStore(INS_CONSTU(JSVAL_TAG_UNDEFINED), vaddr_ins, offset + sTagOffset, accSet); - lir->insStore(INS_CONST(0), vaddr_ins, offset + sPayloadOffset, accSet); -} - -void -TraceRecorder::box_null_into(LIns *dstaddr_ins, ptrdiff_t offset, AccSet accSet) -{ - lir->insStore(INS_CONSTU(JSVAL_TAG_NULL), dstaddr_ins, offset + sTagOffset, accSet); - lir->insStore(INS_CONST(0), dstaddr_ins, offset + sPayloadOffset, accSet); + w.stiValueTag(w.nameImmui(JSVAL_TAG_NULL), addr); + w.stiValuePayload(w.nameImmi(0), addr); } inline LIns* -TraceRecorder::unbox_number_as_double(LIns *vaddr_ins, ptrdiff_t offset, LIns *tag_ins, - VMSideExit *exit, AccSet accSet) +TraceRecorder::unbox_number_as_double(Address addr, LIns *tag_ins, VMSideExit *exit) { - guard(true, lir->ins2(LIR_leui, tag_ins, INS_CONSTU(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)), exit); - LIns *val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet); + guard(true, w.leui(tag_ins, w.nameImmui(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)), exit); + LIns *val_ins = w.ldiValuePayload(addr); LIns* args[] = { val_ins, tag_ins }; - return lir->insCall(&js_UnboxDouble_ci, args); + return w.call(&js_UnboxDouble_ci, args); } inline LIns* -TraceRecorder::unbox_non_double_object(LIns* vaddr_ins, ptrdiff_t offset, LIns* tag_ins, - JSValueType type, VMSideExit* exit, AccSet accSet) +TraceRecorder::unbox_non_double_object(Address addr, LIns* tag_ins, + JSValueType type, VMSideExit* exit) { LIns *val_ins; if (type == JSVAL_TYPE_UNDEFINED) { - val_ins = INS_UNDEFINED(); + val_ins = w.immiUndefined(); } else if (type == JSVAL_TYPE_NULL) { - val_ins = INS_NULL(); + val_ins = w.immpNull(); } else { JS_ASSERT(type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING || type == JSVAL_TYPE_BOOLEAN || type == JSVAL_TYPE_MAGIC); - val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet); + val_ins = w.ldiValuePayload(addr); } - guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TYPE_TO_TAG(type))), exit); + guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TYPE_TO_TAG(type))), exit); return val_ins; } LIns* -TraceRecorder::unbox_object(LIns* vaddr_ins, ptrdiff_t offset, LIns* tag_ins, - JSValueType type, VMSideExit* exit, AccSet accSet) +TraceRecorder::unbox_object(Address addr, LIns* tag_ins, JSValueType type, VMSideExit* exit) { JS_ASSERT(type == JSVAL_TYPE_FUNOBJ || type == JSVAL_TYPE_NONFUNOBJ); - guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_OBJECT)), exit); - LIns *payload_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet); + guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)), exit); + LIns *payload_ins = w.ldiValuePayload(addr); if (type == JSVAL_TYPE_FUNOBJ) guardClass(payload_ins, &js_FunctionClass, exit, LOAD_NORMAL); else @@ -9897,87 +9484,82 @@ TraceRecorder::unbox_object(LIns* vaddr_ins, ptrdiff_t offset, LIns* tag_ins, } LIns* -TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, AccSet accSet, - VMSideExit *exit, bool force_double) +TraceRecorder::unbox_value(const Value &v, Address addr, VMSideExit *exit, bool force_double) { - LIns *tag_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sTagOffset, accSet); + LIns *tag_ins = w.ldiValueTag(addr); if (v.isNumber() && force_double) - return unbox_number_as_double(vaddr_ins, offset, tag_ins, exit, accSet); + return unbox_number_as_double(addr, tag_ins, exit); if (v.isInt32()) { - guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_INT32)), exit); - return i2d(lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet)); + guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_INT32)), exit); + return w.i2d(w.ldiValuePayload(addr)); } if (v.isDouble()) { - guard(true, lir->ins2(LIR_ltui, tag_ins, INS_CONSTU(JSVAL_TAG_CLEAR)), exit); - return lir->insLoad(LIR_ldd, vaddr_ins, offset, accSet); + guard(true, w.ltui(tag_ins, w.nameImmui(JSVAL_TAG_CLEAR)), exit); + return w.ldd(addr); } if (v.isObject()) { JSValueType type = v.toObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ; - return unbox_object(vaddr_ins, offset, tag_ins, type, exit, accSet); + return unbox_object(addr, tag_ins, type, exit); } JSValueType type = v.extractNonDoubleObjectTraceType(); - return unbox_non_double_object(vaddr_ins, offset, tag_ins, type, exit, accSet); + return unbox_non_double_object(addr, tag_ins, type, exit); } void -TraceRecorder::unbox_any_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet) +TraceRecorder::unbox_any_object(Address addr, LIns **obj_ins, LIns **is_obj_ins) { - LIns *tag_ins = lir->insLoad(LIR_ldp, vaddr_ins, sTagOffset, accSet); - *is_obj_ins = lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_OBJECT)); - *obj_ins = lir->insLoad(LIR_ldp, vaddr_ins, sPayloadOffset, accSet); + LIns *tag_ins = w.ldiValueTag(addr); + *is_obj_ins = w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)); + *obj_ins = w.ldiValuePayload(addr); } LIns* -TraceRecorder::is_boxed_true(LIns *vaddr_ins, AccSet accSet) +TraceRecorder::is_boxed_true(Address addr) { - LIns *tag_ins = lir->insLoad(LIR_ldi, vaddr_ins, sTagOffset, accSet); - LIns *bool_ins = lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_BOOLEAN)); - LIns *payload_ins = lir->insLoad(LIR_ldi, vaddr_ins, sPayloadOffset, accSet); - return lir->ins2(LIR_andi, bool_ins, payload_ins); + LIns *tag_ins = w.ldiValueTag(addr); + LIns *bool_ins = w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_BOOLEAN)); + LIns *payload_ins = w.ldiValuePayload(addr); + return w.andi(bool_ins, payload_ins); } LIns* -TraceRecorder::is_boxed_magic(LIns *vaddr_ins, JSWhyMagic why, AccSet accSet) +TraceRecorder::is_boxed_magic(Address addr, JSWhyMagic why) { - LIns *tag_ins = lir->insLoad(LIR_ldi, vaddr_ins, sTagOffset, accSet); - return lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_MAGIC)); + LIns *tag_ins = w.ldiValueTag(addr); + return w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_MAGIC)); } void -TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, ptrdiff_t offset, - AccSet accSet) +TraceRecorder::box_value_into(const Value &v, LIns *v_ins, Address addr) { if (v.isNumber()) { JS_ASSERT(v_ins->isD()); if (fcallinfo(v_ins) == &js_UnboxDouble_ci) { - LIns *tag_ins = fcallarg(v_ins, 0); - LIns *payload_ins = fcallarg(v_ins, 1); - lir->insStore(tag_ins, dstaddr_ins, offset + sTagOffset, accSet); - lir->insStore(payload_ins, dstaddr_ins, offset + sPayloadOffset, accSet); - } else if (isPromoteInt(v_ins)) { - LIns *int_ins = demote(lir, v_ins); - lir->insStore(INS_CONSTU(JSVAL_TAG_INT32), dstaddr_ins, - offset + sTagOffset, accSet); - lir->insStore(int_ins, dstaddr_ins, offset + sPayloadOffset, accSet); + w.stiValueTag(v_ins->callArgN(0), addr); + w.stiValuePayload(v_ins->callArgN(1), addr); + } else if (IsPromoteInt(v_ins)) { + LIns *int_ins = w.demote(v_ins); + w.stiValueTag(w.nameImmui(JSVAL_TAG_INT32), addr); + w.stiValuePayload(int_ins, addr); } else { - lir->insStore(v_ins, dstaddr_ins, offset, accSet); + w.std(v_ins, addr); } return; } if (v.isUndefined()) { - box_undefined_into(dstaddr_ins, offset, accSet); + box_undefined_into(addr); } else if (v.isNull()) { - box_null_into(dstaddr_ins, offset, accSet); + box_null_into(addr); } else { JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag(); - lir->insStore(INS_CONSTU(tag), dstaddr_ins, offset + sTagOffset, accSet); - lir->insStore(v_ins, dstaddr_ins, offset + sPayloadOffset, accSet); + w.stiValueTag(w.nameImmui(tag), addr); + w.stiValuePayload(v_ins, addr); } } @@ -9989,44 +9571,33 @@ TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins) #elif JS_BITS_PER_WORD == 64 -LIns* -TraceRecorder::stobj_get_const_private_ptr(LIns *obj_ins, unsigned slot) -{ - /* N.B. On 64-bit, privates are encoded differently from other pointers. */ - LIns *vaddr_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS); - LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, - slot * sizeof(Value) + sPayloadOffset, ACCSET_SLOTS, LOAD_CONST); - return lir->ins2ImmI(LIR_lshq, v_ins, 1); -} - void -TraceRecorder::box_undefined_into(LIns *vaddr_ins, ptrdiff_t offset, AccSet accSet) +TraceRecorder::box_undefined_into(Address addr) { - lir->insStore(INS_CONSTQWORD(JSVAL_BITS(JSVAL_VOID)), vaddr_ins, offset, accSet); + w.stq(w.nameImmq(JSVAL_BITS(JSVAL_VOID)), addr); } inline LIns * TraceRecorder::non_double_object_value_has_type(LIns *v_ins, JSValueType type) { - return lir->ins2(LIR_eqi, - lir->ins1(LIR_q2i, lir->ins2ImmI(LIR_rshuq, v_ins, JSVAL_TAG_SHIFT)), - INS_CONSTU(JSVAL_TYPE_TO_TAG(type))); + return w.eqi(w.q2i(w.rshuqN(v_ins, JSVAL_TAG_SHIFT)), + w.nameImmui(JSVAL_TYPE_TO_TAG(type))); } inline LIns * TraceRecorder::unpack_ptr(LIns *v_ins) { - return lir->ins2(LIR_andq, v_ins, INS_CONSTQWORD(JSVAL_PAYLOAD_MASK)); + return w.andq(v_ins, w.nameImmq(JSVAL_PAYLOAD_MASK)); } inline LIns * TraceRecorder::unbox_number_as_double(LIns *v_ins, VMSideExit *exit) { guard(true, - lir->ins2(LIR_ltuq, v_ins, INS_CONSTQWORD(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET)), + w.ltuq(v_ins, w.nameImmq(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET)), exit); LIns* args[] = { v_ins }; - return lir->insCall(&js_UnboxDouble_ci, args); + return w.call(&js_UnboxDouble_ci, args); } inline nanojit::LIns* @@ -10035,14 +9606,14 @@ TraceRecorder::unbox_non_double_object(LIns* v_ins, JSValueType type, VMSideExit JS_ASSERT(type <= JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET); LIns *unboxed_ins; if (type == JSVAL_TYPE_UNDEFINED) { - unboxed_ins = INS_UNDEFINED(); + unboxed_ins = w.immiUndefined(); } else if (type == JSVAL_TYPE_NULL) { - unboxed_ins = INS_NULL(); + unboxed_ins = w.immpNull(); } else if (type >= JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET) { unboxed_ins = unpack_ptr(v_ins); } else { JS_ASSERT(type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN || type == JSVAL_TYPE_MAGIC); - unboxed_ins = lir->ins1(LIR_q2i, v_ins); + unboxed_ins = w.q2i(v_ins); } guard(true, non_double_object_value_has_type(v_ins, type), exit); @@ -10055,7 +9626,7 @@ TraceRecorder::unbox_object(LIns* v_ins, JSValueType type, VMSideExit* exit) JS_STATIC_ASSERT(JSVAL_TYPE_OBJECT == JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET); JS_ASSERT(type == JSVAL_TYPE_FUNOBJ || type == JSVAL_TYPE_NONFUNOBJ); guard(true, - lir->ins2(LIR_geuq, v_ins, INS_CONSTQWORD(JSVAL_SHIFTED_TAG_OBJECT)), + w.geuq(v_ins, w.nameImmq(JSVAL_SHIFTED_TAG_OBJECT)), exit); v_ins = unpack_ptr(v_ins); if (type == JSVAL_TYPE_FUNOBJ) @@ -10066,22 +9637,21 @@ TraceRecorder::unbox_object(LIns* v_ins, JSValueType type, VMSideExit* exit) } LIns* -TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, AccSet accSet, - VMSideExit *exit, bool force_double) +TraceRecorder::unbox_value(const Value &v, Address addr, VMSideExit *exit, bool force_double) { - LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, offset, accSet); + LIns *v_ins = w.ldq(addr); if (v.isNumber() && force_double) return unbox_number_as_double(v_ins, exit); if (v.isInt32()) { guard(true, non_double_object_value_has_type(v_ins, JSVAL_TYPE_INT32), exit); - return i2d(lir->ins1(LIR_q2i, v_ins)); + return w.i2d(w.q2i(v_ins)); } if (v.isDouble()) { - guard(true, lir->ins2(LIR_leuq, v_ins, INS_CONSTQWORD(JSVAL_SHIFTED_TAG_MAX_DOUBLE)), exit); - return lir->ins1(LIR_qasd, v_ins); + guard(true, w.leuq(v_ins, w.nameImmq(JSVAL_SHIFTED_TAG_MAX_DOUBLE)), exit); + return w.qasd(v_ins); } if (v.isObject()) { @@ -10094,26 +9664,26 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, Ac } void -TraceRecorder::unbox_any_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet) +TraceRecorder::unbox_any_object(Address addr, LIns **obj_ins, LIns **is_obj_ins) { JS_STATIC_ASSERT(JSVAL_TYPE_OBJECT == JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET); - LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, 0, accSet); - *is_obj_ins = lir->ins2(LIR_geuq, v_ins, INS_CONSTQWORD(JSVAL_TYPE_OBJECT)); + LIns *v_ins = w.ldq(addr); + *is_obj_ins = w.geuq(v_ins, w.nameImmq(JSVAL_TYPE_OBJECT)); *obj_ins = unpack_ptr(v_ins); } LIns* -TraceRecorder::is_boxed_true(LIns *vaddr_ins, AccSet accSet) +TraceRecorder::is_boxed_true(Address addr) { - LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, 0, accSet); - return lir->ins2(LIR_eqq, v_ins, lir->insImmQ(JSVAL_BITS(JSVAL_TRUE))); + LIns *v_ins = w.ldq(addr); + return w.eqq(v_ins, w.immq(JSVAL_BITS(JSVAL_TRUE))); } LIns* -TraceRecorder::is_boxed_magic(LIns *vaddr_ins, JSWhyMagic why, AccSet accSet) +TraceRecorder::is_boxed_magic(Address addr, JSWhyMagic why) { - LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, 0, accSet); - return lir->ins2(LIR_eqq, v_ins, INS_CONSTQWORD(BUILD_JSVAL(JSVAL_TAG_MAGIC, why))); + LIns *v_ins = w.ldq(addr); + return w.eqq(v_ins, w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why))); } LIns* @@ -10122,35 +9692,33 @@ TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins) if (v.isNumber()) { JS_ASSERT(v_ins->isD()); if (fcallinfo(v_ins) == &js_UnboxDouble_ci) - return fcallarg(v_ins, 0); - if (isPromoteInt(v_ins)) { - return lir->ins2(LIR_orq, - lir->ins1(LIR_ui2uq, demote(lir, v_ins)), - INS_CONSTQWORD(JSVAL_SHIFTED_TAG_INT32)); + return v_ins->callArgN(0); + if (IsPromoteInt(v_ins)) { + return w.orq(w.ui2uq(w.demote(v_ins)), + w.nameImmq(JSVAL_SHIFTED_TAG_INT32)); } - return lir->ins1(LIR_dasq, v_ins); + return w.dasq(v_ins); } if (v.isNull()) - return INS_CONSTQWORD(JSVAL_BITS(JSVAL_NULL)); + return w.nameImmq(JSVAL_BITS(JSVAL_NULL)); if (v.isUndefined()) - return INS_CONSTQWORD(JSVAL_BITS(JSVAL_VOID)); + return w.nameImmq(JSVAL_BITS(JSVAL_VOID)); JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag(); uint64 shiftedTag = ((uint64)tag) << JSVAL_TAG_SHIFT; - LIns *shiftedTag_ins = INS_CONSTQWORD(shiftedTag); + LIns *shiftedTag_ins = w.nameImmq(shiftedTag); if (v.hasPtrPayload()) - return lir->ins2(LIR_orq, v_ins, shiftedTag_ins); - return lir->ins2(LIR_orq, lir->ins1(LIR_ui2uq, v_ins), shiftedTag_ins); + return w.orq(v_ins, shiftedTag_ins); + return w.orq(w.ui2uq(v_ins), shiftedTag_ins); } void -TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, ptrdiff_t offset, - AccSet accSet) +TraceRecorder::box_value_into(const Value &v, LIns *v_ins, Address addr) { LIns *boxed_ins = box_value_for_native_call(v, v_ins); - lir->insStore(boxed_ins, dstaddr_ins, offset, accSet); + w.st(boxed_ins, addr); } #endif /* JS_BITS_PER_WORD */ @@ -10158,45 +9726,15 @@ TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, pt LIns* TraceRecorder::box_value_into_alloc(const Value &v, LIns *v_ins) { - LIns *alloc_ins = lir->insAlloc(sizeof(Value)); - box_value_into(v, v_ins, alloc_ins, 0, ACCSET_ALLOC); + LIns *alloc_ins = w.allocp(sizeof(Value)); + box_value_into(v, v_ins, AllocSlotsAddress(alloc_ins)); return alloc_ins; } -LIns* -TraceRecorder::stobj_get_parent(nanojit::LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, parent), ACCSET_OBJ_PARENT), - "parent"); -} - -LIns* -TraceRecorder::stobj_get_private(nanojit::LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, privateData), - ACCSET_OBJ_PRIVATE), - "private"); -} - -LIns* -TraceRecorder::stobj_get_private_uint32(nanojit::LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldi, obj_ins, offsetof(JSObject, privateData), - ACCSET_OBJ_PRIVATE), - "private_uint32"); -} - -LIns* -TraceRecorder::stobj_get_proto(nanojit::LIns* obj_ins) -{ - return addName(lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, proto), ACCSET_OBJ_PROTO), - "proto"); -} - LIns* TraceRecorder::is_string_id(LIns *id_ins) { - return lir->insEqP_0(lir->ins2(LIR_andp, id_ins, INS_CONSTWORD(JSID_TYPE_MASK))); + return w.eqp0(w.andp(id_ins, w.nameImmw(JSID_TYPE_MASK))); } LIns * @@ -10209,7 +9747,7 @@ TraceRecorder::unbox_string_id(LIns *id_ins) LIns * TraceRecorder::unbox_int_id(LIns *id_ins) { - return lir->ins2ImmI(LIR_rshi, p2i(id_ins), 1); + return w.rshiN(w.p2i(id_ins), 1); } JS_REQUIRES_STACK RecordingStatus @@ -10231,7 +9769,7 @@ TraceRecorder::getThis(LIns*& this_ins) JS_ASSERT(&fp->thisValue().toObject() == obj); #endif - this_ins = INS_CONSTOBJ(&fp->thisValue().toObject()); + this_ins = w.immpObjGC(&fp->thisValue().toObject()); return RECORD_CONTINUE; } @@ -10262,7 +9800,7 @@ TraceRecorder::getThis(LIns*& this_ins) RETURN_ERROR("computeThis failed"); /* thisv is a reference, so it'll see the newly computed |this|. */ - this_ins = INS_CONSTOBJ(globalObj); + this_ins = w.immpObjGC(globalObj); set(&thisv, this_ins); return RECORD_CONTINUE; } @@ -10271,8 +9809,7 @@ JS_REQUIRES_STACK void TraceRecorder::guardClassHelper(bool cond, LIns* obj_ins, Class* clasp, VMSideExit* exit, LoadQual loadQual) { - LIns* class_ins = - lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, clasp), ACCSET_OBJ_CLASP, loadQual); + LIns* class_ins = w.ldpObjClasp(obj_ins, loadQual); #ifdef JS_JIT_SPEW char namebuf[32]; @@ -10280,7 +9817,7 @@ TraceRecorder::guardClassHelper(bool cond, LIns* obj_ins, Class* clasp, VMSideEx #else static const char namebuf[] = ""; #endif - guard(cond, addName(lir->ins2(LIR_eqp, class_ins, INS_CONSTPTR(clasp)), namebuf), exit); + guard(cond, w.name(w.eqp(class_ins, w.nameImmpNonGC(clasp)), namebuf), exit); } JS_REQUIRES_STACK void @@ -10313,10 +9850,10 @@ TraceRecorder::guardHasPrototype(JSObject* obj, LIns* obj_ins, VMSideExit* exit) { *pobj = obj->getProto(); - *pobj_ins = stobj_get_proto(obj_ins); + *pobj_ins = w.ldpObjProto(obj_ins); bool cond = *pobj == NULL; - guard(cond, addName(lir->insEqP_0(*pobj_ins), "guard(proto-not-null)"), exit); + guard(cond, w.name(w.eqp0(*pobj_ins), "guard(proto-not-null)"), exit); return !cond; } @@ -10408,15 +9945,12 @@ TraceRecorder::clearCurrentFrameSlotsFromTracker(Tracker& which) class BoxArg { public: - BoxArg(TraceRecorder *tr, LIns *base_ins, ptrdiff_t offset, AccSet accSet) - : tr(tr), base_ins(base_ins), offset(offset), accSet(accSet) {} + BoxArg(TraceRecorder *tr, Address addr) + : tr(tr), addr(addr) {} TraceRecorder *tr; - LIns *base_ins; - ptrdiff_t offset; - AccSet accSet; + Address addr; void operator()(uintN argi, Value *src) { - tr->box_value_into(*src, tr->get(src), base_ins, - offset + argi * sizeof(Value), accSet); + tr->box_value_into(*src, tr->get(src), OffsetAddress(addr, argi * sizeof(Value))); } }; @@ -10442,39 +9976,40 @@ TraceRecorder::putActivationObjects() LIns *args_ins; if (nargs > 0) { - args_ins = lir->insAlloc(nargs * sizeof(Value)); + args_ins = w.allocp(nargs * sizeof(Value)); /* Don't copy all the actuals if we are only boxing for the callobj. */ + Address addr = AllocSlotsAddress(args_ins); if (nargs == nactual) - fp->forEachCanonicalActualArg(BoxArg(this, args_ins, 0, ACCSET_ALLOC)); + fp->forEachCanonicalActualArg(BoxArg(this, addr)); else - fp->forEachFormalArg(BoxArg(this, args_ins, 0, ACCSET_ALLOC)); + fp->forEachFormalArg(BoxArg(this, addr)); } else { - args_ins = INS_CONSTPTR(0); + args_ins = w.nameImmpNonGC(0); } if (have_args) { LIns* argsobj_ins = getFrameObjPtr(fp->addressOfArgs()); LIns* args[] = { args_ins, argsobj_ins, cx_ins }; - lir->insCall(&js_PutArgumentsOnTrace_ci, args); + w.call(&js_PutArgumentsOnTrace_ci, args); } if (have_call) { int nslots = fp->fun()->countVars(); LIns* slots_ins; if (nslots) { - slots_ins = lir->insAlloc(sizeof(Value) * nslots); + slots_ins = w.allocp(sizeof(Value) * nslots); for (int i = 0; i < nslots; ++i) { - box_value_into(fp->slots()[i], get(&fp->slots()[i]), slots_ins, - i * sizeof(Value), ACCSET_ALLOC); + box_value_into(fp->slots()[i], get(&fp->slots()[i]), + AllocSlotsAddress(slots_ins, i)); } } else { - slots_ins = INS_CONSTPTR(0); + slots_ins = w.nameImmpNonGC(0); } LIns* scopeChain_ins = getFrameObjPtr(fp->addressOfScopeChain()); - LIns* args[] = { slots_ins, INS_CONST(nslots), args_ins, - INS_CONST(fp->numFormalArgs()), scopeChain_ins, cx_ins }; - lir->insCall(&js_PutCallObjectOnTrace_ci, args); + LIns* args[] = { slots_ins, w.nameImmi(nslots), args_ins, + w.nameImmi(fp->numFormalArgs()), scopeChain_ins, cx_ins }; + w.call(&js_PutCallObjectOnTrace_ci, args); } } @@ -10495,7 +10030,7 @@ TraceRecorder::record_EnterFrame() debug_only_print0(LC_TMTracer, "----\n"); } ) - LIns* void_ins = INS_UNDEFINED(); + LIns* void_ins = w.immiUndefined(); // Before we enter this frame, we need to clear out any dangling insns left // in the tracer. While we also clear when returning from a function, it is @@ -10542,11 +10077,11 @@ TraceRecorder::record_EnterFrame() // argsObj: clear and set to null nativeFrameTracker.set(fp->addressOfArgs(), NULL); - setFrameObjPtr(fp->addressOfArgs(), INS_NULL()); + setFrameObjPtr(fp->addressOfArgs(), w.immpNull()); // scopeChain: clear, initialize before snapshot, set below nativeFrameTracker.set(fp->addressOfScopeChain(), NULL); - setFrameObjPtr(fp->addressOfScopeChain(), INS_NULL()); + setFrameObjPtr(fp->addressOfScopeChain(), w.immpNull()); // nfixed: clear and set to undefined Value *vp = fp->slots(); @@ -10563,18 +10098,18 @@ TraceRecorder::record_EnterFrame() nativeFrameTracker.set(vp, NULL); LIns* callee_ins = get(&cx->fp()->calleeValue()); - LIns* scopeChain_ins = stobj_get_parent(callee_ins); + LIns* scopeChain_ins = w.ldpObjParent(callee_ins); // set scopeChain for real if (cx->fp()->fun()->isHeavyweight()) { if (js_IsNamedLambda(cx->fp()->fun())) RETURN_STOP_A("can't call named lambda heavyweight on trace"); - LIns* fun_ins = INS_CONSTPTR(cx->fp()->fun()); + LIns* fun_ins = w.nameImmpNonGC(cx->fp()->fun()); LIns* args[] = { scopeChain_ins, callee_ins, fun_ins, cx_ins }; - LIns* call_ins = lir->insCall(&js_CreateCallObjectOnTrace_ci, args); - guard(false, lir->insEqP_0(call_ins), snapshot(OOM_EXIT)); + LIns* call_ins = w.call(&js_CreateCallObjectOnTrace_ci, args); + guard(false, w.eqp0(call_ins), OOM_EXIT); setFrameObjPtr(fp->addressOfScopeChain(), call_ins); } else { @@ -10588,9 +10123,9 @@ TraceRecorder::record_EnterFrame() } if (fp->isConstructing()) { - LIns* args[] = { callee_ins, INS_CONSTPTR(&js_ObjectClass), cx_ins }; - LIns* tv_ins = lir->insCall(&js_CreateThisFromTrace_ci, args); - guard(false, lir->insEqP_0(tv_ins), OOM_EXIT); + LIns* args[] = { callee_ins, w.nameImmpNonGC(&js_ObjectClass), cx_ins }; + LIns* tv_ins = w.call(&js_CreateThisFromTrace_ci, args); + guard(false, w.eqp0(tv_ins), OOM_EXIT); set(&fp->thisValue(), tv_ins); } @@ -10618,7 +10153,7 @@ TraceRecorder::record_LeaveFrame() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_PUSH() { - stack(0, INS_UNDEFINED()); + stack(0, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -10631,7 +10166,8 @@ TraceRecorder::record_JSOP_POPV() // frame because POPV appears only in global and eval code and we don't // trace JSOP_EVAL or leaving the frame where tracing started. LIns *fp_ins = entryFrameIns(); - box_value_into(rval, get(&rval), fp_ins, JSStackFrame::offsetOfReturnValue(), ACCSET_STACKFRAME); + box_value_into(rval, get(&rval), StackFrameAddress(fp_ins, + JSStackFrame::offsetOfReturnValue())); return ARECORD_CONTINUE; } @@ -10677,9 +10213,9 @@ TraceRecorder::record_JSOP_RETURN() #ifdef MOZ_TRACE_JSCALLS if (cx->functionCallback) { - LIns* args[] = { INS_CONST(0), INS_CONSTPTR(cx->fp()->fun()), cx_ins }; - LIns* call_ins = lir->insCall(&functionProbe_ci, args); - guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT); + LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins }; + LIns* call_ins = w.call(&functionProbe_ci, args); + guard(false, w.eqi0(call_ins), MISMATCH_EXIT); } #endif @@ -10732,18 +10268,18 @@ TraceRecorder::record_JSOP_IFNE() LIns* TraceRecorder::newArguments(LIns* callee_ins, bool strict) { - LIns* global_ins = INS_CONSTOBJ(globalObj); - LIns* argc_ins = INS_CONST(cx->fp()->numActualArgs()); + LIns* global_ins = w.immpObjGC(globalObj); + LIns* argc_ins = w.nameImmi(cx->fp()->numActualArgs()); LIns* args[] = { callee_ins, argc_ins, global_ins, cx_ins }; - LIns* argsobj_ins = lir->insCall(&js_NewArgumentsOnTrace_ci, args); - guard(false, lir->insEqP_0(argsobj_ins), OOM_EXIT); + LIns* argsobj_ins = w.call(&js_NewArgumentsOnTrace_ci, args); + guard(false, w.eqp0(argsobj_ins), OOM_EXIT); if (strict) { - LIns* argsData_ins = stobj_get_const_private_ptr(argsobj_ins, JSObject::JSSLOT_ARGS_DATA); + LIns* argsData_ins = w.getObjPrivatizedSlot(argsobj_ins, JSObject::JSSLOT_ARGS_DATA); ptrdiff_t slotsOffset = offsetof(ArgumentsData, slots); - cx->fp()->forEachCanonicalActualArg(BoxArg(this, argsData_ins, slotsOffset, - ACCSET_ARGS_DATA)); + cx->fp()->forEachCanonicalActualArg(BoxArg(this, ArgsSlotsAddress(argsData_ins, + slotsOffset))); } return argsobj_ins; @@ -10770,25 +10306,25 @@ TraceRecorder::record_JSOP_ARGUMENTS() } else { // Generate LIR to create arguments only if it has not already been created. - LIns* mem_ins = lir->insAlloc(sizeof(JSObject *)); + LIns* mem_ins = w.allocp(sizeof(JSObject *)); - LIns* isZero_ins = lir->insEqP_0(a_ins); + LIns* isZero_ins = w.eqp0(a_ins); if (isZero_ins->isImmI(0)) { - lir->insStore(a_ins, mem_ins, 0, ACCSET_ALLOC); + w.stAlloc(a_ins, mem_ins); } else if (isZero_ins->isImmI(1)) { LIns* call_ins = newArguments(callee_ins, strict); - lir->insStore(call_ins, mem_ins, 0, ACCSET_ALLOC); + w.stAlloc(call_ins, mem_ins); } else { - LIns* br1 = unoptimizableCondBranch(LIR_jt, isZero_ins); - lir->insStore(a_ins, mem_ins, 0, ACCSET_ALLOC); - LIns* br2 = lir->insBranch(LIR_j, NULL, NULL); - labelForBranch(br1); + LIns* br1 = w.jtUnoptimizable(isZero_ins); + w.stAlloc(a_ins, mem_ins); + LIns* br2 = w.j(NULL); + w.label(br1); LIns* call_ins = newArguments(callee_ins, strict); - lir->insStore(call_ins, mem_ins, 0, ACCSET_ALLOC); - labelForBranch(br2); + w.stAlloc(call_ins, mem_ins); + w.label(br2); } - args_ins = lir->insLoad(LIR_ldp, mem_ins, 0, ACCSET_ALLOC); + args_ins = w.ldpAlloc(mem_ins); } stack(0, args_ins); @@ -10935,8 +10471,8 @@ TraceRecorder::record_JSOP_ADD() if (l.isString() || r.isString()) { LIns* args[] = { stringify(r), stringify(l), cx_ins }; - LIns* concat = lir->insCall(&js_ConcatStrings_ci, args); - guard(false, lir->insEqP_0(concat), OOM_EXIT); + LIns* concat = w.call(&js_ConcatStrings_ci, args); + guard(false, w.eqp0(concat), OOM_EXIT); set(&l, concat); return ARECORD_CONTINUE; } @@ -10973,21 +10509,20 @@ TraceRecorder::record_JSOP_NOT() { Value& v = stackval(-1); if (v.isBoolean() || v.isUndefined()) { - set(&v, lir->insEqI_0(lir->ins2ImmI(LIR_eqi, get(&v), 1))); + set(&v, w.eqi0(w.eqiN(get(&v), 1))); return ARECORD_CONTINUE; } if (v.isNumber()) { LIns* v_ins = get(&v); - set(&v, lir->ins2(LIR_ori, lir->ins2(LIR_eqd, v_ins, lir->insImmD(0)), - lir->insEqI_0(lir->ins2(LIR_eqd, v_ins, v_ins)))); + set(&v, w.ori(w.eqd0(v_ins), w.eqi0(w.eqd(v_ins, v_ins)))); return ARECORD_CONTINUE; } if (v.isObjectOrNull()) { - set(&v, lir->insEqP_0(get(&v))); + set(&v, w.eqp0(get(&v))); return ARECORD_CONTINUE; } JS_ASSERT(v.isString()); - set(&v, lir->insEqP_0(getStringLength(get(&v)))); + set(&v, w.eqp0(w.getStringLength(get(&v)))); return ARECORD_CONTINUE; } @@ -11017,19 +10552,19 @@ TraceRecorder::record_JSOP_NEG() */ if (oracle && !oracle->isInstructionUndemotable(cx->regs->pc) && - isPromoteInt(a) && + IsPromoteInt(a) && (!v.isInt32() || v.toInt32() != 0) && (!v.isDouble() || v.toDouble() != 0) && -v.toNumber() == (int)-v.toNumber()) { VMSideExit* exit = snapshot(OVERFLOW_EXIT); - a = guard_xov(LIR_subi, lir->insImmI(0), demote(lir, a), exit); + a = guard_xov(LIR_subi, w.immi(0), w.demote(a), exit); if (!a->isImmI() && a->isop(LIR_subxovi)) { - guard(false, lir->ins2ImmI(LIR_eqi, a, 0), exit); // make sure we don't lose a -0 + guard(false, w.eqiN(a, 0), exit); // make sure we don't lose a -0 } - a = lir->ins1(LIR_i2d, a); + a = w.i2d(a); } else { - a = lir->ins1(LIR_negd, a); + a = w.negd(a); } set(&v, a); @@ -11037,24 +10572,23 @@ TraceRecorder::record_JSOP_NEG() } if (v.isNull()) { - set(&v, lir->insImmD(-0.0)); + set(&v, w.immd(-0.0)); return ARECORD_CONTINUE; } if (v.isUndefined()) { - set(&v, lir->insImmD(js_NaN)); + set(&v, w.immd(js_NaN)); return ARECORD_CONTINUE; } if (v.isString()) { LIns* args[] = { get(&v), cx_ins }; - set(&v, lir->ins1(LIR_negd, - lir->insCall(&js_StringToNumber_ci, args))); + set(&v, w.negd(w.call(&js_StringToNumber_ci, args))); return ARECORD_CONTINUE; } JS_ASSERT(v.isBoolean()); - set(&v, lir->ins1(LIR_negd, i2d(get(&v)))); + set(&v, w.negd(w.i2d(get(&v)))); return ARECORD_CONTINUE; } @@ -11072,22 +10606,22 @@ TraceRecorder::record_JSOP_POS() return ARECORD_CONTINUE; if (v.isNull()) { - set(&v, lir->insImmD(0)); + set(&v, w.immd(0)); return ARECORD_CONTINUE; } if (v.isUndefined()) { - set(&v, lir->insImmD(js_NaN)); + set(&v, w.immd(js_NaN)); return ARECORD_CONTINUE; } if (v.isString()) { LIns* args[] = { get(&v), cx_ins }; - set(&v, lir->insCall(&js_StringToNumber_ci, args)); + set(&v, w.call(&js_StringToNumber_ci, args)); return ARECORD_CONTINUE; } JS_ASSERT(v.isBoolean()); - set(&v, i2d(get(&v))); + set(&v, w.i2d(get(&v))); return ARECORD_CONTINUE; } @@ -11141,7 +10675,7 @@ TraceRecorder::getClassPrototype(JSObject* ctor, LIns*& proto_ins) JSObject *proto = &pval.toObject(); JS_ASSERT_IF(clasp != &js_ArrayClass, proto->emptyShapes[0]->getClass() == clasp); - proto_ins = INS_CONSTOBJ(proto); + proto_ins = w.immpObjGC(proto); return RECORD_CONTINUE; } @@ -11170,7 +10704,7 @@ TraceRecorder::getClassPrototype(JSProtoKey key, LIns*& proto_ins) } #endif - proto_ins = INS_CONSTOBJ(proto); + proto_ins = w.immpObjGC(proto); return RECORD_CONTINUE; } @@ -11190,8 +10724,8 @@ TraceRecorder::newString(JSObject* ctor, uint32 argc, Value* argv, Value* rval) CHECK_STATUS(getClassPrototype(ctor, proto_ins)); LIns* args[] = { stringify(argv[0]), proto_ins, cx_ins }; - LIns* obj_ins = lir->insCall(&js_String_tn_ci, args); - guard(false, lir->insEqP_0(obj_ins), OOM_EXIT); + LIns* obj_ins = w.call(&js_String_tn_ci, args); + guard(false, w.eqp0(obj_ins), OOM_EXIT); set(rval, obj_ins); pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; @@ -11206,13 +10740,13 @@ TraceRecorder::newArray(JSObject* ctor, uint32 argc, Value* argv, Value* rval) LIns *arr_ins; if (argc == 0 || (argc == 1 && argv[0].isNumber())) { - LIns *args[] = { argc == 0 ? lir->insImmI(0) : d2i(get(argv)), proto_ins, cx_ins }; - arr_ins = lir->insCall(&js_NewEmptyArray_ci, args); - guard(false, lir->insEqP_0(arr_ins), OOM_EXIT); + LIns *args[] = { argc == 0 ? w.immi(0) : d2i(get(argv)), proto_ins, cx_ins }; + arr_ins = w.call(&js_NewEmptyArray_ci, args); + guard(false, w.eqp0(arr_ins), OOM_EXIT); } else { - LIns *args[] = { INS_CONST(argc), proto_ins, cx_ins }; - arr_ins = lir->insCall(&js_NewPreallocatedArray_ci, args); - guard(false, lir->insEqP_0(arr_ins), OOM_EXIT); + LIns *args[] = { w.nameImmi(argc), proto_ins, cx_ins }; + arr_ins = w.call(&js_NewPreallocatedArray_ci, args); + guard(false, w.eqp0(arr_ins), OOM_EXIT); // arr->slots[i] = box_jsval(vp[i]); for i in 0..argc LIns *slots_ins = NULL; @@ -11241,14 +10775,8 @@ TraceRecorder::propagateFailureToBuiltinStatus(LIns* ok_ins, LIns*& status_ins) */ JS_STATIC_ASSERT(((JS_TRUE & 1) ^ 1) << 1 == 0); JS_STATIC_ASSERT(((JS_FALSE & 1) ^ 1) << 1 == BUILTIN_ERROR); - status_ins = lir->ins2(LIR_ori, - status_ins, - lir->ins2ImmI(LIR_lshi, - lir->ins2ImmI(LIR_xori, - lir->ins2ImmI(LIR_andi, ok_ins, 1), - 1), - 1)); - storeToState(status_ins, builtinStatus); + status_ins = w.ori(status_ins, w.lshiN(w.xoriN(w.andiN(ok_ins, 1), 1), 1)); + w.stStateField(status_ins, builtinStatus); } JS_REQUIRES_STACK void @@ -11261,8 +10789,8 @@ TraceRecorder::emitNativePropertyOp(const Shape* shape, LIns* obj_ins, enterDeepBailCall(); - storeToState(addr_boxed_val_ins, nativeVp); - storeToState(INS_CONST(1), nativeVpLen); + w.stStateField(addr_boxed_val_ins, nativeVp); + w.stStateField(w.nameImmi(1), nativeVpLen); CallInfo* ci = new (traceAlloc()) CallInfo(); ci->_address = uintptr_t(setflag ? shape->setterOp() : shape->getterOp()); @@ -11273,20 +10801,20 @@ TraceRecorder::emitNativePropertyOp(const Shape* shape, LIns* obj_ins, #ifdef DEBUG ci->_name = "JSPropertyOp"; #endif - LIns* args[] = { addr_boxed_val_ins, INS_CONSTID(SHAPE_USERID(shape)), obj_ins, cx_ins }; - LIns* ok_ins = lir->insCall(ci, args); + LIns* args[] = { addr_boxed_val_ins, w.immpIdGC(SHAPE_USERID(shape)), obj_ins, cx_ins }; + LIns* ok_ins = w.call(ci, args); // Cleanup. Immediately clear nativeVp before we might deep bail. - storeToState(INS_NULL(), nativeVp); + w.stStateField(w.immpNull(), nativeVp); leaveDeepBailCall(); // Guard that the call succeeded and builtinStatus is still 0. // If the native op succeeds but we deep-bail here, the result value is // lost! Therefore this can only be used for setters of shared properties. // In that case we ignore the result value anyway. - LIns* status_ins = loadFromState(LIR_ldi, builtinStatus); + LIns* status_ins = w.ldiStateField(builtinStatus); propagateFailureToBuiltinStatus(ok_ins, status_ins); - guard(true, lir->insEqI_0(status_ins), STATUS_EXIT); + guard(true, w.eqi0(status_ins), STATUS_EXIT); } JS_REQUIRES_STACK RecordingStatus @@ -11301,23 +10829,23 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[], enterDeepBailCall(); } - LIns* res_ins = lir->insCall(sn->builtin, args); + LIns* res_ins = w.call(sn->builtin, args); // Immediately unroot the vp as soon we return since we might deep bail next. if (rooted) - storeToState(INS_NULL(), nativeVp); + w.stStateField(w.immpNull(), nativeVp); rval_ins = res_ins; switch (JSTN_ERRTYPE(sn)) { case FAIL_NULL: - guard(false, lir->insEqP_0(res_ins), OOM_EXIT); + guard(false, w.eqp0(res_ins), OOM_EXIT); break; case FAIL_NEG: - res_ins = lir->ins1(LIR_i2d, res_ins); - guard(false, lir->ins2(LIR_ltd, res_ins, lir->insImmD(0)), OOM_EXIT); + res_ins = w.i2d(res_ins); + guard(false, w.ltdN(res_ins, 0), OOM_EXIT); break; case FAIL_NEITHER: - guard(false, lir->ins2ImmI(LIR_eqi, res_ins, JS_NEITHER), OOM_EXIT); + guard(false, w.eqiN(res_ins, JS_NEITHER), OOM_EXIT); break; default:; } @@ -11384,19 +10912,19 @@ TraceRecorder::callSpecializedNative(JSNativeTraceInfo *trcinfo, uintN argc, goto next_specialization; *argp = this_ins; } else if (argtype == 'f') { - *argp = INS_CONSTOBJ(&fval.toObject()); + *argp = w.immpObjGC(&fval.toObject()); } else if (argtype == 'p') { CHECK_STATUS(getClassPrototype(&fval.toObject(), *argp)); } else if (argtype == 'R') { - *argp = INS_CONSTPTR(cx->runtime); + *argp = w.nameImmpNonGC(cx->runtime); } else if (argtype == 'P') { // FIXME: Set pc to imacpc when recording JSOP_CALL inside the // JSOP_GETELEM imacro (bug 476559). if ((*pc == JSOP_CALL) && fp->hasImacropc() && *fp->imacropc() == JSOP_GETELEM) - *argp = INS_CONSTPTR(fp->imacropc()); + *argp = w.nameImmpNonGC(fp->imacropc()); else - *argp = INS_CONSTPTR(pc); + *argp = w.nameImmpNonGC(pc); } else if (argtype == 'D') { /* this, as a number */ if (!tval.isNumber()) goto next_specialization; @@ -11405,7 +10933,7 @@ TraceRecorder::callSpecializedNative(JSNativeTraceInfo *trcinfo, uintN argc, MathCache *mathCache = JS_THREAD_DATA(cx)->getMathCache(cx); if (!mathCache) return RECORD_ERROR; - *argp = INS_CONSTPTR(mathCache); + *argp = w.nameImmpNonGC(mathCache); } else { JS_NOT_REACHED("unknown prefix arg type"); } @@ -11486,15 +11014,15 @@ JS_REQUIRES_STACK RecordingStatus TraceRecorder::callFloatReturningInt(uintN argc, const nanojit::CallInfo *ci) { Value& arg = stackval(-1); - LIns* resptr_ins = lir->insAlloc(sizeof(int32)); + LIns* resptr_ins = w.allocp(sizeof(int32)); LIns* args[] = { resptr_ins, get(&arg) }; - LIns* fits_ins = lir->insCall(ci, args); + LIns* fits_ins = w.call(ci, args); - guard(false, lir->insEqI_0(fits_ins), OVERFLOW_EXIT); + guard(false, w.eqi0(fits_ins), OVERFLOW_EXIT); - LIns* res_ins = lir->insLoad(LIR_ldi, resptr_ins, 0, ACCSET_ALLOC); + LIns* res_ins = w.ldiAlloc(resptr_ins); - set(&stackval(0 - (2 + argc)), lir->ins1(LIR_i2d, res_ins)); + set(&stackval(0 - (2 + argc)), w.i2d(res_ins)); pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; @@ -11519,7 +11047,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) if (native == js_math_ceil || native == js_math_floor || native == js_math_round) { LIns* a = get(&vp[2]); int32 result; - if (isPromote(a)) { + if (IsPromote(a)) { set(&vp[0], a); pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return RECORD_CONTINUE; @@ -11536,18 +11064,16 @@ TraceRecorder::callNative(uintN argc, JSOp mode) } } else if (native == js_math_abs) { LIns* a = get(&vp[2]); - if (isPromoteInt(a)) { - a = demote(lir, a); + if (IsPromoteInt(a)) { + a = w.demote(a); /* abs(INT_MIN) can't be done using integers; exit if we see it. */ - LIns* intMin_ins = addName(lir->insImmI(0x80000000), "INT_MIN"); - LIns* isIntMin_ins = addName(lir->ins2(LIR_eqi, a, intMin_ins), "isIntMin"); + LIns* intMin_ins = w.name(w.immi(0x80000000), "INT_MIN"); + LIns* isIntMin_ins = w.name(w.eqi(a, intMin_ins), "isIntMin"); guard(false, isIntMin_ins, MISMATCH_EXIT); - LIns* neg_ins = lir->ins1(LIR_negi, a); - LIns* isNeg_ins = addName(lir->ins2ImmI(LIR_lti, a, 0), "isNeg"); - LIns* abs_ins = addName(lir->insChoose(isNeg_ins, neg_ins, a, - avmplus::AvmCore::use_cmov()), - "abs"); - set(&vp[0], i2d(abs_ins)); + LIns* neg_ins = w.negi(a); + LIns* isNeg_ins = w.name(w.ltiN(a, 0), "isNeg"); + LIns* abs_ins = w.name(w.cmovi(isNeg_ins, neg_ins, a), "abs"); + set(&vp[0], w.i2d(abs_ins)); pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return RECORD_CONTINUE; } @@ -11640,15 +11166,11 @@ TraceRecorder::callNative(uintN argc, JSOp mode) (native == js_math_min || native == js_math_max)) { LIns* a = get(&vp[2]); LIns* b = get(&vp[3]); - if (isPromote(a) && isPromote(b)) { - a = demote(lir, a); - b = demote(lir, b); - set(&vp[0], - lir->ins1(LIR_i2d, - lir->insChoose(lir->ins2((native == js_math_min) - ? LIR_lti - : LIR_gti, a, b), - a, b, avmplus::AvmCore::use_cmov()))); + if (IsPromote(a) && IsPromote(b)) { + a = w.demote(a); + b = w.demote(b); + LIns* cmp = (native == js_math_min) ? w.lti(a, b) : w.gti(a, b); + set(&vp[0], w.i2d(w.cmovi(cmp, a, b))); pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return RECORD_CONTINUE; } @@ -11673,10 +11195,10 @@ TraceRecorder::callNative(uintN argc, JSOp mode) // Allocate the vp vector and emit code to root it. uintN vplen = 2 + argc; - LIns* invokevp_ins = lir->insAlloc(vplen * sizeof(Value)); + LIns* invokevp_ins = w.allocp(vplen * sizeof(Value)); // vp[0] is the callee. - box_value_into(vp[0], INS_CONSTOBJ(funobj), invokevp_ins, 0, ACCSET_ALLOC); + box_value_into(vp[0], w.immpObjGC(funobj), AllocSlotsAddress(invokevp_ins)); // Calculate |this|. LIns* this_ins; @@ -11698,16 +11220,16 @@ TraceRecorder::callNative(uintN argc, JSOp mode) if (fun->isConstructor()) { vp[1].setMagicWithObjectOrNullPayload(NULL); - newobj_ins = INS_MAGIC_NULL(); + newobj_ins = w.immpMagicNull(); /* Treat this as a regular call, the constructor will behave correctly. */ mode = JSOP_CALL; } else { - args[0] = INS_CONSTOBJ(funobj); - args[1] = INS_CONSTPTR(clasp); + args[0] = w.immpObjGC(funobj); + args[1] = w.nameImmpNonGC(clasp); args[2] = cx_ins; - newobj_ins = lir->insCall(&js_CreateThisFromTrace_ci, args); - guard(false, lir->insEqP_0(newobj_ins), OOM_EXIT); + newobj_ins = w.call(&js_CreateThisFromTrace_ci, args); + guard(false, w.eqp0(newobj_ins), OOM_EXIT); /* * emitNativeCall may take a snapshot below. To avoid having a type @@ -11725,11 +11247,11 @@ TraceRecorder::callNative(uintN argc, JSOp mode) this_ins = get(&vp[1]); } set(&vp[1], this_ins); - box_value_into(vp[1], this_ins, invokevp_ins, 1 * sizeof(Value), ACCSET_ALLOC); + box_value_into(vp[1], this_ins, AllocSlotsAddress(invokevp_ins, 1)); // Populate argv. for (uintN n = 2; n < 2 + argc; n++) { - box_value_into(vp[n], get(&vp[n]), invokevp_ins, n * sizeof(Value), ACCSET_ALLOC); + box_value_into(vp[n], get(&vp[n]), AllocSlotsAddress(invokevp_ins, n)); // For a very long argument list we might run out of LIR space, so // check inside the loop. if (outOfMemory()) @@ -11739,7 +11261,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) // Populate extra slots, including the return value slot for a slow native. if (2 + argc < vplen) { for (uintN n = 2 + argc; n < vplen; n++) { - box_undefined_into(invokevp_ins, n * sizeof(Value), ACCSET_ALLOC); + box_undefined_into(AllocSlotsAddress(invokevp_ins, n)); if (outOfMemory()) RETURN_STOP("out of memory in extra slots"); } @@ -11750,7 +11272,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) RETURN_STOP("untraceable fast native constructor"); native_rval_ins = invokevp_ins; args[0] = invokevp_ins; - args[1] = lir->insImmI(argc); + args[1] = w.immi(argc); args[2] = cx_ins; uint32 typesig = CallInfo::typeSig3(ARGTYPE_I, ARGTYPE_P, ARGTYPE_I, ARGTYPE_P); @@ -11781,8 +11303,8 @@ TraceRecorder::callNative(uintN argc, JSOp mode) // nativeVpLen immediately before emitting the call code. This way we avoid // leaving trace with a bogus nativeVp because we fall off trace while unboxing // values into the stack buffer. - storeToState(INS_CONST(vplen), nativeVpLen); - storeToState(invokevp_ins, nativeVp); + w.stStateField(w.nameImmi(vplen), nativeVpLen); + w.stStateField(invokevp_ins, nativeVp); // argc is the original argc here. It is used to calculate where to place // the return value. @@ -11824,9 +11346,9 @@ TraceRecorder::functionCall(uintN argc, JSOp mode) if (cx->functionCallback) { JSScript *script = FUN_SCRIPT(fun); if (! script || ! script->isEmpty()) { - LIns* args[] = { INS_CONST(1), INS_CONSTPTR(fun), cx_ins }; - LIns* call_ins = lir->insCall(&functionProbe_ci, args); - guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT); + LIns* args[] = { w.nameImmi(1), w.nameImmpNonGC(fun), cx_ins }; + LIns* call_ins = w.call(&functionProbe_ci, args); + guard(false, w.eqi0(call_ins), MISMATCH_EXIT); } } #endif @@ -11853,9 +11375,9 @@ TraceRecorder::functionCall(uintN argc, JSOp mode) RecordingStatus rs = callNative(argc, mode); #ifdef MOZ_TRACE_JSCALLS if (cx->functionCallback) { - LIns* args[] = { INS_CONST(0), INS_CONSTPTR(fun), cx_ins }; - LIns* call_ins = lir->insCall(&functionProbe_ci, args); - guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT); + LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(fun), cx_ins }; + LIns* call_ins = w.call(&functionProbe_ci, args); + guard(false, w.eqi0(call_ins), MISMATCH_EXIT); } #endif return rs; @@ -11928,11 +11450,11 @@ TraceRecorder::record_JSOP_DELPROP() JSAtom* atom = atoms[GET_INDEX(cx->regs->pc)]; enterDeepBailCall(); - LIns* args[] = { strictModeCode_ins, INS_ATOM(atom), get(&lval), cx_ins }; - LIns* rval_ins = lir->insCall(&DeleteStrKey_ci, args); + LIns* args[] = { strictModeCode_ins, w.immpAtomGC(atom), get(&lval), cx_ins }; + LIns* rval_ins = w.call(&DeleteStrKey_ci, args); - LIns* status_ins = loadFromState(LIR_ldi, builtinStatus); - pendingGuardCondition = lir->insEqI_0(status_ins); + LIns* status_ins = w.ldiStateField(builtinStatus); + pendingGuardCondition = w.eqi0(status_ins); leaveDeepBailCall(); set(&lval, rval_ins); @@ -11956,16 +11478,16 @@ TraceRecorder::record_JSOP_DELELEM() LIns* num_ins; CHECK_STATUS_A(makeNumberInt32(get(&idx), &num_ins)); LIns* args[] = { strictModeCode_ins, num_ins, get(&lval), cx_ins }; - rval_ins = lir->insCall(&DeleteIntKey_ci, args); + rval_ins = w.call(&DeleteIntKey_ci, args); } else if (idx.isString()) { LIns* args[] = { strictModeCode_ins, get(&idx), get(&lval), cx_ins }; - rval_ins = lir->insCall(&DeleteStrKey_ci, args); + rval_ins = w.call(&DeleteStrKey_ci, args); } else { RETURN_STOP_A("JSOP_DELELEM on non-int, non-string index"); } - LIns* status_ins = loadFromState(LIR_ldi, builtinStatus); - pendingGuardCondition = lir->insEqI_0(status_ins); + LIns* status_ins = w.ldiStateField(builtinStatus); + pendingGuardCondition = w.eqi0(status_ins); leaveDeepBailCall(); set(&lval, rval_ins); @@ -11978,21 +11500,21 @@ TraceRecorder::record_JSOP_TYPEOF() Value& r = stackval(-1); LIns* type; if (r.isString()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_STRING]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_STRING]); } else if (r.isNumber()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]); } else if (r.isUndefined()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]); } else if (r.isBoolean()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_BOOLEAN]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_BOOLEAN]); } else if (r.isNull()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_OBJECT]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_OBJECT]); } else { if (r.toObject().isFunction()) { - type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_FUNCTION]); + type = w.immpAtomGC(cx->runtime->atomState.typeAtoms[JSTYPE_FUNCTION]); } else { LIns* args[] = { get(&r), cx_ins }; - type = lir->insCall(&js_TypeOfObject_ci, args); + type = w.call(&js_TypeOfObject_ci, args); } } set(&r, type); @@ -12002,7 +11524,7 @@ TraceRecorder::record_JSOP_TYPEOF() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_VOID() { - stack(-1, INS_UNDEFINED()); + stack(-1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -12247,9 +11769,9 @@ TraceRecorder::setProp(Value &l, PropertyCacheEntry* entry, const Shape* shape, * the given object, so forget anything we knew about obj's shape. */ guardedShapeTable.remove(obj_ins); - LIns* args[] = { v_ins, INS_CONSTSHAPE(shape), obj_ins, cx_ins }; - LIns* ok_ins = lir->insCall(&MethodWriteBarrier_ci, args); - guard(false, lir->insEqI_0(ok_ins), OOM_EXIT); + LIns* args[] = { v_ins, w.immpShapeGC(shape), obj_ins, cx_ins }; + LIns* ok_ins = w.call(&MethodWriteBarrier_ci, args); + guard(false, w.eqi0(ok_ins), OOM_EXIT); } // Add a property to the object if necessary. @@ -12258,10 +11780,10 @@ TraceRecorder::setProp(Value &l, PropertyCacheEntry* entry, const Shape* shape, if (obj == globalObj) RETURN_STOP("adding a property to the global object"); - LIns* args[] = { INS_CONSTSHAPE(shape), obj_ins, cx_ins }; + LIns* args[] = { w.immpShapeGC(shape), obj_ins, cx_ins }; const CallInfo *ci = isDefinitelyAtom ? &js_AddAtomProperty_ci : &js_AddProperty_ci; - LIns* ok_ins = lir->insCall(ci, args); - guard(false, lir->insEqI_0(ok_ins), OOM_EXIT); + LIns* ok_ins = w.call(ci, args); + guard(false, w.eqi0(ok_ins), OOM_EXIT); } return nativeSet(obj, obj_ins, shape, v, v_ins); @@ -12276,7 +11798,7 @@ TraceRecorder::setUpwardTrackedVar(Value* stackVp, const Value &v, LIns* v_ins) bool promote = true; if (stackT != otherT) { - if (stackT == JSVAL_TYPE_DOUBLE && otherT == JSVAL_TYPE_INT32 && isPromoteInt(v_ins)) + if (stackT == JSVAL_TYPE_DOUBLE && otherT == JSVAL_TYPE_INT32 && IsPromoteInt(v_ins)) promote = false; else RETURN_STOP("can't trace this upvar mutation"); @@ -12355,17 +11877,17 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, const Shape *sh // inner trace such that the target variable is defined in the outer trace // entry frame. For simplicity, we just fall off trace. guard(false, - lir->ins2(LIR_eqp, entryFrameIns(), stobj_get_private(callobj_ins)), + w.eqp(entryFrameIns(), w.ldpObjPrivate(callobj_ins)), MISMATCH_EXIT); LIns* args[] = { box_value_for_native_call(v, v_ins), - INS_CONSTWORD(JSID_BITS(SHAPE_USERID(shape))), + w.nameImmw(JSID_BITS(SHAPE_USERID(shape))), callobj_ins, cx_ins }; - LIns* call_ins = lir->insCall(ci, args); - guard(false, addName(lir->insEqI_0(call_ins), "guard(set upvar)"), STATUS_EXIT); + LIns* call_ins = w.call(ci, args); + guard(false, w.name(w.eqi0(call_ins), "guard(set upvar)"), STATUS_EXIT); return RECORD_CONTINUE; } @@ -12402,11 +11924,10 @@ TraceRecorder::enterDeepBailCall() { // Take snapshot for DeepBail and store it in cx->bailExit. VMSideExit* exit = snapshot(DEEP_BAIL_EXIT); - lir->insStore(INS_CONSTPTR(exit), cx_ins, offsetof(JSContext, bailExit), ACCSET_CX); + w.stContextField(w.nameImmpNonGC(exit), bailExit); // Tell nanojit not to discard or defer stack writes before this call. - GuardRecord* guardRec = createGuardRecord(exit); - lir->insGuard(LIR_xbarrier, NULL, guardRec); + w.xbarrier(createGuardRecord(exit)); // Forget about guarded shapes, since deep bailers can reshape the world. forgetGuardedShapes(); @@ -12417,7 +11938,7 @@ JS_REQUIRES_STACK void TraceRecorder::leaveDeepBailCall() { // Keep cx->bailExit null when it's invalid. - lir->insStore(INS_NULL(), cx_ins, offsetof(JSContext, bailExit), ACCSET_CX); + w.stContextField(w.immpNull(), bailExit); } JS_REQUIRES_STACK void @@ -12428,7 +11949,7 @@ TraceRecorder::finishGetProp(LIns* obj_ins, LIns* vp_ins, LIns* ok_ins, Value* o // these slots will be ignored anyway. // N.B. monitorRecording expects get(outp)->isLoad() JS_ASSERT(vp_ins->isop(LIR_allocp)); - LIns* result_ins = lir->insLoad(LIR_ldd, vp_ins, 0, ACCSET_ALLOC); + LIns* result_ins = w.lddAlloc(vp_ins); set(outp, result_ins); if (js_CodeSpec[*cx->regs->pc].format & JOF_CALLOP) set(outp + 1, obj_ins); @@ -12580,19 +12101,19 @@ TraceRecorder::getPropertyByName(LIns* obj_ins, Value* idvalp, Value* outp) // Call GetPropertyByName. The vp parameter points to stack because this is // what the interpreter currently does. obj and id are rooted on the // interpreter stack, but the slot at vp is not a root. - LIns* vp_ins = addName(lir->insAlloc(sizeof(Value)), "vp"); - LIns* idvalp_ins = addName(addr(idvalp), "idvalp"); + LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp"); + LIns* idvalp_ins = w.name(addr(idvalp), "idvalp"); PICTable *picTable = new (traceAlloc()) PICTable(); - LIns* pic_ins = INS_CONSTPTR(picTable); + LIns* pic_ins = w.nameImmpNonGC(picTable); LIns* args[] = {pic_ins, vp_ins, idvalp_ins, obj_ins, cx_ins}; - LIns* ok_ins = lir->insCall(&GetPropertyByName_ci, args); + LIns* ok_ins = w.call(&GetPropertyByName_ci, args); // GetPropertyByName can assign to *idvalp, so the tracker has an incorrect // entry for that address. Correct it. (If the value in the address is // never used again, the usual case, Nanojit will kill this load.) - // The AccSet could be made more precise with some effort (idvalp_ins may - // equal 'sp+k'), but it's not worth it because this case is rare. - tracker.set(idvalp, lir->insLoad(LIR_ldp, idvalp_ins, 0, ACCSET_LOAD_ANY)); + // The Address could be made more precise with some effort (idvalp_ins may + // be a stack location), but it's not worth it because this case is rare. + tracker.set(idvalp, w.ldp(AnyAddress(idvalp_ins))); finishGetProp(obj_ins, vp_ins, ok_ins, outp); leaveDeepBailCall(); @@ -12621,9 +12142,9 @@ TraceRecorder::getPropertyByIndex(LIns* obj_ins, LIns* index_ins, Value* outp) // See note in getPropertyByName about vp. enterDeepBailCall(); - LIns* vp_ins = addName(lir->insAlloc(sizeof(Value)), "vp"); + LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp"); LIns* args[] = {vp_ins, index_ins, obj_ins, cx_ins}; - LIns* ok_ins = lir->insCall(&GetPropertyByIndex_ci, args); + LIns* ok_ins = w.call(&GetPropertyByIndex_ci, args); finishGetProp(obj_ins, vp_ins, ok_ins, outp); leaveDeepBailCall(); return RECORD_CONTINUE; @@ -12663,9 +12184,9 @@ TraceRecorder::getPropertyById(LIns* obj_ins, Value* outp) // Call GetPropertyById. See note in getPropertyByName about vp. enterDeepBailCall(); - LIns* vp_ins = addName(lir->insAlloc(sizeof(Value)), "vp"); - LIns* args[] = {vp_ins, INS_CONSTWORD(JSID_BITS(id)), obj_ins, cx_ins}; - LIns* ok_ins = lir->insCall(&GetPropertyById_ci, args); + LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp"); + LIns* args[] = {vp_ins, w.nameImmw(JSID_BITS(id)), obj_ins, cx_ins}; + LIns* ok_ins = w.call(&GetPropertyById_ci, args); finishGetProp(obj_ins, vp_ins, ok_ins, outp); leaveDeepBailCall(); return RECORD_CONTINUE; @@ -12710,9 +12231,9 @@ TraceRecorder::getPropertyWithNativeGetter(LIns* obj_ins, const Shape* shape, Va // FIXME - We should call the getter directly. Using a builtin function for // now because it buys some extra asserts. See bug 508310. enterDeepBailCall(); - LIns* vp_ins = addName(lir->insAlloc(sizeof(Value)), "vp"); - LIns* args[] = {vp_ins, INS_CONSTPTR(shape), obj_ins, cx_ins}; - LIns* ok_ins = lir->insCall(&GetPropertyWithNativeGetter_ci, args); + LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp"); + LIns* args[] = {vp_ins, w.nameImmpNonGC(shape), obj_ins, cx_ins}; + LIns* ok_ins = w.call(&GetPropertyWithNativeGetter_ci, args); finishGetProp(obj_ins, vp_ins, ok_ins, outp); leaveDeepBailCall(); return RECORD_CONTINUE; @@ -12735,13 +12256,13 @@ TraceRecorder::getPropertyWithScriptGetter(JSObject *obj, LIns* obj_ins, const S sp[-1] = sp[-2]; set(&sp[-1], get(&sp[-2])); sp[-2] = getter; - set(&sp[-2], INS_CONSTOBJ(&getter.toObject())); + set(&sp[-2], w.immpObjGC(&getter.toObject())); return callImacroInfallibly(getprop_imacros.scriptgetter); case JSOP_CALLPROP: sp += 2; sp[-2] = getter; - set(&sp[-2], INS_CONSTOBJ(&getter.toObject())); + set(&sp[-2], w.immpObjGC(&getter.toObject())); sp[-1] = sp[-3]; set(&sp[-1], get(&sp[-3])); return callImacroInfallibly(callprop_imacros.scriptgetter); @@ -12751,7 +12272,7 @@ TraceRecorder::getPropertyWithScriptGetter(JSObject *obj, LIns* obj_ins, const S case JSOP_GETLOCALPROP: sp += 2; sp[-2] = getter; - set(&sp[-2], INS_CONSTOBJ(&getter.toObject())); + set(&sp[-2], w.immpObjGC(&getter.toObject())); sp[-1] = ObjectValue(*obj); set(&sp[-1], obj_ins); return callImacroInfallibly(getthisprop_imacros.scriptgetter); @@ -12761,55 +12282,22 @@ TraceRecorder::getPropertyWithScriptGetter(JSObject *obj, LIns* obj_ins, const S } } -JS_REQUIRES_STACK LIns* -TraceRecorder::getStringLengthAndFlags(LIns* str_ins) -{ - return addName(lir->insLoad(LIR_ldp, str_ins, offsetof(JSString, mLengthAndFlags), - ACCSET_STRING), - "mLengthAndFlags"); -} - -JS_REQUIRES_STACK LIns* -TraceRecorder::getStringLength(LIns* str_ins) -{ - return addName(lir->ins2ImmI(LIR_rshup, getStringLengthAndFlags(str_ins), - JSString::FLAGS_LENGTH_SHIFT), - "length"); -} - -JS_REQUIRES_STACK LIns* -TraceRecorder::getStringChars(LIns* str_ins) -{ - return addName(lir->insLoad(LIR_ldp, str_ins, - offsetof(JSString, mChars), - ACCSET_STRING), "mChars"); -} - JS_REQUIRES_STACK RecordingStatus TraceRecorder::getCharCodeAt(JSString *str, LIns* str_ins, LIns* idx_ins, LIns** out) { CHECK_STATUS(makeNumberInt32(idx_ins, &idx_ins)); - idx_ins = lir->insUI2P(idx_ins); - LIns *lengthAndFlags_ins = getStringLengthAndFlags(str_ins); - LIns *br; - if (condBranch(LIR_jt, - lir->insEqP_0(lir->ins2(LIR_andp, - lengthAndFlags_ins, - INS_CONSTWORD(JSString::ROPE_BIT))), - &br)) + idx_ins = w.ui2p(idx_ins); + LIns *lengthAndFlags_ins = w.name(w.ldpStringLengthAndFlags(str_ins), "mLengthAndFlags"); + if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins, w.nameImmw(JSString::ROPE_BIT))))) { - lir->insCall(&js_Flatten_ci, &str_ins); - labelForBranch(br); + w.call(&js_Flatten_ci, &str_ins); + w.label(mbr); } guard(true, - lir->ins2(LIR_ltup, idx_ins, lir->ins2ImmI(LIR_rshup, lengthAndFlags_ins, - JSString::FLAGS_LENGTH_SHIFT)), + w.ltup(idx_ins, w.rshupN(lengthAndFlags_ins, JSString::FLAGS_LENGTH_SHIFT)), snapshot(MISMATCH_EXIT)); - LIns *chars_ins = getStringChars(str_ins); - *out = i2d(lir->insLoad(LIR_ldus2ui, - lir->ins2(LIR_addp, chars_ins, lir->ins2ImmI(LIR_lshp, idx_ins, 1)), 0, - ACCSET_STRING_MCHARS, LOAD_CONST)); + *out = w.i2d(w.getStringChar(str_ins, idx_ins)); return RECORD_CONTINUE; } @@ -12819,58 +12307,41 @@ JS_STATIC_ASSERT(sizeof(JSString) == 16 || sizeof(JSString) == 32); JS_REQUIRES_STACK LIns* TraceRecorder::getUnitString(LIns* str_ins, LIns* idx_ins) { - LIns *chars_ins = getStringChars(str_ins); - LIns *ch_ins = lir->insLoad(LIR_ldus2ui, - lir->ins2(LIR_addp, - chars_ins, - lir->ins2ImmI(LIR_lshp, idx_ins, 1)), - 0, ACCSET_STRING_MCHARS, LOAD_CONST); - guard(true, lir->ins2ImmI(LIR_ltui, ch_ins, UNIT_STRING_LIMIT), snapshot(MISMATCH_EXIT)); - return lir->ins2(LIR_addp, - INS_CONSTPTR(JSString::unitStringTable), - lir->ins2ImmI(LIR_lshp, - lir->insUI2P(ch_ins), - (sizeof(JSString) == 16) ? 4 : 5)); + LIns *ch_ins = w.getStringChar(str_ins, idx_ins); + guard(true, w.ltuiN(ch_ins, UNIT_STRING_LIMIT), MISMATCH_EXIT); + return w.addp(w.nameImmpNonGC(JSString::unitStringTable), + w.lshpN(w.ui2p(ch_ins), (sizeof(JSString) == 16) ? 4 : 5)); } JS_REQUIRES_STACK RecordingStatus TraceRecorder::getCharAt(JSString *str, LIns* str_ins, LIns* idx_ins, JSOp mode, LIns** out) { CHECK_STATUS(makeNumberInt32(idx_ins, &idx_ins)); - idx_ins = lir->insUI2P(idx_ins); - LIns *length_ins = lir->insLoad(LIR_ldp, str_ins, offsetof(JSString, mLengthAndFlags), - ACCSET_STRING); - - LIns *br1; - if (condBranch(LIR_jt, - lir->insEqP_0(lir->ins2(LIR_andp, - length_ins, - INS_CONSTWORD(JSString::ROPE_BIT))), - &br1)) + idx_ins = w.ui2p(idx_ins); + LIns *lengthAndFlags_ins = w.ldpStringLengthAndFlags(str_ins); + if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins, + w.nameImmw(JSString::ROPE_BIT))))) { - lir->insCall(&js_Flatten_ci, &str_ins); - labelForBranch(br1); + w.call(&js_Flatten_ci, &str_ins); + w.label(mbr); } - LIns* inRange = lir->ins2(LIR_ltup, - idx_ins, - lir->ins2ImmI(LIR_rshup, length_ins, JSString::FLAGS_LENGTH_SHIFT)); + LIns* inRange = w.ltup(idx_ins, w.rshupN(lengthAndFlags_ins, JSString::FLAGS_LENGTH_SHIFT)); if (mode == JSOP_GETELEM) { guard(true, inRange, MISMATCH_EXIT); *out = getUnitString(str_ins, idx_ins); } else { - LIns *phi_ins = lir->insAlloc(sizeof(JSString *)); - lir->insStore(LIR_stp, INS_CONSTSTR(cx->runtime->emptyString), phi_ins, 0, ACCSET_ALLOC); + LIns *phi_ins = w.allocp(sizeof(JSString *)); + w.stAlloc(w.nameImmpNonGC(cx->runtime->emptyString), phi_ins); - LIns* br2; - if (condBranch(LIR_jf, inRange, &br2)) { + if (MaybeBranch mbr = w.jf(inRange)) { LIns *unitstr_ins = getUnitString(str_ins, idx_ins); - lir->insStore(LIR_stp, unitstr_ins, phi_ins, 0, ACCSET_ALLOC); - labelForBranch(br2); + w.stAlloc(unitstr_ins, phi_ins); + w.label(mbr); } - *out = lir->insLoad(LIR_ldp, phi_ins, 0, ACCSET_ALLOC); + *out = w.ldpAlloc(phi_ins); } return RECORD_CONTINUE; } @@ -12886,14 +12357,13 @@ JS_REQUIRES_STACK void TraceRecorder::guardNotHole(LIns *argsobj_ins, LIns *idx_ins) { // vp = &argsobj->slots[JSSLOT_ARGS_DATA].slots[idx] - LIns* argsData_ins = stobj_get_const_private_ptr(argsobj_ins, JSObject::JSSLOT_ARGS_DATA); - LIns* slotOffset_ins = lir->ins2(LIR_addp, - INS_CONSTWORD(offsetof(ArgumentsData, slots)), - lir->insUI2P(lir->ins2ImmI(LIR_muli, idx_ins, sizeof(Value)))); - LIns* vp_ins = lir->ins2(LIR_addp, argsData_ins, slotOffset_ins); + LIns* argsData_ins = w.getObjPrivatizedSlot(argsobj_ins, JSObject::JSSLOT_ARGS_DATA); + LIns* slotOffset_ins = w.addp(w.nameImmw(offsetof(ArgumentsData, slots)), + w.ui2p(w.muliN(idx_ins, sizeof(Value)))); + LIns* vp_ins = w.addp(argsData_ins, slotOffset_ins); guard(false, - addName(is_boxed_magic(vp_ins, JS_ARGS_HOLE, ACCSET_ARGS_DATA), "guard(not deleted arg)"), + w.name(is_boxed_magic(ArgsSlotsAddress(vp_ins), JS_ARGS_HOLE), "guard(not deleted arg)"), MISMATCH_EXIT); } @@ -12953,7 +12423,7 @@ TraceRecorder::record_JSOP_GETELEM() Value* vp = &afp->canonicalActualArg(int_idx); if (idx_ins->isImmD()) { JS_ASSERT(int_idx == (int32)idx_ins->immD()); - guardNotHole(obj_ins, INS_CONST(int_idx)); + guardNotHole(obj_ins, w.nameImmi(int_idx)); v_ins = get(vp); } else { // If the index is not a constant expression, we generate LIR to load the value from @@ -12966,8 +12436,8 @@ TraceRecorder::record_JSOP_GETELEM() * 0 <= int_idx < nactual iff unsigned(int_idx) < unsigned(nactual). */ guard(true, - addName(lir->ins2(LIR_ltui, idx_ins, INS_CONSTU(afp->numActualArgs())), - "guard(upvar index in range)"), + w.name(w.ltui(idx_ins, w.nameImmui(afp->numActualArgs())), + "guard(upvar index in range)"), MISMATCH_EXIT); guardNotHole(obj_ins, idx_ins); @@ -12984,43 +12454,33 @@ TraceRecorder::record_JSOP_GETELEM() JSValueType* typemap = new (traceAlloc()) JSValueType[stackSlots]; DetermineTypesVisitor detVisitor(*this, typemap); VisitStackSlots(detVisitor, cx, 0); - typemap_ins = INS_CONSTPTR(typemap + 2 /* callee, this */); + typemap_ins = w.nameImmpNonGC(typemap + 2 /* callee, this */); } else { // In this case, we are in a deeper frame from where the arguments object was // created. The type map at the point of the call out from the creation frame // is accurate. // Note: this relies on the assumption that we abort on setting an element of // an arguments object in any deeper frame. - LIns* fip_ins = lir->insLoad(LIR_ldp, lirbuf->rp, - (callDepth-depth)*sizeof(FrameInfo*), - ACCSET_RSTACK); - typemap_ins = lir->ins2(LIR_addp, fip_ins, INS_CONSTWORD(sizeof(FrameInfo) + 2/*callee,this*/ * sizeof(JSValueType))); + LIns* fip_ins = w.ldpRstack(lirbuf->rp, (callDepth-depth)*sizeof(FrameInfo*)); + typemap_ins = w.addp(fip_ins, w.nameImmw(sizeof(FrameInfo) + 2/*callee,this*/ * sizeof(JSValueType))); } - LIns* typep_ins = lir->ins2(LIR_addp, typemap_ins, - lir->insUI2P(lir->ins2(LIR_muli, - idx_ins, - INS_CONST(sizeof(JSValueType))))); - LIns* type_ins = lir->insLoad(LIR_lduc2ui, typep_ins, 0, ACCSET_TYPEMAP, LOAD_CONST); + LIns* type_ins = w.lduc2uiConstTypeMapEntry(typemap_ins, idx_ins); guard(true, - addName(lir->ins2(LIR_eqi, type_ins, lir->insImmI(type)), - "guard(type-stable upvar)"), + w.name(w.eqi(type_ins, w.immi(type)), "guard(type-stable upvar)"), BRANCH_EXIT); // Read the value out of the native stack area. size_t stackOffset = nativespOffset(&afp->canonicalActualArg(0)); - LIns* args_addr_ins = lir->ins2(LIR_addp, lirbuf->sp, INS_CONSTWORD(stackOffset)); - LIns* argi_addr_ins = lir->ins2(LIR_addp, - args_addr_ins, - lir->insUI2P(lir->ins2(LIR_muli, - idx_ins, - INS_CONST(sizeof(double))))); + LIns* args_addr_ins = w.addp(lirbuf->sp, w.nameImmw(stackOffset)); + LIns* argi_addr_ins = w.addp(args_addr_ins, + w.ui2p(w.muli(idx_ins, w.nameImmi(sizeof(double))))); - // The AccSet could be more precise, but ValidateWriter + // The Address could be more precise, but ValidateWriter // doesn't recognise the complex expression involving 'sp' as - // an ACCSET_STACK access, and it's not worth the effort to be + // an stack access, and it's not worth the effort to be // more precise because this case is rare. - v_ins = stackLoad(argi_addr_ins, ACCSET_LOAD_ANY, type); + v_ins = stackLoad(AnyAddress(argi_addr_ins), type); } JS_ASSERT(v_ins); set(&lval, v_ins); @@ -13048,10 +12508,8 @@ TraceRecorder::record_JSOP_GETELEM() if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Fast path for typed arrays accessed with a integer index. Value* vp; - LIns* addr_ins; - guardClass(obj_ins, obj->getClass(), snapshot(BRANCH_EXIT), LOAD_CONST); - CHECK_STATUS_A(typedArrayElement(lval, idx, vp, v_ins, addr_ins)); + CHECK_STATUS_A(typedArrayElement(lval, idx, vp, v_ins)); set(&lval, v_ins); if (call) set(&idx, obj_ins); @@ -13103,16 +12561,16 @@ TraceRecorder::initOrSetPropertyByName(LIns* obj_ins, Value* idvalp, Value* rval if (init) { LIns* v_ins = box_value_for_native_call(*rvalp, get(rvalp)); enterDeepBailCall(); - LIns* idvalp_ins = addName(addr(idvalp), "idvalp"); + LIns* idvalp_ins = w.name(addr(idvalp), "idvalp"); LIns* args[] = {v_ins, idvalp_ins, obj_ins, cx_ins}; - pendingGuardCondition = lir->insCall(&InitPropertyByName_ci, args); + pendingGuardCondition = w.call(&InitPropertyByName_ci, args); } else { // See note in getPropertyByName about vp. LIns* vp_ins = box_value_into_alloc(*rvalp, get(rvalp)); enterDeepBailCall(); - LIns* idvalp_ins = addName(addr(idvalp), "idvalp"); + LIns* idvalp_ins = w.name(addr(idvalp), "idvalp"); LIns* args[] = { strictModeCode_ins, vp_ins, idvalp_ins, obj_ins, cx_ins }; - pendingGuardCondition = lir->insCall(&SetPropertyByName_ci, args); + pendingGuardCondition = w.call(&SetPropertyByName_ci, args); } leaveDeepBailCall(); @@ -13159,13 +12617,13 @@ TraceRecorder::initOrSetPropertyByIndex(LIns* obj_ins, LIns* index_ins, Value* r LIns* rval_ins = box_value_for_native_call(*rvalp, get(rvalp)); enterDeepBailCall(); LIns* args[] = {rval_ins, index_ins, obj_ins, cx_ins}; - pendingGuardCondition = lir->insCall(&InitPropertyByIndex_ci, args); + pendingGuardCondition = w.call(&InitPropertyByIndex_ci, args); } else { // See note in getPropertyByName about vp. LIns* vp_ins = box_value_into_alloc(*rvalp, get(rvalp)); enterDeepBailCall(); LIns* args[] = {strictModeCode_ins, vp_ins, index_ins, obj_ins, cx_ins}; - pendingGuardCondition = lir->insCall(&SetPropertyByIndex_ci, args); + pendingGuardCondition = w.call(&SetPropertyByIndex_ci, args); } leaveDeepBailCall(); @@ -13208,26 +12666,20 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) js::TypedArray* tarray = js::TypedArray::fromJSObject(obj); - LIns* priv_ins = stobj_get_private(obj_ins); + LIns* priv_ins = w.ldpObjPrivate(obj_ins); // The index was on the stack and is therefore a LIR float; force it to // be an integer. CHECK_STATUS_A(makeNumberInt32(idx_ins, &idx_ins)); // Ensure idx >= 0 && idx < length (by using uint32) - lir->insGuard(LIR_xf, - lir->ins2(LIR_ltui, - idx_ins, - lir->insLoad(LIR_ldi, priv_ins, js::TypedArray::lengthOffset(), - ACCSET_TARRAY, LOAD_CONST)), - createGuardRecord(snapshot(OVERFLOW_EXIT))); + guard(true, + w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), + OVERFLOW_EXIT); // We're now ready to store - LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset(), - ACCSET_TARRAY, LOAD_CONST); - LIns* pidx_ins = lir->insUI2P(idx_ins); - LIns* addr_ins = 0; - + LIns* data_ins = w.ldpConstTypedArrayData(priv_ins); + LIns* pidx_ins = w.ui2p(idx_ins); LIns* typed_v_ins = v_ins; // If it's not a number, convert objects to NaN, @@ -13235,17 +12687,17 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) // for those. if (!v.isNumber()) { if (v.isNull()) { - typed_v_ins = lir->insImmD(0); + typed_v_ins = w.immd(0); } else if (v.isUndefined()) { - typed_v_ins = lir->insImmD(js_NaN); + typed_v_ins = w.immd(js_NaN); } else if (v.isString()) { LIns* args[] = { typed_v_ins, cx_ins }; - typed_v_ins = lir->insCall(&js_StringToNumber_ci, args); + typed_v_ins = w.call(&js_StringToNumber_ci, args); } else if (v.isBoolean()) { JS_ASSERT(v.isBoolean()); - typed_v_ins = i2d(typed_v_ins); + typed_v_ins = w.i2d(typed_v_ins); } else { - typed_v_ins = lir->insImmD(js_NaN); + typed_v_ins = w.immd(js_NaN); } } @@ -13258,22 +12710,18 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT16: case js::TypedArray::TYPE_UINT32: - typed_v_ins = f2u(typed_v_ins); + typed_v_ins = d2u(typed_v_ins); break; case js::TypedArray::TYPE_UINT8_CLAMPED: - if (isPromoteInt(typed_v_ins)) { - typed_v_ins = demote(lir, typed_v_ins); - typed_v_ins = lir->insChoose(lir->ins2ImmI(LIR_lti, typed_v_ins, 0), - lir->insImmI(0), - lir->insChoose(lir->ins2ImmI(LIR_gti, - typed_v_ins, - 0xff), - lir->insImmI(0xff), - typed_v_ins, - avmplus::AvmCore::use_cmov()), - avmplus::AvmCore::use_cmov()); + if (IsPromoteInt(typed_v_ins)) { + typed_v_ins = w.demote(typed_v_ins); + typed_v_ins = w.cmovi(w.ltiN(typed_v_ins, 0), + w.immi(0), + w.cmovi(w.gtiN(typed_v_ins, 0xff), + w.immi(0xff), + typed_v_ins)); } else { - typed_v_ins = lir->insCall(&js_TypedArray_uint8_clamp_double_ci, &typed_v_ins); + typed_v_ins = w.call(&js_TypedArray_uint8_clamp_double_ci, &typed_v_ins); } break; case js::TypedArray::TYPE_FLOAT32: @@ -13288,26 +12736,21 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8_CLAMPED: case js::TypedArray::TYPE_UINT8: - addr_ins = lir->ins2(LIR_addp, data_ins, pidx_ins); - lir->insStore(LIR_sti2c, typed_v_ins, addr_ins, 0, ACCSET_TARRAY_DATA); + w.sti2cTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 1)); - lir->insStore(LIR_sti2s, typed_v_ins, addr_ins, 0, ACCSET_TARRAY_DATA); + w.sti2sTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; case js::TypedArray::TYPE_INT32: case js::TypedArray::TYPE_UINT32: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 2)); - lir->insStore(LIR_sti, typed_v_ins, addr_ins, 0, ACCSET_TARRAY_DATA); + w.stiTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; case js::TypedArray::TYPE_FLOAT32: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 2)); - lir->insStore(LIR_std2f, typed_v_ins, addr_ins, 0, ACCSET_TARRAY_DATA); + w.std2fTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; case js::TypedArray::TYPE_FLOAT64: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 3)); - lir->insStore(LIR_std, typed_v_ins, addr_ins, 0, ACCSET_TARRAY_DATA); + w.stdTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; default: JS_NOT_REACHED("Unknown typed array type in tracer"); @@ -13334,58 +12777,49 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex) // Grow the array if the index exceeds the capacity. This happens // rarely, eg. less than 1% of the time in SunSpider. - LIns* capacity_ins = - addName(lir->insLoad(LIR_ldi, obj_ins, - offsetof(JSObject, capacity), ACCSET_OBJ_CAPACITY), - "capacity"); + LIns* capacity_ins = w.ldiDenseArrayCapacity(obj_ins); /* - * It's important that CSE works around this control-flow diamond - * because it really helps series of GETELEM and SETELEM operations. - * Likewise with the diamond below. + * It's important that CSE works across this control-flow diamond + * because it really helps series of interleaved GETELEM and SETELEM + * operations. Likewise with the diamond below. */ - suspendCSE(); - LIns* br; - if (condBranch(LIR_jt, lir->ins2(LIR_ltui, idx_ins, capacity_ins), &br)) { + w.pauseAddingCSEValues(); + if (MaybeBranch mbr = w.jt(w.ltui(idx_ins, capacity_ins))) { LIns* args[] = { idx_ins, obj_ins, cx_ins }; - LIns* res_ins = lir->insCall(&js_EnsureDenseArrayCapacity_ci, args); - guard(false, lir->insEqI_0(res_ins), mismatchExit); - labelForBranch(br); + LIns* res_ins = w.call(&js_EnsureDenseArrayCapacity_ci, args); + guard(false, w.eqi0(res_ins), mismatchExit); + w.label(mbr); } - resumeCSE(); + w.resumeAddingCSEValues(); // Get the address of the element. - LIns *slots_ins = slots(obj_ins); - JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. - LIns *addr_ins = lir->ins2(LIR_addp, slots_ins, - lir->ins2ImmI(LIR_lshp, lir->insUI2P(idx_ins), 3)); + LIns *elem_ins = w.getDslotAddress(obj_ins, idx_ins); // If we are overwriting a hole: // - Guard that we don't have any indexed properties along the prototype chain. // - Check if the length has changed; if so, update it to index+1. // This happens moderately often, eg. close to 10% of the time in // SunSpider, and for some benchmarks it's close to 100%. - LIns* cond = lir->ins2(LIR_eqi, + Address dslotAddr = DSlotsAddress(elem_ins); + LIns* isHole_ins = w.eqi( #if JS_BITS_PER_WORD == 32 - lir->insLoad(LIR_ldi, addr_ins, sTagOffset, ACCSET_SLOTS), + w.ldiValueTag(dslotAddr), #else - lir->ins1(LIR_q2i, lir->ins2ImmI(LIR_rshuq, - lir->insLoad(LIR_ldq, addr_ins, 0, ACCSET_SLOTS), - JSVAL_TAG_SHIFT)), + w.q2i(w.rshuqN(w.ldq(dslotAddr), JSVAL_TAG_SHIFT)), #endif - INS_CONSTU(JSVAL_TAG_MAGIC)); - suspendCSE(); - LIns* br2; - if (condBranch(LIR_jf, cond, &br2)) { + w.nameImmui(JSVAL_TAG_MAGIC)); + w.pauseAddingCSEValues(); + if (MaybeBranch mbr = w.jf(isHole_ins)) { LIns* args[] = { idx_ins, obj_ins, cx_ins }; - LIns* res_ins = addName(lir->insCall(&js_Array_dense_setelem_hole_ci, args), - "hasNoIndexedProperties"); - guard(false, lir->insEqI_0(res_ins), mismatchExit); - labelForBranch(br2); + LIns* res_ins = w.name(w.call(&js_Array_dense_setelem_hole_ci, args), + "hasNoIndexedProperties"); + guard(false, w.eqi0(res_ins), mismatchExit); + w.label(mbr); } - resumeCSE(); + w.resumeAddingCSEValues(); // Right, actually set the element. - box_value_into(v, v_ins, addr_ins, 0, ACCSET_SLOTS); + box_value_into(v, v_ins, dslotAddr); } jsbytecode* pc = cx->regs->pc; @@ -13411,11 +12845,11 @@ TraceRecorder::record_JSOP_CALLNAME() NameResult nr; CHECK_STATUS_A(scopeChainProp(obj, vp, ins, nr)); stack(0, ins); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } - LIns* obj_ins = INS_CONSTOBJ(globalObj); + LIns* obj_ins = w.immpObjGC(globalObj); JSObject* obj2; PCVal pcval; @@ -13424,8 +12858,8 @@ TraceRecorder::record_JSOP_CALLNAME() if (pcval.isNull() || !pcval.isFunObj()) RETURN_STOP_A("callee is not an object"); - stack(0, INS_CONSTOBJ(&pcval.toFunObj())); - stack(1, INS_UNDEFINED()); + stack(0, w.immpObjGC(&pcval.toFunObj())); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -13481,21 +12915,20 @@ TraceRecorder::upvar(JSScript* script, JSUpvarArray* uva, uintN index, Value& v) slot = cookieSlot - fp->numFormalArgs(); } - LIns* outp = lir->insAlloc(sizeof(double)); + LIns* outp = w.allocp(sizeof(double)); LIns* args[] = { outp, - INS_CONST(callDepth), - INS_CONST(slot), - INS_CONST(level), + w.nameImmi(callDepth), + w.nameImmi(slot), + w.nameImmi(level), cx_ins }; - LIns* call_ins = lir->insCall(ci, args); + LIns* call_ins = w.call(ci, args); JSValueType type = getCoercedType(v); guard(true, - addName(lir->ins2(LIR_eqi, call_ins, lir->insImmI(type)), - "guard(type-stable upvar)"), + w.name(w.eqi(call_ins, w.immi(type)), "guard(type-stable upvar)"), BRANCH_EXIT); - return stackLoad(outp, ACCSET_ALLOC, type); + return stackLoad(AllocSlotsAddress(outp), type); } /* @@ -13503,35 +12936,27 @@ TraceRecorder::upvar(JSScript* script, JSUpvarArray* uva, uintN index, Value& v) * the correct LIR load operator is used. */ LIns* -TraceRecorder::stackLoad(LIns* base, AccSet accSet, uint8 type) +TraceRecorder::stackLoad(Address addr, uint8 type) { - LOpcode loadOp; switch (type) { case JSVAL_TYPE_DOUBLE: - loadOp = LIR_ldd; - break; + return w.ldd(addr); case JSVAL_TYPE_NONFUNOBJ: case JSVAL_TYPE_STRING: case JSVAL_TYPE_FUNOBJ: case JSVAL_TYPE_NULL: - loadOp = LIR_ldp; - break; + return w.ldp(addr); case JSVAL_TYPE_INT32: + return w.i2d(w.ldi(addr)); case JSVAL_TYPE_BOOLEAN: case JSVAL_TYPE_UNDEFINED: case JSVAL_TYPE_MAGIC: - loadOp = LIR_ldi; - break; + return w.ldi(addr); case JSVAL_TYPE_BOXED: default: JS_NOT_REACHED("found jsval type in an upvar type map entry"); return NULL; } - - LIns* result = lir->insLoad(loadOp, base, 0, accSet); - if (type == JSVAL_TYPE_INT32) - result = lir->ins1(LIR_i2d, result); - return result; } JS_REQUIRES_STACK AbortableRecordingStatus @@ -13554,7 +12979,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLUPVAR() { CHECK_STATUS_A(record_JSOP_GETUPVAR()); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -13564,12 +12989,12 @@ TraceRecorder::record_JSOP_GETFCSLOT() JSObject& callee = cx->fp()->callee(); LIns* callee_ins = get(&cx->fp()->calleeValue()); - LIns* upvars_ins = stobj_get_const_private_ptr(callee_ins, - JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); + LIns* upvars_ins = w.getObjPrivatizedSlot(callee_ins, JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); unsigned index = GET_UINT16(cx->regs->pc); - LIns *v_ins = unbox_value(callee.getFlatClosureUpvar(index), upvars_ins, index * sizeof(Value), - ACCSET_FCSLOTS, snapshot(BRANCH_EXIT)); + LIns *v_ins = unbox_value(callee.getFlatClosureUpvar(index), + FCSlotsAddress(upvars_ins, index), + snapshot(BRANCH_EXIT)); stack(0, v_ins); return ARECORD_CONTINUE; } @@ -13578,7 +13003,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLFCSLOT() { CHECK_STATUS_A(record_JSOP_GETFCSLOT()); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -13600,7 +13025,7 @@ TraceRecorder::guardCallee(Value& callee) tree->gcthings.addUnique(callee); guard(true, - lir->ins2(LIR_eqp, stobj_get_private(callee_ins), INS_CONSTPTR(callee_fun)), + w.eqp(w.ldpObjPrivate(callee_ins), w.nameImmpNonGC(callee_fun)), branchExit); /* @@ -13634,9 +13059,7 @@ TraceRecorder::guardCallee(Value& callee) RETURN_STOP("closure scoped by neither the global object nor a Call object"); guard(true, - lir->ins2(LIR_eqp, - stobj_get_parent(callee_ins), - INS_CONSTOBJ(parent)), + w.eqp(w.ldpObjParent(callee_ins), w.immpObjGC(parent)), branchExit); } } @@ -13662,8 +13085,8 @@ TraceRecorder::guardArguments(JSObject *obj, LIns* obj_ins, unsigned *depthp) guardClass(obj_ins, obj->getClass(), exit, LOAD_CONST); LIns* args_ins = getFrameObjPtr(afp->addressOfArgs()); - LIns* cmp = lir->ins2(LIR_eqp, args_ins, obj_ins); - lir->insGuard(LIR_xf, cmp, createGuardRecord(exit)); + LIns* cmp = w.eqp(args_ins, obj_ins); + guard(true, cmp, exit); return afp; } @@ -13681,12 +13104,12 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc, if (fun->u.i.script->isEmpty()) { LIns* rval_ins; if (constructing) { - LIns* args[] = { get(&fval), INS_CONSTPTR(&js_ObjectClass), cx_ins }; - LIns* tv_ins = lir->insCall(&js_CreateThisFromTrace_ci, args); - guard(false, lir->insEqP_0(tv_ins), OOM_EXIT); + LIns* args[] = { get(&fval), w.nameImmpNonGC(&js_ObjectClass), cx_ins }; + LIns* tv_ins = w.call(&js_CreateThisFromTrace_ci, args); + guard(false, w.eqp0(tv_ins), OOM_EXIT); rval_ins = tv_ins; } else { - rval_ins = INS_UNDEFINED(); + rval_ins = w.immiUndefined(); } stack(-2 - argc, rval_ins); return RECORD_CONTINUE; @@ -13722,7 +13145,7 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc, fi = traceMonitor->frameCache->memoize(fi); if (!fi) RETURN_STOP("out of memory"); - lir->insStore(INS_CONSTPTR(fi), lirbuf->rp, callDepth * sizeof(FrameInfo*), ACCSET_RSTACK); + w.stRstack(w.nameImmpNonGC(fi), lirbuf->rp, callDepth * sizeof(FrameInfo*)); #if defined JS_JIT_SPEW debug_only_printf(LC_TMTracer, "iFC frameinfo=%p, stack=%d, map=", (void*)fi, @@ -13828,9 +13251,7 @@ TraceRecorder::record_JSOP_APPLY() guardDenseArray(aobj_ins, MISMATCH_EXIT); length = aobj->getArrayLength(); guard(true, - lir->ins2ImmI(LIR_eqi, - stobj_get_private_uint32(aobj_ins), - length), + w.eqiN(w.lduiObjPrivate(aobj_ins), length), BRANCH_EXIT); } else if (aobj->isArguments()) { unsigned depth; @@ -13888,9 +13309,9 @@ TraceRecorder::record_NativeCallComplete() if (JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_STATUS) { /* Keep cx->bailExit null when it's invalid. */ - lir->insStore(INS_NULL(), cx_ins, offsetof(JSContext, bailExit), ACCSET_CX); + w.stContextField(w.immpNull(), bailExit); - LIns* status = loadFromState(LIR_ldi, builtinStatus); + LIns* status = w.ldiStateField(builtinStatus); if (pendingSpecializedNative == &generatedSpecializedNative) { LIns* ok_ins = v_ins; @@ -13900,26 +13321,27 @@ TraceRecorder::record_NativeCallComplete() * indicating the error status. */ + Address nativeRvalAddr = AllocSlotsAddress(native_rval_ins); if (pendingSpecializedNative->flags & JSTN_CONSTRUCTOR) { LIns *cond_ins; LIns *x; // v_ins := the object payload from native_rval_ins // cond_ins := true if native_rval_ins contains a JSObject* - unbox_any_object(native_rval_ins, &v_ins, &cond_ins, ACCSET_ALLOC); + unbox_any_object(nativeRvalAddr, &v_ins, &cond_ins); // x := v_ins if native_rval_ins contains a JSObject*, NULL otherwise - x = lir->insChoose(cond_ins, v_ins, INS_CONSTWORD(0), avmplus::AvmCore::use_cmov()); + x = w.cmovp(cond_ins, v_ins, w.nameImmw(0)); // v_ins := newobj_ins if native_rval_ins doesn't contain a JSObject*, // the object payload from native_rval_ins otherwise - v_ins = lir->insChoose(lir->insEqP_0(x), newobj_ins, x, avmplus::AvmCore::use_cmov()); + v_ins = w.cmovp(w.eqp0(x), newobj_ins, x); } else { - v_ins = lir->insLoad(LIR_ldd, native_rval_ins, 0, ACCSET_ALLOC); + v_ins = w.ldd(nativeRvalAddr); } set(&v, v_ins); propagateFailureToBuiltinStatus(ok_ins, status); } - guard(true, lir->insEqI_0(status), STATUS_EXIT); + guard(true, w.eqi0(status), STATUS_EXIT); } if (pendingSpecializedNative->flags & JSTN_UNBOX_AFTER) { @@ -13929,11 +13351,11 @@ TraceRecorder::record_NativeCallComplete() * about the top of the stack here, which is where we expected boxed values. */ JS_ASSERT(&v == &cx->regs->sp[-1] && get(&v) == v_ins); - set(&v, unbox_value(v, native_rval_ins, 0, ACCSET_ALLOC, snapshot(BRANCH_EXIT))); + set(&v, unbox_value(v, AllocSlotsAddress(native_rval_ins), snapshot(BRANCH_EXIT))); } else if (pendingSpecializedNative->flags & (JSTN_RETURN_NULLABLE_STR | JSTN_RETURN_NULLABLE_OBJ)) { guard(v.isNull(), - addName(lir->insEqP_0(v_ins), "guard(nullness)"), + w.name(w.eqp0(v_ins), "guard(nullness)"), BRANCH_EXIT); } else if (JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_NEG) { /* Already added i2d in functionCall. */ @@ -13942,7 +13364,7 @@ TraceRecorder::record_NativeCallComplete() /* Convert the result to double if the builtin returns int32. */ if (v.isNumber() && pendingSpecializedNative->builtin->returnType() == ARGTYPE_I) { - set(&v, lir->ins1(LIR_i2d, v_ins)); + set(&v, w.i2d(v_ins)); } } @@ -13962,7 +13384,7 @@ TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr) return scopeChainProp(obj, vp, ins, nr); /* Can't use prop here, because we don't want unboxing from global slots. */ - LIns* obj_ins = INS_CONSTOBJ(globalObj); + LIns* obj_ins = w.immpObjGC(globalObj); uint32 slot; JSObject* obj2; @@ -14080,7 +13502,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp, } } while (guardHasPrototype(obj, obj_ins, &obj, &obj_ins, exit)); - set(outp, INS_UNDEFINED()); + set(outp, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -14148,7 +13570,7 @@ TraceRecorder::propTail(JSObject* obj, LIns* obj_ins, JSObject* obj2, PCVal pcva * (this constant object instruction will be CSE'ed with the constant * emitted by test_property_cache, whose shape is guarded). */ - obj_ins = (obj2 == obj->getProto()) ? stobj_get_proto(obj_ins) : INS_CONSTOBJ(obj2); + obj_ins = (obj2 == obj->getProto()) ? w.ldpObjProto(obj_ins) : w.immpObjGC(obj2); obj = obj2; } @@ -14175,8 +13597,8 @@ TraceRecorder::propTail(JSObject* obj, LIns* obj_ins, JSObject* obj2, PCVal pcva */ if (isMethod && !cx->fp()->hasImacropc()) { enterDeepBailCall(); - LIns* args[] = { v_ins, INS_CONSTSHAPE(shape), obj_ins, cx_ins }; - v_ins = lir->insCall(&MethodReadBarrier_ci, args); + LIns* args[] = { v_ins, w.immpShapeGC(shape), obj_ins, cx_ins }; + v_ins = w.call(&MethodReadBarrier_ci, args); leaveDeepBailCall(); } @@ -14208,39 +13630,34 @@ TraceRecorder::denseArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ * holes by resizeDenseArrayElements() so we can read them and get * the correct value. */ - LIns* capacity_ins = - addName(lir->insLoad(LIR_ldi, obj_ins, - offsetof(JSObject, capacity), ACCSET_OBJ_CAPACITY), - "capacity"); - + LIns* capacity_ins = w.ldiDenseArrayCapacity(obj_ins); jsuint capacity = obj->getDenseArrayCapacity(); bool within = (jsuint(idx) < capacity); if (!within) { /* If not idx < capacity, stay on trace (and read value as undefined). */ - guard(true, lir->ins2(LIR_geui, idx_ins, capacity_ins), branchExit); + guard(true, w.geui(idx_ins, capacity_ins), branchExit); CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT))); // Return undefined and indicate that we didn't actually read this (addr_ins). - v_ins = INS_UNDEFINED(); + v_ins = w.immiUndefined(); addr_ins = NULL; return RECORD_CONTINUE; } /* Guard that index is within capacity. */ - guard(true, lir->ins2(LIR_ltui, idx_ins, capacity_ins), branchExit); + guard(true, w.ltui(idx_ins, capacity_ins), branchExit); /* Load the value and guard on its type to unbox it. */ vp = &obj->slots[jsuint(idx)]; JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. - addr_ins = lir->ins2(LIR_addp, slots(obj_ins), - lir->ins2ImmI(LIR_lshp, lir->insUI2P(idx_ins), 3)); - v_ins = unbox_value(*vp, addr_ins, 0, ACCSET_SLOTS, branchExit); + addr_ins = w.addp(w.name(w.ldpObjSlots(obj_ins), "slots"), w.lshpN(w.ui2p(idx_ins), 3)); + v_ins = unbox_value(*vp, DSlotsAddress(addr_ins), branchExit); /* Don't let the hole value escape. Turn it into an undefined. */ if (vp->isMagic()) { CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT))); - v_ins = INS_UNDEFINED(); + v_ins = w.immiUndefined(); } return RECORD_CONTINUE; } @@ -14250,13 +13667,12 @@ LIns * TraceRecorder::canonicalizeNaNs(LIns *dval_ins) { /* NaNs are the only floating point values that do not == themselves. */ - LIns *isnonnan_ins = lir->ins2(LIR_eqd, dval_ins, dval_ins); - return lir->insChoose(isnonnan_ins, dval_ins, lir->insImmD(js_NaN), true); + LIns *isnonnan_ins = w.eqd(dval_ins, dval_ins); + return w.cmovd(isnonnan_ins, dval_ins, w.immd(js_NaN)); } JS_REQUIRES_STACK AbortableRecordingStatus -TraceRecorder::typedArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ins, - LIns*& addr_ins) +TraceRecorder::typedArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ins) { JS_ASSERT(oval.isObject() && ival.isInt32()); @@ -14265,23 +13681,20 @@ TraceRecorder::typedArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ jsint idx = ival.toInt32(); LIns* idx_ins; CHECK_STATUS_A(makeNumberInt32(get(&ival), &idx_ins)); - LIns* pidx_ins = lir->insUI2P(idx_ins); + LIns* pidx_ins = w.ui2p(idx_ins); js::TypedArray* tarray = js::TypedArray::fromJSObject(obj); JS_ASSERT(tarray); /* priv_ins will load the TypedArray* */ - LIns* priv_ins = stobj_get_private(obj_ins); + LIns* priv_ins = w.ldpObjPrivate(obj_ins); /* for out-of-range, do the same thing that the interpreter does, which is return undefined */ if ((jsuint) idx >= tarray->length) { guard(false, - lir->ins2(LIR_ltui, - idx_ins, - lir->insLoad(LIR_ldi, priv_ins, js::TypedArray::lengthOffset(), - ACCSET_TARRAY, LOAD_CONST)), + w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), BRANCH_EXIT); - v_ins = INS_UNDEFINED(); + v_ins = w.immiUndefined(); return ARECORD_CONTINUE; } @@ -14295,50 +13708,38 @@ TraceRecorder::typedArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ * length. */ guard(true, - lir->ins2(LIR_ltui, - idx_ins, - lir->insLoad(LIR_ldi, priv_ins, js::TypedArray::lengthOffset(), - ACCSET_TARRAY, LOAD_CONST)), + w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), BRANCH_EXIT); /* We are now ready to load. Do a different type of load * depending on what type of thing we're loading. */ - LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset(), - ACCSET_TARRAY, LOAD_CONST); + LIns* data_ins = w.ldpConstTypedArrayData(priv_ins); switch (tarray->type) { case js::TypedArray::TYPE_INT8: - addr_ins = lir->ins2(LIR_addp, data_ins, pidx_ins); - v_ins = lir->ins1(LIR_i2d, lir->insLoad(LIR_ldc2i, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.i2d(w.ldc2iTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: - addr_ins = lir->ins2(LIR_addp, data_ins, pidx_ins); - v_ins = lir->ins1(LIR_ui2d, lir->insLoad(LIR_lduc2ui, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.ui2d(w.lduc2uiTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_INT16: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 1)); - v_ins = lir->ins1(LIR_i2d, lir->insLoad(LIR_lds2i, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.i2d(w.lds2iTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_UINT16: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 1)); - v_ins = lir->ins1(LIR_ui2d, lir->insLoad(LIR_ldus2ui, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.ui2d(w.ldus2uiTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_INT32: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 2)); - v_ins = lir->ins1(LIR_i2d, lir->insLoad(LIR_ldi, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.i2d(w.ldiTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_UINT32: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 2)); - v_ins = lir->ins1(LIR_ui2d, lir->insLoad(LIR_ldi, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = w.ui2d(w.ldiTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_FLOAT32: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 2)); - v_ins = canonicalizeNaNs(lir->insLoad(LIR_ldf2d, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = canonicalizeNaNs(w.ldf2dTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_FLOAT64: - addr_ins = lir->ins2(LIR_addp, data_ins, lir->ins2ImmI(LIR_lshp, pidx_ins, 3)); - v_ins = canonicalizeNaNs(lir->insLoad(LIR_ldd, addr_ins, 0, ACCSET_TARRAY_DATA)); + v_ins = canonicalizeNaNs(w.lddTypedArrayElement(data_ins, pidx_ins)); break; default: JS_NOT_REACHED("Unknown typed array type in tracer"); @@ -14381,7 +13782,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_DOUBLE() { double d = consts[GET_INDEX(cx->regs->pc)].toDouble(); - stack(0, lir->insImmD(d)); + stack(0, w.immd(d)); return ARECORD_CONTINUE; } @@ -14389,28 +13790,28 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_STRING() { JSAtom* atom = atoms[GET_INDEX(cx->regs->pc)]; - stack(0, INS_ATOM(atom)); + stack(0, w.immpAtomGC(atom)); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_ZERO() { - stack(0, lir->insImmD(0)); + stack(0, w.immd(0)); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_ONE() { - stack(0, lir->insImmD(1)); + stack(0, w.immd(1)); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_NULL() { - stack(0, INS_NULL()); + stack(0, w.immpNull()); return ARECORD_CONTINUE; } @@ -14426,14 +13827,14 @@ TraceRecorder::record_JSOP_THIS() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_FALSE() { - stack(0, lir->insImmI(0)); + stack(0, w.immi(0)); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_TRUE() { - stack(0, lir->insImmI(1)); + stack(0, w.immi(1)); return ARECORD_CONTINUE; } @@ -14489,7 +13890,7 @@ TraceRecorder::record_JSOP_OBJECT() JSObject* obj; obj = script->getObject(index); - stack(0, INS_CONSTOBJ(obj)); + stack(0, w.immpObjGC(obj)); return ARECORD_CONTINUE; } @@ -14536,7 +13937,7 @@ TraceRecorder::record_JSOP_SETLOCAL() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_UINT16() { - stack(0, lir->insImmD(GET_UINT16(cx->regs->pc))); + stack(0, w.immd(GET_UINT16(cx->regs->pc))); return ARECORD_CONTINUE; } @@ -14551,13 +13952,13 @@ TraceRecorder::record_JSOP_NEWINIT() LIns *v_ins; if (key == JSProto_Array) { - LIns *args[] = { lir->insImmI(count), cx_ins }; - v_ins = lir->insCall(&js_InitializerArray_ci, args); + LIns *args[] = { w.immi(count), cx_ins }; + v_ins = w.call(&js_InitializerArray_ci, args); } else { - LIns *args[] = { lir->insImmI(count), cx_ins }; - v_ins = lir->insCall(&js_InitializerObject_ci, args); + LIns *args[] = { w.immi(count), cx_ins }; + v_ins = w.call(&js_InitializerObject_ci, args); } - guard(false, lir->insEqP_0(v_ins), OOM_EXIT); + guard(false, w.eqp0(v_ins), OOM_EXIT); stack(0, v_ins); return ARECORD_CONTINUE; } @@ -14681,9 +14082,9 @@ TraceRecorder::record_JSOP_ITER() enterDeepBailCall(); - LIns* objp_ins = lir->insAlloc(sizeof(JSObject*)); - LIns* args[] = { objp_ins, lir->insImmI(flags), obj_ins, cx_ins }; - LIns* ok_ins = lir->insCall(&ObjectToIterator_ci, args); + LIns* objp_ins = w.allocp(sizeof(JSObject*)); + LIns* args[] = { objp_ins, w.immi(flags), obj_ins, cx_ins }; + LIns* ok_ins = w.call(&ObjectToIterator_ci, args); // We need to guard on ok_ins, but this requires a snapshot of the state // after this op. monitorRecording will do it for us. @@ -14691,7 +14092,7 @@ TraceRecorder::record_JSOP_ITER() leaveDeepBailCall(); - stack(-1, addName(lir->insLoad(LIR_ldp, objp_ins, 0, ACCSET_ALLOC), "iterobj")); + stack(-1, w.name(w.ldpAlloc(objp_ins), "iterobj")); return ARECORD_CONTINUE; } @@ -14732,24 +14133,21 @@ TraceRecorder::record_JSOP_MOREITER() void *cursor = ni->props_cursor; void *end = ni->props_end; - LIns *ni_ins = stobj_get_private(iterobj_ins); - LIns *cursor_ins = - addName(lir->insLoad(LIR_ldp, ni_ins, - offsetof(NativeIterator, props_cursor), ACCSET_ITER), "cursor"); - LIns *end_ins = addName(lir->insLoad(LIR_ldp, ni_ins, offsetof(NativeIterator, props_end), - ACCSET_ITER), "end"); + LIns *ni_ins = w.ldpObjPrivate(iterobj_ins); + LIns *cursor_ins = w.ldpIterCursor(ni_ins); + LIns *end_ins = w.ldpIterEnd(ni_ins); /* Figure out whether the native iterator contains more values. */ cond = cursor < end; - cond_ins = lir->ins2(LIR_ltp, cursor_ins, end_ins); + cond_ins = w.ltp(cursor_ins, end_ins); } else { guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); enterDeepBailCall(); - LIns* vp_ins = lir->insAlloc(sizeof(Value)); + LIns* vp_ins = w.allocp(sizeof(Value)); LIns* args[] = { vp_ins, iterobj_ins, cx_ins }; - LIns* ok_ins = lir->insCall(&IteratorMore_ci, args); + LIns* ok_ins = w.call(&IteratorMore_ci, args); /* * We cannot use pendingGuardCondition since monitorRecording may not be @@ -14759,7 +14157,7 @@ TraceRecorder::record_JSOP_MOREITER() * If IteratorMore fails, we will reexecute this op in the interpreter, * but js_IteratoreMore is idempotent so this is ok. */ - guard(false, lir->insEqI_0(ok_ins), STATUS_EXIT); + guard(false, w.eqi0(ok_ins), STATUS_EXIT); leaveDeepBailCall(); @@ -14775,7 +14173,7 @@ TraceRecorder::record_JSOP_MOREITER() return ARECORD_ABORTED; cond = (rooter.value().isTrue()); - cond_ins = is_boxed_true(vp_ins, ACCSET_ALLOC); + cond_ins = is_boxed_true(AllocSlotsAddress(vp_ins)); } jsbytecode* pc = cx->regs->pc; @@ -14809,7 +14207,7 @@ TraceRecorder::record_JSOP_ENDITER() enterDeepBailCall(); LIns* args[] = { stack(-1), cx_ins }; - LIns* ok_ins = lir->insCall(&CloseIterator_ci, args); + LIns* ok_ins = w.call(&CloseIterator_ci, args); // We need to guard on ok_ins, but this requires a snapshot of the state // after this op. monitorRecording will do it for us. @@ -14822,17 +14220,17 @@ TraceRecorder::record_JSOP_ENDITER() #if JS_BITS_PER_WORD == 32 JS_REQUIRES_STACK void -TraceRecorder::storeMagic(JSWhyMagic why, nanojit::LIns *addr_ins, ptrdiff_t offset, AccSet accSet) +TraceRecorder::storeMagic(JSWhyMagic why, Address addr) { - lir->insStore(INS_MAGIC_WHY(why), addr_ins, offset + sPayloadOffset, accSet); - lir->insStore(INS_MAGIC_WHY(JSVAL_TAG_MAGIC), addr_ins, offset + sTagOffset, accSet); + w.stiValuePayload(w.immpMagicWhy(why), addr); + w.stiValueTag(w.immpMagicWhy(JSVAL_TAG_MAGIC), addr); } #elif JS_BITS_PER_WORD == 64 JS_REQUIRES_STACK void -TraceRecorder::storeMagic(JSWhyMagic why, nanojit::LIns *addr_ins, ptrdiff_t offset, AccSet accSet) +TraceRecorder::storeMagic(JSWhyMagic why, Address addr) { - LIns *magic = INS_CONSTQWORD(BUILD_JSVAL(JSVAL_TAG_MAGIC, why)); - lir->insStore(magic, addr_ins, offset, accSet); + LIns *magic = w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why)); + w.stq(magic, addr); } #endif @@ -14847,20 +14245,21 @@ TraceRecorder::unboxNextValue(LIns* &v_ins) guardClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); - LIns *ni_ins = stobj_get_private(iterobj_ins); - LIns *cursor_ins = addName(lir->insLoad(LIR_ldp, ni_ins, offsetof(NativeIterator, props_cursor), ACCSET_ITER), "cursor"); + LIns *ni_ins = w.ldpObjPrivate(iterobj_ins); + LIns *cursor_ins = w.ldpIterCursor(ni_ins); /* Emit code to stringify the id if necessary. */ + Address cursorAddr = IterPropsAddress(cursor_ins); if (!(((NativeIterator *) iterobj->getPrivate())->flags & JSITER_FOREACH)) { /* Read the next id from the iterator. */ jsid id = *ni->currentKey(); - LIns *id_ins = addName(lir->insLoad(LIR_ldp, cursor_ins, 0, ACCSET_ITER_PROPS), "id"); + LIns *id_ins = w.name(w.ldp(cursorAddr), "id"); /* * Most iterations over object properties never have to actually deal with * any numeric properties, so we guard here instead of branching. */ - guard(JSID_IS_STRING(id), is_string_id(id_ins), snapshot(BRANCH_EXIT)); + guard(JSID_IS_STRING(id), is_string_id(id_ins), BRANCH_EXIT); if (JSID_IS_STRING(id)) { v_ins = unbox_string_id(id_ins); @@ -14869,29 +14268,28 @@ TraceRecorder::unboxNextValue(LIns* &v_ins) JS_ASSERT(JSID_IS_INT(id)); LIns *id_to_int_ins = unbox_int_id(id_ins); LIns* args[] = { id_to_int_ins, cx_ins }; - v_ins = lir->insCall(&js_IntToString_ci, args); - guard(false, lir->insEqP_0(v_ins), OOM_EXIT); + v_ins = w.call(&js_IntToString_ci, args); + guard(false, w.eqp0(v_ins), OOM_EXIT); } /* Increment the cursor by one jsid and store it back. */ - cursor_ins = lir->ins2(LIR_addp, cursor_ins, INS_CONSTWORD(sizeof(jsid))); + cursor_ins = w.addp(cursor_ins, w.nameImmw(sizeof(jsid))); } else { /* Read the next value from the iterator. */ Value v = *ni->currentValue(); - v_ins = unbox_value(v, cursor_ins, 0, ACCSET_ITER_PROPS, snapshot(BRANCH_EXIT)); + v_ins = unbox_value(v, cursorAddr, snapshot(BRANCH_EXIT)); /* Increment the cursor by one Value and store it back. */ - cursor_ins = lir->ins2(LIR_addp, cursor_ins, INS_CONSTWORD(sizeof(Value))); + cursor_ins = w.addp(cursor_ins, w.nameImmw(sizeof(Value))); } - lir->insStore(LIR_stp, cursor_ins, ni_ins, offsetof(NativeIterator, props_cursor), - ACCSET_ITER); + w.stpIterCursor(cursor_ins, ni_ins); } else { guardNotClass(iterobj_ins, &js_IteratorClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); - v_ins = unbox_value(cx->iterValue, cx_ins, offsetof(JSContext, iterValue), - ACCSET_CX, snapshot(BRANCH_EXIT)); - storeMagic(JS_NO_ITER_VALUE, cx_ins, offsetof(JSContext, iterValue), ACCSET_CX); + Address iterValueAddr = CxAddress(iterValue); + v_ins = unbox_value(cx->iterValue, iterValueAddr, snapshot(BRANCH_EXIT)); + storeMagic(JS_NO_ITER_VALUE, iterValueAddr); } return ARECORD_CONTINUE; @@ -15026,7 +14424,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target if (!foundCallObj) { JS_ASSERT(targetObj == globalObj); - targetIns = INS_CONSTPTR(globalObj); + targetIns = w.nameImmpNonGC(globalObj); return RECORD_CONTINUE; } @@ -15047,8 +14445,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target if (!exit) exit = snapshot(BRANCH_EXIT); guard(true, - addName(lir->ins2ImmI(LIR_eqi, shape_ins(obj_ins), obj->shape()), - "guard_shape"), + w.name(w.eqiN(w.ldiObjShape(obj_ins), obj->shape()), "guard_shape"), exit); } } @@ -15059,7 +14456,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target break; obj = obj->getParent(); - obj_ins = stobj_get_parent(obj_ins); + obj_ins = w.ldpObjParent(obj_ins); } targetIns = obj_ins; @@ -15109,7 +14506,7 @@ TraceRecorder::record_JSOP_BINDNAME() * function closure or the current scopeChain, so there is nothing inner to * it. Therefore this must be the right base object. */ - stack(0, INS_CONSTOBJ(obj)); + stack(0, w.immpObjGC(obj)); return ARECORD_CONTINUE; } @@ -15125,10 +14522,10 @@ TraceRecorder::record_JSOP_BINDNAME() Value *callee = &cx->fp()->calleeValue(); obj = callee->toObject().getParent(); if (obj == globalObj) { - stack(0, INS_CONSTOBJ(obj)); + stack(0, w.immpObjGC(obj)); return ARECORD_CONTINUE; } - LIns *obj_ins = stobj_get_parent(get(callee)); + LIns *obj_ins = w.ldpObjParent(get(callee)); // Find the target object. JSAtom *atom = atoms[GET_INDEX(cx->regs->pc)]; @@ -15148,7 +14545,7 @@ TraceRecorder::record_JSOP_BINDNAME() // If |obj2| is the global object, we can refer to it directly instead of walking up // the scope chain. There may still be guards on intervening call objects. - stack(0, obj2 == globalObj ? INS_CONSTOBJ(obj2) : obj2_ins); + stack(0, obj2 == globalObj ? w.immpObjGC(obj2) : obj2_ins); return ARECORD_CONTINUE; } @@ -15184,18 +14581,18 @@ TraceRecorder::record_JSOP_IN() LIns* num_ins; CHECK_STATUS_A(makeNumberInt32(get(&lval), &num_ins)); LIns* args[] = { num_ins, obj_ins, cx_ins }; - x = lir->insCall(&js_HasNamedPropertyInt32_ci, args); + x = w.call(&js_HasNamedPropertyInt32_ci, args); } else if (lval.isString()) { if (!js_ValueToStringId(cx, lval, &id)) RETURN_ERROR_A("left operand of JSOP_IN didn't convert to a string-id"); LIns* args[] = { get(&lval), obj_ins, cx_ins }; - x = lir->insCall(&js_HasNamedProperty_ci, args); + x = w.call(&js_HasNamedProperty_ci, args); } else { RETURN_STOP_A("string or integer expected"); } - guard(false, lir->ins2ImmI(LIR_eqi, x, JS_NEITHER), OOM_EXIT); - x = lir->ins2ImmI(LIR_eqi, x, 1); + guard(false, w.eqiN(x, JS_NEITHER), OOM_EXIT); + x = w.eqiN(x, 1); TraceMonitor &localtm = *traceMonitor; @@ -15253,9 +14650,9 @@ TraceRecorder::record_JSOP_INSTANCEOF() enterDeepBailCall(); LIns* args[] = {val_ins, get(&ctor), cx_ins}; - stack(-2, lir->insCall(&HasInstanceOnTrace_ci, args)); - LIns* status_ins = loadFromState(LIR_ldi, builtinStatus); - pendingGuardCondition = lir->insEqI_0(status_ins); + stack(-2, w.call(&HasInstanceOnTrace_ci, args)); + LIns* status_ins = w.ldiStateField(builtinStatus); + pendingGuardCondition = w.eqi0(status_ins); leaveDeepBailCall(); return ARECORD_CONTINUE; @@ -15407,7 +14804,7 @@ TraceRecorder::record_JSOP_LAMBDA() JSOp op2 = JSOp(*pc2); if (op2 == JSOP_INITMETHOD) { - stack(0, INS_CONSTOBJ(FUN_OBJECT(fun))); + stack(0, w.immpObjGC(FUN_OBJECT(fun))); return ARECORD_CONTINUE; } @@ -15415,7 +14812,7 @@ TraceRecorder::record_JSOP_LAMBDA() Value lval = stackval(-1); if (!lval.isPrimitive() && lval.toObject().canHaveMethodBarrier()) { - stack(0, INS_CONSTOBJ(FUN_OBJECT(fun))); + stack(0, w.immpObjGC(FUN_OBJECT(fun))); return ARECORD_CONTINUE; } } else if (fun->joinable()) { @@ -15443,7 +14840,7 @@ TraceRecorder::record_JSOP_LAMBDA() if ((iargc == 1 && native == array_sort) || (iargc == 2 && native == str_replace)) { - stack(0, INS_CONSTOBJ(FUN_OBJECT(fun))); + stack(0, w.immpObjGC(FUN_OBJECT(fun))); return ARECORD_CONTINUE; } } @@ -15452,7 +14849,7 @@ TraceRecorder::record_JSOP_LAMBDA() op2 = JSOp(*pc2); if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0) { - stack(0, INS_CONSTOBJ(FUN_OBJECT(fun))); + stack(0, w.immpObjGC(FUN_OBJECT(fun))); return ARECORD_CONTINUE; } } @@ -15461,8 +14858,8 @@ TraceRecorder::record_JSOP_LAMBDA() LIns *proto_ins; CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); - LIns* args[] = { INS_CONSTOBJ(globalObj), proto_ins, INS_CONSTFUN(fun), cx_ins }; - LIns* x = lir->insCall(&js_NewNullClosure_ci, args); + LIns* args[] = { w.immpObjGC(globalObj), proto_ins, w.immpFunGC(fun), cx_ins }; + LIns* x = w.call(&js_NewNullClosure_ci, args); stack(0, x); return ARECORD_CONTINUE; } @@ -15474,10 +14871,10 @@ TraceRecorder::record_JSOP_LAMBDA() CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); LIns* scopeChain_ins = scopeChain(); JS_ASSERT(scopeChain_ins); - LIns* args[] = { proto_ins, scopeChain_ins, INS_CONSTPTR(fun), cx_ins }; - LIns* call_ins = lir->insCall(&js_CloneFunctionObject_ci, args); + LIns* args[] = { proto_ins, scopeChain_ins, w.nameImmpNonGC(fun), cx_ins }; + LIns* call_ins = w.call(&js_CloneFunctionObject_ci, args); guard(false, - addName(lir->insEqP_0(call_ins), "guard(js_CloneFunctionObject)"), + w.name(w.eqp0(call_ins), "guard(js_CloneFunctionObject)"), OOM_EXIT); stack(0, call_ins); @@ -15496,21 +14893,16 @@ TraceRecorder::record_JSOP_LAMBDA_FC() if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH)) RETURN_STOP_A("Unable to trace creating lambda in let"); - LIns* args[] = { - scopeChain(), - INS_CONSTFUN(fun), - cx_ins - }; - LIns* closure_ins = lir->insCall(&js_AllocFlatClosure_ci, args); + LIns* args[] = { scopeChain(), w.immpFunGC(fun), cx_ins }; + LIns* closure_ins = w.call(&js_AllocFlatClosure_ci, args); guard(false, - addName(lir->ins2(LIR_eqp, closure_ins, INS_NULL()), - "guard(js_AllocFlatClosure)"), + w.name(w.eqp(closure_ins, w.immpNull()), "guard(js_AllocFlatClosure)"), OOM_EXIT); if (fun->u.i.nupvars) { JSUpvarArray *uva = fun->u.i.script->upvars(); - LIns* upvars_ins = stobj_get_const_private_ptr(closure_ins, - JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); + LIns* upvars_ins = w.getObjPrivatizedSlot(closure_ins, + JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); for (uint32 i = 0, n = uva->length; i < n; i++) { Value v; @@ -15518,7 +14910,7 @@ TraceRecorder::record_JSOP_LAMBDA_FC() if (!v_ins) return ARECORD_STOP; - box_value_into(v, v_ins, upvars_ins, i * sizeof(Value), ACCSET_FCSLOTS); + box_value_into(v, v_ins, FCSlotsAddress(upvars_ins, i)); } } @@ -15593,9 +14985,9 @@ TraceRecorder::guardArgsLengthNotAssigned(LIns* argsobj_ins) { // The following implements JSObject::isArgsLengthOverridden on trace. // ARGS_LENGTH_OVERRIDDEN_BIT is set if length was overridden. - LIns *len_ins = stobj_get_slot_uint32(argsobj_ins, JSObject::JSSLOT_ARGS_LENGTH); - LIns *ovr_ins = lir->ins2(LIR_andi, len_ins, INS_CONST(JSObject::ARGS_LENGTH_OVERRIDDEN_BIT)); - guard(true, lir->insEqI_0(ovr_ins), snapshot(MISMATCH_EXIT)); + LIns *len_ins = w.getArgsLength(argsobj_ins); + LIns *ovr_ins = w.andi(len_ins, w.nameImmi(JSObject::ARGS_LENGTH_OVERRIDDEN_BIT)); + guard(true, w.eqi0(ovr_ins), MISMATCH_EXIT); return len_ins; } @@ -15617,13 +15009,12 @@ TraceRecorder::record_JSOP_ARGCNT() RETURN_STOP_A("can't trace JSOP_ARGCNT if arguments.length has been modified"); LIns *a_ins = getFrameObjPtr(fp->addressOfArgs()); if (callDepth == 0) { - LIns *br; - if (condBranch(LIR_jt, lir->insEqP_0(a_ins), &br)) { + if (MaybeBranch mbr = w.jt(w.eqp0(a_ins))) { guardArgsLengthNotAssigned(a_ins); - labelForBranch(br); + w.label(mbr); } } - stack(0, lir->insImmD(fp->numActualArgs())); + stack(0, w.immd(fp->numActualArgs())); return ARECORD_CONTINUE; } @@ -15636,8 +15027,8 @@ TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj) LIns *proto_ins; CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); - LIns* args[] = { INS_CONSTOBJ(globalObj), proto_ins, INS_CONSTFUN(fun), cx_ins }; - LIns* x = lir->insCall(&js_NewNullClosure_ci, args); + LIns* args[] = { w.immpObjGC(globalObj), proto_ins, w.immpFunGC(fun), cx_ins }; + LIns* x = w.call(&js_NewNullClosure_ci, args); var(slot, x); return ARECORD_CONTINUE; } @@ -15761,11 +15152,11 @@ TraceRecorder::record_JSOP_REGEXP() LIns* args[] = { proto_ins, - INS_CONSTOBJ(script->getRegExp(index)), + w.immpObjGC(script->getRegExp(index)), cx_ins }; - LIns* regex_ins = lir->insCall(&js_CloneRegExpObject_ci, args); - guard(false, lir->insEqP_0(regex_ins), OOM_EXIT); + LIns* regex_ins = w.call(&js_CloneRegExpObject_ci, args); + guard(false, w.eqp0(regex_ins), OOM_EXIT); stack(0, regex_ins); return ARECORD_CONTINUE; @@ -15956,8 +15347,8 @@ TraceRecorder::record_JSOP_CALLPROP() if (!js_GetClassPrototype(cx, NULL, protoKey, &obj)) RETURN_ERROR_A("GetClassPrototype failed!"); - obj_ins = INS_CONSTOBJ(obj); - debug_only_stmt(obj_ins = addName(obj_ins, protoname);) + obj_ins = w.immpObjGC(obj); + debug_only_stmt(obj_ins = w.name(obj_ins, protoname);) this_ins = get(&l); // use primitive as |this| } @@ -15974,7 +15365,7 @@ TraceRecorder::record_JSOP_CALLPROP() if (!PrimitiveThisTest(fun, l)) RETURN_STOP_A("callee does not accept primitive |this|"); } - set(&l, INS_CONSTOBJ(&pcval.toFunObj())); + set(&l, w.immpObjGC(&pcval.toFunObj())); } else { if (l.isPrimitive()) RETURN_STOP_A("callprop of primitive method"); @@ -15994,7 +15385,7 @@ TraceRecorder::record_JSOP_DELDESC() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_UINT24() { - stack(0, lir->insImmD(GET_UINT24(cx->regs->pc))); + stack(0, w.immd(GET_UINT24(cx->regs->pc))); return ARECORD_CONTINUE; } @@ -16050,9 +15441,9 @@ TraceRecorder::record_JSOP_STOP() #ifdef MOZ_TRACE_JSCALLS if (cx->functionCallback) { - LIns* args[] = { INS_CONST(0), INS_CONSTPTR(cx->fp()->fun()), cx_ins }; - LIns* call_ins = lir->insCall(&functionProbe_ci, args); - guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT); + LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins }; + LIns* call_ins = w.call(&functionProbe_ci, args); + guard(false, w.eqi0(call_ins), MISMATCH_EXIT); } #endif @@ -16067,7 +15458,7 @@ TraceRecorder::record_JSOP_STOP() if (fp->isConstructing()) { rval_ins = get(&fp->thisValue()); } else { - rval_ins = INS_UNDEFINED(); + rval_ins = w.immiUndefined(); } clearCurrentFrameSlotsFromTracker(nativeFrameTracker); return ARECORD_CONTINUE; @@ -16106,7 +15497,7 @@ TraceRecorder::record_JSOP_ENTERBLOCK() JSObject* obj; obj = cx->fp()->script()->getObject(getFullIndex(0)); - LIns* void_ins = INS_UNDEFINED(); + LIns* void_ins = w.immiUndefined(); for (int i = 0, n = OBJ_BLOCK_COUNT(cx, obj); i < n; i++) stack(i, void_ins); return ARECORD_CONTINUE; @@ -16144,8 +15535,8 @@ TraceRecorder::record_JSOP_ARRAYPUSH() LIns *elt_ins = box_value_for_native_call(elt, get(&elt)); LIns *args[] = { elt_ins, array_ins, cx_ins }; - LIns *ok_ins = lir->insCall(&js_ArrayCompPush_tn_ci, args); - guard(false, lir->insEqI_0(ok_ins), OOM_EXIT); + LIns *ok_ins = w.call(&js_ArrayCompPush_tn_ci, args); + guard(false, w.eqi0(ok_ins), OOM_EXIT); return ARECORD_CONTINUE; } @@ -16221,7 +15612,7 @@ TraceRecorder::record_JSOP_CALLLOCAL() { uintN slot = GET_SLOTNO(cx->regs->pc); stack(0, var(slot)); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -16230,28 +15621,28 @@ TraceRecorder::record_JSOP_CALLARG() { uintN slot = GET_ARGNO(cx->regs->pc); stack(0, arg(slot)); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_BINDGNAME() { - stack(0, INS_CONSTOBJ(globalObj)); + stack(0, w.immpObjGC(globalObj)); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_INT8() { - stack(0, lir->insImmD(GET_INT8(cx->regs->pc))); + stack(0, w.immd(GET_INT8(cx->regs->pc))); return ARECORD_CONTINUE; } JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_INT32() { - stack(0, lir->insImmD(GET_INT32(cx->regs->pc))); + stack(0, w.immd(GET_INT32(cx->regs->pc))); return ARECORD_CONTINUE; } @@ -16262,7 +15653,7 @@ TraceRecorder::record_JSOP_LENGTH() if (l.isPrimitive()) { if (!l.isString()) RETURN_STOP_A("non-string primitive JSOP_LENGTH unsupported"); - set(&l, lir->ins1(LIR_i2d, p2i(getStringLength(get(&l))))); + set(&l, w.i2d(w.p2i(w.getStringLength(get(&l))))); return ARECORD_CONTINUE; } @@ -16283,9 +15674,7 @@ TraceRecorder::record_JSOP_LENGTH() // slot_ins is the value from the slot; right-shift to get the length // (see JSObject::getArgsInitialLength in jsfun.cpp). - LIns* v_ins = - lir->ins1(LIR_i2d, lir->ins2ImmI(LIR_rshi, - slot_ins, JSObject::ARGS_PACKED_BITS_COUNT)); + LIns* v_ins = w.i2d(w.rshiN(slot_ins, JSObject::ARGS_PACKED_BITS_COUNT)); set(&l, v_ins); return ARECORD_CONTINUE; } @@ -16298,14 +15687,11 @@ TraceRecorder::record_JSOP_LENGTH() JS_ASSERT(obj->isSlowArray()); guardClass(obj_ins, &js_SlowArrayClass, snapshot(BRANCH_EXIT), LOAD_NORMAL); } - v_ins = lir->ins1(LIR_i2d, stobj_get_private_uint32(obj_ins)); + v_ins = w.i2d(w.lduiObjPrivate(obj_ins)); } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Ensure array is a typed array and is the same type as what was written guardClass(obj_ins, obj->getClass(), snapshot(BRANCH_EXIT), LOAD_NORMAL); - v_ins = lir->ins1(LIR_i2d, lir->insLoad(LIR_ldi, - stobj_get_private(obj_ins), - js::TypedArray::lengthOffset(), - ACCSET_TARRAY, LOAD_CONST)); + v_ins = w.i2d(w.ldiConstTypedArrayLength(w.ldpObjPrivate(obj_ins))); } else { if (!obj->isNative()) RETURN_STOP_A("can't trace length property access on non-array, non-native object"); @@ -16324,9 +15710,9 @@ TraceRecorder::record_JSOP_NEWARRAY() uint32 len = GET_UINT16(cx->regs->pc); cx->assertValidStackDepth(len); - LIns* args[] = { lir->insImmI(len), proto_ins, cx_ins }; - LIns* v_ins = lir->insCall(&js_NewPreallocatedArray_ci, args); - guard(false, lir->insEqP_0(v_ins), OOM_EXIT); + LIns* args[] = { w.immi(len), proto_ins, cx_ins }; + LIns* v_ins = w.call(&js_NewPreallocatedArray_ci, args); + guard(false, w.eqp0(v_ins), OOM_EXIT); LIns* slots_ins = NULL; uint32 count = 0; @@ -16344,7 +15730,7 @@ TraceRecorder::record_JSOP_NEWARRAY() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_HOLE() { - stack(0, INS_MAGIC_WHY(JS_ARRAY_HOLE)); + stack(0, w.immpMagicWhy(JS_ARRAY_HOLE)); return ARECORD_CONTINUE; } @@ -16384,8 +15770,8 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_UNBRAND() { LIns* args_ins[] = { stack(-1), cx_ins }; - LIns* call_ins = lir->insCall(&js_Unbrand_ci, args_ins); - guard(false, lir->insEqI_0(call_ins), OOM_EXIT); + LIns* call_ins = w.call(&js_Unbrand_ci, args_ins); + guard(false, w.eqi0(call_ins), OOM_EXIT); return ARECORD_CONTINUE; } @@ -16398,8 +15784,8 @@ TraceRecorder::record_JSOP_UNBRANDTHIS() return InjectStatus(status); LIns* args_ins[] = { this_ins, cx_ins }; - LIns* call_ins = lir->insCall(&js_Unbrand_ci, args_ins); - guard(false, lir->insEqI_0(call_ins), OOM_EXIT); + LIns* call_ins = w.call(&js_Unbrand_ci, args_ins); + guard(false, w.eqi0(call_ins), OOM_EXIT); return ARECORD_CONTINUE; } @@ -16440,7 +15826,7 @@ TraceRecorder::record_JSOP_CALLGLOBAL() Value &v = globalObj->getSlotRef(slot); stack(0, get(&v)); - stack(1, INS_UNDEFINED()); + stack(1, w.immiUndefined()); return ARECORD_CONTINUE; } @@ -17357,386 +16743,3 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) } /* namespace js */ - -#ifdef DEBUG -namespace nanojit { - -static bool -match(LIns* base, LOpcode opcode, AccSet accSet, int32_t disp) -{ - return base->isop(opcode) && - base->accSet() == accSet && - base->disp() == disp; -} - -static bool -match(LIns* base, LOpcode opcode, AccSet accSet, LoadQual loadQual, int32_t disp) -{ - return base->isop(opcode) && - base->accSet() == accSet && - base->loadQual() == loadQual && - base->disp() == disp; -} - -static bool -couldBeObjectOrString(LIns* ins) -{ - bool ret = false; - - if (ins->isop(LIR_callp)) { - // ins = callp ... # could be a call to an object-creating function - ret = true; - - } else if (ins->isop(LIR_ldp)) { - // ins = ldp ... # could be an object, eg. loaded from the stack - ret = true; - - } else if (ins->isImmP()) { - // ins = immp ... # could be a pointer to an object - uintptr_t val = uintptr_t(ins->immP()); - if (val == 0 || val > 4096) - ret = true; // Looks like a pointer - - } else if (ins->isop(LIR_cmovp)) { - // ins = cmovp , - ret = couldBeObjectOrString(ins->oprnd2()) && - couldBeObjectOrString(ins->oprnd3()); - - } else if (!avmplus::AvmCore::use_cmov() && - ins->isop(LIR_ori) && - ins->oprnd1()->isop(LIR_andi) && - ins->oprnd2()->isop(LIR_andi)) - { - // This is a partial check for the insChoose() code that only occurs - // is use_cmov() is false. - // - // ins_oprnd1 = andi ... - // ins_oprnd2 = andi ... - // ins = ori ins_oprnd1, ins_oprnd2 - ret = true; - -#if JS_BITS_PER_WORD == 64 - } else if (ins->isop(LIR_andq) && - ins->oprnd1()->isop(LIR_ldq) && - ins->oprnd2()->isImmQ() && - uintptr_t(ins->oprnd2()->immQ()) == JSVAL_PAYLOAD_MASK) - { - // ins_oprnd1 = ldq ... - // ins_oprnd2 = immq JSVAL_PAYLOAD_MASK - // ins = andq ins_oprnd1, ins_oprnd2 - ret = true; -#endif - } else if (ins->isop(LIR_addp) && - ((ins->oprnd1()->isImmP() && - (void*)ins->oprnd1()->immP() == JSString::unitStringTable) || - (ins->oprnd2()->isImmP() && - (void*)ins->oprnd2()->immP() == JSString::unitStringTable))) - { - // (String only) - // ins = addp ..., JSString::unitStringTable - // OR - // ins = addp JSString::unitStringTable, ... - ret = true; - } - - return ret; -} - -static bool -isConstPrivatePtr(LIns* ins, unsigned slot) -{ -#if JS_BITS_PER_WORD == 32 - // ins = ldp.slots/c ...[] - return match(ins, LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value) + sPayloadOffset); -#elif JS_BITS_PER_WORD == 64 - // ins_oprnd1 = ldp.slots/c ...[] - // ins_oprnd2 = immi 1 - // ins = lshq ins_oprnd1, ins_oprnd2 - return ins->isop(LIR_lshq) && - match(ins->oprnd1(), LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value)) && - ins->oprnd2()->isImmI(1); -#endif -} - -/* - * Any time you use an AccSet annotation other than ACCSET_ALL, you are making - * a promise to Nanojit about the properties of the annotated load/store/call. - * If that annotation is wrong, it could cause rare and subtle bugs. So this - * function does its damnedest to prevent such bugs occurring by carefully - * checking every load and store. - * - * For some access regions, we can check perfectly -- eg. for an ACCSET_STATE - * load/store, the base pointer must be 'state'. For others, we can only - * check imperfectly -- eg. for an ACCSET_OBJ_CLASP load/store, we can check that - * the base pointer has one of several forms, but it's possible that a - * non-object has that form as well. This imperfect checking is unfortunate - * but unavoidable. Also, multi-region load/store AccSets are not checked, - * and so are best avoided (they're rarely needed). Finally, the AccSet - * annotations on calls cannot be checked here; in some cases they can be - * partially checked via assertions (eg. by checking that certain values - * are not changed by the function). - */ -void ValidateWriter::checkAccSet(LOpcode op, LIns* base, int32_t disp, AccSet accSet) -{ - bool ok; - - NanoAssert(accSet != ACCSET_NONE); - - #define dispWithin(Struct) \ - (0 <= disp && disp < int32_t(sizeof(Struct))) - - switch (accSet) { - case ACCSET_STATE: - // base = paramp 0 0 - // ins = {ld,st}X.state base[] - ok = dispWithin(TracerState) && - base->isop(LIR_paramp) && - base->paramKind() == 0 && - base->paramArg() == 0; - break; - - case ACCSET_STACK: - // base = ldp.state ...[offsetof(TracerState, sp)] - // ins = {ld,st}X.sp base[...] - // OR - // base_oprnd1 = ldp.state ...[offsetof(TraceState, sp)] - // base = addp base_oprnd1, ... - // ins = {ld,st}X.sp base[...] - ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp)) || - (base->isop(LIR_addp) && - match(base->oprnd1(), LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp))); - break; - - case ACCSET_RSTACK: - // base = ldp.state ...[offsetof(TracerState, rp)] - // ins = {ld,st}p.rp base[...] - // OR - // base = ldp.state ...[offsetof(TracerState, callstackBaseOffset)] - // ins = {ld,st}p.rp base[...] - ok = (op == LIR_ldp || op == LIR_stp) && - (match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, rp)) || - match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, callstackBase))); - break; - - case ACCSET_CX: - // base = ldp.state ...[offsetof(TracerState, cx)] - // ins = {ld,st}X.cx base[] - ok = dispWithin(JSContext) && - match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, cx)); - break; - - case ACCSET_EOS: - // base = ldp.state ...[offsetof(TracerState, eos)] - // ins = {ld,st}X.eos base[...] - ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, eos)); - break; - - case ACCSET_ALLOC: - // base = allocp ... - // ins = {ld,st}X.alloc base[...] - // OR - // base_oprnd1 = allocp ... - // base = addp base_oprnd1, ... - // ins = {ld,st}X.alloc base[...] - ok = base->isop(LIR_allocp) || - (base->isop(LIR_addp) && - base->oprnd1()->isop(LIR_allocp)); - break; - - case ACCSET_FRAMEREGS: - // base = ldp.cx ...[offsetof(JSContext, regs)] - // ins = ldp.regs base[] - ok = op == LIR_ldp && - dispWithin(JSFrameRegs) && - match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, regs)); - break; - - case ACCSET_STACKFRAME: - // base = ldp.regs ...[offsetof(JSFrameRegs, fp)] - // ins = {ld,st}X.sf base[] - ok = dispWithin(JSStackFrame) && - match(base, LIR_ldp, ACCSET_FRAMEREGS, offsetof(JSFrameRegs, fp)); - break; - - case ACCSET_RUNTIME: - // base = ldp.cx ...[offsetof(JSContext, runtime)] - // ins = ldp.rt base[] - ok = dispWithin(JSRuntime) && - match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, runtime)); - break; - - // This check is imperfect. - // - // base = - // ins = ldp.obj base[offsetof(JSObject, )] - #define OK_OBJ_FIELD(ldop, field) \ - op == ldop && \ - disp == offsetof(JSObject, field) && \ - couldBeObjectOrString(base) - - case ACCSET_OBJ_CLASP: - ok = OK_OBJ_FIELD(LIR_ldp, clasp); - break; - - case ACCSET_OBJ_FLAGS: - ok = OK_OBJ_FIELD(LIR_ldi, flags); - break; - - case ACCSET_OBJ_SHAPE: - ok = OK_OBJ_FIELD(LIR_ldi, objShape); - break; - - case ACCSET_OBJ_PROTO: - ok = OK_OBJ_FIELD(LIR_ldp, proto); - break; - - case ACCSET_OBJ_PARENT: - ok = OK_OBJ_FIELD(LIR_ldp, parent); - break; - - case ACCSET_OBJ_PRIVATE: - // base = - // ins = ldp.objprivate base[offsetof(JSObject, privateData)] - ok = (op == LIR_ldi || op == LIR_ldp) && - disp == offsetof(JSObject, privateData) && - couldBeObjectOrString(base); - break; - - case ACCSET_OBJ_CAPACITY: - ok = OK_OBJ_FIELD(LIR_ldi, capacity); - break; - - case ACCSET_OBJ_SLOTS: - ok = OK_OBJ_FIELD(LIR_ldp, slots); - break; - - case ACCSET_SLOTS: - // This check is imperfect. - // - // base = # direct slot access - // ins = {ld,st}X.slots base[...] - // OR - // base = ldp.objslots ...[offsetof(JSObject, slots)] # indirect slot access - // ins = {ld,st}X.slots base[...] - // OR - // base_oprnd1 = ldp.objslots ...[offsetof(JSObject, slots)] # indirect scaled slot access - // base = addp base_oprnd1, ... - // ins = {ld,st}X.slots base[...] - ok = couldBeObjectOrString(base) || - match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)) || - (base->isop(LIR_addp) && - match(base->oprnd1(), LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots))); - break; - - case ACCSET_TARRAY: - // This check is imperfect. - // - // base = ldp.objprivate ...[offsetof(JSObject, privateData)] - // ins = ld{i,p}.tarray base[] - ok = (op == LIR_ldi || op == LIR_ldp) && - dispWithin(TypedArray) && - match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); - break; - - case ACCSET_TARRAY_DATA: - // base_oprnd1 = ldp.tarray ...[TypedArray::dataOffset()] - // base = addp base_oprnd1, ... - // ins = {ld,st}X.tdata base[...] - ok = base->isop(LIR_addp) && - match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, TypedArray::dataOffset()); - break; - - case ACCSET_ITER: - // base = ldp.objprivate ...[offsetof(JSObject, privateData)] - // ins = {ld,st}p.iter base[] - ok = (op == LIR_ldp || op == LIR_stp) && - dispWithin(NativeIterator) && - match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); - break; - - case ACCSET_ITER_PROPS: - // base = ldp.iter ...[offsetof(NativeIterator, props_cursor)] - // ins = ld{i,p,d}.iterprops base[0|4] - ok = (op == LIR_ldi || op == LIR_ldp || op == LIR_ldd) && - (disp == 0 || disp == 4) && - match(base, LIR_ldp, ACCSET_ITER, offsetof(NativeIterator, props_cursor)); - break; - - case ACCSET_STRING: - // This check is imperfect. - // - // base = - // ins = {ld,st}X.str base[] - ok = dispWithin(JSString) && - couldBeObjectOrString(base); - break; - - case ACCSET_STRING_MCHARS: - // base = ldp.string ...[offsetof(JSString, mChars)] - // ins = ldus2ui.strchars/c base[0] - // OR - // base_oprnd1 = ldp.string ...[offsetof(JSString, mChars)] - // base = addp base_oprnd1, ... - // ins = ldus2ui.strchars/c base[0] - ok = op == LIR_ldus2ui && - disp == 0 && - (match(base, LIR_ldp, ACCSET_STRING, offsetof(JSString, mChars)) || - (base->isop(LIR_addp) && - match(base->oprnd1(), LIR_ldp, ACCSET_STRING, offsetof(JSString, mChars)))); - break; - - case ACCSET_TYPEMAP: - // This check is imperfect, things get complicated once you get back - // farther than 'base'. But the parts we check are pretty distinctive - // and should be good enough. - // - // base = addp base_oprnd1, ... - // ins = lduc2ui.typemap/c base[0] - ok = op == LIR_lduc2ui && - disp == 0 && - base->isop(LIR_addp); - break; - - case ACCSET_FCSLOTS: - // This check is imperfect. - // - // base = - // ins = {ld,st}X.fcslots base[...] - ok = isConstPrivatePtr(base, JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); - break; - - case ACCSET_ARGS_DATA: - // This check is imperfect. - // - // base = - // ins = st{i,p,d}.argsdata base[...] - // OR - // base_oprnd1 = - // base = addp base_oprnd1, ... - // ins = {ld,st}X.argsdata base[...] - ok = (isConstPrivatePtr(base, JSObject::JSSLOT_ARGS_DATA) || - (base->isop(LIR_addp) && - isConstPrivatePtr(base->oprnd1(), JSObject::JSSLOT_ARGS_DATA))); - break; - - default: - // This assertion will fail if any single-region AccSets aren't covered - // by the switch -- only multi-region AccSets should be handled here. - JS_ASSERT(!isSingletonAccSet(accSet)); - ok = true; - break; - } - - if (!ok) { - InsBuf b1, b2; - printer->formatIns(&b1, base); - JS_snprintf(b2.buf, b2.len, "base = (%s); disp = %d", b1.buf, disp); - errorAccSet(lirNames[op], accSet, b2.buf); - } -} - -} - -#endif - - diff --git a/js/src/jstracer.h b/js/src/jstracer.h index f798e0a691b..ea27e2ef2b0 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -52,13 +52,10 @@ #include "jslock.h" #include "jsnum.h" #include "jsvector.h" +#include "Writer.h" namespace js { -#if defined(DEBUG) && !defined(JS_JIT_SPEW) -#define JS_JIT_SPEW -#endif - template class Queue { T* _data; @@ -230,25 +227,6 @@ public: TreeFragment* toTreeFragment(); }; -#if defined(JS_JIT_SPEW) || defined(NJ_NO_VARIADIC_MACROS) - -enum LC_TMBits { - /* - * Output control bits for all non-Nanojit code. Only use bits 16 and - * above, since Nanojit uses 0 .. 15 itself. - */ - LC_TMMinimal = 1<<16, - LC_TMTracer = 1<<17, - LC_TMRecorder = 1<<18, - LC_TMAbort = 1<<19, - LC_TMStats = 1<<20, - LC_TMRegexp = 1<<21, - LC_TMTreeVis = 1<<22, - LC_TMProfiler = 1<<23 -}; - -#endif - #ifdef NJ_NO_VARIADIC_MACROS #define debug_only_stmt(action) /* */ @@ -1045,10 +1023,6 @@ class TraceRecorder /* If non-null, the side exit from which we are growing. */ VMSideExit* const anchor; - /* The LIR-generation pipeline used to build |fragment|. */ - nanojit::LirWriter* const lir; - nanojit::CseFilter* const cse_filter; - /* Instructions yielding the corresponding trace-const members of TracerState. */ nanojit::LIns* const cx_ins; nanojit::LIns* const eos_ins; @@ -1137,25 +1111,28 @@ class TraceRecorder /* Temporary JSValueType array used to construct temporary typemaps. */ js::Vector tempTypeMap; + /* Used to generate LIR. Has a short name because it's used a lot. */ + tjit::Writer w; + /************************************************************* 10 bajillion member functions */ - /* - * These can be put around a control-flow diamond if it's important that - * CSE work across the diamond. Duplicated expressions within the diamond - * will be CSE'd, but expressions defined within the diamond won't be - * added to the tables of CSEable expressions. Loads are still - * invalidated if they alias any stores that occur within diamonds. + /* + * These would be in Writer if they didn't modify TraceRecorder state. + * They are invoked the via macros below that make them look like they are + * part of Writer (hence the "w_" prefix, which looks like "w."). */ - void suspendCSE() { if (cse_filter) cse_filter->suspend(); } - void resumeCSE() { if (cse_filter) cse_filter->resume(); } + nanojit::LIns* w_immpObjGC(JSObject* obj); + nanojit::LIns* w_immpFunGC(JSFunction* fun); + nanojit::LIns* w_immpStrGC(JSString* str); + nanojit::LIns* w_immpShapeGC(const js::Shape* shape); + nanojit::LIns* w_immpIdGC(jsid id); - nanojit::LIns* insImmVal(const Value& val); - nanojit::LIns* insImmObj(JSObject* obj); - nanojit::LIns* insImmFun(JSFunction* fun); - nanojit::LIns* insImmStr(JSString* str); - nanojit::LIns* insImmShape(const js::Shape* shape); - nanojit::LIns* insImmId(jsid id); - nanojit::LIns* p2i(nanojit::LIns* ins); + #define immpObjGC(obj) name(w_immpObjGC(obj), #obj) + #define immpFunGC(fun) name(w_immpFunGC(fun), #fun) + #define immpStrGC(str) name(w_immpStrGC(str), #str) + #define immpAtomGC(atom) name(w_immpStrGC(ATOM_TO_STRING(atom)), "ATOM_TO_STRING(" #atom ")") + #define immpShapeGC(shape) name(w_immpShapeGC(shape), #shape) + #define immpIdGC(id) name(w_immpIdGC(id), #id) /* * Examines current interpreter state to record information suitable for returning to the @@ -1197,11 +1174,9 @@ class TraceRecorder JS_REQUIRES_STACK ptrdiff_t nativeStackSlot(const Value* p) const; JS_REQUIRES_STACK ptrdiff_t nativespOffsetImpl(const void* p) const; JS_REQUIRES_STACK ptrdiff_t nativespOffset(const Value* p) const; - JS_REQUIRES_STACK void importImpl(nanojit::LIns* base, ptrdiff_t offset, nanojit::AccSet accSet, - const void* p, JSValueType t, + JS_REQUIRES_STACK void importImpl(tjit::Address addr, const void* p, JSValueType t, const char *prefix, uintN index, JSStackFrame *fp); - JS_REQUIRES_STACK void import(nanojit::LIns* base, ptrdiff_t offset, nanojit::AccSet accSet, - const Value* p, JSValueType t, + JS_REQUIRES_STACK void import(tjit::Address addr, const Value* p, JSValueType t, const char *prefix, uintN index, JSStackFrame *fp); JS_REQUIRES_STACK void import(TreeFragment* tree, nanojit::LIns* sp, unsigned stackSlots, unsigned callDepth, unsigned ngslots, JSValueType* typeMap); @@ -1220,9 +1195,6 @@ class TraceRecorder JS_REQUIRES_STACK nanojit::LIns* guard_xov(nanojit::LOpcode op, nanojit::LIns* d0, nanojit::LIns* d1, VMSideExit* exit); - nanojit::LIns* addName(nanojit::LIns* ins, const char* name); - nanojit::LIns* insComment(const char* str); - nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset, bool demote); @@ -1290,7 +1262,7 @@ class TraceRecorder JS_REQUIRES_STACK nanojit::LIns* var(unsigned n); JS_REQUIRES_STACK void var(unsigned n, nanojit::LIns* i); JS_REQUIRES_STACK nanojit::LIns* upvar(JSScript* script, JSUpvarArray* uva, uintN index, Value& v); - nanojit::LIns* stackLoad(nanojit::LIns* addr, nanojit::AccSet accSet, uint8 type); + nanojit::LIns* stackLoad(tjit::Address addr, uint8 type); JS_REQUIRES_STACK nanojit::LIns* stack(int n); JS_REQUIRES_STACK void stack(int n, nanojit::LIns* i); @@ -1298,14 +1270,8 @@ class TraceRecorder JS_REQUIRES_STACK nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1, nanojit::LIns* s0, nanojit::LIns* s1); - bool condBranch(nanojit::LOpcode op, nanojit::LIns* cond, nanojit::LIns** brOut); - nanojit::LIns* unoptimizableCondBranch(nanojit::LOpcode op, nanojit::LIns* cond); - void labelForBranch(nanojit::LIns* br); - void labelForBranches(nanojit::LIns* br1, nanojit::LIns* br2); - - nanojit::LIns* i2d(nanojit::LIns* i); nanojit::LIns* d2i(nanojit::LIns* f, bool resultCanBeImpreciseIfFractional = false); - nanojit::LIns* f2u(nanojit::LIns* f); + nanojit::LIns* d2u(nanojit::LIns* d); JS_REQUIRES_STACK RecordingStatus makeNumberInt32(nanojit::LIns* d, nanojit::LIns** num_ins); JS_REQUIRES_STACK nanojit::LIns* stringify(const Value& v); @@ -1349,8 +1315,6 @@ class TraceRecorder void forgetGuardedShapes(); - inline nanojit::LIns* shape_ins(nanojit::LIns *obj_ins); - inline nanojit::LIns* slots(nanojit::LIns *obj_ins); JS_REQUIRES_STACK AbortableRecordingStatus test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2, PCVal& pcval); JS_REQUIRES_STACK RecordingStatus guardPropertyCacheHit(nanojit::LIns* obj_ins, @@ -1366,16 +1330,8 @@ class TraceRecorder void stobj_set_slot(JSObject *obj, nanojit::LIns* obj_ins, unsigned slot, nanojit::LIns*& slots_ins, const Value &v, nanojit::LIns* v_ins); - nanojit::LIns* stobj_get_slot_uint32(nanojit::LIns* obj_ins, unsigned slot); nanojit::LIns* unbox_slot(JSObject *obj, nanojit::LIns *obj_ins, uint32 slot, VMSideExit *exit); - nanojit::LIns* stobj_get_parent(nanojit::LIns* obj_ins); - nanojit::LIns* stobj_get_private(nanojit::LIns* obj_ins); - nanojit::LIns* stobj_get_private_uint32(nanojit::LIns* obj_ins); - nanojit::LIns* stobj_get_proto(nanojit::LIns* obj_ins); - - /* For slots holding private pointers. */ - nanojit::LIns* stobj_get_const_private_ptr(nanojit::LIns *obj_ins, unsigned slot); JS_REQUIRES_STACK AbortableRecordingStatus name(Value*& vp, nanojit::LIns*& ins, NameResult& nr); JS_REQUIRES_STACK AbortableRecordingStatus prop(JSObject* obj, nanojit::LIns* obj_ins, @@ -1391,14 +1347,12 @@ class TraceRecorder VMSideExit* exit); JS_REQUIRES_STACK nanojit::LIns *canonicalizeNaNs(nanojit::LIns *dval_ins); JS_REQUIRES_STACK AbortableRecordingStatus typedArrayElement(Value& oval, Value& idx, Value*& vp, - nanojit::LIns*& v_ins, - nanojit::LIns*& addr_ins); + nanojit::LIns*& v_ins); JS_REQUIRES_STACK AbortableRecordingStatus getProp(JSObject* obj, nanojit::LIns* obj_ins); JS_REQUIRES_STACK AbortableRecordingStatus getProp(Value& v); JS_REQUIRES_STACK RecordingStatus getThis(nanojit::LIns*& this_ins); - JS_REQUIRES_STACK void storeMagic(JSWhyMagic why, nanojit::LIns *addr_ins, ptrdiff_t offset, - nanojit::AccSet accSet); + JS_REQUIRES_STACK void storeMagic(JSWhyMagic why, tjit::Address addr); JS_REQUIRES_STACK AbortableRecordingStatus unboxNextValue(nanojit::LIns* &v_ins); JS_REQUIRES_STACK VMSideExit* enterDeepBailCall(); @@ -1419,9 +1373,6 @@ class TraceRecorder nanojit::LIns* obj_ins, const js::Shape* shape); - JS_REQUIRES_STACK nanojit::LIns* getStringLengthAndFlags(nanojit::LIns* str_ins); - JS_REQUIRES_STACK nanojit::LIns* getStringLength(nanojit::LIns* str_ins); - JS_REQUIRES_STACK nanojit::LIns* getStringChars(nanojit::LIns* str_ins); JS_REQUIRES_STACK RecordingStatus getCharCodeAt(JSString *str, nanojit::LIns* str_ins, nanojit::LIns* idx_ins, nanojit::LIns** out_ins); @@ -1449,18 +1400,15 @@ class TraceRecorder JS_REQUIRES_STACK AbortableRecordingStatus setElem(int lval_spindex, int idx_spindex, int v_spindex); - void box_undefined_into(nanojit::LIns *dstaddr_ins, ptrdiff_t offset, nanojit::AccSet accSet); + void box_undefined_into(tjit::Address addr); #if JS_BITS_PER_WORD == 32 - void box_null_into(nanojit::LIns *dstaddr_ins, ptrdiff_t offset, nanojit::AccSet accSet); - nanojit::LIns* unbox_number_as_double(nanojit::LIns* vaddr_ins, ptrdiff_t offset, - nanojit::LIns* tag_ins, VMSideExit* exit, - nanojit::AccSet accSet); - nanojit::LIns* unbox_object(nanojit::LIns* vaddr_ins, ptrdiff_t offset, - nanojit::LIns* tag_ins, JSValueType type, VMSideExit* exit, - nanojit::AccSet accSet); - nanojit::LIns* unbox_non_double_object(nanojit::LIns* vaddr_ins, ptrdiff_t offset, - nanojit::LIns* tag_ins, JSValueType type, - VMSideExit* exit, nanojit::AccSet accSet); + void box_null_into(tjit::Address addr); + nanojit::LIns* unbox_number_as_double(tjit::Address addr, nanojit::LIns* tag_ins, + VMSideExit* exit); + nanojit::LIns* unbox_object(tjit::Address addr, nanojit::LIns* tag_ins, JSValueType type, + VMSideExit* exit); + nanojit::LIns* unbox_non_double_object(tjit::Address addr, nanojit::LIns* tag_ins, + JSValueType type, VMSideExit* exit); #elif JS_BITS_PER_WORD == 64 nanojit::LIns* non_double_object_value_has_type(nanojit::LIns* v_ins, JSValueType type); nanojit::LIns* unpack_ptr(nanojit::LIns* v_ins); @@ -1469,22 +1417,18 @@ class TraceRecorder nanojit::LIns* unbox_non_double_object(nanojit::LIns* v_ins, JSValueType type, VMSideExit* exit); #endif - nanojit::LIns* unbox_value(const Value& v, nanojit::LIns* vaddr_ins, - ptrdiff_t offset, nanojit::AccSet accSet, VMSideExit* exit, + nanojit::LIns* unbox_value(const Value& v, tjit::Address addr, VMSideExit* exit, bool force_double=false); - void unbox_any_object(nanojit::LIns* vaddr_ins, nanojit::LIns** obj_ins, - nanojit::LIns** is_obj_ins, nanojit::AccSet accSet); - nanojit::LIns* is_boxed_true(nanojit::LIns* vaddr_ins, nanojit::AccSet accSet); - nanojit::LIns* is_boxed_magic(nanojit::LIns* vaddr_ins, JSWhyMagic why, nanojit::AccSet accSet); + void unbox_any_object(tjit::Address addr, nanojit::LIns** obj_ins, nanojit::LIns** is_obj_ins); + nanojit::LIns* is_boxed_true(tjit::Address addr); + nanojit::LIns* is_boxed_magic(tjit::Address addr, JSWhyMagic why); nanojit::LIns* is_string_id(nanojit::LIns* id_ins); nanojit::LIns* unbox_string_id(nanojit::LIns* id_ins); nanojit::LIns* unbox_int_id(nanojit::LIns* id_ins); /* Box a slot on trace into the given address at the given offset. */ - void box_value_into(const Value& v, nanojit::LIns* v_ins, - nanojit::LIns* dstaddr_ins, ptrdiff_t offset, - nanojit::AccSet accSet); + void box_value_into(const Value& v, nanojit::LIns* v_ins, tjit::Address addr); /* * Box a slot so that it may be passed with value semantics to a native. On diff --git a/js/src/tracejit/Writer.cpp b/js/src/tracejit/Writer.cpp new file mode 100644 index 00000000000..59177bdbc46 --- /dev/null +++ b/js/src/tracejit/Writer.cpp @@ -0,0 +1,548 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=99 ft=cpp: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released + * May 28, 2008. + * + * The Initial Developer of the Original Code is + * the Mozilla Corporation. + * + * Contributor(s): + * Nicholas Nethercote + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "jsprf.h" +#include "jstl.h" +#include "Writer.h" +#include "nanojit.h" + +namespace js { +namespace tjit { + +using namespace nanojit; + +class FuncFilter : public LirWriter +{ +public: + FuncFilter(LirWriter *out): + LirWriter(out) + { + } + + LIns *ins2(LOpcode v, LIns *s0, LIns *s1) + { + if (s0 == s1 && v == LIR_eqd) { + if (IsPromote(s0)) { + // double(int) and double(uint) cannot be nan + return insImmI(1); + } + if (s0->isop(LIR_muld) || s0->isop(LIR_subd) || s0->isop(LIR_addd)) { + LIns *lhs = s0->oprnd1(); + LIns *rhs = s0->oprnd2(); + if (IsPromote(lhs) && IsPromote(rhs)) { + // add/sub/mul promoted ints can't be nan + return insImmI(1); + } + } + } else if (isCmpDOpcode(v)) { + if (IsPromoteInt(s0) && IsPromoteInt(s1)) { + // demote fcmp to cmp + v = cmpOpcodeD2I(v); + return out->ins2(v, Demote(out, s0), Demote(out, s1)); + } else if (IsPromoteUint(s0) && IsPromoteUint(s1)) { + // uint compare + v = cmpOpcodeD2UI(v); + return out->ins2(v, Demote(out, s0), Demote(out, s1)); + } + } + return out->ins2(v, s0, s1); + } +}; + +void +Writer::init(LogControl *logc_) +{ + JS_ASSERT(logc_); + logc = logc_; + + LirWriter *&lir = InitConst(this->lir); + CseFilter *&cse = InitConst(this->cse); + lir = new (alloc) LirBufWriter(lirbuf, AvmCore::config); +#ifdef DEBUG + ValidateWriter *validate2; + lir = validate2 = + new (alloc) ValidateWriter(lir, lirbuf->printer, "end of writer pipeline"); +#endif +#ifdef JS_JIT_SPEW + if (logc->lcbits & LC_TMRecorder) + lir = new (alloc) VerboseWriter(*alloc, lir, lirbuf->printer, logc); +#endif + // CseFilter must be downstream of SoftFloatFilter (see bug 527754 for why). + if (avmplus::AvmCore::config.cseopt) + lir = cse = new (alloc) CseFilter(lir, TM_NUM_USED_ACCS, *alloc); + lir = new (alloc) ExprFilter(lir); + lir = new (alloc) FuncFilter(lir); +#ifdef DEBUG + ValidateWriter *validate1 = + new (alloc) ValidateWriter(lir, lirbuf->printer, "start of writer pipeline"); + lir = validate1; +#endif +} + +bool +IsPromoteInt(LIns* ins) +{ + if (ins->isop(LIR_i2d)) + return true; + if (ins->isImmD()) { + jsdouble d = ins->immD(); + return d == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d); + } + return false; +} + +bool +IsPromoteUint(LIns* ins) +{ + if (ins->isop(LIR_ui2d)) + return true; + if (ins->isImmD()) { + jsdouble d = ins->immD(); + return d == jsdouble(jsuint(d)) && !JSDOUBLE_IS_NEGZERO(d); + } + return false; +} + +bool +IsPromote(LIns* ins) +{ + return IsPromoteInt(ins) || IsPromoteUint(ins); +} + +LIns * +Demote(LirWriter *out, LIns *ins) +{ + JS_ASSERT(ins->isD()); + if (ins->isCall()) + return ins->callArgN(0); + if (ins->isop(LIR_i2d) || ins->isop(LIR_ui2d)) + return ins->oprnd1(); + JS_ASSERT(ins->isImmD()); + double cf = ins->immD(); + int32_t ci = cf > 0x7fffffff ? uint32_t(cf) : int32_t(cf); + return out->insImmI(ci); +} + +} /* namespace tjit */ +} /* namespace js */ + +#ifdef DEBUG +namespace nanojit { + +using namespace js; +using namespace js::tjit; + +static bool +match(LIns *base, LOpcode opcode, AccSet accSet, int32_t disp) +{ + return base->isop(opcode) && + base->accSet() == accSet && + base->disp() == disp; +} + +static bool +match(LIns *base, LOpcode opcode, AccSet accSet, LoadQual loadQual, int32_t disp) +{ + return base->isop(opcode) && + base->accSet() == accSet && + base->loadQual() == loadQual && + base->disp() == disp; +} + +static bool +couldBeObjectOrString(LIns *ins) +{ + bool ret = false; + + if (ins->isop(LIR_callp)) { + // ins = callp ... # could be a call to an object-creating function + ret = true; + + } else if (ins->isop(LIR_ldp)) { + // ins = ldp ... # could be an object, eg. loaded from the stack + ret = true; + + } else if (ins->isImmP()) { + // ins = immp ... # could be a pointer to an object + uintptr_t val = uintptr_t(ins->immP()); + if (val == 0 || val > 4096) + ret = true; // Looks like a pointer + + } else if (ins->isop(LIR_cmovp)) { + // ins = cmovp , + ret = couldBeObjectOrString(ins->oprnd2()) && + couldBeObjectOrString(ins->oprnd3()); + + } else if (!avmplus::AvmCore::use_cmov() && + ins->isop(LIR_ori) && + ins->oprnd1()->isop(LIR_andi) && + ins->oprnd2()->isop(LIR_andi)) + { + // This is a partial check for the insChoose() code that only occurs + // is use_cmov() is false. + // + // ins_oprnd1 = andi ... + // ins_oprnd2 = andi ... + // ins = ori ins_oprnd1, ins_oprnd2 + ret = true; + +#if JS_BITS_PER_WORD == 64 + } else if (ins->isop(LIR_andq) && + ins->oprnd1()->isop(LIR_ldq) && + ins->oprnd2()->isImmQ() && + uintptr_t(ins->oprnd2()->immQ()) == JSVAL_PAYLOAD_MASK) + { + // ins_oprnd1 = ldq ... + // ins_oprnd2 = immq JSVAL_PAYLOAD_MASK + // ins = andq ins_oprnd1, ins_oprnd2 + ret = true; +#endif + } else if (ins->isop(LIR_addp) && + ((ins->oprnd1()->isImmP() && + (void *)ins->oprnd1()->immP() == JSString::unitStringTable) || + (ins->oprnd2()->isImmP() && + (void *)ins->oprnd2()->immP() == JSString::unitStringTable))) + { + // (String only) + // ins = addp ..., JSString::unitStringTable + // OR + // ins = addp JSString::unitStringTable, ... + ret = true; + } + + return ret; +} + +static bool +isConstPrivatePtr(LIns *ins, unsigned slot) +{ +#if JS_BITS_PER_WORD == 32 + // ins = ldp.slots/c ...[] + return match(ins, LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value) + sPayloadOffset); +#elif JS_BITS_PER_WORD == 64 + // ins_oprnd1 = ldp.slots/c ...[] + // ins_oprnd2 = immi 1 + // ins = lshq ins_oprnd1, ins_oprnd2 + return ins->isop(LIR_lshq) && + match(ins->oprnd1(), LIR_ldp, ACCSET_SLOTS, LOAD_CONST, slot * sizeof(Value)) && + ins->oprnd2()->isImmI(1); +#endif +} + +/* + * Any time you use an AccSet annotation other than ACCSET_ALL, you are making + * a promise to Nanojit about the properties of the annotated load/store/call. + * If that annotation is wrong, it could cause rare and subtle bugs. So this + * function does its damnedest to prevent such bugs occurring by carefully + * checking every load and store. + * + * For some access regions, we can check perfectly -- eg. for an ACCSET_STATE + * load/store, the base pointer must be 'state'. For others, we can only + * check imperfectly -- eg. for an ACCSET_OBJ_CLASP load/store, we can check that + * the base pointer has one of several forms, but it's possible that a + * non-object has that form as well. This imperfect checking is unfortunate + * but unavoidable. Also, multi-region load/store AccSets are not checked, + * and so are best avoided (they're rarely needed). Finally, the AccSet + * annotations on calls cannot be checked here; in some cases they can be + * partially checked via assertions (eg. by checking that certain values + * are not changed by the function). + */ +void ValidateWriter::checkAccSet(LOpcode op, LIns *base, int32_t disp, AccSet accSet) +{ + bool ok; + + NanoAssert(accSet != ACCSET_NONE); + + #define dispWithin(Struct) \ + (0 <= disp && disp < int32_t(sizeof(Struct))) + + switch (accSet) { + case ACCSET_STATE: + // base = paramp 0 0 + // ins = {ld,st}X.state base[] + ok = dispWithin(TracerState) && + base->isop(LIR_paramp) && + base->paramKind() == 0 && + base->paramArg() == 0; + break; + + case ACCSET_STACK: + // base = ldp.state ...[offsetof(TracerState, sp)] + // ins = {ld,st}X.sp base[...] + // OR + // base_oprnd1 = ldp.state ...[offsetof(TraceState, sp)] + // base = addp base_oprnd1, ... + // ins = {ld,st}X.sp base[...] + ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp)) || + (base->isop(LIR_addp) && + match(base->oprnd1(), LIR_ldp, ACCSET_STATE, offsetof(TracerState, sp))); + break; + + case ACCSET_RSTACK: + // base = ldp.state ...[offsetof(TracerState, rp)] + // ins = {ld,st}p.rp base[...] + // OR + // base = ldp.state ...[offsetof(TracerState, callstackBaseOffset)] + // ins = {ld,st}p.rp base[...] + ok = (op == LIR_ldp || op == LIR_stp) && + (match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, rp)) || + match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, callstackBase))); + break; + + case ACCSET_CX: + // base = ldp.state ...[offsetof(TracerState, cx)] + // ins = {ld,st}X.cx base[] + ok = dispWithin(JSContext) && + match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, cx)); + break; + + case ACCSET_EOS: + // base = ldp.state ...[offsetof(TracerState, eos)] + // ins = {ld,st}X.eos base[...] + ok = match(base, LIR_ldp, ACCSET_STATE, offsetof(TracerState, eos)); + break; + + case ACCSET_ALLOC: + // base = allocp ... + // ins = {ld,st}X.alloc base[...] + // OR + // base_oprnd1 = allocp ... + // base = addp base_oprnd1, ... + // ins = {ld,st}X.alloc base[...] + ok = base->isop(LIR_allocp) || + (base->isop(LIR_addp) && + base->oprnd1()->isop(LIR_allocp)); + break; + + case ACCSET_FRAMEREGS: + // base = ldp.cx ...[offsetof(JSContext, regs)] + // ins = ldp.regs base[] + ok = op == LIR_ldp && + dispWithin(JSFrameRegs) && + match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, regs)); + break; + + case ACCSET_STACKFRAME: + // base = ldp.regs ...[offsetof(JSFrameRegs, fp)] + // ins = {ld,st}X.sf base[] + ok = dispWithin(JSStackFrame) && + match(base, LIR_ldp, ACCSET_FRAMEREGS, offsetof(JSFrameRegs, fp)); + break; + + case ACCSET_RUNTIME: + // base = ldp.cx ...[offsetof(JSContext, runtime)] + // ins = ldp.rt base[] + ok = dispWithin(JSRuntime) && + match(base, LIR_ldp, ACCSET_CX, offsetof(JSContext, runtime)); + break; + + // This check is imperfect. + // + // base = + // ins = ldp.obj base[offsetof(JSObject, )] + #define OK_OBJ_FIELD(ldop, field) \ + op == ldop && \ + disp == offsetof(JSObject, field) && \ + couldBeObjectOrString(base) + + case ACCSET_OBJ_CLASP: + ok = OK_OBJ_FIELD(LIR_ldp, clasp); + break; + + case ACCSET_OBJ_FLAGS: + ok = OK_OBJ_FIELD(LIR_ldi, flags); + break; + + case ACCSET_OBJ_SHAPE: + ok = OK_OBJ_FIELD(LIR_ldi, objShape); + break; + + case ACCSET_OBJ_PROTO: + ok = OK_OBJ_FIELD(LIR_ldp, proto); + break; + + case ACCSET_OBJ_PARENT: + ok = OK_OBJ_FIELD(LIR_ldp, parent); + break; + + case ACCSET_OBJ_PRIVATE: + // base = + // ins = ldp.objprivate base[offsetof(JSObject, privateData)] + ok = (op == LIR_ldi || op == LIR_ldp) && + disp == offsetof(JSObject, privateData) && + couldBeObjectOrString(base); + break; + + case ACCSET_OBJ_CAPACITY: + ok = OK_OBJ_FIELD(LIR_ldi, capacity); + break; + + case ACCSET_OBJ_SLOTS: + ok = OK_OBJ_FIELD(LIR_ldp, slots); + break; + + case ACCSET_SLOTS: + // This check is imperfect. + // + // base = # direct slot access + // ins = {ld,st}X.slots base[...] + // OR + // base = ldp.objslots ...[offsetof(JSObject, slots)] # indirect slot access + // ins = {ld,st}X.slots base[...] + // OR + // base_oprnd1 = ldp.objslots ...[offsetof(JSObject, slots)] # indirect scaled slot access + // base = addp base_oprnd1, ... + // ins = {ld,st}X.slots base[...] + ok = couldBeObjectOrString(base) || + match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)) || + (base->isop(LIR_addp) && + match(base->oprnd1(), LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots))); + break; + + case ACCSET_TARRAY: + // This check is imperfect. + // + // base = ldp.objprivate ...[offsetof(JSObject, privateData)] + // ins = ld{i,p}.tarray base[] + ok = (op == LIR_ldi || op == LIR_ldp) && + dispWithin(TypedArray) && + match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); + break; + + case ACCSET_TARRAY_DATA: + // base_oprnd1 = ldp.tarray ...[TypedArray::dataOffset()] + // base = addp base_oprnd1, ... + // ins = {ld,st}X.tdata base[...] + ok = base->isop(LIR_addp) && + match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, TypedArray::dataOffset()); + break; + + case ACCSET_ITER: + // base = ldp.objprivate ...[offsetof(JSObject, privateData)] + // ins = {ld,st}p.iter base[] + ok = (op == LIR_ldp || op == LIR_stp) && + dispWithin(NativeIterator) && + match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); + break; + + case ACCSET_ITER_PROPS: + // base = ldp.iter ...[offsetof(NativeIterator, props_cursor)] + // ins = ld{i,p,d}.iterprops base[0|4] + ok = (op == LIR_ldi || op == LIR_ldp || op == LIR_ldd) && + (disp == 0 || disp == 4) && + match(base, LIR_ldp, ACCSET_ITER, offsetof(NativeIterator, props_cursor)); + break; + + case ACCSET_STRING: + // This check is imperfect. + // + // base = + // ins = {ld,st}X.str base[] + ok = dispWithin(JSString) && + couldBeObjectOrString(base); + break; + + case ACCSET_STRING_MCHARS: + // base = ldp.string ...[offsetof(JSString, mChars)] + // ins = ldus2ui.strchars/c base[0] + // OR + // base_oprnd1 = ldp.string ...[offsetof(JSString, mChars)] + // base = addp base_oprnd1, ... + // ins = ldus2ui.strchars/c base[0] + ok = op == LIR_ldus2ui && + disp == 0 && + (match(base, LIR_ldp, ACCSET_STRING, offsetof(JSString, mChars)) || + (base->isop(LIR_addp) && + match(base->oprnd1(), LIR_ldp, ACCSET_STRING, offsetof(JSString, mChars)))); + break; + + case ACCSET_TYPEMAP: + // This check is imperfect, things get complicated once you get back + // farther than 'base'. But the parts we check are pretty distinctive + // and should be good enough. + // + // base = addp base_oprnd1, ... + // ins = lduc2ui.typemap/c base[0] + ok = op == LIR_lduc2ui && + disp == 0 && + base->isop(LIR_addp); + break; + + case ACCSET_FCSLOTS: + // This check is imperfect. + // + // base = + // ins = {ld,st}X.fcslots base[...] + ok = isConstPrivatePtr(base, JSObject::JSSLOT_FLAT_CLOSURE_UPVARS); + break; + + case ACCSET_ARGS_DATA: + // This check is imperfect. + // + // base = + // ins = st{i,p,d}.argsdata base[...] + // OR + // base_oprnd1 = + // base = addp base_oprnd1, ... + // ins = {ld,st}X.argsdata base[...] + ok = (isConstPrivatePtr(base, JSObject::JSSLOT_ARGS_DATA) || + (base->isop(LIR_addp) && + isConstPrivatePtr(base->oprnd1(), JSObject::JSSLOT_ARGS_DATA))); + break; + + default: + // This assertion will fail if any single-region AccSets aren't covered + // by the switch -- only multi-region AccSets should be handled here. + JS_ASSERT(!isSingletonAccSet(accSet)); + ok = true; + break; + } + + if (!ok) { + InsBuf b1, b2; + printer->formatIns(&b1, base); + JS_snprintf(b2.buf, b2.len, "base = (%s); disp = %d", b1.buf, disp); + errorAccSet(lirNames[op], accSet, b2.buf); + } +} + +} + +#endif + diff --git a/js/src/tracejit/Writer.h b/js/src/tracejit/Writer.h new file mode 100644 index 00000000000..6ea0ac830ca --- /dev/null +++ b/js/src/tracejit/Writer.h @@ -0,0 +1,1185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=99 ft=cpp: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released + * May 28, 2008. + * + * The Initial Developer of the Original Code is + * the Mozilla Corporation. + * + * Contributor(s): + * Nicholas Nethercote + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef tracejit_Writer_h___ +#define tracejit_Writer_h___ + +#include "jsiter.h" +#include "jsobj.h" +#include "jsstr.h" +#include "jstypedarray.h" +#include "nanojit.h" + +namespace js { +namespace tjit { + +namespace nj = nanojit; + +#if defined(DEBUG) && !defined(JS_JIT_SPEW) +#define JS_JIT_SPEW +#endif + +#if defined(JS_JIT_SPEW) || defined(NJ_NO_VARIADIC_MACROS) + +enum LC_TMBits { + /* + * Output control bits for all non-Nanojit code. Only use bits 16 and + * above, since Nanojit uses 0 .. 15 itself. + */ + LC_TMMinimal = 1<<16, + LC_TMTracer = 1<<17, + LC_TMRecorder = 1<<18, + LC_TMAbort = 1<<19, + LC_TMStats = 1<<20, + LC_TMTreeVis = 1<<21, + LC_TMProfiler = 1<<22 +}; + +#endif + +/* + * See LIR.h for the definition of the AccSet type. + * + * *** WARNING WARNING WARNING *** + * + * Any incorrect access region annotations on loads/stores/calls could lead to + * subtle bugs that manifest rarely, eg. when two loads are CSE'd that + * shouldn't be. + * + * If you add a new access region you will need to add some sanity checking to + * ValidateWriter::checkAccSet(). Do not skimp on this checking! Make it as + * strong as you can. Look at the existing cases for inspiration. This + * checking helps prevent these subtle bugs. + * + * Furthermore, do not add a "catch-all" region such as "ACCSET_OTHER". There + * are two reasons for this. First, no checking could be done on loads/stores + * bearing it. Second, it would be too easy for someone in the future who + * doesn't understand how AccSets work to use it inappropriately. Only + * ACCSET_ALL (the union of all access regions) should be used as a catch-all, + * it can always be used safely, but it reduces optimization possibilities. + * + * Most of the access regions are type-based, ie. all structs of a particular + * type combined together form a region. This is less precise than + * considering each struct separately, but also much simpler. + * + * - ACCSET_STATE: The TracerState struct. + * - ACCSET_STACK: The stack. + * - ACCSET_RSTACK: The return stack. + * - ACCSET_CX: All JSContext structs. + * - ACCSET_EOS: The globals area. + * - ACCSET_ALLOC: All memory blocks allocated with LIR_allocp (in + * other words, this region is the AR space). + * - ACCSET_FRAMEREGS: All JSFrameRegs structs. + * - ACCSET_STACKFRAME: All JSStackFrame objects. + * - ACCSET_RUNTIME: The JSRuntime object. + * - ACCSET_OBJ_CLASP: The 'clasp' field of all JSObjects. + * - ACCSET_OBJ_FLAGS: The 'flags' field of all JSObjects. + * - ACCSET_OBJ_SHAPE: The 'shape' field of all JSObjects. + * - ACCSET_OBJ_PROTO: The 'proto' field of all JSObjects. + * - ACCSET_OBJ_PARENT: The 'parent' field of all JSObjects. + * - ACCSET_OBJ_PRIVATE: The 'private' field of all JSObjects. + * - ACCSET_OBJ_CAPACITY: The 'capacity' field of all JSObjects. + * - ACCSET_OBJ_SLOTS: The 'slots' field of all JSObjects. + * - ACCSET_SLOTS: The slots (be they fixed or dynamic) of all JSObjects. + * - ACCSET_TARRAY: All TypedArray structs. + * - ACCSET_TARRAY_DATA: All TypedArray data arrays. + * - ACCSET_ITER: All NativeIterator structs. + * - ACCSET_ITER_PROPS: The props_arrays of all NativeIterator structs. + * - ACCSET_STRING: All JSString structs. + * - ACCSET_STRING_MCHARS: All JSString mchars arrays. + * - ACCSET_TYPEMAP: All typemaps form a single region. + * - ACCSET_FCSLOTS: All fcslots arrays form a single region. + * - ACCSET_ARGS_DATA: All Arguments data arrays form a single region. + */ +static const nanojit::AccSet ACCSET_STATE = (1 << 0); +static const nanojit::AccSet ACCSET_STACK = (1 << 1); +static const nanojit::AccSet ACCSET_RSTACK = (1 << 2); +static const nanojit::AccSet ACCSET_CX = (1 << 3); +static const nanojit::AccSet ACCSET_EOS = (1 << 4); +static const nanojit::AccSet ACCSET_ALLOC = (1 << 5); +static const nanojit::AccSet ACCSET_FRAMEREGS = (1 << 6); +static const nanojit::AccSet ACCSET_STACKFRAME = (1 << 7); +static const nanojit::AccSet ACCSET_RUNTIME = (1 << 8); + +// Nb: JSObject::{lastProp,map,flags} don't have an AccSet because they are never accessed on trace +static const nanojit::AccSet ACCSET_OBJ_CLASP = (1 << 9); +static const nanojit::AccSet ACCSET_OBJ_FLAGS = (1 << 10); +static const nanojit::AccSet ACCSET_OBJ_SHAPE = (1 << 11); +static const nanojit::AccSet ACCSET_OBJ_PROTO = (1 << 12); +static const nanojit::AccSet ACCSET_OBJ_PARENT = (1 << 13); +static const nanojit::AccSet ACCSET_OBJ_PRIVATE = (1 << 14); +static const nanojit::AccSet ACCSET_OBJ_CAPACITY = (1 << 15); +static const nanojit::AccSet ACCSET_OBJ_SLOTS = (1 << 16); // the pointer to the slots + +static const nanojit::AccSet ACCSET_SLOTS = (1 << 17); // the slots themselves +static const nanojit::AccSet ACCSET_TARRAY = (1 << 18); +static const nanojit::AccSet ACCSET_TARRAY_DATA = (1 << 19); +static const nanojit::AccSet ACCSET_ITER = (1 << 20); +static const nanojit::AccSet ACCSET_ITER_PROPS = (1 << 21); +static const nanojit::AccSet ACCSET_STRING = (1 << 22); +static const nanojit::AccSet ACCSET_STRING_MCHARS = (1 << 23); +static const nanojit::AccSet ACCSET_TYPEMAP = (1 << 24); +static const nanojit::AccSet ACCSET_FCSLOTS = (1 << 25); +static const nanojit::AccSet ACCSET_ARGS_DATA = (1 << 26); + +static const uint8_t TM_NUM_USED_ACCS = 27; // number of access regions used by TraceMonkey + +/* + * An Address describes everything about a loaded/stored memory location. One + * only be created via the sub-classes below and only accessed via class + * Writer; this is so that AccSets are encapsulated as much as possible. + */ +struct Address +{ + friend class Writer; + + private: + nj::LIns *base; + int32 offset; + nj::AccSet accSet; + + protected: + Address(nj::LIns *base, int32 offset, nj::AccSet accSet) + : base(base), offset(offset), accSet(accSet) {} + + Address(Address addr, int32 offset) + : base(addr.base), offset(addr.offset + offset), accSet(addr.accSet) {} +}; + + +/* Addresses, ordered by AccSet. */ + +struct StackAddress : Address +{ + StackAddress(nj::LIns *base, int32 offset) + : Address(base, offset, ACCSET_STACK) {} +}; + +struct CxAddress : Address +{ + CxAddress(nj::LIns *base, int32 offset) + : Address(base, offset, ACCSET_CX) {} +}; +#define CxAddress(fieldname) \ + CxAddress(cx_ins, offsetof(JSContext, fieldname)) + +struct EosAddress : Address +{ + EosAddress(nj::LIns *base, int32 offset) + : Address(base, offset, ACCSET_EOS) {} +}; + +struct AllocSlotsAddress : Address +{ + AllocSlotsAddress(nj::LIns *base, unsigned slot = 0) + : Address(base, slot * sizeof(Value), ACCSET_ALLOC) {} +}; + +struct StackFrameAddress : Address +{ + StackFrameAddress(nj::LIns *base, int32 offset) + : Address(base, offset, ACCSET_STACKFRAME) {} +}; + +struct FSlotsAddress : Address +{ + FSlotsAddress(nj::LIns *base, unsigned slot) + : Address(base, JSObject::getFixedSlotOffset(slot), ACCSET_SLOTS) {} +}; + +struct DSlotsAddress : Address +{ + DSlotsAddress(nj::LIns *base, unsigned slot = 0) + : Address(base, slot * sizeof(Value), ACCSET_SLOTS) {} +}; + +struct IterPropsAddress : Address +{ + IterPropsAddress(nj::LIns *base) + : Address(base, 0, ACCSET_ITER_PROPS) {} +}; + +struct FCSlotsAddress : Address +{ + FCSlotsAddress(nj::LIns *base, unsigned slot = 0) + : Address(base, slot * sizeof(Value), ACCSET_FCSLOTS) {} +}; + +struct ArgsSlotsAddress : Address +{ + ArgsSlotsAddress(nj::LIns *base, unsigned slot = 0) + : Address(base, slot * sizeof(Value), ACCSET_ARGS_DATA) {} +}; + +struct AnyAddress : Address +{ + AnyAddress(nj::LIns *base, int32 offset = 0) + : Address(base, offset, nj::ACCSET_ALL) + { + JS_ASSERT(nj::ACCSET_LOAD_ANY == nj::ACCSET_STORE_ANY && + nj::ACCSET_LOAD_ANY == nj::ACCSET_ALL); + } +}; + +/* An offset from a previous Address. */ +struct OffsetAddress : Address +{ + OffsetAddress(Address addr, int32 offset) + : Address(addr, offset) {} +}; + +bool IsPromoteInt(nj::LIns *ins); +bool IsPromoteUint(nj::LIns *ins); +bool IsPromote(nj::LIns *ins); +nj::LIns *Demote(nj::LirWriter *out, nj::LIns *ins); + +/* These would be private to class Writer if they weren't used in AccSet checking. */ +static const size_t sPayloadOffset = offsetof(jsval_layout, s.payload); +#if JS_BITS_PER_WORD == 32 +static const size_t sTagOffset = offsetof(jsval_layout, s.tag); +#endif + +struct MaybeBranch { + bool set; + nj::LIns *br; + MaybeBranch() : set(false), br(NULL) {} + MaybeBranch(nj::LIns *ins) : set(true), br(ins) {} + operator bool() { return set; } + typedef nj::LIns* LInsp; + operator LInsp() { + JS_ASSERT(set); + return br; + } +}; + +/* + * This class provides a layer above Nanojit's basic LirWriter interface. + * The goals of this layer are as follows. + * + * - More concise than the vanilla NJ interface, to promote readability. + * + * - But still a relatively thin layer. + * + * - Completely occludes NJ's interface so that there is no possibility of + * using a combination of both interfaces. This is good because there are + * some cases where the NJ interface is error-prone when used with + * TraceMonkey (eg. when using the NJ interface it's easy to forget to + * handle the cases where a conditional branch is always or never taken). + * + * - Requires only basic Nanojit state (eg. LirBuffer); doesn't rely on state + * from TraceRecorder. + * + * - There should be one or more functions for every opcode that's used (if + * one is missing, please add it), plus minimal generic ones (eg. ins2()). + * This makes for a lot of functions, but promotes readability. + * + * - Loads/stores get special treatment, due to AccSets. AccSets aren't + * exposed at all, although someone using the interface will still need to + * understand them; the goal is not to completely hide their presence but + * to make their use indirect so that it is difficult to get them wrong. + * + * Type/field-specific load/store functions are used where possible. When + * this isn't possible, details about memory locations are abstracted in the + * Address type, which encapsulates a base pointer, an offset and an AccSet. + * + * The only place where AccSets need to be used directly is when specifying + * the .storeAccSet of a CallInfo. + * + * - Functions that insert moderately complex LIR sequences (eg. multiple + * loads) have a 'get' prefix in their name. + */ +class Writer +{ + private: + nj::Allocator *alloc; + nj::LirBuffer *lirbuf; // passed in from outside + nj::LirWriter *const lir; // created in this class + nj::CseFilter *const cse; // created in this class + + nj::LogControl *logc; // passed in from outside + + public: + Writer(nj::Allocator *alloc, nj::LirBuffer *lirbuf) + : alloc(alloc), lirbuf(lirbuf), lir(NULL), cse(NULL), logc(NULL) {} + + void init(nj::LogControl *logc); + + nj::LIns *name(nj::LIns *ins, const char *name) const { +#ifdef JS_JIT_SPEW + /* No point adding names unless .lcbits > 0. */ + if (logc->lcbits > 0) + lirbuf->printer->lirNameMap->addName(ins, name); +#endif + return ins; + } + + /* + * These two don't generate any code, they control the internal state of + * the CseFilter. They can be put around a control-flow diamond if it's + * important that CSE work across the diamond. (If they aren't used, the + * diamond will reset all CSE state.) Duplicated expressions within the + * diamond will be CSE'd, but expressions defined within the diamond won't + * be added to the tables of CSEable expressions. Loads are still + * invalidated if they alias any stores that occur within diamonds. + */ + void pauseAddingCSEValues() { if (cse) cse->suspend(); } + void resumeAddingCSEValues() { if (cse) cse->resume(); } + + /* Miscellaneous operations */ + + nj::LIns *start() const { + return lir->ins0(nj::LIR_start); + } + + nj::LIns *paramp(int32 arg, int32 kind) const { + return lir->insParam(arg, kind); + } + + nj::LIns *allocp(int32 size) const { + return lir->insAlloc(size); + } + + nj::LIns *livep(nj::LIns *x) const { + return lir->ins1(nj::LIR_livep, x); + } + + void comment(const char *str) { + #ifdef JS_JIT_SPEW + lir->insComment(str); + #endif + } + + /* Specific loads and stores (those not taking an Address argument). Ordered by AccSets.*/ + + nj::LIns *ldStateFieldHelper(nj::LOpcode op, nj::LIns *state, int32 offset) const { + return lir->insLoad(op, state, offset, ACCSET_STATE); + } + #define ldiStateField(fieldname) \ + ldStateFieldHelper(LIR_ldi, lirbuf->state, offsetof(TracerState, fieldname)) + #define ldpStateField(fieldname) \ + ldStateFieldHelper(LIR_ldp, lirbuf->state, offsetof(TracerState, fieldname)) + + nj::LIns *stStateFieldHelper(nj::LIns *value, nj::LIns *state, int32 offset) const { + return lir->insStore(value, state, offset, ACCSET_STATE); + } + #define stStateField(value, fieldname) \ + stStateFieldHelper(value, lirbuf->state, offsetof(TracerState, fieldname)) + + nj::LIns *ldpRstack(nj::LIns *rp, int32 offset) const { + return lir->insLoad(nj::LIR_ldp, rp, offset, ACCSET_RSTACK); + } + + nj::LIns *stRstack(nj::LIns *value, nj::LIns *rp, int32 offset) const { + return lir->insStore(value, rp, offset, ACCSET_RSTACK); + } + + nj::LIns *ldpContextFieldHelper(nj::LIns *cx, int32 offset, nj::LoadQual loadQual) const { + return lir->insLoad(nj::LIR_ldp, cx, offset, ACCSET_CX, loadQual); + } + #define ldpContextField(fieldname) \ + ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_NORMAL) + #define ldpConstContextField(fieldname) \ + ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_CONST) + + nj::LIns *stContextField(nj::LIns *value, nj::LIns *cx, int32 offset) const { + return lir->insStore(value, cx, offset, ACCSET_CX); + } + #define stContextField(value, fieldname) \ + stContextField((value), cx_ins, offsetof(JSContext, fieldname)) + + nj::LIns *ldiAlloc(nj::LIns *alloc) const { + return lir->insLoad(nj::LIR_ldi, alloc, 0, ACCSET_ALLOC); + } + + nj::LIns *ldpAlloc(nj::LIns *alloc) const { + return lir->insLoad(nj::LIR_ldp, alloc, 0, ACCSET_ALLOC); + } + + nj::LIns *lddAlloc(nj::LIns *alloc) const { + return lir->insLoad(nj::LIR_ldd, alloc, 0, ACCSET_ALLOC); + } + + nj::LIns *stAlloc(nj::LIns *value, nj::LIns *alloc) const { + return lir->insStore(value, alloc, 0, ACCSET_ALLOC); + } + + nj::LIns *ldpFrameFp(nj::LIns *regs) const { + return lir->insLoad(nj::LIR_ldp, regs, offsetof(JSFrameRegs, fp), ACCSET_FRAMEREGS); + } + + nj::LIns *ldpStackFrameScopeChain(nj::LIns *frame) const { + return lir->insLoad(nj::LIR_ldp, frame, JSStackFrame::offsetOfScopeChain(), + ACCSET_STACKFRAME); + } + + nj::LIns *ldiRuntimeProtoHazardShape(nj::LIns *runtime) const { + return name(lir->insLoad(nj::LIR_ldi, runtime, offsetof(JSRuntime, protoHazardShape), + ACCSET_RUNTIME), + "protoHazardShape"); + } + + nj::LIns *ldpObjClasp(nj::LIns *obj, nj::LoadQual loadQual) const { + return lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, clasp), ACCSET_OBJ_CLASP, + loadQual); + } + + nj::LIns *ldiObjFlags(nj::LIns *obj) const { + return lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, flags), ACCSET_OBJ_FLAGS); + } + + nj::LIns *ldiObjShape(nj::LIns *obj) const { + return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, objShape), ACCSET_OBJ_SHAPE), + "objShape"); + } + + nj::LIns *ldpObjProto(nj::LIns *obj) const { + return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, proto), ACCSET_OBJ_PROTO), + "proto"); + } + + nj::LIns *ldpObjParent(nj::LIns *obj) const { + return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, parent), ACCSET_OBJ_PARENT), + "parent"); + } + + nj::LIns *ldpObjPrivate(nj::LIns *obj) const { + return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, privateData), + ACCSET_OBJ_PRIVATE), + "private"); + } + + nj::LIns *lduiObjPrivate(nj::LIns *obj) const { + return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, privateData), + ACCSET_OBJ_PRIVATE), + "private_uint32"); + } + + nj::LIns *ldiDenseArrayCapacity(nj::LIns *array) const { + return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, capacity), + ACCSET_OBJ_CAPACITY), + "capacity"); + } + + nj::LIns *ldpObjSlots(nj::LIns *obj) const { + return lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS); + } + + nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const { + return lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY, + nj::LOAD_CONST); + } + + nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const { + return lir->insLoad(nj::LIR_ldp, array, js::TypedArray::dataOffset(), ACCSET_TARRAY, + nj::LOAD_CONST); + } + + nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_ldc2i, addp(elems, index), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *lduc2uiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_lduc2ui, addp(elems, index), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *lds2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_lds2i, addp(elems, lshpN(index, 1)), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *ldus2uiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_ldus2ui, addp(elems, lshpN(index, 1)), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *ldiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_ldi, addp(elems, lshpN(index, 2)), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *ldf2dTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_ldf2d, addp(elems, lshpN(index, 2)), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *lddTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { + return lir->insLoad(nj::LIR_ldd, addp(elems, lshpN(index, 3)), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *sti2cTypedArrayElement(nj::LIns *value, nj::LIns *elems, nj::LIns *index) const { + return lir->insStore(nj::LIR_sti2c, value, addp(elems, index), 0, ACCSET_TARRAY_DATA); + } + + nj::LIns *sti2sTypedArrayElement(nj::LIns *value, nj::LIns *elems, nj::LIns *index) const { + return lir->insStore(nj::LIR_sti2s, value, addp(elems, lshpN(index, 1)), 0, + ACCSET_TARRAY_DATA); + } + + nj::LIns *stiTypedArrayElement(nj::LIns *value, nj::LIns *elems, nj::LIns *index) const { + return lir->insStore(nj::LIR_sti, value, addp(elems, lshpN(index, 2)), 0, + ACCSET_TARRAY_DATA); + } + + nj::LIns *std2fTypedArrayElement(nj::LIns *value, nj::LIns *elems, nj::LIns *index) const { + return lir->insStore(nj::LIR_std2f, value, addp(elems, lshpN(index, 2)), 0, + ACCSET_TARRAY_DATA); + } + + nj::LIns *stdTypedArrayElement(nj::LIns *value, nj::LIns *elems, nj::LIns *index) const { + return lir->insStore(nj::LIR_std, value, addp(elems, lshpN(index, 3)), 0, + ACCSET_TARRAY_DATA); + } + + nj::LIns *ldpIterCursor(nj::LIns *iter) const { + return name(lir->insLoad(nj::LIR_ldp, iter, offsetof(NativeIterator, props_cursor), + ACCSET_ITER), + "cursor"); + } + + nj::LIns *ldpIterEnd(nj::LIns *iter) const { + return name(lir->insLoad(nj::LIR_ldp, iter, offsetof(NativeIterator, props_end), + ACCSET_ITER), + "end"); + } + + nj::LIns *stpIterCursor(nj::LIns *cursor, nj::LIns *iter) const { + return lir->insStore(nj::LIR_stp, cursor, iter, offsetof(NativeIterator, props_cursor), + ACCSET_ITER); + } + + nj::LIns *ldpStringLengthAndFlags(nj::LIns *str) const { + return lir->insLoad(nj::LIR_ldp, str, offsetof(JSString, mLengthAndFlags), ACCSET_STRING); + } + + nj::LIns *ldpStringChars(nj::LIns *str) const { + return name(lir->insLoad(nj::LIR_ldp, str, offsetof(JSString, mChars), ACCSET_STRING), + "mChars"); + } + + nj::LIns *lduc2uiConstTypeMapEntry(nj::LIns *typemap, nj::LIns *index) const { + nj::LIns *entry = addp(typemap, ui2p(muli(index, name(immi(sizeof(JSValueType)), + "sizeof(JSValueType)")))); + return lir->insLoad(nj::LIR_lduc2ui, entry, 0, ACCSET_TYPEMAP, nj::LOAD_CONST); + } + + nj::LIns *ldiVolatile(nj::LIns *base) const { + return lir->insLoad(nj::LIR_ldi, base, 0, nj::ACCSET_LOAD_ANY, nj::LOAD_VOLATILE); + } + + nj::LIns *stiVolatile(nj::LIns *value, nj::LIns *base) const { + return lir->insStore(nj::LIR_sti, value, base, 0, nj::ACCSET_STORE_ANY); + } + + nj::LIns *ldiVMSideExitFieldHelper(nj::LIns *lr, int32 offset) const { + return lir->insLoad(nj::LIR_ldi, lr, offset, nj::ACCSET_LOAD_ANY); + } + #define ldiVMSideExitField(lr, fieldname) \ + ldiVMSideExitFieldHelper((lr), offsetof(VMSideExit, fieldname)) + + nj::LIns *ldpGuardRecordExit(nj::LIns *gr) const { + /* + * We use ACCSET_LOAD_ANY for the GuardRecord and VMSideExit loads; + * they're immediately after a fragment call, and so won't be + * optimizable anyway. + */ + return lir->insLoad(nj::LIR_ldp, gr, offsetof(nj::GuardRecord, exit), nj::ACCSET_LOAD_ANY); + } + + nj::LIns *stTprintArg(nj::LIns *insa[], nj::LIns *args, int index) const { + JS_ASSERT(insa[index]); + /* The AccSet doesn't matter much here, this is debug-only code. */ + return lir->insStore(insa[index], args, sizeof(double) * index, nj::ACCSET_STORE_ANY); + } + + /* Generic loads and stores (those taking an Address argument). */ + +#if JS_BITS_PER_WORD == 32 + nj::LIns *ldiValueTag(Address addr) const { + return lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sTagOffset, addr.accSet); + } + + nj::LIns *stiValueTag(nj::LIns *tag, Address addr) const { + JS_ASSERT(tag->isI()); + return lir->insStore(tag, addr.base, addr.offset + sTagOffset, addr.accSet); + } + + nj::LIns *ldiValuePayload(Address addr) const { + return lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sPayloadOffset, addr.accSet); + } + + nj::LIns *stiValuePayload(nj::LIns *payload, Address addr) const { + JS_ASSERT(payload->isI()); + return lir->insStore(payload, addr.base, addr.offset + sPayloadOffset, addr.accSet); + } +#endif // JS_BITS_PER_WORD == 32 + + nj::LIns *ldi(Address addr) const { + return lir->insLoad(nj::LIR_ldi, addr.base, addr.offset, addr.accSet); + } + +#ifdef NANOJIT_64BIT + nj::LIns *ldq(Address addr) const { + return lir->insLoad(nj::LIR_ldq, addr.base, addr.offset, addr.accSet); + } + + nj::LIns *stq(nj::LIns *value, Address addr) const { + return lir->insStore(nj::LIR_stq, value, addr.base, addr.offset, addr.accSet); + } +#endif + + nj::LIns *ldp(Address addr) const { + return lir->insLoad(nj::LIR_ldp, addr.base, addr.offset, addr.accSet); + } + + nj::LIns *ldd(Address addr) const { + return lir->insLoad(nj::LIR_ldd, addr.base, addr.offset, addr.accSet); + } + + nj::LIns *std(nj::LIns *value, Address addr) const { + return lir->insStore(nj::LIR_std, value, addr.base, addr.offset, addr.accSet); + } + + nj::LIns *st(nj::LIns *value, Address addr) const { + return lir->insStore(value, addr.base, addr.offset, addr.accSet); + } + + /* Calls */ + + nj::LIns *call(const nj::CallInfo *call, nj::LIns *args[]) const { + return lir->insCall(call, args); + } + + /* Branches and labels */ + + nj::LIns *j(nj::LIns *target) const { + return lir->insBranch(nj::LIR_j, /* cond = */NULL, target); + } + + /* + * If the branch is always taken, return false; the code jumped over by the + * branch need not be generated. If the branch is never taken, return true + * and put NULL in *brOut. Otherwise, return true and put the branch in + * *brOut. + */ + MaybeBranch jt(nj::LIns *cond) { + if (cond->isImmI(1)) + return MaybeBranch(); /* branch is always taken */ + return MaybeBranch(lir->insBranch(nj::LIR_jt, cond, NULL)); /* NULL if never taken */ + } + + /* Like jt(). */ + MaybeBranch jf(nj::LIns *cond) { + if (cond->isImmI(0)) + return MaybeBranch(); /* branch is always taken */ + return MaybeBranch(lir->insBranch(nj::LIR_jf, cond, NULL)); /* NULL if never taken */ + } + + /* + * Like jf(), but for when we know the branch condition cannot be + * optimized to a constant, eg. because one of the operands is the result + * of a volatile load. + */ + nj::LIns *jfUnoptimizable(nj::LIns *cond) const { + JS_ASSERT(!cond->isImmI()); + return lir->insBranch(nj::LIR_jf, cond, /* target = */NULL); + } + + /* Like jfUnoptimizable(). */ + nj::LIns *jtUnoptimizable(nj::LIns *cond) const { + JS_ASSERT(!cond->isImmI()); + return lir->insBranch(nj::LIR_jt, cond, /* target = */NULL); + } + + nj::LIns *label() const { + return lir->ins0(nj::LIR_label); + } + + /* + * Inserts a label and updates 'branch' to branch to it, if 'branch' is non-NULL. + * ('branch' may be NULL if it was a conditional branch and its condition was + * a constant value that resulted in the branch never being taken.) + */ + void label(nj::LIns *br) { + if (br) { + JS_ASSERT(br->isop(nj::LIR_j) || br->isop(nj::LIR_jt) || br->isop(nj::LIR_jf)); + br->setTarget(label()); + } + } + + /* Similar to label(LIns *), but for two branches. */ + void label(nj::LIns *br1, nj::LIns *br2) { + if (br1 || br2) { + nj::LIns *label_ = label(); + if (br1) { + JS_ASSERT(br1->isop(nj::LIR_j) || br1->isop(nj::LIR_jt) || br1->isop(nj::LIR_jf)); + br1->setTarget(label_); + } + if (br2) { + JS_ASSERT(br2->isop(nj::LIR_j) || br2->isop(nj::LIR_jt) || br2->isop(nj::LIR_jf)); + br2->setTarget(label_); + } + } + } + + /* Guards */ + + nj::LIns *x(nj::GuardRecord *gr) const { + return lir->insGuard(nj::LIR_x, /* cond = */NULL, gr); + } + + nj::LIns *xf(nj::LIns *cond, nj::GuardRecord *gr) const { + return lir->insGuard(nj::LIR_xf, cond, gr); + } + + nj::LIns *xt(nj::LIns *cond, nj::GuardRecord *gr) const { + return lir->insGuard(nj::LIR_xt, cond, gr); + } + + nj::LIns *xtbl(nj::LIns *index, nj::GuardRecord *gr) const { + return lir->insGuard(nj::LIR_xtbl, index, gr); + } + + nj::LIns *xbarrier(nj::GuardRecord *gr) const { + return lir->insGuard(nj::LIR_xbarrier, /* cond = */NULL, gr); + } + + /* Immediates */ + + nj::LIns *immi(int32 i) const { + return lir->insImmI(i); + } + + nj::LIns *immiUndefined() const { + return name(immi(0), "0"); + } + + /* + * These must be macros because they stringify their argument. Likewise + * with similar 'nameXYZ' operations below, + * + * These nameXYZ() macros have the 'name' prefix to distinguish them from the + * non-naming XYZ() functions. + */ + #define nameImmi(i) name(w.immi(i), #i) + #define nameImmui(ui) name(w.immi((uint32_t)ui), #ui) + +#ifdef NANOJIT_64BIT + nj::LIns *immq(uint64 q) const { + return lir->insImmQ(q); + } + + #define nameImmq(q) name(w.immq(q), #q) +#endif + + /* + * immpNonGC() can be used to embed arbitrary pointers into the native + * code. It should not be used directly to embed GC thing pointers unless + * they've already been rooted(hence the name). Instead, the + * TraceRecorder::immpXyzGC() variants should be used because they ensure + * that the embedded pointer will be kept alive across GCs. These types + * make it difficult to inadvertently get this wrong. + */ + nj::LIns *immpNonGC(const void *p) const { + return lir->insImmP(p); + } + + #define nameImmpNonGC(p) name(w.immpNonGC(p), #p) + #define nameImmw(ww) name(w.immpNonGC((void *) (ww)), #ww) + + nj::LIns *immpNull() const { + return name(immpNonGC(NULL), "NULL"); + } + + #define immpMagicWhy(why) name(w.immpNonGC((void *)(size_t)(why)), #why) + + nj::LIns *immpMagicNull() const { + return name(immpNonGC(NULL), "MAGIC_NULL"); + } + + nj::LIns *immd(double d) const { + return lir->insImmD(d); + } + + /* Comparisons */ + + nj::LIns *eqi(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_eqi, x, y); + } + + nj::LIns *eqi0(nj::LIns *x) const { + return lir->insEqI_0(x); + } + + nj::LIns *eqiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_eqi, x, imm); + } + + nj::LIns *lti(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_lti, x, y); + } + + nj::LIns *ltiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_lti, x, imm); + } + + nj::LIns *gti(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_gti, x, y); + } + + nj::LIns *gtiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_gti, x, imm); + } + + nj::LIns *geiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_gei, x, imm); + } + + nj::LIns *ltui(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_ltui, x, y); + } + + nj::LIns *ltuiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_ltui, x, imm); + } + + nj::LIns *leui(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_leui, x, y); + } + + nj::LIns *geui(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_geui, x, y); + } + +#ifdef NANOJIT_64BIT + nj::LIns *eqq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_eqq, x, y); + } + + nj::LIns *ltuq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_ltuq, x, y); + } + + nj::LIns *leuq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_leuq, x, y); + } + + nj::LIns *geuq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_geuq, x, y); + } +#endif + + nj::LIns *eqp(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_eqp, x, y); + } + + nj::LIns *eqp0(nj::LIns *x) const { + return lir->insEqP_0(x); + } + + nj::LIns *ltp(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_ltp, x, y); + } + + nj::LIns *ltup(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_ltup, x, y); + } + + nj::LIns *eqd(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_eqd, x, y); + } + + nj::LIns *eqd0(nj::LIns *x) const { + return lir->ins2(nj::LIR_eqd, x, immd(0)); + } + + nj::LIns *ltdN(nj::LIns *x, jsdouble imm) const { + return lir->ins2(nj::LIR_ltd, x, immd(imm)); + } + + /* Arithmetic */ + + nj::LIns *negi(nj::LIns *x) const { + return lir->ins1(nj::LIR_negi, x); + } + + nj::LIns *addi(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_addi, x, y); + } + + nj::LIns *subi(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_subi, x, y); + } + + nj::LIns *muli(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_muli, x, y); + } + + nj::LIns *muliN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_muli, x, imm); + } + + nj::LIns *divi(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_divi, x, y); + } + + nj::LIns *modi(nj::LIns *x) const { + return lir->ins1(nj::LIR_modi, x); + } + + nj::LIns *andi(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_andi, x, y); + } + + nj::LIns *andiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_andi, x, imm); + } + + nj::LIns *ori(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_ori, x, y); + } + + nj::LIns *xoriN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_xori, x, imm); + } + + nj::LIns *lshiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_lshi, x, imm); + } + + nj::LIns *rshiN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_rshi, x, imm); + } + +#ifdef NANOJIT_64BIT + nj::LIns *andq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_andq, x, y); + } + + nj::LIns *orq(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_orq, x, y); + } + + nj::LIns *lshqN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_lshq, x, imm); + } + + nj::LIns *rshuqN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_rshuq, x, imm); + } +#endif + + nj::LIns *addp(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_addp, x, y); + } + + nj::LIns *andp(nj::LIns *x, nj::LIns *y) const { + return lir->ins2(nj::LIR_andp, x, y); + } + + nj::LIns *lshpN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_lshp, x, imm); + } + + nj::LIns *rshupN(nj::LIns *x, int32 imm) const { + return lir->ins2ImmI(nj::LIR_rshup, x, imm); + } + + nj::LIns *negd(nj::LIns *x) const { + return lir->ins1(nj::LIR_negd, x); + } + + nj::LIns *cmovi(nj::LIns *cond, nj::LIns *t, nj::LIns *f) const { + /* We can only use cmovi if the configuration says we can. */ + NanoAssert(t->isI() && f->isI()); + return lir->insChoose(cond, t, f, avmplus::AvmCore::use_cmov()); + } + + nj::LIns *cmovp(nj::LIns *cond, nj::LIns *t, nj::LIns *f) const { + /* We can only use cmovp if the configuration says we can. */ + NanoAssert(t->isP() && f->isP()); + return lir->insChoose(cond, t, f, avmplus::AvmCore::use_cmov()); + } + + nj::LIns *cmovd(nj::LIns *cond, nj::LIns *t, nj::LIns *f) const { + /* We can always use cmovd. */ + NanoAssert(t->isD() && f->isD()); + return lir->insChoose(cond, t, f, /* use_cmov = */true); + } + + /* Conversions */ + +#ifdef NANOJIT_64BIT + nj::LIns *ui2uq(nj::LIns *ins) const { + return lir->ins1(nj::LIR_ui2uq, ins); + } + + nj::LIns *q2i(nj::LIns *ins) const { + return lir->ins1(nj::LIR_q2i, ins); + } +#endif + + nj::LIns *i2p(nj::LIns *x) const { + return lir->insI2P(x); + } + + nj::LIns *ui2p(nj::LIns *x) const { + return lir->insUI2P(x); + } + + nj::LIns *p2i(nj::LIns *x) const { + #ifdef NANOJIT_64BIT + return lir->ins1(nj::LIR_q2i, x); + #else + return x; + #endif + } + + nj::LIns *i2d(nj::LIns *ins) const { + return lir->ins1(nj::LIR_i2d, ins); + } + + nj::LIns *ui2d(nj::LIns *ins) const { + return lir->ins1(nj::LIR_ui2d, ins); + } + + /* + * This is not called d2i() because that could be easily confused with + * TraceRecorder::d2i(), which is usually what should be used. + */ + nj::LIns *rawD2i(nj::LIns *ins) const { + return lir->ins1(nj::LIR_d2i, ins); + } + +#ifdef NANOJIT_64BIT + nj::LIns *dasq(nj::LIns *ins) const { + return lir->ins1(nj::LIR_dasq, ins); + } + + nj::LIns *qasd(nj::LIns *ins) const { + return lir->ins1(nj::LIR_qasd, ins); + } +#endif + + nj::LIns *demote(nj::LIns *ins) const { + return Demote(lir, ins); + } + + /* Overflow arithmetic */ + + nj::LIns *addxovi(nj::LIns *x, nj::LIns *y, nj::GuardRecord *gr) const { + return lir->insGuardXov(nj::LIR_addxovi, x, y, gr); + } + + nj::LIns *subxovi(nj::LIns *x, nj::LIns *y, nj::GuardRecord *gr) const { + return lir->insGuardXov(nj::LIR_subxovi, x, y, gr); + } + + nj::LIns *mulxovi(nj::LIns *x, nj::LIns *y, nj::GuardRecord *gr) const { + return lir->insGuardXov(nj::LIR_mulxovi, x, y, gr); + } + + /* + * Ones not specific to a single opcode. These should not be used if an + * opcode-specific function can be used instead. + */ + + nj::LIns *ins1(nj::LOpcode op, nj::LIns *x) const { + return lir->ins1(op, x); + } + + nj::LIns *ins2(nj::LOpcode op, nj::LIns *x, nj::LIns *y) const { + return lir->ins2(op, x, y); + } + + /* Operations involving non-trivial combinations of multiple instructions. */ + + /* + * Nb: this "Privatized" refers to the Private API in jsvalue.h. It + * doesn't refer to the JSObj::privateData slot! Confusing. + */ + nj::LIns *getObjPrivatizedSlot(nj::LIns *obj, uint32 slot) const { +#if JS_BITS_PER_WORD == 32 + nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), + ACCSET_OBJ_SLOTS); + return lir->insLoad(nj::LIR_ldi, vaddr_ins, + slot * sizeof(Value) + sPayloadOffset, ACCSET_SLOTS, nj::LOAD_CONST); + +#elif JS_BITS_PER_WORD == 64 + /* N.B. On 64-bit, privatized value are encoded differently from other pointers. */ + nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), + ACCSET_OBJ_SLOTS); + nj::LIns *v_ins = lir->insLoad(nj::LIR_ldq, vaddr_ins, + slot * sizeof(Value) + sPayloadOffset, + ACCSET_SLOTS, nj::LOAD_CONST); + return lshqN(v_ins, 1); +#endif + } + + nj::LIns *getDslotAddress(nj::LIns *obj, nj::LIns *idx) const { + nj::LIns *slots = name(ldpObjSlots(obj), "slots"); + JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this. + return addp(slots, lshpN(ui2p(idx), 3)); + } + + nj::LIns *getStringLength(nj::LIns *str) const { + return name(rshupN(name(ldpStringLengthAndFlags(str), "mLengthAndFlags"), + JSString::FLAGS_LENGTH_SHIFT), "length"); + } + + nj::LIns *getStringChar(nj::LIns *str, nj::LIns *idx) const { + nj::LIns *chars = ldpStringChars(str); + return lir->insLoad(nj::LIR_ldus2ui, addp(chars, lshpN(idx, 1)), 0, + ACCSET_STRING_MCHARS, nj::LOAD_CONST); + } + + nj::LIns *getStringChar0(nj::LIns *str) const { + nj::LIns *chars = ldpStringChars(str); + return lir->insLoad(nj::LIR_ldus2ui, chars, 0, ACCSET_STRING_MCHARS, nj::LOAD_CONST); + } + + nj::LIns *getArgsLength(nj::LIns *args) const { + uint32 slot = JSObject::JSSLOT_ARGS_LENGTH; + nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, args, offsetof(JSObject, slots), + ACCSET_OBJ_SLOTS); + return lir->insLoad(nj::LIR_ldi, vaddr_ins, slot * sizeof(Value) + sPayloadOffset, + ACCSET_SLOTS); + } +}; + +} /* namespace tjit */ +} /* namespace js */ + +#endif /* tracejit_Writer_h___ */ + From dfd14af5e6970f05135006491044cc350cefc16e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Oct 2010 18:58:58 -0700 Subject: [PATCH 138/263] Fix ARM bustage caused by bug 602703. --- js/src/tracejit/Writer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/tracejit/Writer.h b/js/src/tracejit/Writer.h index 6ea0ac830ca..577517b4193 100644 --- a/js/src/tracejit/Writer.h +++ b/js/src/tracejit/Writer.h @@ -950,6 +950,7 @@ class Writer return lir->ins2ImmI(nj::LIR_muli, x, imm); } +#if defined NANOJIT_IA32 || defined NANOJIT_X64 nj::LIns *divi(nj::LIns *x, nj::LIns *y) const { return lir->ins2(nj::LIR_divi, x, y); } @@ -957,6 +958,7 @@ class Writer nj::LIns *modi(nj::LIns *x) const { return lir->ins1(nj::LIR_modi, x); } +#endif nj::LIns *andi(nj::LIns *x, nj::LIns *y) const { return lir->ins2(nj::LIR_andi, x, y); From 5f3e99f7986d3b00f3bc68b9066dde73be43130f Mon Sep 17 00:00:00 2001 From: Paul Biggar Date: Thu, 28 Oct 2010 12:23:00 -0700 Subject: [PATCH 139/263] Bug 605133 - Synchronize common areas of configure.in and js/src/configure.in. r=jimb --- configure.in | 20 +- js/src/configure.in | 858 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 696 insertions(+), 182 deletions(-) diff --git a/configure.in b/configure.in index af629d52aa6..fd013fd3c74 100644 --- a/configure.in +++ b/configure.in @@ -622,6 +622,9 @@ case "$target" in # Make sure compilers are valid CFLAGS="$CFLAGS -TC -nologo" CXXFLAGS="$CXXFLAGS -TP -nologo" + # MSVC warning C4345 warns of newly conformant behavior as of VS2003. + # MSVC warning C4800 is ubiquitous, useless, and annoying. + CXXFLAGS="$CXXFLAGS -wd4345 -wd4800" AC_LANG_SAVE AC_LANG_C AC_TRY_COMPILE([#include ], @@ -2740,6 +2743,11 @@ alpha*-*-osf*) *-solaris*) AC_DEFINE(SOLARIS) TARGET_NSPR_MDCPUCFG='\"md/_solaris.cfg\"' + if test -z "$CROSS_COMPILE" && pkginfo -q SUNWpr && pkginfo -q SUNWprd; then + NO_NSPR_CONFIG_SYSTEM_LDFLAGS="-L/usr/lib/mps -R/usr/lib/mps -lnspr4" + NO_NSPR_CONFIG_SYSTEM_CFLAGS="-I/usr/include/mps" + NO_NSPR_CONFIG_SYSTEM_VERSION=["`pkgparam SUNWpr SUNW_PRODVERS | sed -e 's/^[1-9][0-9]*\.[0-9][0-9]*$/&.0/'`"] + fi SYSTEM_MAKEDEPEND= MOZ_FIX_LINK_PATHS= # $ORIGIN/.. is for shared libraries under components/ to locate shared @@ -3798,9 +3806,9 @@ dnl Checks for library functions. dnl ======================================================== AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP -AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat64 lstat64 truncate64 statvfs64 setbuf isatty) -AC_CHECK_FUNCS(flockfile getpagesize) -AC_CHECK_FUNCS(localtime_r strtok_r) +AC_CHECK_FUNCS([fchmod flockfile getc_unlocked _getc_nolock getpagesize \ + lchown localtime_r lstat64 memmove random rint sbrk snprintf \ + stat64 statvfs statvfs64 strerror strtok_r truncate64]) dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt _SAVE_LDFLAGS=$LDFLAGS @@ -5260,7 +5268,6 @@ cairo-cocoa) MOZ_WIDGET_TOOLKIT=cocoa AC_DEFINE(MOZ_WIDGET_COCOA) MOZ_USER_DIR="Mozilla" - AC_DEFINE(XP_MACOSX) TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL' TK_CFLAGS="-DNO_X11" LDFLAGS="$LDFLAGS -framework Cocoa -lobjc" @@ -7061,6 +7068,7 @@ if test -n "$MOZ_THUMB2"; then case "$target_cpu" in arm*) if test "$GNU_CC"; then + AC_DEFINE(MOZ_THUMB2) CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" @@ -8018,7 +8026,6 @@ dnl ======================================================== dnl C++ rtti dnl Should be smarter and check that the compiler does indeed have rtti dnl ======================================================== - MOZ_ARG_ENABLE_BOOL(cpp-rtti, [ --enable-cpp-rtti Enable C++ RTTI ], [ _MOZ_USE_RTTI=1 ], @@ -9089,7 +9096,7 @@ if test "$USING_HCC"; then AC_SUBST(CXX) fi -AC_MSG_CHECKING([for posix_fallocate]) +AC_MSG_CHECKING([for posix_fallocate]) AC_TRY_LINK([#define _XOPEN_SOURCE 600 #include ], [posix_fallocate(0, 0, 0);], @@ -9160,6 +9167,7 @@ dnl ======================================================== if test "$OS_ARCH" = "BeOS"; then AC_DEFINE(XP_BEOS) elif test "$OS_ARCH" = "Darwin"; then + AC_DEFINE(XP_MACOSX) AC_DEFINE(XP_UNIX) AC_DEFINE(UNIX_ASYNC_DNS) elif test "$OS_ARCH" = "OpenVMS"; then diff --git a/js/src/configure.in b/js/src/configure.in index 619fd104123..46d491d77bb 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -42,6 +42,8 @@ dnl Mac OS X 10.4 support dnl Giorgio Maone dnl MSVC l10n compatible version check dnl Ben Turner +dnl Windows x64 support +dnl Makoto Kato dnl dnl Alternatively, the contents of this file may be used under the terms of dnl either the GNU General Public License Version 2 or later (the "GPL"), or @@ -108,6 +110,7 @@ NSPR_VERSION=4 dnl Set the minimum version of toolkit libs used by mozilla dnl ======================================================== PERL_VERSION=5.006 +PYTHON_VERSION=2.5 WINDRES_VERSION=2.14.90 W32API_VERSION=3.8 @@ -200,11 +203,17 @@ esac fi COMPILE_ENVIRONMENT=1 -MOZ_ARG_ENABLE_BOOL(compile-environment, +MOZ_ARG_DISABLE_BOOL(compile-environment, [ --disable-compile-environment Disable compiler/library checks.], - COMPILE_ENVIRONMENT=1, COMPILE_ENVIRONMENT= ) +AC_SUBST(COMPILE_ENVIRONMENT) + +dnl Check for Perl first -- needed for win32 SDK checks +MOZ_PATH_PROGS(PERL, $PERL perl5 perl ) +if test -z "$PERL" -o "$PERL" = ":"; then + AC_MSG_ERROR([perl not found in \$PATH]) +fi MOZ_ARG_ENABLE_BOOL(shared-js, [ --disable-shared-js @@ -225,7 +234,8 @@ dnl = here, so that the compiler checks can succeed dnl ======================================================== MOZ_ARG_WITH_STRING(android-ndk, -[ --with-android-ndk=DIR location where the Android NDK can be found], +[ --with-android-ndk=DIR + location where the Android NDK can be found], android_ndk=$withval) MOZ_ARG_WITH_STRING(android-toolchain, @@ -240,11 +250,29 @@ MOZ_ARG_WITH_STRING(android-version, android_version=$withval, android_version=5) +MOZ_ARG_WITH_STRING(android-sdk, +[ --with-android-sdk=DIR + location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)], + android_sdk=$withval) + +MOZ_ARG_WITH_STRING(android-tools, +[ --with-android-tools=DIR + location where the Android Tools can be found (base directory, e.g. .../android/tools)], + android_tools=$withval) + if test "$target" = "arm-android-eabi" ; then if test -z "$android_ndk" ; then AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.]) fi + if test -z "$android_sdk" ; then + AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.]) + fi + + if test -z "$android_tools" ; then + AC_MSG_ERROR([You must specify --with-android-tools=/path/to/sdk/tools when targeting Android.]) + fi + if test -z "$android_toolchain" ; then android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0 fi @@ -252,6 +280,7 @@ if test "$target" = "arm-android-eabi" ; then if test -z "$android_platform" ; then android_platform="$android_ndk"/build/platforms/android-"$android_version"/arch-"$target_cpu" fi + dnl set up compilers AS="$android_toolchain"/bin/arm-eabi-as CC="$android_toolchain"/bin/arm-eabi-gcc @@ -263,9 +292,14 @@ if test "$target" = "arm-android-eabi" ; then STRIP="$android_toolchain"/bin/arm-eabi-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" - CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CFLAGS" - CXXFLAGS="-mandroid -std=gnu++0x -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions $CXXFLAGS" - LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" + CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CFLAGS" + CXXFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CXXFLAGS" + + dnl Add -llog by default, since we use it all over the place. + dnl Add --allow-shlib-undefined, because libGLESv2 links to an + dnl undefined symbol (present on the hardware, just not in the + dnl NDK.) + LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS" dnl prevent cross compile section from using these flags as host flags if test -z "$HOST_CPPFLAGS" ; then @@ -281,6 +315,13 @@ if test "$target" = "arm-android-eabi" ; then HOST_LDFLAGS=" " fi + ANDROID_NDK="${android_ndk}" + ANDROID_TOOLCHAIN="{android_toolchain}" + ANDROID_PLATFORM="{android_platform}" + ANDROID_SDK="${android_sdk}" + ANDROID_TOOLS="${android_tools}" + ANDROID_VERSION="${android_version}" + # save these for libffi's subconfigure, # which doesn't know how to figure this stuff out on its own ANDROID_CFLAGS="$CFLAGS" @@ -289,12 +330,23 @@ if test "$target" = "arm-android-eabi" ; then AC_DEFINE(ANDROID) AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version) - AC_DEFINE(FORCE_LITTLE_ENDIAN) + AC_SUBST(ANDROID_VERSION) + CROSS_COMPILE=1 + MOZ_CHROME_FILE_FORMAT=omni fi +AC_SUBST(ANDROID_NDK) +AC_SUBST(ANDROID_TOOLCHAIN) +AC_SUBST(ANDROID_PLATFORM) +AC_SUBST(ANDROID_SDK) +AC_SUBST(ANDROID_TOOLS) + dnl ======================================================== dnl Checks for compilers. dnl ======================================================== +dnl Set CROSS_COMPILE in the environment when running configure +dnl to use the cross-compile setup for now +dnl ======================================================== dnl AR_FLAGS set here so HOST_AR_FLAGS can be set correctly (see bug 538269) AR_FLAGS='cr $@' @@ -303,6 +355,7 @@ if test "$COMPILE_ENVIRONMENT"; then if test "$target" != "$host"; then echo "cross compiling from $host to $target" + cross_compiling=yes _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" @@ -365,8 +418,8 @@ if test "$target" != "$host"; then dnl checks will fail. Fake a working SDK in that case. _SAVE_CFLAGS=$CFLAGS _SAVE_CXXFLAGS=$CXXLAGS - CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" - CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" + CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk $CFLAGS" + CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk $CXXFLAGS" ;; esac @@ -428,12 +481,6 @@ if test "$target" != "$host"; then AC_CHECK_PROGS(STRIP, $STRIP "${target_alias}-strip" "${target}-strip", :) AC_CHECK_PROGS(WINDRES, $WINDRES "${target_alias}-windres" "${target}-windres", :) AC_DEFINE(CROSS_COMPILE) - - dnl If we cross compile for ppc on Mac OS X x86, cross_compiling will - dnl have erroneously been set to "no", because the x86 build host is - dnl able to run ppc code in a translated environment, making a cross - dnl compiler appear native. So we override that here. - cross_compiling=yes else AC_PROG_CC AC_PROG_CXX @@ -514,16 +561,34 @@ dnl ======================================================== case "$target" in *-wince|*-winmo) WINVER=500 + WINSDK_TARGETVER=502 ;; *) - if test -n "$GNU_CC"; then - WINVER=501 - else - WINVER=500 - fi + WINVER=502 + dnl Target the Windows 7 SDK by default + WINSDK_TARGETVER=601 ;; esac +MOZ_ARG_WITH_STRING(windows-version, +[ --with-windows-version=WINSDK_TARGETVER + Highest Windows version to target using this SDK + 502: Windows Server 2003 + 600: Windows Vista + 601: Windows 7], + WINSDK_TARGETVER=$withval) + +case "$WINSDK_TARGETVER" in +502|600|601) + MOZ_WINSDK_TARGETVER=0${WINSDK_TARGETVER}0000 + ;; + +*) + AC_MSG_ERROR([Invalid value for --with-windows-version ($WINSDK_TARGETVER), must be 502, 600 or 601]); + ;; + +esac + case "$target" in *-cygwin*|*-mingw*|*-msvc*|*-mks*|*-wince|*-winmo) if test "$GCC" != "yes"; then @@ -634,8 +699,112 @@ case "$target" in fi INCREMENTAL_LINKER=1 + # Identify which version of the SDK we're building with + # Windows Server 2008 and newer SDKs have WinSDKVer.h, get the version + # from there + AC_CHECK_HEADERS([winsdkver.h]) + if test "$ac_cv_header_winsdkver_h" = "yes"; then + # Get the highest _WIN32_WINNT and NTDDI versions supported + # Take the higher of the two + # This is done because the Windows 7 beta SDK reports its + # NTDDI_MAXVER to be 0x06000100 instead of 0x06010000, as it should + AC_CACHE_CHECK(for highest Windows version supported by this SDK, + ac_cv_winsdk_maxver, + [cat > conftest.h < +#include + +#if (NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) > NTDDI_MAXVER) +#define WINSDK_MAXVER NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) +#else +#define WINSDK_MAXVER NTDDI_MAXVER +#endif + +WINSDK_MAXVER +EOF + ac_cv_winsdk_maxver=`$CPP conftest.h 2>/dev/null | tail -n1` + rm -f conftest.h + ]) + MOZ_WINSDK_MAXVER=${ac_cv_winsdk_maxver} + else + # The Vista SDK is the only one to have sdkddkver.h but not + # WinSDKVer.h + AC_CHECK_HEADERS([sdkddkver.h]) + if test "$ac_cv_header_sdkddkver_h" = "yes"; then + MOZ_WINSDK_MAXVER=0x06000000 + else + # Assume the Server 2003 Platform SDK + MOZ_WINSDK_MAXVER=0x05020000 + fi + fi + unset _MSVC_VER_FILTER + AC_CACHE_CHECK(for std::_Throw, ac_cv_have_std__Throw, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" + AC_TRY_COMPILE([#include ], + [std::_Throw(std::exception()); return 0;], + ac_cv_have_std__Throw="yes", + ac_cv_have_std__Throw="no") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + + if test "$ac_cv_have_std__Throw" == "yes"; then + AC_CACHE_CHECK(for |class __declspec(dllimport) exception| bug, + ac_cv_have_dllimport_exception_bug, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" + AC_TRY_LINK([#include ], + [std::vector v; return v.at(1);], + ac_cv_have_dllimport_exception_bug="no", + ac_cv_have_dllimport_exception_bug="yes") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + if test "$ac_cv_have_dllimport_exception_bug" = "no"; then + WRAP_STL_INCLUDES=1 + MOZ_MSVC_STL_WRAP__Throw=1 + AC_DEFINE(MOZ_MSVC_STL_WRAP__Throw) + fi + else + AC_CACHE_CHECK(for overridable _RAISE, + ac_cv_have__RAISE, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="${CXXFLAGS} -D_HAS_EXCEPTIONS=0" + AC_TRY_COMPILE([#include + #undef _RAISE + #define _RAISE(x) externallyDefinedFunction((x).what()) + #include + ], + [std::vector v; return v.at(1);], + ac_cv_have__RAISE="no", + ac_cv_have__RAISE="yes") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + if test "$ac_cv_have__RAISE" = "yes"; then + WRAP_STL_INCLUDES=1 + MOZ_MSVC_STL_WRAP__RAISE=1 + AC_DEFINE(MOZ_MSVC_STL_WRAP__RAISE) + else + AC_MSG_ERROR([Gecko exception wrapping doesn't understand your your MSVC/SDK. Please file a bug describing this error and your build configuration.]) + fi + fi + + if test "$WRAP_STL_INCLUDES" = "1"; then + STL_FLAGS='-D_HAS_EXCEPTIONS=0 -I$(DIST)/stl_wrappers' + fi else # Check w32api version _W32API_MAJOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $1 }'` @@ -671,12 +840,31 @@ case "$target" in then AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.]) fi + + # Server 2003 is the highest version supported + MOZ_WINSDK_MAXVER=0x05020000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) AC_DEFINE_UNQUOTED(_WIN32_WINNT,0x$WINVER) # Require OS features provided by IE 5.0 AC_DEFINE_UNQUOTED(_WIN32_IE,0x0500) + + # If the maximum version supported by this SDK is lower than the target + # version, error out + AC_MSG_CHECKING([for Windows SDK being recent enough]) + if $PERL -e "exit(0x$MOZ_WINSDK_TARGETVER > $MOZ_WINSDK_MAXVER)"; then + AC_MSG_RESULT("yes") + else + AC_MSG_RESULT("no") + AC_MSG_ERROR([You are targeting Windows version 0x$MOZ_WINSDK_TARGETVER, but your SDK only supports up to version $MOZ_WINSDK_MAXVER. Install and use an updated SDK, or target a lower version using --with-windows-version. Alternatively, try running the Windows SDK Configuration Tool and selecting a newer SDK. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.]) + fi + + AC_DEFINE_UNQUOTED(MOZ_WINSDK_TARGETVER,0x$MOZ_WINSDK_TARGETVER) + # Definitions matching sdkddkver.h + AC_DEFINE_UNQUOTED(MOZ_NTDDI_WS03, 0x05020000) + AC_DEFINE_UNQUOTED(MOZ_NTDDI_LONGHORN, 0x06000000) + AC_DEFINE_UNQUOTED(MOZ_NTDDI_WIN7, 0x06010000) ;; esac @@ -726,12 +914,6 @@ fi fi # COMPILE_ENVIRONMENT -if test "$cross_compiling" = "yes"; then - CROSS_COMPILE=1 -else - CROSS_COMPILE= -fi - # Check to see if we are running in a broken QEMU scratchbox. # We know that anything below 1.0.16 is broken. AC_CHECK_PROGS(SBCONF, sb-conf ve, "") @@ -755,15 +937,16 @@ AC_SUBST(GNU_CXX) AC_SUBST(INTEL_CC) AC_SUBST(INTEL_CXX) +AC_SUBST(STL_FLAGS) +AC_SUBST(WRAP_STL_INCLUDES) +AC_SUBST(MOZ_MSVC_STL_WRAP__Throw) +AC_SUBST(MOZ_MSVC_STL_WRAP__RAISE) + dnl ======================================================== dnl Checks for programs. dnl ======================================================== AC_PROG_INSTALL AC_PROG_LN_S -MOZ_PATH_PROGS(PERL, $PERL perl5 perl ) -if test -z "$PERL" -o "$PERL" = ":"; then - AC_MSG_ERROR([perl not found in \$PATH]) -fi if test -z "$TINDERBOX_SKIP_PERL_VERSION_CHECK"; then AC_MSG_CHECKING([for minimum required perl version >= $PERL_VERSION]) @@ -786,7 +969,7 @@ else AC_MSG_RESULT([yes]) fi -MOZ_PATH_PROGS(PYTHON, $PYTHON python) +MOZ_PATH_PROGS(PYTHON, $PYTHON python2.6 python2.5 python2.4 python) if test -z "$PYTHON"; then AC_MSG_ERROR([python was not found in \$PATH]) fi @@ -873,7 +1056,7 @@ dnl Check for MacOS deployment target version dnl ======================================================== MOZ_ARG_ENABLE_STRING(macos-target, - [ --enable-macos-target=VER (default=10.4) + [ --enable-macos-target=VER (default=10.5) Set the minimum MacOS version needed at runtime], [_MACOSX_DEPLOYMENT_TARGET=$enableval]) @@ -883,11 +1066,20 @@ case "$target" in dnl Use the specified value export MACOSX_DEPLOYMENT_TARGET=$_MACOSX_DEPLOYMENT_TARGET AC_DEFINE_UNQUOTED(__ENVIRONMENT_MAC_OS_X_VERION_MIN_REQUIRED__,$_MACOSX_DEPLOYMENT_TARGET) - elif test -z "$MACOSX_DEPLOYMENT_TARGET" ; then + else dnl No value specified on the command line or in the environment, - dnl use the lesser of the application's minimum or the architecture's - dnl minimum. - export MACOSX_DEPLOYMENT_TARGET=10.4 + dnl use architecture minimum. + case "${target_cpu}" in + ppc*) + export MACOSX_DEPLOYMENT_TARGET=10.5 + ;; + i*86) + export MACOSX_DEPLOYMENT_TARGET=10.5 + ;; + x86_64) + export MACOSX_DEPLOYMENT_TARGET=10.6 + ;; + esac fi ;; esac @@ -957,17 +1149,25 @@ fi fi # COMPILE_ENVIRONMENT -if test -z "$MAKE"; then - case "$host_os" in - cygwin*|mingw*|mks*|msvc*) - MOZ_PATH_PROGS(MAKE, $MAKE make gmake, :) - ;; - *) - MOZ_PATH_PROGS(MAKE, $MAKE gmake make, :) - ;; - esac +if test -n "$MAKE"; then + if test `echo $MAKE | grep -c make.py` != 1; then + NOT_PYMAKE=$MAKE + fi fi +case "$host_os" in +cygwin*|mingw*|mks*|msvc*) + MOZ_PATH_PROGS(GMAKE, $GMAKE $NOT_PYMAKE make gmake, :) + ;; +*) + MOZ_PATH_PROGS(GMAKE, $GMAKE $NOT_PYMAKE gmake make, :) + ;; +esac +if test "$GMAKE" = ":"; then + AC_MSG_ERROR([GNU make not found]) +fi +AC_SUBST(GMAKE) + if test "$COMPILE_ENVIRONMENT"; then AC_PATH_XTRA @@ -999,7 +1199,7 @@ WIN_TOP_SRC= MOZ_USER_DIR=".mozilla" MOZ_JS_LIBS='-L$(libdir) -lmozjs' -MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(PREFIX)/lib' +MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib' MOZ_COMPONENT_NSPR_LIBS='-L$(LIBXUL_DIST)/bin $(NSPR_LIBS)' @@ -1007,8 +1207,6 @@ USE_DEPENDENT_LIBS=1 _PLATFORM_DEFAULT_TOOLKIT=cairo-gtk2 -MOZ_THUMB2= - if test -n "$CROSS_COMPILE"; then OS_TARGET="${target_os}" OS_ARCH=`echo $target_os | sed -e 's|/|_|g'` @@ -1023,6 +1221,9 @@ if test -n "$CROSS_COMPILE"; then winmo*) OS_ARCH=WINCE ;; darwin*) OS_ARCH=Darwin OS_TARGET=Darwin ;; esac + case "${target}" in + arm-android-eabi) OS_ARCH=Linux OS_TARGET=Android ;; + esac else OS_TARGET=`uname -s` OS_ARCH=`uname -s | sed -e 's|/|_|g'` @@ -1060,6 +1261,9 @@ case "$HOST_OS_ARCH" in cygwin*|mingw*|mks*|msvc*) HOST_OS_ARCH=WINNT ;; +darwin*) + HOST_OS_ARCH=Darwin + ;; linux*) HOST_OS_ARCH=Linux ;; @@ -1126,7 +1330,9 @@ esac case "$OS_ARCH" in WINNT) - OS_TEST=`uname -p` + if test -z "$CROSS_COMPILE" ; then + OS_TEST=`uname -p` + fi ;; Windows_NT) # @@ -1230,13 +1436,17 @@ UnixWare) OS_RELEASE=`uname -v` ;; WINCE) - WINCE=1 OS_ARCH=WINCE - if test "$WINCE_WINDOWS_MOBILE"; then + case "${target_os}" in + *winmo) OS_TARGET=WINMO - else + WINCE_WINDOWS_MOBILE=1 + AC_DEFINE(WINCE_WINDOWS_MOBILE) + ;; + *) OS_TARGET=WINCE - fi + ;; + esac ;; Darwin) case "${target_cpu}" in @@ -1271,7 +1481,11 @@ case "$OS_TEST" in CPU_ARCH=x86 ;; -powerpc* | ppc | rs6000) +powerpc64 | ppc64) + CPU_ARCH=ppc64 + ;; + +powerpc | ppc | rs6000) CPU_ARCH=ppc ;; @@ -1279,6 +1493,14 @@ Alpha | alpha | ALPHA) CPU_ARCH=Alpha ;; +s390) + CPU_ARCH=s390 + ;; + +s390x) + CPU_ARCH=s390x + ;; + hppa* | parisc) CPU_ARCH=hppa ;; @@ -1334,7 +1556,7 @@ if test "$GNU_CC"; then if test -z "$INTEL_CC"; then # Don't use -Wcast-align with ICC case "$CPU_ARCH" in - # And don't use it on hppa, ia64, sparc, or arm since it's noisy there + # And don't use it on hppa, ia64, sparc, arm, since it's noisy there hppa | ia64 | sparc | arm) ;; *) @@ -1384,7 +1606,7 @@ if test "$GNU_CXX"; then if test -z "$INTEL_CC"; then # Don't use -Wcast-align with ICC case "$CPU_ARCH" in - # And don't use it on hppa, ia64, sparc, or arm since it's noisy there + # And don't use it on hppa, ia64, sparc, arm, since it's noisy there hppa | ia64 | sparc | arm) ;; *) @@ -1431,6 +1653,25 @@ if test "$GNU_CXX"; then if test "$ac_has_wno_variadic_macros" = "yes"; then _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-variadic-macros" fi + + AC_CACHE_CHECK(whether the compiler supports -Werror=return-type, + ac_has_werror_return_type, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + _SAVE_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -Werror=return-type" + AC_TRY_COMPILE([], + [return(0);], + ac_has_werror_return_type="yes", + ac_has_werror_return_type="no") + CXXFLAGS="$_SAVE_CXXFLAGS" + AC_LANG_RESTORE + ]) + if test "$ac_has_werror_return_type" = "yes"; then + _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type" + fi + else _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_JS_CONFDEFS_H_ $(ACDEFINES)' fi @@ -1565,6 +1806,8 @@ case "$host" in ;; *cygwin*|*mingw*|*mks*|*msvc*|*wince|*winmo) + # we need Python 2.5 on Windows + PYTHON_VERSION=2.5 if test -n "$_WIN32_MSVC"; then HOST_AR=lib HOST_AR_FLAGS='-NOLOGO -OUT:"$@"' @@ -1580,6 +1823,7 @@ case "$host" in case "$host" in *mingw*) dnl MinGW/MSYS does not need CYGWIN_WRAPPER + PERL="/bin/sh ${_topsrcdir}/build/msys-perl-wrapper" ;; *) CYGWIN_WRAPPER="${srcdir}/build/cygwin-wrapper" @@ -1597,6 +1841,12 @@ case "$host" in fi ;; esac + + case "${host_cpu}" in + x86_64) + HOST_CFLAGS="$HOST_CFLAGS -D_AMD64_" + ;; + esac ;; *-darwin*) @@ -1631,6 +1881,18 @@ case "$host" in ;; esac +dnl We require version 2.4 or newer of Python to build, +dnl and 2.5 or newer on Windows. +AC_MSG_CHECKING([for minimum required Python version >= $PYTHON_VERSION]) +changequote(,) +$PYTHON -c "import sys; sys.exit(sys.version[:3] < sys.argv[1])" $PYTHON_VERSION +_python_res=$? +changequote([,]) +if test "$_python_res" != 0; then + AC_MSG_ERROR([Python $PYTHON_VERSION or higher is required.]) +fi +AC_MSG_RESULT([yes]) + dnl ======================================================== dnl System overrides of the defaults for target dnl ======================================================== @@ -1803,6 +2065,7 @@ ia64*-hpux*) MOZ_FIX_LINK_PATHS= SYSTEM_MAKEDEPEND= AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES) + AC_DEFINE(_LARGEFILE64_SOURCE) ;; *-hpux*) @@ -1884,14 +2147,15 @@ ia64*-hpux*) ;; *-*linux*) - # Note: both GNU_CXX and INTEL_CXX are set when using Intel's C compiler. - if test "$INTEL_CXX"; then + # Note: both GNU_CC and INTEL_CC are set when using Intel's C compiler. + # Similarly for GNU_CXX and INTEL_CXX. + if test "$INTEL_CC" -o "$INTEL_CXX"; then # -Os has been broken on Intel's C/C++ compilers for quite a # while; Intel recommends against using it. MOZ_OPTIMIZE_FLAGS="-O2" MOZ_DEBUG_FLAGS="-g" - elif test "$GNU_CXX"; then - GCC_VERSION=`$CXX -v 2>&1 | awk '/^gcc version/ { print $3 }'` + elif test "$GNU_CC" -o "$GNU_CXX"; then + GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'` case $GCC_VERSION in 4.1.*|4.2.*|4.5.*) # -Os is broken on gcc 4.1.x 4.2.x, 4.5.x we need to tweak it to get good results. @@ -1899,9 +2163,9 @@ ia64*-hpux*) esac # If we're building with --enable-profiling, we need a frame pointer. if test -z "$MOZ_PROFILING"; then - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" else - MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-omit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK" fi MOZ_DEBUG_FLAGS="-g" fi @@ -1948,7 +2212,7 @@ ia64*-hpux*) WARNINGS_AS_ERRORS='-WX' - MOZ_OPTIMIZE_FLAGS='-O1' + MOZ_OPTIMIZE_FLAGS='-Ox' AR_FLAGS='-NOLOGO -OUT:"$@"' ASM_SUFFIX=asm CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)" @@ -1956,11 +2220,12 @@ ia64*-hpux*) DLL_PREFIX= DOXYGEN=: DSO_LDOPTS=-SUBSYSTEM:WINDOWSCE - DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' GARBAGE= IMPORT_LIB_SUFFIX=lib - LIBS="$LIBS" - LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib' + dnl Need to force-link against mozalloc because it's used in the shunt + LIBS="$LIBS \$(LIBXUL_DIST)/lib/mozalloc.lib" + LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' LIB_PREFIX= LIB_SUFFIX=lib MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ $(DSO_LDOPTS)' @@ -1979,10 +2244,9 @@ ia64*-hpux*) TARGET_NSPR_MDCPUCFG='\"md/_wince.cfg\"' UNZIP=unzip XARGS=xargs - XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib' ZIP=zip - AC_DEFINE(WINCE) AC_DEFINE(HAVE_SNPRINTF) AC_DEFINE(_WINDOWS) AC_DEFINE(WIN32) @@ -1992,9 +2256,10 @@ ia64*-hpux*) AC_DEFINE(STDC_HEADERS) AC_DEFINE(NEW_H, ) AC_DEFINE(WIN32_LEAN_AND_MEAN) + AC_DEFINE(HAVE_LOCALTIME_R) TARGET_MD_ARCH=win32 - _PLATFORM_DEFAULT_TOOLKIT='windows' + _PLATFORM_DEFAULT_TOOLKIT='cairo-windows' BIN_SUFFIX='.exe' MOZ_USER_DIR="Mozilla" @@ -2065,8 +2330,8 @@ ia64*-hpux*) LIBS="$LIBS -lgdi32 -lwinmm -lwsock32" MOZ_JS_LIBS='-L$(libdir) -lmozjs' MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core' - XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom' + DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc' + XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc' DLL_PREFIX= IMPORT_LIB_SUFFIX=dll.a GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'` @@ -2076,7 +2341,7 @@ ia64*-hpux*) HOST_CXX='$(CXX)' HOST_LD='$(LD)' if test "$AS_BIN"; then - AS="$(basename "$AS_BIN")" + AS="$(basename "$AS_BIN")" fi AR='lib -NOLOGO -OUT:"$@"' AR_FLAGS= @@ -2117,9 +2382,9 @@ ia64*-hpux*) fi MOZ_JS_LIBS='$(libdir)/mozjs.lib' MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib' - XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib' - LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)' if test $_MSC_VER -ge 1400; then LDFLAGS="$LDFLAGS -NXCOMPAT" @@ -2183,11 +2448,12 @@ ia64*-hpux*) AC_MSG_ERROR([MOZ_TOOLS is not set]) fi - MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd` + MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd -W` if test "$?" != "0" -o -z "$MOZ_TOOLS_DIR"; then AC_MSG_ERROR([cd \$MOZ_TOOLS failed. MOZ_TOOLS ==? $MOZ_TOOLS]) fi - if test `echo ${PATH}: | grep -ic "$MOZ_TOOLS_DIR/bin:"` = 0; then + MOZ_TOOLS_BIN_DIR="$(cd "$MOZ_TOOLS_DIR/bin" && pwd)" + if test `echo ${PATH}: | grep -ic "$MOZ_TOOLS_BINDIR:"` = 0; then AC_MSG_ERROR([\$MOZ_TOOLS\\bin must be in your path.]) fi MOZ_TOOLS_DIR=`$CYGPATH_W $MOZ_TOOLS_DIR | $CYGPATH_S` @@ -2220,8 +2486,8 @@ ia64*-hpux*) AC_DEFINE(_MIPS_) ;; x86_64-*) - AC_DEFINE(_AMD64_) - ;; + AC_DEFINE(_AMD64_) + ;; *) AC_DEFINE(_CPU_ARCH_NOT_DEFINED) ;; @@ -2536,6 +2802,21 @@ alpha*-*-osf*) HOST_NSPR_MDCPUCFG='\"md/_os2.cfg\"' ;; +*-android*) + AC_DEFINE(NO_PW_GECOS) + no_x=yes + _PLATFORM_DEFAULT_TOOLKIT=cairo-android + TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"' + + MOZ_GFX_OPTIMIZE_MOBILE=1 + # If we're building with --enable-profiling, we need a frame pointer. + if test -z "$MOZ_PROFILING"; then + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer" + else + MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fno-omit-frame-pointer" + fi + ;; + esac dnl Only one oddball right now (QNX), but this gives us flexibility @@ -2740,13 +3021,28 @@ AC_SUBST(NANOJIT_ARCH) if test -z "$SKIP_COMPILER_CHECKS"; then dnl Checks for typedefs, structures, and compiler characteristics. dnl ======================================================== -AC_LANG_C AC_HEADER_STDC AC_C_CONST AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T +AC_LANG_CPLUSPLUS +AC_MSG_CHECKING(for __stdcall) +AC_CACHE_VAL(ac_cv___stdcall, + [AC_TRY_COMPILE([template struct foo; + template <> struct foo {}; + template <> struct foo {};], + [], + [ac_cv___stdcall=true], + [ac_cv___stdcall=false])]) +if test "$ac_cv___stdcall" = true ; then + AC_DEFINE(HAVE_STDCALL) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi +AC_LANG_C AC_MSG_CHECKING(for ssize_t) AC_CACHE_VAL(ac_cv_type_ssize_t, [AC_TRY_COMPILE([#include @@ -3044,6 +3340,8 @@ EOF "$ac_cv_have_visibility_class_bug" = "no"; then VISIBILITY_FLAGS='-I$(DIST)/system_wrappers_js -include $(topsrcdir)/config/gcc_hidden.h' WRAP_SYSTEM_INCLUDES=1 + STL_FLAGS='-I$(DIST)/stl_wrappers' + WRAP_STL_INCLUDES=1 else VISIBILITY_FLAGS='-fvisibility=hidden' fi # have visibility pragma bug @@ -3060,6 +3358,26 @@ fi # Sun Studio on Solaris AC_SUBST(WRAP_SYSTEM_INCLUDES) AC_SUBST(VISIBILITY_FLAGS) +dnl Check for __force_align_arg_pointer__ for SSE2 on gcc +dnl ======================================================== +if test "$GNU_CC"; then + CFLAGS_save="${CFLAGS}" + CFLAGS="${CFLAGS} -Werror" + AC_CACHE_CHECK(for __force_align_arg_pointer__ attribute, + ac_cv_force_align_arg_pointer, + [AC_TRY_COMPILE([__attribute__ ((__force_align_arg_pointer__)) void test() {}], + [], + ac_cv_force_align_arg_pointer="yes", + ac_cv_force_align_arg_pointer="no")]) + CFLAGS="${CFLAGS_save}" + if test "$ac_cv_force_align_arg_pointer" = "yes"; then + HAVE_GCC_ALIGN_ARG_POINTER=1 + else + HAVE_GCC_ALIGN_ARG_POINTER= + fi +fi +AC_SUBST(HAVE_GCC_ALIGN_ARG_POINTER) + dnl Checks for header files. dnl ======================================================== AC_HEADER_DIRENT @@ -3074,10 +3392,15 @@ AC_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h) AC_CHECK_HEADERS(gnu/libc-version.h nl_types.h) AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(X11/XKBlib.h) +AC_CHECK_HEADERS(io.h) dnl These are all the places some variant of statfs can be hiding. AC_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h) +dnl Quota support +AC_CHECK_HEADERS(sys/quota.h) +AC_CHECK_HEADERS(linux/quota.h) + dnl Try for MMX support dnl NB - later gcc versions require -mmmx for this header to be successfully dnl included (or another option which implies it, such as -march=pentium-mmx) @@ -3173,6 +3496,34 @@ case $target in AC_CHECK_LIB(socket, socket) esac +AC_MSG_CHECKING(for ARM SIMD support in compiler) +AC_TRY_COMPILE([], + [asm("uqadd8 r1, r1, r2");], + result="yes", result="no") +AC_MSG_RESULT("$result") +if test "$result" = "yes"; then + AC_DEFINE(HAVE_ARM_SIMD) + HAVE_ARM_SIMD=1 +fi +AC_SUBST(HAVE_ARM_SIMD) + +AC_MSG_CHECKING(for ARM NEON support in compiler) +_SAVE_CFLAGS="$CFLAGS" +if test "$GNU_CC"; then + # gcc needs -mfpu=neon to recognize NEON instructions + CFLAGS="$CFLAGS -mfpu=neon -mfloat-abi=softfp" +fi +AC_TRY_COMPILE([], + [asm("vadd.i8 d0, d0, d0");], + result="yes", result="no") +AC_MSG_RESULT("$result") +if test "$result" = "yes"; then + AC_DEFINE(HAVE_ARM_NEON) + HAVE_ARM_NEON=1 +fi +CFLAGS="$_SAVE_CFLAGS" +AC_SUBST(HAVE_ARM_NEON) + dnl ======================================================== dnl = pthread support dnl = Start by checking whether the system support pthreads @@ -3223,7 +3574,7 @@ then echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then - if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then + if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthread=yes case "$target_os" in freebsd*) @@ -3248,7 +3599,7 @@ then echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then - if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then + if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthreads=yes CFLAGS="$CFLAGS -pthreads" CXXFLAGS="$CXXFLAGS -pthreads" @@ -3362,11 +3713,29 @@ dnl Checks for library functions. dnl ======================================================== AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP - AC_CHECK_FUNCS([fchmod flockfile getc_unlocked _getc_nolock getpagesize \ lchown localtime_r lstat64 memmove random rint sbrk snprintf \ stat64 statvfs statvfs64 strerror strtok_r truncate64]) +dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt +_SAVE_LDFLAGS=$LDFLAGS +LDFLAGS="$LDFLAGS -lrt" +AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC) and -lrt, + ac_cv_have_clock_monotonic, + [AC_TRY_LINK([#include ], + [ struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); ], + ac_cv_have_clock_monotonic=yes, + ac_cv_have_clock_monotonic=no)]) +LDFLAGS=$_SAVE_LDFLAGS +if test "$ac_cv_have_clock_monotonic" = "yes"; then + HAVE_CLOCK_MONOTONIC=1 + REALTIME_LIBS=-lrt + AC_DEFINE(HAVE_CLOCK_MONOTONIC) + AC_SUBST(HAVE_CLOCK_MONOTONIC) + AC_SUBST(REALTIME_LIBS) +fi + dnl Windows functions, for mingw. AC_TRY_LINK([#include ], [SYSTEMTIME st;FILETIME ft;SystemTimeToFileTime(&st,&ft);], @@ -3663,6 +4032,7 @@ if test "$GNU_CC"; then ac_cv_gcc_arm_eabi="yes", ac_cv_gcc_arm_eabi="no")]) if test "$ac_cv_gcc_arm_eabi" = "yes"; then + HAVE_ARM_EABI=1 ARM_ABI_PREFIX=eabi- else ARM_ABI_PREFIX=oabi- @@ -3977,8 +4347,79 @@ if test "$ac_cv_trouble_comparing_to_zero" = yes ; then AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) fi +# try harder, when checking for __thread support, see bug 521750 comment #33 and below +_SAVE_LDFLAGS=$LDFLAGS +LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS $DSO_LDOPTS" +AC_CACHE_CHECK(for __thread keyword for TLS variables, + ac_cv_thread_keyword, + [AC_TRY_LINK([__thread bool tlsIsMainThread = false;], + [return tlsIsMainThread;], + ac_cv_thread_keyword=yes, + ac_cv_thread_keyword=no)]) +LDFLAGS=$_SAVE_LDFLAGS +if test "$ac_cv_thread_keyword" = yes; then + # mips builds fail with TLS variables because of a binutils bug. + # See bug 528687 + case "${target}" in + mips*-*) + : + ;; + *-android*) + : + ;; + *) + AC_DEFINE(HAVE_THREAD_TLS_KEYWORD) + ;; + esac +fi +dnl Check for the existence of various allocation headers/functions +MALLOC_H= +AC_CHECK_HEADER(malloc.h, [MALLOC_H=malloc.h]) +if test "$MALLOC_H" = ""; then + AC_CHECK_HEADER(malloc/malloc.h, [MALLOC_H=malloc/malloc.h]) + if test "$MALLOC_H" = ""; then + AC_CHECK_HEADER(sys/malloc.h, [MALLOC_H=sys/malloc.h]) + fi +fi +if test "$MALLOC_H" != ""; then + AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) +fi + +MOZ_ALLOCATING_FUNCS="strndup posix_memalign memalign valloc" +AC_CHECK_FUNCS(strndup posix_memalign memalign valloc) + +dnl See if compiler supports some gcc-style attributes + +AC_CACHE_CHECK(for __attribute__((always_inline)), + ac_cv_attribute_always_inline, + [AC_TRY_COMPILE([], + [inline void f(void) __attribute__((always_inline));], + ac_cv_attribute_always_inline=yes, + ac_cv_attribute_always_inline=no)]) + +AC_CACHE_CHECK(for __attribute__((malloc)), + ac_cv_attribute_malloc, + [AC_TRY_COMPILE([], + [void* f(int) __attribute__((malloc));], + ac_cv_attribute_malloc=yes, + ac_cv_attribute_malloc=no)]) + +AC_CACHE_CHECK(for __attribute__((warn_unused_result)), + ac_cv_attribute_warn_unused, + [AC_TRY_COMPILE([], + [int f(void) __attribute__((warn_unused_result));], + ac_cv_attribute_warn_unused=yes, + ac_cv_attribute_warn_unused=no)]) + +AC_CACHE_CHECK(for __attribute__((noreturn)), + ac_cv_attribute_noreturn, + [AC_TRY_COMPILE([], + [void f(void) __attribute__((noreturn));], + ac_cv_attribute_noreturn=yes, + ac_cv_attribute_noreturn=no)]) + dnl End of C++ language/feature checks AC_LANG_C @@ -3999,7 +4440,9 @@ AC_CACHE_CHECK(for LC_MESSAGES, ac_cv_i18n_lc_messages=no)]) if test "$ac_cv_i18n_lc_messages" = yes; then AC_DEFINE(HAVE_I18N_LC_MESSAGES) -fi +fi + +AC_HAVE_FUNCS(localeconv) fi # SKIP_COMPILER_CHECKS @@ -4013,6 +4456,41 @@ dnl ======================================================== dnl The macros used for command line options dnl are defined in build/autoconf/altoptions.m4. +dnl If the compiler supports these attributes, define them as +dnl convenience macros. +if test "$ac_cv_attribute_always_inline" = yes ; then + AC_DEFINE(NS_ALWAYS_INLINE, [__attribute__((always_inline))]) +else + AC_DEFINE(NS_ALWAYS_INLINE,) +fi + +if test "$ac_cv_attribute_malloc" = yes ; then + AC_DEFINE(NS_ATTR_MALLOC, [__attribute__((malloc))]) +else + AC_DEFINE(NS_ATTR_MALLOC,) +fi + +if test "$ac_cv_attribute_warn_unused" = yes ; then + AC_DEFINE(NS_WARN_UNUSED_RESULT, [__attribute__((warn_unused_result))]) +else + AC_DEFINE(NS_WARN_UNUSED_RESULT,) +fi + +if test "$ac_cv_attribute_noreturn" = yes ; then + AC_DEFINE(NS_NORETURN, [__attribute__((noreturn))]) +else + AC_DEFINE(NS_NORETURN,) +fi + +dnl We can't run TRY_COMPILE tests on Windows, so hard-code some +dnl features that Windows actually does support. + +if test -n "$SKIP_COMPILER_CHECKS"; then + dnl Windows has malloc.h + AC_DEFINE(MALLOC_H, []) + AC_DEFINE(HAVE_FORCEINLINE) + AC_DEFINE(HAVE_LOCALECONV) +fi # SKIP_COMPILER_CHECKS dnl ======================================================== dnl = @@ -4056,6 +4534,7 @@ if test "$_USE_SYSTEM_NSPR" && (test "$NSPR_CFLAGS" -o "$NSPR_LIBS"); then See 'configure --help'.]) fi +dnl Top-level Mozilla switched to requiring NSPR 4.8.6 (bug 560582), but we don't need it in JS. if test -n "$_USE_SYSTEM_NSPR"; then MOZ_NATIVE_NSPR= AM_PATH_NSPR(4.7.0, [MOZ_NATIVE_NSPR=1]) @@ -4078,18 +4557,6 @@ if test -n "$MOZ_NATIVE_NSPR"; then CFLAGS=$_SAVE_CFLAGS fi -dnl ======================================================== -dnl Use ARM userspace kernel helpers; tell NSPR to enable -dnl their usage and use them in spidermonkey. -dnl ======================================================== -MOZ_ARG_WITH_BOOL(arm-kuser, -[ --with-arm-kuser Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)], - USE_ARM_KUSER=1, - USE_ARM_KUSER=) -if test -n "$USE_ARM_KUSER"; then - AC_DEFINE(USE_ARM_KUSER) -fi - dnl ======================================================== dnl = dnl = Application @@ -4101,6 +4568,27 @@ MOZ_ARG_HEADER(Application) BUILD_STATIC_LIBS= ENABLE_TESTS=1 +MOZ_THUMB2= +USE_ARM_KUSER= + +case "${target}" in + arm-android-eabi) + USE_ARM_KUSER=1 + MOZ_THUMB2=1 + ;; +esac + +dnl ======================================================== +dnl Use ARM userspace kernel helpers; tell NSPR to enable +dnl their usage and use them in spidermonkey. +dnl ======================================================== +MOZ_ARG_WITH_BOOL(arm-kuser, +[ --with-arm-kuser Use kuser helpers (Linux/ARM only -- requires kernel 2.6.13 or later)], + USE_ARM_KUSER=1,) +if test -n "$USE_ARM_KUSER"; then + AC_DEFINE(USE_ARM_KUSER) +fi + dnl ======================================================== dnl = dnl = Components & Features @@ -4108,33 +4596,6 @@ dnl = dnl ======================================================== MOZ_ARG_HEADER(Components and Features) -dnl ======================================================== - -dnl ======================================================== -dnl = Enable building the Thumb2 instruction set -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(thumb2, - [ --enable-thumb2 Enable Thumb2 instruction set], - MOZ_THUMB2=1,) - -if test -n "$MOZ_THUMB2"; then - case "$target_cpu" in - arm*) - if test "$GNU_CC"; then - AC_DEFINE(MOZ_THUMB2) - CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" - CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" - ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" - else - AC_MSG_ERROR([--enable-thumb2 is not supported for non-GNU toolchains]) - fi - ;; - *) - AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures]) - ;; - esac -fi - dnl ======================================================== dnl = Localization dnl ======================================================== @@ -4159,6 +4620,34 @@ dnl = dnl ======================================================== MOZ_ARG_HEADER(Individual module options) +dnl ======================================================== +dnl = Enable building the Thumb2 instruction set +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(thumb2, + [ --enable-thumb2 Enable Thumb2 instruction set], + MOZ_THUMB2=1, + MOZ_THUMB2=) + +if test -n "$MOZ_THUMB2"; then + case "$target_cpu" in + arm*) + if test "$GNU_CC"; then + AC_DEFINE(MOZ_THUMB2) + CFLAGS="$CFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" + CXXFLAGS="$CXXFLAGS -march=armv7-a -mthumb -Wa, -march=armv7-a -Wa, -mthumb" + ASFLAGS="$ASFLAGS -march=armv7-a -mthumb" + else + AC_MSG_ERROR([--enable-thumb2 is not supported for non-GNU toolchains]) + fi + ;; + *) + AC_MSG_ERROR([--enable-thumb2 is not supported for non-ARM CPU architectures]) + ;; + esac +fi + +AC_SUBST(MOZ_THUMB2) + dnl ======================================================== dnl = dnl = Debugging Options @@ -4170,33 +4659,13 @@ dnl ======================================================== dnl = Disable building with debug info. dnl = Debugging is OFF by default dnl ======================================================== -if test -z "$MOZ_DEBUG_FLAGS" -then - case "$target" in - *-irix*) - if test "$GNU_CC"; then - GCC_VERSION=`$CC -v 2>&1 | awk '/version/ { print $3 }'` - case "$GCC_VERSION" in - 2.95.*) - MOZ_DEBUG_FLAGS="" - ;; - *) - MOZ_DEBUG_FLAGS="-g" - ;; - esac - else - MOZ_DEBUG_FLAGS="-g" - fi - ;; - *) - MOZ_DEBUG_FLAGS="-g" - ;; - esac +if test -z "$MOZ_DEBUG_FLAGS"; then + MOZ_DEBUG_FLAGS="-g" fi MOZ_ARG_ENABLE_STRING(debug, [ --enable-debug[=DBG] Enable building with developer debug info - (Using compiler flags DBG)], + (using compiler flags DBG)], [ if test "$enableval" != "no"; then MOZ_DEBUG=1 if test -n "$enableval" -a "$enableval" != "yes"; then @@ -4211,13 +4680,12 @@ MOZ_ARG_ENABLE_STRING(debug, MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG -DTRACING" MOZ_ARG_WITH_STRING(debug-label, [ --with-debug-label=LABELS - Enabled the use of DEBUG_label ifdefs - (comma separated)], + Define DEBUG_ for each comma-separated + value given.], [ for option in `echo $withval | sed 's/,/ /g'`; do MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${option}" done]) - MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED" if test -n "$MOZ_DEBUG"; then @@ -4311,6 +4779,17 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then fi dnl ======================================================== +dnl = Disable any treating of compile warnings as errors +dnl ======================================================== +MOZ_ARG_DISABLE_BOOL(warnings-as-errors, +[ --disable-warnings-as-errors + Disable treating of warnings as errors], + MOZ_DISABLE_WARNINGS_AS_ERRORS=1, + MOZ_DISABLE_WARNINGS_AS_ERRORS= ) +if test "$MOZ_DISABLE_WARNINGS_AS_ERRORS"; then + WARNINGS_AS_ERRORS='' +fi + dnl = Enable trace malloc dnl ======================================================== NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC} @@ -4388,7 +4867,14 @@ if test "$MOZ_MEMORY"; then AC_DEFINE(MOZ_MEMORY_WINDOWS) # the interesting bits will get passed down in MOZ_MEMORY_LDFLAGS ;; - *-*wince|*-*winmo) + *-*wince) + AC_DEFINE(MOZ_MEMORY_WINCE) + AC_DEFINE(MOZ_MEMORY_WINDOWS) + if test -z "$WINCE_WINDOWS_MOBILE"; then + AC_DEFINE(MOZ_MEMORY_WINCE6) + fi + ;; + *-*winmo) AC_DEFINE(MOZ_MEMORY_WINCE) AC_DEFINE(MOZ_MEMORY_WINDOWS) ;; @@ -4400,6 +4886,13 @@ if test "$MOZ_MEMORY"; then AC_MSG_ERROR([--enable-jemalloc not supported on ${target}]) ;; esac + + if test "$OS_ARCH" != "Darwin"; then + dnl NB: this must be kept in sync with jemalloc.h + AC_DEFINE(HAVE_JEMALLOC_VALLOC) + AC_DEFINE(HAVE_JEMALLOC_POSIX_MEMALIGN) + AC_DEFINE(HAVE_JEMALLOC_MEMALIGN) + fi fi AC_SUBST(MOZ_MEMORY) AC_SUBST(MOZ_MEMORY_LDFLAGS) @@ -4426,22 +4919,6 @@ MOZ_ARG_WITH_STRING(wrap-malloc, [ --with-wrap-malloc=DIR Location of malloc wrapper library], WRAP_MALLOC_LIB=$withval) -dnl ======================================================== -dnl = Build jsctypes if it's enabled -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(ctypes, -[ --enable-ctypes Enable js-ctypes (default=no)], - JS_HAS_CTYPES=1, - JS_HAS_CTYPES= ) -AC_SUBST(JS_HAS_CTYPES) -if test "$JS_HAS_CTYPES"; then - if test "$_MSC_VER" -a -z $AS; then - # Error out if we're on MSVC and MASM is unavailable. - AC_MSG_ERROR([No suitable assembler found. An assembler is required to build js-ctypes. If you are building with MS Visual Studio 8 Express, you may download the MASM 8.0 package, upgrade to Visual Studio 9 Express, or install the Vista SDK.]) - fi - AC_DEFINE(JS_HAS_CTYPES) -fi - dnl ======================================================== dnl = Use JS Call tracing dnl ======================================================== @@ -4540,7 +5017,7 @@ if test -n "$MOZ_VTUNE"; then fi dnl ======================================================== -dnl Zealous GC +dnl Zealous JavaScript GC dnl ======================================================== MOZ_ARG_ENABLE_BOOL(gczeal, [ --enable-gczeal Enable zealous GCing], @@ -4559,13 +5036,11 @@ MOZ_ARG_WITH_STRING(ccache, CCACHE=$withval, CCACHE="no") if test "$CCACHE" != "no"; then - if test -n "$CCACHE"; then - if test "$CCACHE" = "yes"; then - CCACHE= - else - if test ! -e "$CCACHE"; then - AC_MSG_ERROR([$CCACHE not found]) - fi + if test -z "$CCACHE" -o "$CCACHE" = "yes"; then + CCACHE= + else + if test ! -e "$CCACHE"; then + AC_MSG_ERROR([$CCACHE not found]) fi fi MOZ_PATH_PROGS(CCACHE, $CCACHE ccache) @@ -5076,6 +5551,21 @@ dnl ======================================================== MOZ_ARG_HEADER(Standalone module options (Not for building Mozilla)) dnl ======================================================== +dnl = Build jsctypes if it's enabled +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(ctypes, +[ --enable-ctypes Enable js-ctypes (default=no)], + JS_HAS_CTYPES=1, + JS_HAS_CTYPES= ) +AC_SUBST(JS_HAS_CTYPES) +if test "$JS_HAS_CTYPES"; then + if test "$_MSC_VER" -a -z $AS; then + # Error out if we're on MSVC and MASM is unavailable. + AC_MSG_ERROR([No suitable assembler found. An assembler is required to build js-ctypes. If you are building with MS Visual Studio 8 Express, you may download the MASM 8.0 package, upgrade to Visual Studio 9 Express, or install the Vista SDK.]) + fi + AC_DEFINE(JS_HAS_CTYPES) +fi + if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi @@ -5150,8 +5640,6 @@ AC_SUBST(MOZ_OS2_USE_DECLSPEC) AC_SUBST(MOZ_POST_DSO_LIB_COMMAND) AC_SUBST(MOZ_POST_PROGRAM_COMMAND) AC_SUBST(MOZ_TIMELINE) -AC_SUBST(WINCE) -AC_SUBST(WINCE_WINDOWS_MOBILE) AC_SUBST(MOZ_APP_NAME) AC_SUBST(MOZ_APP_DISPLAYNAME) @@ -5173,6 +5661,10 @@ AC_SUBST(AS_PERL) AC_SUBST(WIN32_REDIST_DIR) AC_SUBST(PYTHON) +AC_SUBST(WINCE) +AC_SUBST(WINCE_SDK_DIR) +AC_SUBST(WINCE_WINDOWS_MOBILE) + dnl Echo the CFLAGS to remove extra whitespace. CFLAGS=`echo \ $_WARNINGS_CFLAGS \ @@ -5265,6 +5757,20 @@ if test "$USING_HCC"; then AC_SUBST(CXX) fi +AC_MSG_CHECKING([for posix_fallocate]) +AC_TRY_LINK([#define _XOPEN_SOURCE 600 + #include ], + [posix_fallocate(0, 0, 0);], + [ac_cv___posix_fallocate=true], + [ac_cv___posix_fallocate=false]) + +if test "$ac_cv___posix_fallocate" = true ; then + AC_DEFINE(HAVE_POSIX_FALLOCATE) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + dnl Check for missing components if test "$COMPILE_ENVIRONMENT"; then if test "$MOZ_X11"; then From 954c83cd7bcb9b3541b3d90cc309d3f0954aebe9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 29 Oct 2010 10:28:31 -0700 Subject: [PATCH 140/263] IC for JSOP_CALLELEM (bug 604031, r=dmandelin). --- .../tests/jaeger/testDenseCallElem.js | 89 ++++++++++++++++++ .../jit-test/tests/jaeger/testPropCallElem.js | 93 +++++++++++++++++++ .../tests/jaeger/testPropCallElem2.js | 20 ++++ js/src/methodjit/Compiler.cpp | 18 ++-- js/src/methodjit/Compiler.h | 4 +- js/src/methodjit/FastOps.cpp | 63 ++++++++++--- js/src/methodjit/PolyIC.cpp | 82 +++++++++++++++- js/src/methodjit/PolyIC.h | 1 + 8 files changed, 344 insertions(+), 26 deletions(-) create mode 100644 js/src/jit-test/tests/jaeger/testDenseCallElem.js create mode 100644 js/src/jit-test/tests/jaeger/testPropCallElem.js create mode 100644 js/src/jit-test/tests/jaeger/testPropCallElem2.js diff --git a/js/src/jit-test/tests/jaeger/testDenseCallElem.js b/js/src/jit-test/tests/jaeger/testDenseCallElem.js new file mode 100644 index 00000000000..eadb77f55b9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/testDenseCallElem.js @@ -0,0 +1,89 @@ +// 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 new file mode 100644 index 00000000000..fd067bbf7a5 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/testPropCallElem.js @@ -0,0 +1,93 @@ +// 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 new file mode 100644 index 00000000000..328193ae4b2 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/testPropCallElem2.js @@ -0,0 +1,20 @@ +// 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 0a895bbc838..66d4cd004f8 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1189,7 +1189,7 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_LENGTH) BEGIN_CASE(JSOP_GETELEM) - if (!jsop_getelem()) + if (!jsop_getelem(false)) return Compile_Error; END_CASE(JSOP_GETELEM) @@ -1766,11 +1766,7 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_UINT24) BEGIN_CASE(JSOP_CALLELEM) - prepareStubCall(Uses(2)); - stubCall(stubs::CallElem); - frame.popn(2); - frame.pushSynced(); - frame.pushSynced(); + jsop_getelem(true); END_CASE(JSOP_CALLELEM) BEGIN_CASE(JSOP_STOP) @@ -4492,3 +4488,13 @@ 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 3bf27b46e14..6307aa8513d 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -351,6 +351,7 @@ 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(); @@ -416,7 +417,8 @@ 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 jsop_getelem(bool isCall); + bool isCacheableBaseAndIndex(FrameEntry *obj, FrameEntry *id); void jsop_stricteq(JSOp op); void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void 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 2f9dc0c77b5..f9abaea567a 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1360,30 +1360,39 @@ mjit::Compiler::jsop_setelem() stubcc.rejoin(Changes(0)); } -bool -mjit::Compiler::jsop_getelem() +static inline bool +IsCacheableGetElem(FrameEntry *obj, FrameEntry *id) { - FrameEntry *obj = frame.peek(-2); - FrameEntry *id = frame.peek(-1); - - if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) { - jsop_getelem_slow(); - return true; - } - + if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) + return false; if (id->isTypeKnown() && !(id->getKnownType() == JSVAL_TYPE_INT32 #ifdef JS_POLYIC || id->getKnownType() == JSVAL_TYPE_STRING #endif )) { - jsop_getelem_slow(); - return true; + return false; } if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_INT32 && id->isConstant() && id->getValue().toInt32() < 0) { - jsop_getelem_slow(); + 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(); return true; } @@ -1411,6 +1420,14 @@ mjit::Compiler::jsop_getelem() // 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. @@ -1456,6 +1473,14 @@ mjit::Compiler::jsop_getelem() 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 { @@ -1470,15 +1495,23 @@ mjit::Compiler::jsop_getelem() objTypeGuard.get().linkTo(stubcc.masm.label(), &stubcc.masm); #ifdef JS_POLYIC passICAddress(&ic); - ic.slowPathCall = stubcc.call(ic::GetElement); + if (isCall) + ic.slowPathCall = stubcc.call(ic::CallElement); + else + ic.slowPathCall = stubcc.call(ic::GetElement); #else - ic.slowPathCall = stubcc.call(stubs::GetElem); + if (isCall) + ic.slowPathCall = stubcc.call(stubs::CallElem); + else + 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 df2b29e24e5..0c051bdad2d 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -50,6 +50,7 @@ #include "jsscopeinlines.h" #include "jspropertycache.h" #include "jspropertycacheinlines.h" +#include "jsinterpinlines.h" #include "jsautooplen.h" #if defined JS_POLYIC @@ -1944,6 +1945,12 @@ 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) { @@ -1960,7 +1967,10 @@ LookupStatus GetElementIC::disable(JSContext *cx, const char *reason) { slowCallPatched = true; - BaseIC::disable(cx, reason, JS_FUNC_TO_DATA_PTR(void *, DisabledGetElem)); + void *stub = (op == JSOP_GETELEM) + ? JS_FUNC_TO_DATA_PTR(void *, DisabledGetElem) + : JS_FUNC_TO_DATA_PTR(void *, DisabledCallElem); + BaseIC::disable(cx, reason, stub); return Lookup_Uncacheable; } @@ -2053,6 +2063,13 @@ 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); @@ -2073,9 +2090,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 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())); + 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())); cx->free(chars); #endif @@ -2158,6 +2175,63 @@ 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 dad2448aedd..31341e53c9d 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -443,6 +443,7 @@ 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 */ From 39f1fe3e0a282e6c7e84e7ff2f7a6b974991fd7e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 1 Nov 2010 14:50:34 -0400 Subject: [PATCH 141/263] Bug 579540 - Intermittent timeout in browser/base/content/test/browser_bug553455.js, followed by various failures about number of installed extensions or notifications, probably depending on when it timed out; r=gavin a=orange-fix Try to increase the timeout to twice its previous amount in the hopes that it fixes the intermittent timeout in this test. --- browser/base/content/test/browser_bug553455.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/test/browser_bug553455.js b/browser/base/content/test/browser_bug553455.js index c1fd682f80f..339779fa998 100644 --- a/browser/base/content/test/browser_bug553455.js +++ b/browser/base/content/test/browser_bug553455.js @@ -597,7 +597,7 @@ var XPInstallObserver = { }; function test() { - requestLongerTimeout(2); + requestLongerTimeout(4); waitForExplicitFinish(); Services.prefs.setBoolPref("extensions.logging.enabled", true); From 0f84e63f4e32ffaf6435d3c4363e3bd1487b6577 Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Mon, 1 Nov 2010 09:47:23 -0400 Subject: [PATCH 142/263] Bug 594635: Fixes for OOP Core Animation NPAPI, fixes Quicktime plugin on Mac OS X. r=benwa a=josh/johnath --- dom/plugins/PluginInstanceParent.cpp | 2 +- dom/plugins/PluginModuleParent.cpp | 40 ++++++++++++++++++++-------- dom/plugins/PluginModuleParent.h | 4 +-- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/dom/plugins/PluginInstanceParent.cpp b/dom/plugins/PluginInstanceParent.cpp index 5f108f9da5b..fb63a3e04f2 100644 --- a/dom/plugins/PluginInstanceParent.cpp +++ b/dom/plugins/PluginInstanceParent.cpp @@ -1441,7 +1441,7 @@ PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus) void PluginInstanceParent::Invalidate() { - NPRect windowRect = {0, 0, mShWidth, mShHeight}; + NPRect windowRect = {0, 0, mShHeight, mShWidth}; RecvNPN_InvalidateRect(windowRect); } #endif diff --git a/dom/plugins/PluginModuleParent.cpp b/dom/plugins/PluginModuleParent.cpp index 5e3ab74cb52..0f4db3c4b87 100644 --- a/dom/plugins/PluginModuleParent.cpp +++ b/dom/plugins/PluginModuleParent.cpp @@ -127,6 +127,12 @@ PluginModuleParent::~PluginModuleParent() { NS_ASSERTION(OkToCleanup(), "unsafe destruction"); +#ifdef OS_MACOSX + if (mCATimer) { + mCATimer->Cancel(); + } +#endif + if (!mShutdown) { NS_WARNING("Plugin host deleted the module without shutting down."); NPError err; @@ -911,6 +917,17 @@ PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId) #ifdef OS_MACOSX #define DEFAULT_REFRESH_MS 20 // CoreAnimation: 50 FPS + +void +CAUpdate(nsITimer *aTimer, void *aClosure) { + nsTObserverArray *ips = + static_cast *>(aClosure); + nsTObserverArray::ForwardIterator iter(*ips); + while (iter.HasMore()) { + iter.GetNext()->Invalidate(); + } +} + void PluginModuleParent::AddToRefreshTimer(PluginInstanceParent *aInstance) { if (mCATimerTargets.Contains(aInstance)) { @@ -919,8 +936,17 @@ PluginModuleParent::AddToRefreshTimer(PluginInstanceParent *aInstance) { mCATimerTargets.AppendElement(aInstance); if (mCATimerTargets.Length() == 1) { - mCATimer.Start(base::TimeDelta::FromMilliseconds(DEFAULT_REFRESH_MS), - this, &PluginModuleParent::CAUpdate); + if (!mCATimer) { + nsresult rv; + nsCOMPtr xpcomTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + NS_WARNING("Could not create Core Animation timer for plugin."); + return; + } + mCATimer = xpcomTimer; + } + mCATimer->InitWithFuncCallback(CAUpdate, &mCATimerTargets, DEFAULT_REFRESH_MS, + nsITimer::TYPE_REPEATING_SLACK); } } @@ -928,15 +954,7 @@ void PluginModuleParent::RemoveFromRefreshTimer(PluginInstanceParent *aInstance) { PRBool visibleRemoved = mCATimerTargets.RemoveElement(aInstance); if (visibleRemoved && mCATimerTargets.IsEmpty()) { - mCATimer.Stop(); - } -} - -void -PluginModuleParent::CAUpdate() { - nsTObserverArray::ForwardIterator iter(mCATimerTargets); - while (iter.HasMore()) { - iter.GetNext()->Invalidate(); + mCATimer->Cancel(); } } #endif diff --git a/dom/plugins/PluginModuleParent.h b/dom/plugins/PluginModuleParent.h index 523a7a86de7..5cd5e814fc9 100644 --- a/dom/plugins/PluginModuleParent.h +++ b/dom/plugins/PluginModuleParent.h @@ -61,6 +61,7 @@ #include "nsHashKeys.h" #include "nsIFileStreams.h" #include "nsTObserverArray.h" +#include "nsITimer.h" namespace mozilla { namespace plugins { @@ -264,8 +265,7 @@ private: nsString mHangID; #ifdef OS_MACOSX - void CAUpdate(); - base::RepeatingTimer mCATimer; + nsCOMPtr mCATimer; nsTObserverArray mCATimerTargets; #endif }; From ed937ae331aeb8f1918513258b57ced79b6daf7c Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 1 Nov 2010 13:13:00 -0700 Subject: [PATCH 143/263] Bug 576620 - crash: getParameter stack corruption in the paths returning 4 ints - r=joe, a=blocking-beta7 --- content/canvas/src/WebGLContextGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 7078c039ede..2bf58ed371a 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -1639,7 +1639,7 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval) case LOCAL_GL_SCISSOR_BOX: // 4 ints case LOCAL_GL_VIEWPORT: // 4 ints { - GLint iv[2] = { 0 }; + GLint iv[4] = { 0 }; gl->fGetIntegerv(pname, iv); wrval->SetAsArray(nsIDataType::VTYPE_INT32, nsnull, 4, static_cast(iv)); From 8cfb01a2d5bbdf36a068f6253b71b40736b7e33c Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Mon, 1 Nov 2010 14:30:07 -0700 Subject: [PATCH 144/263] Bug 608507 - some minor test cleanup. r=dtownsend, a=test fix --- .../extensions/test/browser/browser_bug557956.js | 14 +++++++------- .../test/xpinstall/browser_signed_naming.js | 2 +- .../test/xpinstall/browser_signed_trigger.js | 2 +- .../test/xpinstall/browser_signed_untrusted.js | 2 +- .../test/xpinstall/browser_signed_url.js | 2 +- .../test/xpinstall/browser_trigger_redirect.js | 2 +- .../test/xpinstall/browser_unsigned_trigger.js | 2 +- .../xpinstall/browser_unsigned_trigger_iframe.js | 2 +- .../test/xpinstall/browser_unsigned_url.js | 2 +- .../extensions/test/xpinstall/browser_whitelist.js | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js index 7ea3da9bbb3..31aa5885d90 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js @@ -387,14 +387,14 @@ add_test(function() { ]; open_compatibility_window(inactiveAddonIds, function(aWindow) { - var doc = aWindow.document; - wait_for_page(aWindow, "mismatch", function(aWindow) { - var items = get_list_names(doc.getElementById("mismatch.incompatible")); - is(items.length, 1, "Should have seen 1 still incompatible items"); - is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); + var doc = aWindow.document; + wait_for_page(aWindow, "mismatch", function(aWindow) { + var items = get_list_names(doc.getElementById("mismatch.incompatible")); + is(items.length, 1, "Should have seen 1 still incompatible items"); + is(items[0], "Addon3 1.0", "Should have seen addon3 still incompatible"); - var button = doc.documentElement.getButton("next"); - EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); + var button = doc.documentElement.getButton("next"); + EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow); wait_for_page(aWindow, "noupdates", function(aWindow) { var button = doc.documentElement.getButton("finish"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js index 6c0d60ebc95..f0c4f4286ee 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_naming.js @@ -30,7 +30,7 @@ function get_item(items, url) { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + let items = window.document.getElementById("itemList").childNodes; is(items.length, 3, "Should be 3 items listed in the confirmation dialog"); let item = get_item(items, TESTROOT + "signed.xpi"); if (item) { diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js index ffb21f38c0e..cefce2a4c37 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js @@ -18,7 +18,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "Signed XPI Test", "Should have seen the name from the trigger list"); is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js index 70dd11479ec..afb34d8a3f6 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_untrusted.js @@ -18,7 +18,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "Signed XPI Test", "Should have had the filename for the item name"); is(items[0].url, TESTROOT + "signed-untrusted.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js index b6a8860f04f..351092a435a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_url.js @@ -11,7 +11,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + let items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "Signed XPI Test", "Should have had the name"); is(items[0].url, TESTROOT + "signed.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js index e47f40e646b..c953698bcda 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js @@ -14,7 +14,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js index ec374e56779..4e2046306b1 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js @@ -22,7 +22,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js index e0422a5e601..34073b0bddb 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js @@ -23,7 +23,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name"); is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js index e0f783732db..bc3be4f9e37 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_url.js @@ -11,7 +11,7 @@ function test() { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + let items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have had the filename for the item name"); is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js index c4d1900fb08..b3be94c6a8c 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js @@ -23,7 +23,7 @@ function allow_blocked(installInfo) { } function confirm_install(window) { - items = window.document.getElementById("itemList").childNodes; + var items = window.document.getElementById("itemList").childNodes; is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); is(items[0].name, "XPI Test", "Should have seen the name from the trigger list"); is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); From ad5637c9665cbcad1b8a6af55456ac6fcfc84e0d Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Mon, 1 Nov 2010 14:30:30 -0700 Subject: [PATCH 145/263] Bug 608586 - [SeaMonkey] mochitest-browser-chrome: .../browser-window/browser_bug562797.js fails. r=dtownsend, a=test fix --- .../test/browser/browser_bug562797.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js index a54302445c5..51f19ac1b09 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js @@ -96,6 +96,12 @@ function is_in_detail(aManager, view, canGoBack, canGoForward) { check_state(aManager, canGoBack, canGoForward); } +function double_click_addon_element(aManager, aId) { + var addon = get_addon_element(aManager, aId); + addon.parentNode.ensureElementIsVisible(addon); + EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager); +} + // Tests simple forward and back navigation and that the right heading and // category is selected add_test(function() { @@ -127,8 +133,7 @@ add_test(function() { info("Part 5"); is_in_list(aManager, "addons://list/extension", false, true); - EventUtils.synthesizeMouseAtCenter(get_addon_element(aManager, "test1@tests.mozilla.org"), - { clickCount: 2 }, aManager); + double_click_addon_element(aManager, "test1@tests.mozilla.org"); wait_for_view_load(aManager, function(aManager) { info("Part 6"); @@ -348,8 +353,7 @@ add_test(function() { is_in_search(aManager, "bar", true, false); check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); - EventUtils.synthesizeMouseAtCenter(get_addon_element(aManager, "test2@tests.mozilla.org"), - { clickCount: 2 }, aManager); + double_click_addon_element(aManager, "test2@tests.mozilla.org"); wait_for_view_load(aManager, function(aManager) { info("Part 3"); @@ -397,8 +401,7 @@ add_test(function() { is_in_search(aManager, "bar", true, false); check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]); - EventUtils.synthesizeMouseAtCenter(get_addon_element(aManager, "test2@tests.mozilla.org"), - { clickCount: 2 }, aManager); + double_click_addon_element(aManager, "test2@tests.mozilla.org"); wait_for_view_load(aManager, function(aManager) { info("Part 3"); @@ -495,8 +498,7 @@ add_test(function() { info("Part 1"); is_in_list(aManager, "addons://list/extension", false, false); - EventUtils.synthesizeMouseAtCenter(get_addon_element(aManager, "test1@tests.mozilla.org"), - { clickCount: 2 }, aManager); + double_click_addon_element(aManager, "test1@tests.mozilla.org"); wait_for_view_load(aManager, function(aManager) { info("Part 2"); @@ -532,8 +534,7 @@ add_test(function() { info("Part 1"); is_in_list(aManager, "addons://list/extension", false, false); - EventUtils.synthesizeMouseAtCenter(get_addon_element(aManager, "test1@tests.mozilla.org"), - { clickCount: 2 }, aManager); + double_click_addon_element(aManager, "test1@tests.mozilla.org"); wait_for_view_load(aManager, function(aManager) { info("Part 2"); From 5113d5e127ecefac49bbb170bfeccd518d8a1312 Mon Sep 17 00:00:00 2001 From: Clint Talbert Date: Mon, 1 Nov 2010 14:52:08 -0700 Subject: [PATCH 146/263] Bug 608393 Update Mozmill on mozilla central to 1.5.1 rc2 r=jhammel a=NPOTB --HG-- extra : rebase_source : c1d58027a8f218457efcf77a6ae3c09c7f9a4d30 --- .../jsbridge/jsbridge/extension/install.rdf | 2 +- testing/mozmill/jsbridge/setup.py | 4 +- testing/mozmill/mozmill/mozmill/__init__.py | 5 +- .../mozmill/mozmill/extension/install.rdf | 2 +- .../extension/resource/modules/init.js | 12 +- .../extension/resource/modules/utils.js | 18 +- testing/mozmill/mozmill/setup.py | 4 +- .../mozmill/mozrunner/mozrunner/winprocess.py | 29 +-- testing/mozmill/mozrunner/setup.py | 2 +- .../testStartStopPBMode.js | 172 ------------------ 10 files changed, 48 insertions(+), 202 deletions(-) delete mode 100644 testing/mozmill/tests/firefox/testPrivateBrowsing/testStartStopPBMode.js diff --git a/testing/mozmill/jsbridge/jsbridge/extension/install.rdf b/testing/mozmill/jsbridge/jsbridge/extension/install.rdf index 00ed1da2803..e5b55281e19 100644 --- a/testing/mozmill/jsbridge/jsbridge/extension/install.rdf +++ b/testing/mozmill/jsbridge/jsbridge/extension/install.rdf @@ -4,7 +4,7 @@ jsbridge@mozilla.com jsbridge - 2.4.1 + 2.4.1rc2 Mikeal Rogers Python to JavaScript bridge diff --git a/testing/mozmill/jsbridge/setup.py b/testing/mozmill/jsbridge/setup.py index fad5466a3c0..efa658e2df5 100644 --- a/testing/mozmill/jsbridge/setup.py +++ b/testing/mozmill/jsbridge/setup.py @@ -42,9 +42,9 @@ desc = """Python to JavaScript bridge interface.""" summ = """A powerful and extensible Python to JavaScript bridge interface.""" PACKAGE_NAME = "jsbridge" -PACKAGE_VERSION = "2.4.1" +PACKAGE_VERSION = "2.4.1rc2" -requires = ['mozrunner == 2.5.2'] +requires = ['mozrunner == 2.5.2rc2'] if not sys.version.startswith('2.6'): requires.append('simplejson') diff --git a/testing/mozmill/mozmill/mozmill/__init__.py b/testing/mozmill/mozmill/mozmill/__init__.py index e393dcec471..9a4af6e7cd9 100644 --- a/testing/mozmill/mozmill/mozmill/__init__.py +++ b/testing/mozmill/mozmill/mozmill/__init__.py @@ -769,11 +769,12 @@ class CLI(jsbridge.CLI): self.mozmill.report_disconnect() print 'TEST-UNEXPECTED-FAIL | Disconnect Error: Application unexpectedly closed' + # shutdown the test harness + self.mozmill.stop(fatal=disconnected) + # print statistics and send the JSON report self.mozmill.report(self.options.report) - # shutdown the test harness - self.mozmill.stop(fatal=disconnected) if self.mozmill.fails or disconnected: sys.exit(1) else: diff --git a/testing/mozmill/mozmill/mozmill/extension/install.rdf b/testing/mozmill/mozmill/mozmill/extension/install.rdf index 34d783252bf..f03ff570ba7 100755 --- a/testing/mozmill/mozmill/mozmill/extension/install.rdf +++ b/testing/mozmill/mozmill/mozmill/extension/install.rdf @@ -4,7 +4,7 @@ mozmill@mozilla.com MozMill - 1.5.1 + 1.5.1rc2 Adam Christian A testing extension based on the Windmill Testing Framework client source diff --git a/testing/mozmill/mozmill/mozmill/extension/resource/modules/init.js b/testing/mozmill/mozmill/mozmill/extension/resource/modules/init.js index ba084c6449b..91a8c0554b0 100644 --- a/testing/mozmill/mozmill/mozmill/extension/resource/modules/init.js +++ b/testing/mozmill/mozmill/mozmill/extension/resource/modules/init.js @@ -94,14 +94,20 @@ function initialize() { var observerService = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); observerService.addObserver(windowObserver, "toplevel-window-ready", false); - + // Attach event listeners to all open windows var enumerator = Cc["@mozilla.org/appshell/window-mediator;1"]. getService(Ci.nsIWindowMediator).getEnumerator(""); while (enumerator.hasMoreElements()) { - attachEventListeners(enumerator.getNext()); + var win = enumerator.getNext(); + attachEventListeners(win); + + // For windows or dialogs already open we have to explicitly set the property + // otherwise windows which load really quick never gets the property set and + // we fail to create the controller + win.documentLoaded = true; }; } - + initialize(); diff --git a/testing/mozmill/mozmill/mozmill/extension/resource/modules/utils.js b/testing/mozmill/mozmill/mozmill/extension/resource/modules/utils.js index 77e8d589ffb..38215f3efa3 100644 --- a/testing/mozmill/mozmill/mozmill/extension/resource/modules/utils.js +++ b/testing/mozmill/mozmill/mozmill/extension/resource/modules/utils.js @@ -368,15 +368,21 @@ function setPreference(aName, aValue) { /** * Sleep for the given amount of milliseconds + * + * @param {number} milliseconds + * Sleeps the given number of milliseconds */ function sleep(milliseconds) { - var self = {init: false}; + // We basically just call this once after the specified number of milliseconds + var timeup = false; + function wait() { timeup = true; } + hwindow.setTimeout(wait, milliseconds); - waitFor(function() { - var init = self.init; - self.init = !init; - return init; - }, "The sleep call should never fail", (milliseconds + 1000), milliseconds); + var thread = Components.classes["@mozilla.org/thread-manager;1"]. + getService().currentThread; + while(!timeup) { + thread.processNextEvent(true); + } } /** diff --git a/testing/mozmill/mozmill/setup.py b/testing/mozmill/mozmill/setup.py index d65be041e11..77ef12582fe 100644 --- a/testing/mozmill/mozmill/setup.py +++ b/testing/mozmill/mozmill/setup.py @@ -41,7 +41,7 @@ desc = """UI Automation tool for Mozilla applications.""" summ = """A tool for full UI automation of Mozilla applications.""" PACKAGE_NAME = "mozmill" -PACKAGE_VERSION = "1.5.1" +PACKAGE_VERSION = "1.5.1rc2" setup(name=PACKAGE_NAME, version=PACKAGE_VERSION, @@ -61,7 +61,7 @@ setup(name=PACKAGE_NAME, mozmill-restart = mozmill:restart_cli """, platforms =['Any'], - install_requires = ['jsbridge == 2.4.1', 'mozrunner == 2.5.2'], + install_requires = ['jsbridge == 2.4.1rc2', 'mozrunner == 2.5.2rc2'], classifiers=['Development Status :: 4 - Beta', 'Environment :: Console', 'Intended Audience :: Developers', diff --git a/testing/mozmill/mozrunner/mozrunner/winprocess.py b/testing/mozmill/mozrunner/mozrunner/winprocess.py index 044305cd581..08f7fdd12ab 100644 --- a/testing/mozmill/mozrunner/mozrunner/winprocess.py +++ b/testing/mozmill/mozrunner/mozrunner/winprocess.py @@ -236,18 +236,23 @@ GetCurrentProcess = GetCurrentProcessProto( GetCurrentProcess.errcheck = ErrCheckHandle # IsProcessInJob() -IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # Process Handle - HANDLE, # Job Handle - LPBOOL # Result - ) -IsProcessInJobFlags = ((1, "ProcessHandle"), - (1, "JobHandle", HANDLE(0)), - (2, "Result")) -IsProcessInJob = IsProcessInJobProto( - ("IsProcessInJob", windll.kernel32), - IsProcessInJobFlags) -IsProcessInJob.errcheck = ErrCheckBool +try: + IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type + HANDLE, # Process Handle + HANDLE, # Job Handle + LPBOOL # Result + ) + IsProcessInJobFlags = ((1, "ProcessHandle"), + (1, "JobHandle", HANDLE(0)), + (2, "Result")) + IsProcessInJob = IsProcessInJobProto( + ("IsProcessInJob", windll.kernel32), + IsProcessInJobFlags) + IsProcessInJob.errcheck = ErrCheckBool +except AttributeError: + # windows 2k doesn't have this API + def IsProcessInJob(process): + return False # ResumeThread() diff --git a/testing/mozmill/mozrunner/setup.py b/testing/mozmill/mozrunner/setup.py index f0df9bb04c9..a8e8d160f68 100644 --- a/testing/mozmill/mozrunner/setup.py +++ b/testing/mozmill/mozrunner/setup.py @@ -42,7 +42,7 @@ desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Th summ = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)""" PACKAGE_NAME = "mozrunner" -PACKAGE_VERSION = "2.5.2" +PACKAGE_VERSION = "2.5.2rc2" deps = [] diff --git a/testing/mozmill/tests/firefox/testPrivateBrowsing/testStartStopPBMode.js b/testing/mozmill/tests/firefox/testPrivateBrowsing/testStartStopPBMode.js deleted file mode 100644 index 56a9197902f..00000000000 --- a/testing/mozmill/tests/firefox/testPrivateBrowsing/testStartStopPBMode.js +++ /dev/null @@ -1,172 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is MozMill Test code. - * - * The Initial Developer of the Original Code is Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Henrik Skupin - * Aaron Train - * Anthony Hughes - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -// Include necessary modules -const RELATIVE_ROOT = '../../shared-modules'; -const MODULE_REQUIRES = ['PrivateBrowsingAPI', 'TabbedBrowsingAPI', 'UtilsAPI']; - -const TIMEOUT = 5000; - -const LOCAL_TEST_FOLDER = collector.addHttpResource('../test-files/'); -const LOCAL_TEST_PAGES = [ - {url: LOCAL_TEST_FOLDER + 'layout/mozilla.html', id: 'community'}, - {url: 'about:', id: 'aboutPageList'} -]; - -var setupModule = function() { - controller = mozmill.getBrowserController(); - modifier = controller.window.document.documentElement. - getAttribute("titlemodifier_privatebrowsing"); - - // Create Private Browsing instance and set handler - pb = new PrivateBrowsingAPI.privateBrowsing(controller); - pb.handler = pbStartHandler; - - TabbedBrowsingAPI.closeAllTabs(controller); -} - -var teardownModule = function() { - pb.reset(); -} - -/** - * Enable Private Browsing Mode - */ -var testEnablePrivateBrowsingMode = function() { - // Make sure we are not in PB mode and show a prompt - pb.enabled = false; - pb.showPrompt = true; - - // Open websites in separate tabs - var newTab = new elementslib.Elem(controller.menus['file-menu'].menu_newNavigatorTab); - - for each (var page in LOCAL_TEST_PAGES) { - controller.open(page.url); - controller.waitForPageLoad(); - - controller.click(newTab); - } - - // Start the Private Browsing mode - pb.start(); - - // Check that only one tab is open - controller.assertJS("subject.isOnlyOneTab == true", - {isOnlyOneTab: controller.tabs.length == 1}); - - // Title modifier should have been set - controller.assertJS("subject.hasTitleModifier == true", - {hasTitleModifier: controller.window.document. - title.indexOf(modifier) != -1}); - - // Check descriptions on the about:privatebrowsing page - var description = UtilsAPI.getEntity(pb.getDtds(), "privatebrowsingpage.description"); - var learnMore = UtilsAPI.getEntity(pb.getDtds(), "privatebrowsingpage.learnMore"); - var longDescElem = new elementslib.ID(controller.tabs.activeTab, "errorLongDescText"); - var moreInfoElem = new elementslib.ID(controller.tabs.activeTab, "moreInfoLink"); - controller.waitForElement(longDescElem, TIMEOUT); - controller.assertText(longDescElem, description); - controller.assertText(moreInfoElem, learnMore); -} - -/** - * Stop the Private Browsing mode - */ -var testStopPrivateBrowsingMode = function() { - // Force enable Private Browsing mode - pb.enabled = true; - - // Stop Private Browsing mode - pb.stop(); - - // All tabs should be restored - controller.assertJS("subject.allTabsRestored == true", - {allTabsRestored: controller.tabs.length == LOCAL_TEST_PAGES.length + 1}); - - for (var i = 0; i < LOCAL_TEST_PAGES.length; i++) { - controller.waitForPageLoad(controller.tabs.getTab(i)); - - var elem = new elementslib.ID(controller.tabs.getTab(i), LOCAL_TEST_PAGES[i].id); - controller.assertNode(elem); - } - - // No title modifier should have been set - controller.assertJS("subject.noTitleModifier == true", - {noTitleModifier: controller.window.document. - title.indexOf(modifier) == -1}); -} - -/** - * Verify Ctrl/Cmd+Shift+P keyboard shortcut for Private Browsing mode - */ -var testKeyboardShortcut = function() { - // Make sure we are not in PB mode and show a prompt - pb.enabled = false; - pb.showPrompt = true; - - // Start the Private Browsing mode via the keyboard shortcut - pb.start(true); - - // Stop the Private Browsing mode via the keyboard shortcut - pb.stop(true); -} - -/** - * Handle the modal dialog to enter the Private Browsing mode - * - * @param {MozMillController} controller - * MozMillController of the window to operate on - */ -var pbStartHandler = function(controller) { - // Check to not ask anymore for entering Private Browsing mode - var checkbox = new elementslib.ID(controller.window.document, 'checkbox'); - controller.waitThenClick(checkbox, TIMEOUT); - - var okButton = new elementslib.Lookup(controller.window.document, - '/id("commonDialog")' + - '/anon({"anonid":"buttons"})' + - '/{"dlgtype":"accept"}'); - controller.click(okButton); -} - -/** - * Map test functions to litmus tests - */ -// testEnablePrivateBrowsingMode.meta = {litmusids : [9154]}; -// testStopPrivateBrowsingMode.meta = {litmusids : [9155]}; -// testKeyboardShortcut.meta = {litmusids : [9186]}; From c0e1c71e7cf6b216b36a2afe795de1f809a60c21 Mon Sep 17 00:00:00 2001 From: Bob Moss Date: Mon, 1 Nov 2010 14:52:08 -0700 Subject: [PATCH 147/263] Bug 606265 - add ability to set timezone to android agent r=ctalbert a=NPOTB --HG-- extra : rebase_source : 873f9e6d6b034d86d99634b090dafa5860bcab21 --- .../sutagent/android/AndroidManifest.xml | 3 + build/mobile/sutagent/android/DoCommand.java | 624 +++++++++++++----- .../sutagent/android/SUTAgentAndroid.java | 2 +- 3 files changed, 471 insertions(+), 158 deletions(-) diff --git a/build/mobile/sutagent/android/AndroidManifest.xml b/build/mobile/sutagent/android/AndroidManifest.xml index ddc5dbf5a25..658a3de8797 100644 --- a/build/mobile/sutagent/android/AndroidManifest.xml +++ b/build/mobile/sutagent/android/AndroidManifest.xml @@ -65,4 +65,7 @@ + + + \ No newline at end of file diff --git a/build/mobile/sutagent/android/DoCommand.java b/build/mobile/sutagent/android/DoCommand.java index 4618c0ab3ef..0f0ce68681e 100755 --- a/build/mobile/sutagent/android/DoCommand.java +++ b/build/mobile/sutagent/android/DoCommand.java @@ -51,6 +51,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; @@ -59,9 +60,12 @@ import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.TimeZone; import java.util.Timer; import java.util.zip.Adler32; @@ -87,6 +91,7 @@ import com.mozilla.SUTAgentAndroid.SUTAgentAndroid; import android.app.Activity; import android.app.ActivityManager; +import android.app.AlarmManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.ContextWrapper; @@ -95,12 +100,14 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Configuration; import android.net.Uri; import android.os.Build; import android.os.Debug; import android.os.Environment; import android.os.StatFs; import android.os.SystemClock; +import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; @@ -118,13 +125,13 @@ public class DoCommand { String currentDir = "/"; String sErrorPrefix = "##AGENT-WARNING## "; - private final String prgVersion = "SUTAgentAndroid Version 0.85"; + private final String prgVersion = "SUTAgentAndroid Version 0.87"; public enum Command { RUN ("run"), EXEC ("exec"), - ARUN ("arun"), + ENVRUN ("envrun"), KILL ("kill"), PS ("ps"), DEVINFO ("info"), @@ -173,6 +180,8 @@ public class DoCommand { UNINST ("uninst"), TEST ("test"), VER ("ver"), + TZGET ("tzget"), + TZSET ("tzset"), UNKNOWN ("unknown"); private final String theCmd; @@ -207,7 +216,7 @@ public class DoCommand { Command cCmd = null; Command cSubCmd = null; - String [] Argv = parseCmdLine(theCmdLine); + String [] Argv = parseCmdLine2(theCmdLine); int Argc = Argv.length; @@ -223,6 +232,17 @@ public class DoCommand { strReturn = GetClok(); break; + case TZGET: + strReturn = GetTimeZone(); + break; + + case TZSET: + if (Argc == 2) + strReturn = SetTimeZone(Argv[1]); + else + strReturn = sErrorPrefix + "Wrong number of arguments for settz command!"; + break; + case UPDT: strReturn = StartUpdateOMatic(Argv[1], Argv[2]); break; @@ -327,16 +347,6 @@ public class DoCommand { break; case REBT: -// try { -// reboot(null); -// Power.reboot(null); -// Power.shutdown(); -// } -// catch (IOException e) -// { - // TODO Auto-generated catch block -// e.printStackTrace(); -// } RunReboot(cmdOut); break; @@ -497,6 +507,25 @@ public class DoCommand { case TEST: // boolean bRet = false; +/* + Configuration userConfig = new Configuration(); + Settings.System.getConfiguration( contextWrapper.getContentResolver(), userConfig ); + Calendar cal = Calendar.getInstance( userConfig.locale); + TimeZone ctz = cal.getTimeZone(); + String sctzLongName = ctz.getDisplayName(); + String pstzName = TimeZone.getDefault().getDisplayName(); +*/ + String sTimeZoneName = GetTimeZone(); + + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone tz2 = TimeZone.getTimeZone("GMT-08:00"); + int nOffset = (-8 * 3600000); + String [] zoneNames = TimeZone.getAvailableIDs(nOffset); + int nNumMatches = zoneNames.length; + TimeZone.setDefault(tz); + + String sOldTZ = System.setProperty("persist.sys.timezone", "America/Los_Angeles"); + /* byte[] buffer = new byte [4096]; int nRead = 0; @@ -591,7 +620,7 @@ public class DoCommand { } */ // strReturn = InstallApplication(); - strReturn = InstallApp(Argv[1], cmdOut); +// strReturn = InstallApp(Argv[1], cmdOut); // strReturn = UninstallApplication(); // String sPingCheck = SendPing("www.mozilla.org",null); @@ -653,6 +682,24 @@ public class DoCommand { */ break; + case ENVRUN: + if (Argc >= 2) + { + String [] theArgs = new String [Argc - 1]; + + for (int lcv = 1; lcv < Argc; lcv++) + { + theArgs[lcv - 1] = Argv[lcv]; + } + + strReturn = StartPrg2(theArgs, cmdOut); + } + else + { + strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!"; + } + break; + case EXEC: case RUN: if (Argc >= 2) @@ -828,12 +875,28 @@ public class DoCommand { } } - public String [] parseCmdLine(String theCmdLine) { + public String [] parseCmdLine2(String theCmdLine) + { + String cmdString; String workingString; String workingString2; + String workingString3; List lst = new ArrayList(); - int nLength = theCmdLine.length(); - int nFirstSpace = theCmdLine.indexOf(' '); + int nLength = 0; + int nFirstSpace = -1; + + // Null cmd line + if (theCmdLine == null) + { + String [] theArgs = new String [1]; + theArgs[0] = new String(""); + return(theArgs); + } + else + { + nLength = theCmdLine.length(); + nFirstSpace = theCmdLine.indexOf(' '); + } if (nFirstSpace == -1) { @@ -843,7 +906,134 @@ public class DoCommand { } // Get the command - lst.add(new String(theCmdLine.substring(0, nFirstSpace))); + cmdString = new String(theCmdLine.substring(0, nFirstSpace)); + lst.add(cmdString); + + // Jump past the command and trim + workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim(); + + while ((nLength = workingString.length()) > 0) + { + int nEnd = 0; + int nStart = 0; + + // if we have a quote + if (workingString.startsWith("\"")) + { + // point to the first non quote char + nStart = 1; + // find the matching quote + nEnd = workingString.indexOf('"', nStart); + + char prevChar; + + while(nEnd != -1) + { + // check to see if the quotation mark has been escaped + prevChar = workingString.charAt(nEnd - 1); + if (prevChar == '\\') + { + // if escaped, point past this quotation mark and find the next + nEnd++; + if (nEnd < nLength) + nEnd = workingString.indexOf('"', nEnd); + else + nEnd = -1; + } + else + break; + } + + // there isn't one + if (nEnd == -1) + { + // point at the quote + nStart = 0; + // so find the next space + nEnd = workingString.indexOf(' ', nStart); + // there isn't one of those either + if (nEnd == -1) + nEnd = nLength; // Just grab the rest of the cmdline + } + } + else // no quote so find the next space + { + nEnd = workingString.indexOf(' ', nStart); + // there isn't one of those + if (nEnd == -1) + nEnd = nLength; // Just grab the rest of the cmdline + } + + // get the substring + workingString2 = workingString.substring(nStart, nEnd); + + // if we have escaped quotes + if (workingString2.contains("\\\"")) + { + do + { + // replace escaped quote with embedded quote + workingString3 = workingString2.replace("\\\"", "\""); + workingString2 = workingString3; + } + while(workingString2.contains("\\\"")); + } + + // add it to the list + lst.add(new String(workingString2)); + + // if we are dealing with a quote + if (nStart > 0) + nEnd++; // point past the end one + + // jump past the substring and trim it + workingString = (workingString.substring(nEnd)).trim(); + } + + // ok we're done package up the results + int nItems = lst.size(); + + String [] theArgs = new String [nItems]; + + for (int lcv = 0; lcv < nItems; lcv++) + { + theArgs[lcv] = lst.get(lcv); + } + + return(theArgs); + } + + public String [] parseCmdLine(String theCmdLine) { + String cmdString; + String workingString; + String workingString2; + List lst = new ArrayList(); + int nLength = 0; + int nFirstSpace = -1; + + // Null cmd line + if (theCmdLine == null) + { + String [] theArgs = new String [1]; + theArgs[0] = new String(""); + return(theArgs); + } + else + { + nLength = theCmdLine.length(); + nFirstSpace = theCmdLine.indexOf(' '); + } + + if (nFirstSpace == -1) + { + String [] theArgs = new String [1]; + theArgs[0] = new String(theCmdLine); + return(theArgs); + } + + // Get the command + cmdString = new String(theCmdLine.substring(0, nFirstSpace)); + lst.add(cmdString); // Jump past the command and trim workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim(); @@ -871,6 +1061,11 @@ public class DoCommand { if (nEnd == -1) nEnd = nLength; // Just grab the rest of the cmdline } + else + { + nStart = 0; + nEnd++; + } } else // no quote so find the next space { @@ -887,8 +1082,8 @@ public class DoCommand { lst.add(new String(workingString2)); // if we are dealing with a quote - if (nStart > 0) - nEnd++; // point past the end one +// if (nStart > 0) +// nEnd++; // point past the end one // jump past the substring and trim it workingString = (workingString.substring(nEnd)).trim(); @@ -1116,7 +1311,6 @@ public class DoCommand { public String StatProcess(String string) { String sRet = ""; -// ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); int [] nPids = new int [1]; @@ -1160,7 +1354,6 @@ public class DoCommand { public String GetAppRoot(String AppName) { String sRet = ""; -// Context ctx = SUTAgentAndroid.me.getApplicationContext(); Context ctx = contextWrapper.getApplicationContext(); if (ctx != null) @@ -1234,8 +1427,8 @@ public class DoCommand { try { digest = java.security.MessageDigest.getInstance("MD5"); } - catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block + catch (NoSuchAlgorithmException e) + { e.printStackTrace(); } @@ -1420,12 +1613,10 @@ public class DoCommand { } catch (FileNotFoundException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } @@ -1534,12 +1725,6 @@ public class DoCommand { @SuppressWarnings("unused") boolean bRet = ftp.completePendingCommand(); outStream.flush(); - /* - if (ftp.retrieveFile("pub/mozilla.org/firefox/releases/3.6b4/wince-arm/en-US/firefox-3.6b4.cab", outStream)) - { - outStream.flush(); - } - */ outStream.close(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); @@ -1564,7 +1749,6 @@ public class DoCommand { } catch (SocketException e) { - // TODO Auto-generated catch block sRet = e.getMessage(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); @@ -1573,7 +1757,6 @@ public class DoCommand { } catch (IOException e) { - // TODO Auto-generated catch block sRet = e.getMessage(); strRet = ftp.getReplyString(); reply = ftp.getReplyCode(); @@ -1652,7 +1835,6 @@ public class DoCommand { theArgs[2] = "kill"; String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n"; -// ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List lProcesses = aMgr.getRunningAppProcesses(); int lcv = 0; @@ -1661,7 +1843,6 @@ public class DoCommand { for (lcv = 0; lcv < lProcesses.size(); lcv++) { -// if (lProcesses.get(lcv).processName.contentEquals(sProcName)) if (lProcesses.get(lcv).processName.contains(sProcName)) { strProcName = lProcesses.get(lcv).processName; @@ -1684,12 +1865,9 @@ public class DoCommand { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } -// SUTAgentAndroid.me.finishActivity(SUTAgentAndroid.START_PRG); - // Give the messages a chance to be processed try { Thread.sleep(2000); @@ -1698,7 +1876,6 @@ public class DoCommand { { e.printStackTrace(); } -// aMgr.restartPackage(strProcName); break; } } @@ -1709,7 +1886,6 @@ public class DoCommand { lProcesses = aMgr.getRunningAppProcesses(); for (lcv = 0; lcv < lProcesses.size(); lcv++) { -// if (lProcesses.get(lcv).processName.contentEquals(sProcName)) if (lProcesses.get(lcv).processName.contains(sProcName)) { sRet = sErrorPrefix + "Unable to kill " + nPID + " " + strProcName + "\n"; @@ -1724,12 +1900,9 @@ public class DoCommand { public boolean IsProcessDead(String sProcName) { boolean bRet = false; -// ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List lProcesses = aMgr.getProcessesInErrorState(); int lcv = 0; -// String strProcName = ""; -// int nPID = 0; if (lProcesses != null) { @@ -1738,8 +1911,6 @@ public class DoCommand { if (lProcesses.get(lcv).processName.contentEquals(sProcName) && lProcesses.get(lcv).condition != ActivityManager.ProcessErrorStateInfo.NO_ERROR) { -// strProcName = lProcesses.get(lcv).processName; -// nPID = lProcesses.get(lcv).pid; bRet = true; break; } @@ -1752,7 +1923,6 @@ public class DoCommand { public String GetProcessInfo() { String sRet = ""; -// ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); List lProcesses = aMgr.getRunningAppProcesses(); int nProcs = lProcesses.size(); @@ -1817,12 +1987,10 @@ public class DoCommand { public long GetMemoryConfig() { -// ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE); ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo(); aMgr.getMemoryInfo(outInfo); long lMem = outInfo.availMem; -// float fMem = (float) lMem / (float)(1024.0 * 1024.0); return (lMem); } @@ -1866,12 +2034,10 @@ public class DoCommand { } catch (UnknownHostException e) { - // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { - // TODO Auto-generated catch block sRet += "reg exception thrown"; e.printStackTrace(); } @@ -1911,25 +2077,76 @@ public class DoCommand { } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block sRet = e.getLocalizedMessage(); e.printStackTrace(); } catch (ClientProtocolException e) { - // TODO Auto-generated catch block sRet = e.getLocalizedMessage(); e.printStackTrace(); } catch (IOException e) { - // TODO Auto-generated catch block sRet = e.getLocalizedMessage(); e.printStackTrace(); } return(sRet); } + + public String GetTimeZone() + { + String sRet = ""; + TimeZone tz; + + tz = TimeZone.getDefault(); + Date now = new Date(); + sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG); + + return(sRet); + } + + public String SetTimeZone(String sTimeZone) + { + String sRet = "Unable to set timezone to " + sTimeZone; + TimeZone tz = null; + AlarmManager amgr = null; + + if ((sTimeZone.length() > 0) && (sTimeZone.startsWith("GMT"))) + { + amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE); + if (amgr != null) + amgr.setTimeZone(sTimeZone); + } + else + { + String [] zoneNames = TimeZone.getAvailableIDs(); + int nNumMatches = zoneNames.length; + int lcv = 0; + + for (lcv = 0; lcv < nNumMatches; lcv++) + { + if (zoneNames[lcv].equalsIgnoreCase(sTimeZone)) + break; + } + + if (lcv < nNumMatches) + { + amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE); + if (amgr != null) + amgr.setTimeZone(zoneNames[lcv]); + } + } + + if (amgr != null) + { + tz = TimeZone.getDefault(); + Date now = new Date(); + sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG); + } + + return(sRet); + } public String GetSystemTime() { @@ -1943,17 +2160,8 @@ public class DoCommand { public String SetSystemTime(String sDate, String sTime, OutputStream out) { -// Debug.waitForDebugger(); String sRet = ""; -// Intent prgIntent = new Intent(android.provider.Settings.ACTION_DATE_SETTINGS); -// prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); -// contextWrapper.startActivity(prgIntent); - - // 2010/09/22 - // 15:41:00 - // 0123456789012345678 - if (((sDate != null) && (sTime != null)) && (sDate.contains("/") || sDate.contains(".")) && (sTime.contains(":"))) @@ -1966,14 +2174,11 @@ public class DoCommand { int mins = Integer.parseInt(sTime.substring(3,5)); int secs = Integer.parseInt(sTime.substring(6,8)); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + Calendar cal = new GregorianCalendar(TimeZone.getDefault()); cal.set(year, month - 1, day, hour, mins, secs); long lMillisecs = cal.getTime().getTime(); -// boolean bRet = SystemClock.setCurrentTimeMillis(lMillisecs); String sM = Long.toString(lMillisecs); -// long lm = 1285175618316L; - String sTest = cal.getTime().toGMTString(); String sMillis = sM.substring(0, sM.length() - 3) + "." + sM.substring(sM.length() - 3); String [] theArgs = new String [3]; @@ -1996,7 +2201,6 @@ public class DoCommand { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -2045,24 +2249,6 @@ public class DoCommand { return (sRet); } -/* - private boolean IsProcRunning(Process pProc) - { - boolean bRet = false; - int nExitCode = 0; - - try - { - nExitCode = pProc.exitValue(); - } - catch (IllegalThreadStateException z) - { - bRet = true; - } - - return(bRet); - } -*/ public String NewKillProc(String sProcId, OutputStream out) { @@ -2107,9 +2293,6 @@ public class DoCommand { try { pProc = Runtime.getRuntime().exec(theArgs); -// sutErr = pProc.getErrorStream(); // Stderr -// sutIn = pProc.getOutputStream(); // Stdin -// sutOut = pProc.getInputStream(); // Stdout RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); outThrd.join(5000); @@ -2123,7 +2306,6 @@ public class DoCommand { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } @@ -2133,7 +2315,6 @@ public class DoCommand { public String GetTmpDir() { String sRet = ""; -// Context ctx = SUTAgentAndroid.me.getApplicationContext(); Context ctx = contextWrapper.getApplicationContext(); File dir = ctx.getFilesDir(); ctx = null; @@ -2245,7 +2426,6 @@ public class DoCommand { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } @@ -2269,7 +2449,6 @@ public class DoCommand { outThrd.start(); outThrd.join(60000); int nRet = pProc.exitValue(); -// boolean bRet = outThrd.isAlive(); sRet = "\nuninst complete [" + nRet + "]"; } catch (IOException e) @@ -2403,7 +2582,6 @@ public class DoCommand { { String sRet = ""; -// Context ctx = SUTAgentAndroid.me.getApplicationContext(); Context ctx = contextWrapper.getApplicationContext(); PackageManager pm = ctx.getPackageManager(); @@ -2435,17 +2613,12 @@ public class DoCommand { try { contextWrapper.startActivity(prgIntent); -// Thread.sleep(5000); sRet = "exit"; } catch(ActivityNotFoundException anf) { anf.printStackTrace(); } -// catch (InterruptedException e) -// { -// e.printStackTrace(); -// } ctx = null; return (sRet); @@ -2458,7 +2631,6 @@ public class DoCommand { String sUrl = ""; String sRedirFileName = ""; -// Context ctx = SUTAgentAndroid.me.getApplicationContext(); Context ctx = contextWrapper.getApplicationContext(); PackageManager pm = ctx.getPackageManager(); @@ -2486,7 +2658,7 @@ public class DoCommand { if (sArgs.length > 1) { - if (sArgs[0].contains("android.browser")) +// if (sArgs[0].contains("android.browser")) prgIntent.setAction(Intent.ACTION_VIEW); if (sArgs[0].contains("fennec")) @@ -2530,10 +2702,7 @@ public class DoCommand { try { -// ctx.startActivity(prgIntent); contextWrapper.startActivity(prgIntent); -// SUTAgentAndroid.me.startActivity(prgIntent); -// SUTAgentAndroid.me.startActivityForResult(prgIntent, SUTAgentAndroid.START_PRG); } catch(ActivityNotFoundException anf) { @@ -2551,12 +2720,11 @@ public class DoCommand { try { pProc = Runtime.getRuntime().exec(progArray); - sutErr = pProc.getErrorStream(); // Stderr - sutIn = pProc.getOutputStream(); // Stdin - sutOut = pProc.getInputStream(); // Stdout RedirOutputThread outThrd = new RedirOutputThread(pProc, out); outThrd.start(); outThrd.join(10000); + int nRetCode = pProc.exitValue(); + sRet = "return code [" + nRetCode + "]"; } catch (IOException e) { @@ -2564,8 +2732,147 @@ public class DoCommand { } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); + sRet = "Timed out!"; + } + + return (sRet); + } +/* + @SuppressWarnings("unchecked") + public static void set(String key, String value) throws Exception + { + Class[] classes = Collections.class.getDeclaredClasses(); + Map env = System.getenv(); + for(Class cl : classes) + { + if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) + { + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + Object obj = field.get(env); + Map map = (Map) obj; + map.put(key, value); + } + } + } + +*/ + public String StartPrg2(String [] progArray, OutputStream out) + { + String sRet = ""; + + int nArraySize = 0; + int nArgs = progArray.length - 1; // 1st arg is the environment string + int lcv = 0; + int temp = 0; + + String sEnvString = progArray[0]; + + // Set up command line args stripping off the environment string + String [] theArgs = new String [nArgs]; + for (lcv = 0; lcv < nArgs; lcv++) + { + theArgs[lcv] = progArray[lcv + 1]; + } + + try + { + String [] envStrings = sEnvString.split(","); + Map newEnv = new HashMap(); + + for (lcv = 0; lcv < envStrings.length; lcv++) + { + temp = envStrings[lcv].indexOf("="); + if (temp > 0) + { + newEnv.put( envStrings[lcv].substring(0, temp), + envStrings[lcv].substring(temp + 1, envStrings[lcv].length())); + } + } + + Map sysEnv = System.getenv(); + + nArraySize = sysEnv.size(); + + for (Map.Entry entry : newEnv.entrySet()) + { + if (!sysEnv.containsKey(entry.getKey())) + { + nArraySize++; + } + } + + String[] envArray = new String[nArraySize]; + + int i = 0; + int offset; + String sKey = ""; + String sValue = ""; + + for (Map.Entry entry : sysEnv.entrySet()) + { + sKey = entry.getKey(); + if (newEnv.containsKey(sKey)) + { + sValue = newEnv.get(sKey); + if ((offset = sValue.indexOf("$" + sKey)) != -1) + { + envArray[i++] = sKey + + "=" + + sValue.substring(0, offset) + + entry.getValue() + + sValue.substring(offset + sKey.length() + 1); + } + else + envArray[i++] = sKey + "=" + sValue; + newEnv.remove(sKey); + } + else + envArray[i++] = entry.getKey() + "=" + entry.getValue(); + } + + for (Map.Entry entry : newEnv.entrySet()) + { + envArray[i++] = entry.getKey() + "=" + entry.getValue(); + } + + pProc = Runtime.getRuntime().exec(theArgs, envArray); + + RedirOutputThread outThrd = new RedirOutputThread(pProc, out); + outThrd.start(); + outThrd.join(10000); + int nRetCode = pProc.exitValue(); + sRet = "return code [" + nRetCode + "]"; + } + catch(UnsupportedOperationException e) + { + if (e != null) + e.printStackTrace(); + } + catch(ClassCastException e) + { + if (e != null) + e.printStackTrace(); + } + catch(IllegalArgumentException e) + { + if (e != null) + e.printStackTrace(); + } + catch(NullPointerException e) + { + if (e != null) + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (InterruptedException e) + { + e.printStackTrace(); + sRet = "Timed out!"; } return (sRet); @@ -2603,55 +2910,58 @@ public class DoCommand { */ private String PrintUsage() { - String sRet = "run [executable] [args] - start program no wait\n" + - "exec [executable] [args] - start program wait\n" + - "fire [executable] [args] - start program no wait\n" + - "arun [executable] [args] - start program no wait\n" + - "kill [program name] - kill program no path\n" + - "killall - kill all processes started\n" + - "ps - list of running processes\n" + - "info - list of device info\n" + - " [os] - os version for device\n" + - " [id] - unique identifier for device\n" + - " [uptime] - uptime for device\n" + - " [systime] - current system time on device\n" + - " [screen] - width, height and bits per pixel for device\n" + - " [memory] - physical, free, available, storage memory for device\n" + - " [processes] - list of running processes see 'ps'\n" + - "deadman timeout - set the duration for the deadman timer\n" + - "alrt [on/off] - start or stop sysalert behavior\n" + - "disk [arg] - prints disk space info\n" + - "cp file1 file2 - copy file1 to file2 on device\n" + - "time file - timestamp for file on device\n" + - "hash file - generate hash for file on device\n" + - "cd directory - change cwd on device\n" + - "cat file - cat file on device\n" + - "cwd - display cwd on device\n" + - "mv file1 file2 - move file1 to file2 on device\n" + - "push filename - push file to device\n" + - "rm file - delete file on device\n" + - "rmdr directory - delete directory on device even if not empty\n" + - "mkdr directory - create directory on device\n" + - "dirw directory - tests whether the directory is writable on the device\n" + - "stat processid - stat process on device\n" + - "dead processid - print whether the process is alive or hung on device\n" + - "mems - dump memory stats on device\n" + - "ls - print directory on device\n" + - "tmpd - print temp directory on device\n" + - "ping [hostname/ipaddr] - ping a network device\n" + - "unzp zipfile destdir - unzip the zipfile into the destination dir\n" + - "zip zipfile src - zip the source file/dir into zipfile\n" + - "rebt - reboot device\n" + - "inst /path/filename.apk - install the referenced apk file\n" + - "uninst packagename - uninstall the referenced package\n" + - "updt pkgname pkgfile - unpdate the referenced package\n" + - "clok - the current device time expressed as the number of millisecs since epoch\n" + - "settime date time - sets the device date and time (YYYY/MM/DD HH:MM:SS)\n" + - "rebt - reboot device\n" + - "quit - disconnect SUTAgent\n" + - "exit - close SUTAgent\n" + - "ver - SUTAgent version\n" + - "help - you're reading it"; + String sRet = + "run [executable] [args] - start program no wait\n" + + "exec [executable] [args] - start program wait\n" + + "fire [executable] [args] - start program no wait\n" + + "envrun [env pairs] [cmdline] - start program no wait\n" + + "kill [program name] - kill program no path\n" + + "killall - kill all processes started\n" + + "ps - list of running processes\n" + + "info - list of device info\n" + + " [os] - os version for device\n" + + " [id] - unique identifier for device\n" + + " [uptime] - uptime for device\n" + + " [systime] - current system time on device\n" + + " [screen] - width, height and bits per pixel for device\n" + + " [memory] - physical, free, available, storage memory for device\n" + + " [processes] - list of running processes see 'ps'\n" + + "deadman timeout - set the duration for the deadman timer\n" + + "alrt [on/off] - start or stop sysalert behavior\n" + + "disk [arg] - prints disk space info\n" + + "cp file1 file2 - copy file1 to file2 on device\n" + + "time file - timestamp for file on device\n" + + "hash file - generate hash for file on device\n" + + "cd directory - change cwd on device\n" + + "cat file - cat file on device\n" + + "cwd - display cwd on device\n" + + "mv file1 file2 - move file1 to file2 on device\n" + + "push filename - push file to device\n" + + "rm file - delete file on device\n" + + "rmdr directory - delete directory on device even if not empty\n" + + "mkdr directory - create directory on device\n" + + "dirw directory - tests whether the directory is writable on the device\n" + + "stat processid - stat process on device\n" + + "dead processid - print whether the process is alive or hung on device\n" + + "mems - dump memory stats on device\n" + + "ls - print directory on device\n" + + "tmpd - print temp directory on device\n" + + "ping [hostname/ipaddr] - ping a network device\n" + + "unzp zipfile destdir - unzip the zipfile into the destination dir\n" + + "zip zipfile src - zip the source file/dir into zipfile\n" + + "rebt - reboot device\n" + + "inst /path/filename.apk - install the referenced apk file\n" + + "uninst packagename - uninstall the referenced package\n" + + "updt pkgname pkgfile - unpdate the referenced package\n" + + "clok - the current device time expressed as the number of millisecs since epoch\n" + + "settime date time - sets the device date and time (YYYY/MM/DD HH:MM:SS)\n" + + "tzset timezone - sets the device timezone format is GMTxhh:mm x = +/- or a recognized Olsen string\n" + + "tzget - returns the current timezone set on the device\n" + + "rebt - reboot device\n" + + "quit - disconnect SUTAgent\n" + + "exit - close SUTAgent\n" + + "ver - SUTAgent version\n" + + "help - you're reading it"; return (sRet); } } diff --git a/build/mobile/sutagent/android/SUTAgentAndroid.java b/build/mobile/sutagent/android/SUTAgentAndroid.java index dcd27dc396e..b695721940d 100755 --- a/build/mobile/sutagent/android/SUTAgentAndroid.java +++ b/build/mobile/sutagent/android/SUTAgentAndroid.java @@ -391,7 +391,7 @@ public class SUTAgentAndroid extends Activity { sb.append("Overheated "); sb.append((((float)(nBatteryTemp))/10)); - sb.append("(°C)"); + sb.append("(C)"); } else { From 70c3f08d5cd9541a909f818eb5f777c6bb14901a Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Mon, 1 Nov 2010 16:19:54 -0700 Subject: [PATCH 148/263] Bug 604136 - [Windows SeaMonkey] mochitest-browser-chrome: 'browser_bug562890.js | Test timed out'. r=dtownsend, a=test fix --- toolkit/mozapps/extensions/test/browser/browser_bug562890.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug562890.js b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js index c81423bac7c..3a223e7f2e0 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug562890.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug562890.js @@ -7,6 +7,8 @@ */ function test() { + requestLongerTimeout(2); + waitForExplicitFinish(); var addonPrefsURI = TESTROOT + "addon_prefs.xul"; @@ -64,6 +66,7 @@ function test() { } }); + addonList.ensureElementIsVisible(addonItem); EventUtils.synthesizeMouseAtCenter(prefsBtn, { }, aManager); }); From 08d8cc3e4e628eaad3f06034bc2f856994819d3e Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 29 Oct 2010 10:42:35 -0700 Subject: [PATCH 149/263] Bug 596031 - 'this' is wrong in getters and setters when a proxy object is on the prototype chain. r=brendan/jorendorff/gal --HG-- extra : transplant_source : %9A%16%D6%DF%A3%C4%3F%08%B0-%19%B2%91%0Ee%1B%CC%95%DB%A4 --- js/src/jsarray.cpp | 2 +- js/src/jscntxtinlines.h | 15 +++++ js/src/jsobj.cpp | 63 +++++++++++++------ js/src/jsobj.h | 23 +++++-- js/src/jsproxy.cpp | 38 ++++------- js/src/jstracer.cpp | 5 +- js/src/jstypedarray.cpp | 2 +- js/src/jsvalue.h | 6 +- js/src/jswrapper.cpp | 5 +- js/src/jsxml.cpp | 2 +- js/src/tests/js1_8_5/extensions/jstests.list | 1 + .../js1_8_5/extensions/proxy-proto-setter.js | 49 +++++++++++++++ js/src/tests/js1_8_5/regress/jstests.list | 3 +- .../tests/js1_8_5/regress/regress-607863.js | 13 ++++ 14 files changed, 165 insertions(+), 62 deletions(-) create mode 100644 js/src/tests/js1_8_5/extensions/proxy-proto-setter.js create mode 100644 js/src/tests/js1_8_5/regress/regress-607863.js diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index cd21b609143..d4595965b3c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -688,7 +688,7 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp) } static JSBool -array_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +array_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { uint32 i; diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 646468df6c4..05c4d8ad3a4 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -738,6 +738,21 @@ CallJSPropertyOpSetter(JSContext *cx, js::PropertyOp op, JSObject *obj, jsid id, return op(cx, obj, id, vp); } +inline bool +CallSetter(JSContext *cx, JSObject *obj, jsid id, PropertyOp op, uintN attrs, uintN shortid, + js::Value *vp) +{ + if (attrs & JSPROP_SETTER) + return ExternalGetOrSet(cx, obj, id, CastAsObjectJsval(op), JSACC_WRITE, 1, vp, vp); + + if (attrs & JSPROP_GETTER) + return js_ReportGetterOnlyAssignment(cx); + + if (attrs & JSPROP_SHORTID) + id = INT_TO_JSID(shortid); + return CallJSPropertyOpSetter(cx, op, obj, id, vp); +} + } /* namespace js */ #endif /* jscntxtinlines_h___ */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 98f044cd2d4..51276ca9862 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3023,7 +3023,7 @@ with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, } static JSBool -with_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { return obj->getProto()->getProperty(cx, id, vp); } @@ -4933,7 +4933,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value } static JS_ALWAYS_INLINE bool -js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, +js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uintN getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { @@ -5019,8 +5019,11 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, return JS_TRUE; } - if (!obj2->isNative()) - return obj2->getProperty(cx, id, vp); + if (!obj2->isNative()) { + return obj2->isProxy() + ? JSProxy::get(cx, obj2, receiver, id, vp) + : obj2->getProperty(cx, id, vp); + } shape = (Shape *) prop; *shapeOut = shape; @@ -5031,39 +5034,41 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, } /* This call site is hot -- use the always-inlined variant of js_NativeGet(). */ - if (!js_NativeGetInline(cx, obj, obj2, shape, getHow, vp)) + if (!js_NativeGetInline(cx, receiver, obj2, shape, getHow, vp)) return JS_FALSE; return JS_TRUE; } -extern bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, +bool +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, uint32 getHow, Value *vp, const Shape **shapeOut, JSObject **holderOut) { - return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, shapeOut, holderOut); + return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, + shapeOut, holderOut); } static JS_ALWAYS_INLINE JSBool -js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) +js_GetPropertyHelperInline(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, + uint32 getHow, Value *vp) { const Shape *shape; JSObject *holder; - return js_GetPropertyHelperWithShapeInline(cx, obj, id, getHow, vp, &shape, &holder); -} - -extern JSBool -js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) -{ - return js_GetPropertyHelperInline(cx, obj, id, getHow, vp); + return js_GetPropertyHelperWithShapeInline(cx, obj, receiver, id, getHow, vp, &shape, &holder); } JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, Value *vp) +{ + return js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp); +} + +JSBool +js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */ - return js_GetPropertyHelperInline(cx, obj, id, JSGET_METHOD_BARRIER, vp); + return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp); } JSBool @@ -5099,7 +5104,7 @@ js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, Value *vp) if (obj->isXML()) return js_GetXMLMethod(cx, obj, id, vp); #endif - return op(cx, obj, id, vp); + return op(cx, obj, obj, id, vp); } JS_FRIEND_API(bool) @@ -5180,8 +5185,26 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, if (protoIndex < 0) return JS_FALSE; if (prop) { - if (!pobj->isNative()) + if (!pobj->isNative()) { + if (pobj->isProxy()) { + AutoPropertyDescriptorRooter pd(cx); + if (!pobj->getProxyHandler()->getPropertyDescriptor(cx, pobj, id, true, &pd)) + return false; + + if (pd.attrs & JSPROP_SHARED) + return CallSetter(cx, obj, id, pd.setter, pd.attrs, pd.shortid, vp); + + if (pd.attrs & JSPROP_READONLY) { + if (strict) + return obj->reportReadOnly(cx, id); + if (JS_HAS_STRICT_OPTION(cx)) + return obj->reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING); + return true; + } + } + prop = NULL; + } } else { /* We should never add properties to lexical blocks. */ JS_ASSERT(!obj->isBlock()); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 42971355e04..16f55901cdb 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -209,7 +209,13 @@ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value, js::PropertyOp getter, js::PropertyOp setter, uintN attrs); extern JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); +js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp); + +inline JSBool +js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp) +{ + return js_GetProperty(cx, obj, obj, id, vp); +} namespace js { @@ -1064,9 +1070,13 @@ struct JSObject : js::gc::Cell { return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); } - JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { + JSBool getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp) { js::PropertyIdOp op = getOps()->getProperty; - return (op ? op : js_GetProperty)(cx, this, id, vp); + return (op ? op : (js::PropertyIdOp)js_GetProperty)(cx, this, receiver, id, vp); + } + + JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) { + return getProperty(cx, this, id, vp); } JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) { @@ -1085,7 +1095,7 @@ struct JSObject : js::gc::Cell { } JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict) { - js::StrictPropertyIdOp op = getOps()->deleteProperty; + js::DeleteIdOp op = getOps()->deleteProperty; return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict); } @@ -1569,8 +1579,9 @@ extern JSBool js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, js::Value *vp); extern bool -js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, jsid id, uint32 getHow, - js::Value *vp, const js::Shape **shapeOut, JSObject **holderOut); +js_GetPropertyHelperWithShape(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, + uint32 getHow, js::Value *vp, + const js::Shape **shapeOut, JSObject **holderOut); extern JSBool js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ac1bacf1763..c4d7e45d2dc 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -127,7 +127,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, return true; } if (desc.attrs & JSPROP_GETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.getter), + return ExternalGetOrSet(cx, receiver, id, CastAsObjectJsval(desc.getter), JSACC_READ, 0, NULL, vp); } if (!(desc.attrs & JSPROP_SHARED)) @@ -136,7 +136,7 @@ JSProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, vp->setUndefined(); if (desc.attrs & JSPROP_SHORTID) id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOp(cx, desc.getter, proxy, id, vp); + return CallJSPropertyOp(cx, desc.getter, receiver, id, vp); } bool @@ -148,43 +148,29 @@ JSProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, return false; /* The control-flow here differs from ::get() because of the fall-through case below. */ if (desc.obj) { - if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { - if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), - JSACC_WRITE, 1, vp, vp); - } - if (desc.attrs & JSPROP_SHORTID) - id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); - } + if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) + return CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, vp); if (desc.attrs & JSPROP_READONLY) return true; desc.value = *vp; - return defineProperty(cx, proxy, id, &desc); + return defineProperty(cx, receiver, id, &desc); } if (!getPropertyDescriptor(cx, proxy, id, true, &desc)) return false; if (desc.obj) { - if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) { - if (desc.attrs & JSPROP_SETTER) { - return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter), - JSACC_WRITE, 1, vp, vp); - } - if (desc.attrs & JSPROP_SHORTID) - id = INT_TO_JSID(desc.shortid); - return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp); - } + if (desc.setter && ((desc.attrs & JSPROP_SETTER) || desc.setter != PropertyStub)) + return CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, vp); if (desc.attrs & JSPROP_READONLY) return true; /* fall through */ } - desc.obj = proxy; + desc.obj = receiver; desc.value = *vp; desc.attrs = JSPROP_ENUMERATE; desc.getter = NULL; desc.setter = NULL; desc.shortid = 0; - return defineProperty(cx, proxy, id, &desc); + return defineProperty(cx, receiver, id, &desc); } bool @@ -862,15 +848,15 @@ proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, } static JSBool -proxy_GetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { - return JSProxy::get(cx, obj, obj, id, vp); + return JSProxy::get(cx, obj, receiver, id, vp); } static JSBool proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { - // TODO: throwing away strict + // FIXME (bug 596351): throwing away strict. return JSProxy::set(cx, obj, obj, id, vp); } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 7b516112f2a..1d674ac734b 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -12032,7 +12032,7 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC /* Delegate to the op, if present. */ PropertyIdOp op = obj->getOps()->getProperty; if (op) { - bool result = op(cx, obj, id, vp); + bool result = op(cx, obj, obj, id, vp); if (!result) SetBuiltinError(cx); return cx->tracerState->builtinStatus == 0; @@ -12047,7 +12047,8 @@ GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PIC const Shape *shape; JSObject *holder; - if (!js_GetPropertyHelperWithShape(cx, obj, id, JSGET_METHOD_BARRIER, vp, &shape, &holder)) { + if (!js_GetPropertyHelperWithShape(cx, obj, obj, id, JSGET_METHOD_BARRIER, vp, &shape, + &holder)) { SetBuiltinError(cx); return false; } diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 6ffdc14764f..fc6f913a646 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -493,7 +493,7 @@ class TypedArrayTemplate } static JSBool - obj_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) + obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); diff --git a/js/src/jsvalue.h b/js/src/jsvalue.h index a1fad41ab0d..bc0a00f1e75 100644 --- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -898,10 +898,12 @@ typedef JSBool (* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, PropertyOp getter, PropertyOp setter, uintN attrs); typedef JSBool -(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp); +(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); typedef JSBool (* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); typedef JSBool +(* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +typedef JSBool (* CallOp)(JSContext *cx, uintN argc, Value *vp); typedef JSBool (* LookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, @@ -999,7 +1001,7 @@ struct ObjectOps { js::StrictPropertyIdOp setProperty; js::AttributesOp getAttributes; js::AttributesOp setAttributes; - js::StrictPropertyIdOp deleteProperty; + js::DeleteIdOp deleteProperty; js::NewEnumerateOp enumerate; js::TypeOfOp typeOf; js::TraceOp trace; diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index b3f4da8cfdf..3a0af41c2de 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -204,13 +204,14 @@ JSWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) bool JSWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - GET(JS_GetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); + GET(wrappedObject(wrapper)->getProperty(cx, receiver, id, vp)); } bool JSWrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) { - SET(JS_SetPropertyById(cx, wrappedObject(wrapper), id, Jsvalify(vp))); + // FIXME (bug 596351): Need deal with strict mode. + SET(wrappedObject(wrapper)->setProperty(cx, id, vp, false)); } bool diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index f61320e2ec9..e6b832688ed 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -4743,7 +4743,7 @@ xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, } static JSBool -xml_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) +xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) { vp->setUndefined(); diff --git a/js/src/tests/js1_8_5/extensions/jstests.list b/js/src/tests/js1_8_5/extensions/jstests.list index 89c116e6007..2570fcbd873 100644 --- a/js/src/tests/js1_8_5/extensions/jstests.list +++ b/js/src/tests/js1_8_5/extensions/jstests.list @@ -12,6 +12,7 @@ script scripted-proxies.js script array-length-protochange.js script parseInt-octal.js script proxy-enumerateOwn-duplicates.js +skip-if(!xulRuntime.shell) script proxy-proto-setter.js skip-if(!xulRuntime.shell) script reflect-parse.js script destructure-accessor.js script censor-strict-caller.js diff --git a/js/src/tests/js1_8_5/extensions/proxy-proto-setter.js b/js/src/tests/js1_8_5/extensions/proxy-proto-setter.js new file mode 100644 index 00000000000..1f17a95c95d --- /dev/null +++ b/js/src/tests/js1_8_5/extensions/proxy-proto-setter.js @@ -0,0 +1,49 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ +// Contributor: Blake Kaplan + +function expect(actual, arg) { + reportCompare(expect.expected, actual, arg); +} + +var window = { set x(y) { expect(this, y) }, y: 4 }; +expect.expected = window; +window.x = "setting through a setter directly"; +window.y = 5; +reportCompare(5, window.y, "setting properties works"); +var easy = { easy: 'yes', __proto__: window } +expect.expected = easy; +easy.x = "setting through a setter all-native on prototype"; +easy.y = 6; +reportCompare(5, window.y, "window.y remains as it was"); +reportCompare(6, easy.y, "shadowing works properly"); + +var sandbox = evalcx(''); +sandbox.window = window; +sandbox.print = print; +sandbox.expect = expect; +var hard = evalcx('Object.create(window)', sandbox); +expect.expected = hard; +hard.x = "a setter through proxy -> native"; +hard.y = 6; +reportCompare(5, window.y, "window.y remains as it was through a proxy"); +reportCompare(6, hard.y, "shadowing works on proxies"); + +hard.__proto__ = { 'passed': true } +reportCompare(true, hard.passed, "can set proxy.__proto__ through a native"); + +var inverse = evalcx('({ set x(y) { expect(this, y); }, y: 4 })', sandbox); +expect.expected = inverse; +inverse.x = "setting through a proxy directly"; +inverse.y = 5; +reportCompare(5, inverse.y, "setting properties works on proxies"); + +var inversehard = Object.create(inverse); +expect.expected = inversehard; +inversehard.x = "setting through a setter with a proxy on the proto chain"; +inversehard.y = 6; +reportCompare(5, inverse.y, "inverse.y remains as it was"); +reportCompare(6, inversehard.y, "shadowing works native -> proxy"); + +inversehard.__proto__ = { 'passed': true } +reportCompare(true, inversehard.passed, "can set native.__proto__ through a proxy"); diff --git a/js/src/tests/js1_8_5/regress/jstests.list b/js/src/tests/js1_8_5/regress/jstests.list index 6c757e175a5..d577160082b 100644 --- a/js/src/tests/js1_8_5/regress/jstests.list +++ b/js/src/tests/js1_8_5/regress/jstests.list @@ -12,7 +12,7 @@ script regress-551763-0.js script regress-551763-1.js script regress-551763-2.js script regress-555246-0.js -fails-if(xulRuntime.shell) script regress-555246-1.js +script regress-555246-1.js script regress-559438.js script regress-560101.js script regress-560998-1.js @@ -48,3 +48,4 @@ script regress-598176.js script regress-600067.js script regress-600137.js script regress-602621.js +fails-if(!xulRuntime.shell) script regress-607863.js diff --git a/js/src/tests/js1_8_5/regress/regress-607863.js b/js/src/tests/js1_8_5/regress/regress-607863.js new file mode 100644 index 00000000000..2eb463df890 --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-607863.js @@ -0,0 +1,13 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var sandbox = evalcx(''); +var foreign = evalcx('({ get f() this, set x(v) { result = this } })', sandbox); +var local = Object.create(foreign); + +reportCompare(local, local.f, "this should be set correctly in getters"); +local.x = 42; +reportCompare(local, sandbox.result, "this should be set correctly in setters"); From ade40c675c6c3d70928c6e78880bd2412bec99a4 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Fri, 29 Oct 2010 12:49:32 -0700 Subject: [PATCH 150/263] bug 607767 - Fix rewrapping native objects across compartment boundaries. r=jst --- dom/base/nsDOMClassInfo.cpp | 50 ++++++++++--------- dom/base/nsDOMClassInfo.h | 2 + dom/base/nsHistory.h | 1 + js/src/xpconnect/idl/nsIXPCScriptable.idl | 6 +-- js/src/xpconnect/public/xpc_map_end.h | 9 ---- js/src/xpconnect/src/xpcprivate.h | 3 +- .../xpconnect/src/xpcwrappednativejsops.cpp | 48 ++---------------- js/src/xpconnect/wrappers/WrapperFactory.cpp | 33 +++++++++--- ...ole_bug_580030_errors_after_page_reload.js | 4 +- 9 files changed, 63 insertions(+), 93 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index da7107f6a1e..de2fbe6a1cb 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -74,6 +74,7 @@ // General helper includes #include "nsGlobalWindow.h" +#include "nsHistory.h" #include "nsIContent.h" #include "nsIAttribute.h" #include "nsIDocument.h" @@ -661,7 +662,8 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(BarProp, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(History, nsHistorySH, - ARRAY_SCRIPTABLE_FLAGS) + ARRAY_SCRIPTABLE_FLAGS | + nsIXPCScriptable::WANT_PRECREATE) NS_DEFINE_CLASSINFO_DATA(Screen, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH, @@ -4582,15 +4584,6 @@ nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, return NS_ERROR_UNEXPECTED; } -NS_IMETHODIMP -nsDOMClassInfo::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, - JSObject * obj, JSObject * *_retval) -{ - NS_WARNING("nsDOMClassInfo::InnerObject Don't call me!"); - - return NS_ERROR_UNEXPECTED; -} - static nsresult GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager, const nsString &aName, @@ -7097,7 +7090,7 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx, nsCOMPtr sgo = do_GetInterface(ds); if (!sgo) { NS_WARNING("Refusing to create a location in the wrong scope because the " - "docshell is being destroyed"); + "docshell is being destroyed"); return NS_ERROR_UNEXPECTED; } @@ -9914,6 +9907,28 @@ nsStringArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // History helper +NS_IMETHODIMP +nsHistorySH::PreCreate(nsISupports *nativeObj, JSContext *cx, + JSObject *globalObj, JSObject **parentObj) +{ + nsHistory *history = (nsHistory *)nativeObj; + nsIDocShell *ds = history->GetDocShell(); + if (!ds) { + NS_WARNING("Refusing to create a history object in the wrong scope"); + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr sgo = do_GetInterface(ds); + if (!sgo) { + NS_WARNING("Refusing to create a history object in the wrong scope because the " + "docshell is being destroyed"); + return NS_ERROR_UNEXPECTED; + } + + *parentObj = sgo->GetGlobalJSObject(); + return NS_OK; +} + NS_IMETHODIMP nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsid id, jsval *vp, PRBool *_retval) @@ -9925,19 +9940,6 @@ nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } - nsresult rv = - sSecMan->CheckPropertyAccess(cx, obj, mData->mName, sItem_id, - nsIXPCSecurityManager::ACCESS_CALL_METHOD); - - if (NS_FAILED(rv)) { - // Let XPConnect know that the access was not granted. - *_retval = PR_FALSE; - - return NS_OK; - } - - // sec check - return nsStringArraySH::GetProperty(wrapper, cx, obj, id, vp, _retval); } diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index 31ca748fc5d..c6ec031348c 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -1270,6 +1270,8 @@ protected: nsAString& aResult); public: + NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, + JSObject *globalObj, JSObject **parentObj); NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsid id, jsval *vp, PRBool *_retval); diff --git a/dom/base/nsHistory.h b/dom/base/nsHistory.h index a0b05caa485..8daa825cde6 100644 --- a/dom/base/nsHistory.h +++ b/dom/base/nsHistory.h @@ -58,6 +58,7 @@ public: // nsIDOMHistory NS_DECL_NSIDOMHISTORY + nsIDocShell *GetDocShell() { return mDocShell; } void SetDocShell(nsIDocShell *aDocShell); protected: diff --git a/js/src/xpconnect/idl/nsIXPCScriptable.idl b/js/src/xpconnect/idl/nsIXPCScriptable.idl index 575749ac0c6..55ef7cb6fa3 100644 --- a/js/src/xpconnect/idl/nsIXPCScriptable.idl +++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl @@ -80,7 +80,7 @@ * to *_retval unless they want to return PR_FALSE. */ -[uuid(5d309b93-e9b4-4374-bcd5-44245c83408f)] +[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)] interface nsIXPCScriptable : nsISupports { /* bitflags used for 'flags' (only 32 bits available!) */ @@ -115,7 +115,6 @@ interface nsIXPCScriptable : nsISupports const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27; const PRUint32 WANT_EQUALITY = 1 << 28; const PRUint32 WANT_OUTER_OBJECT = 1 << 29; - const PRUint32 WANT_INNER_OBJECT = 1 << 30; // The high order bit is RESERVED for consumers of these flags. // No implementor of this interface should ever return flags @@ -197,9 +196,6 @@ interface nsIXPCScriptable : nsISupports JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); - JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper, - in JSContextPtr cx, in JSObjectPtr obj); - void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto); }; diff --git a/js/src/xpconnect/public/xpc_map_end.h b/js/src/xpconnect/public/xpc_map_end.h index 5d4e65792aa..e0d317041b8 100644 --- a/js/src/xpconnect/public/xpc_map_end.h +++ b/js/src/xpconnect/public/xpc_map_end.h @@ -118,10 +118,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags) #ifdef XPC_MAP_WANT_OUTER_OBJECT nsIXPCScriptable::WANT_OUTER_OBJECT | #endif -#ifdef XPC_MAP_WANT_INNER_OBJECT - nsIXPCScriptable::WANT_INNER_OBJECT | -#endif - #ifdef XPC_MAP_FLAGS XPC_MAP_FLAGS | #endif @@ -227,11 +223,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::OuterObject(nsIXPConnectWrappedNative *wrapper, {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} #endif -#ifndef XPC_MAP_WANT_INNER_OBJECT -NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval) - {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} -#endif - #ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *proto) {return NS_OK;} diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 79759815e37..65c4e69390a 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -2004,7 +2004,6 @@ public: JSBool WantTrace() GET_IT(WANT_TRACE) JSBool WantEquality() GET_IT(WANT_EQUALITY) JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) - JSBool WantInnerObject() GET_IT(WANT_INNER_OBJECT) JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY) JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY) @@ -2546,10 +2545,10 @@ public: XPCNativeSet* GetSet() const {XPCAutoLock al(GetLock()); return mSet;} -private: void SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;} +private: inline void ExpireWrapper() {mMaybeScope = (XPCWrappedNativeScope*) diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 3a0d49c89f0..6173a19ce91 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -857,45 +857,6 @@ XPC_WN_OuterObject(JSContext *cx, JSObject *obj) return obj; } -static JSObject * -XPC_WN_InnerObject(JSContext *cx, JSObject *obj) -{ - XPCWrappedNative *wrapper = - static_cast(obj->getPrivate()); - if(!wrapper) - { - Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); - - return nsnull; - } - - if(!wrapper->IsValid()) - { - Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); - - return nsnull; - } - - XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); - if(si && si->GetFlags().WantInnerObject()) - { - JSObject *newThis; - nsresult rv = - si->GetCallback()->InnerObject(wrapper, cx, obj, &newThis); - - if(NS_FAILED(rv)) - { - Throw(rv, cx); - - return nsnull; - } - - obj = newThis; - } - - return obj; -} - js::Class XPC_WN_NoHelper_JSClass = { "XPCWrappedNative_NoHelper", // name; WRAPPER_SLOTS | @@ -925,8 +886,8 @@ js::Class XPC_WN_NoHelper_JSClass = { // ClassExtension { JS_VALUEIFY(js::EqualityOp, XPC_WN_Equality), - XPC_WN_OuterObject, - XPC_WN_InnerObject, + nsnull, // outerObject + nsnull, // innerObject nsnull, // iteratorObject nsnull, // wrappedObject }, @@ -1589,11 +1550,8 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) if(mFlags.WantOuterObject()) mJSClass.base.ext.outerObject = XPC_WN_OuterObject; - if(mFlags.WantInnerObject()) - mJSClass.base.ext.innerObject = XPC_WN_InnerObject; - if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT | - nsIXPCScriptable::WANT_INNER_OBJECT))) + if(!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT)) mCanBeSlim = JS_TRUE; } diff --git a/js/src/xpconnect/wrappers/WrapperFactory.cpp b/js/src/xpconnect/wrappers/WrapperFactory.cpp index 54eeb64392f..639c7cdc78d 100644 --- a/js/src/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp @@ -126,10 +126,6 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj if (!wn->GetClassInfo()) return DoubleWrap(cx, obj, flags); - // We know that DOM objects only allow one object, we can return early. - if (wn->HasProto() && wn->GetProto()->ClassIsDOMObject()) - return DoubleWrap(cx, obj, flags); - XPCCallContext ccx(JS_CALLER, cx, obj); if (NATIVE_HAS_FLAG(&ccx, WantPreCreate)) { // We have a precreate hook. This object might enforce that we only @@ -159,13 +155,38 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj if (!ac.enter(cx, scope)) return nsnull; + // NB: Passing a holder here inhibits slim wrappers under + // WrapNativeToJSVal. + nsCOMPtr holder; jsval v; nsresult rv = nsXPConnect::FastGetXPConnect()->WrapNativeToJSVal(cx, scope, wn->Native(), nsnull, &NS_GET_IID(nsISupports), PR_FALSE, - &v, nsnull); - if (NS_SUCCEEDED(rv)) + &v, getter_AddRefs(holder)); + if (NS_SUCCEEDED(rv)) { obj = JSVAL_TO_OBJECT(v); + NS_ASSERTION(IS_WN_WRAPPER(obj), "bad object"); + + XPCWrappedNative *newwn = static_cast(xpc_GetJSPrivate(obj)); + if (newwn->GetSet()->GetInterfaceCount() == 1) { + // Some objects claim to implement nsIClassInfo, but don't + // actually implement GetInterfaces. In those cases, the + // newly-created WN will not have any useful functions or + // properties on it. We detect that here and use the old WN's + // set on the new wrapper. + +#ifdef DEBUG + { + XPCNativeInterface *iface = newwn->GetSet()->GetInterfaceAt(0); + JSString *name = JSID_TO_STRING(iface->GetName()); + NS_ASSERTION(!strcmp("nsISupports", JS_GetStringBytes(name)), "weird interface"); + } +#endif + + newwn->SetSet(wn->GetSet()); + } + + } return DoubleWrap(cx, obj, flags); } diff --git a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_580030_errors_after_page_reload.js b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_580030_errors_after_page_reload.js index 641da50a3ad..33cc57004ec 100644 --- a/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_580030_errors_after_page_reload.js +++ b/toolkit/components/console/hudservice/tests/browser/browser_webconsole_bug_580030_errors_after_page_reload.js @@ -69,9 +69,9 @@ function testErrorsAfterPageReload(aEvent) { Services.console.registerListener(consoleObserver); var button = content.document.querySelector("button").wrappedJSObject; - var clickEvent = content.wrappedJSObject.document.createEvent("MouseEvents").wrappedJSObject; + var clickEvent = content.document.createEvent("MouseEvents"); clickEvent.initMouseEvent("click", true, true, - content.wrappedJSObject, 0, 0, 0, 0, 0, false, false, + content, 0, 0, 0, 0, 0, false, false, false, false, 0, null); executeSoon(function() { From f1dbf9e82cc361e8b687edf7007cb7e441ea24e1 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 1 Nov 2010 18:28:14 -0700 Subject: [PATCH 151/263] Bug 602223 - Use the global object instead of the parent so we're sure to have a non-null parent. r=gal a=blocking beta7 --- js/src/jswrapper.cpp | 2 ++ js/src/xpconnect/wrappers/WrapperFactory.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 3a0af41c2de..808d8cde5ba 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -295,6 +295,7 @@ JSObject * JSWrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, JSWrapper *handler) { + JS_ASSERT(parent); return NewProxyObject(cx, handler, ObjectValue(*obj), proto, parent, obj->isCallable() ? obj : NULL, NULL); } @@ -345,6 +346,7 @@ AutoCompartment::enter() context->compartment = destination; JSObject *scopeChain = target->getGlobal(); + JS_ASSERT(scopeChain->isNative()); frame.construct(); if (!context->stack().pushDummyFrame(context, *scopeChain, &frame.ref())) { frame.destroy(); diff --git a/js/src/xpconnect/wrappers/WrapperFactory.cpp b/js/src/xpconnect/wrappers/WrapperFactory.cpp index 639c7cdc78d..100fcb4249b 100644 --- a/js/src/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp @@ -71,7 +71,7 @@ DoubleWrap(JSContext *cx, JSObject *obj, uintN flags) { if (flags & WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG) { js::SwitchToCompartment sc(cx, obj->compartment()); - return JSWrapper::New(cx, obj, NULL, obj->getParent(), + return JSWrapper::New(cx, obj, NULL, obj->getGlobal(), &WaiveXrayWrapperWrapper); } return obj; @@ -323,7 +323,7 @@ WrapperFactory::WaiveXrayAndWrap(JSContext *cx, jsval *vp) { js::SwitchToCompartment sc(cx, obj->compartment()); - obj = JSWrapper::New(cx, obj, NULL, obj->getParent(), &WaiveXrayWrapperWrapper); + obj = JSWrapper::New(cx, obj, NULL, obj->getGlobal(), &WaiveXrayWrapperWrapper); if (!obj) return false; } From 635d017df67bcbe8af851cd3e02b7d775bba7fba Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 1 Nov 2010 19:57:43 -0700 Subject: [PATCH 152/263] Fix bustage from bug 602223. a=bustage --- js/src/xpconnect/wrappers/WrapperFactory.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/src/xpconnect/wrappers/WrapperFactory.cpp b/js/src/xpconnect/wrappers/WrapperFactory.cpp index 100fcb4249b..fe4703de13d 100644 --- a/js/src/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp @@ -302,7 +302,8 @@ WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj) JSObject *xrayHolder = LW::createHolder(cx, obj, obj->getParent()); if (!xrayHolder) return NULL; - JSObject *wrapperObj = JSWrapper::New(cx, obj, obj->getProto(), NULL, &LW::singleton); + JSObject *wrapperObj = JSWrapper::New(cx, obj, obj->getProto(), obj->getParent(), + &LW::singleton); if (!wrapperObj) return NULL; wrapperObj->setProxyExtra(js::ObjectValue(*xrayHolder)); @@ -336,7 +337,7 @@ JSObject * WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *obj) { JSObject *wrapperObj = - JSWrapper::New(cx, obj, obj->getProto(), NULL, + JSWrapper::New(cx, obj, obj->getProto(), obj->getGlobal(), &FilteringWrapper::singleton); return wrapperObj; From d6f94ac76e4ad6bfc801c9e2c6054fee11251b49 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 1 Nov 2010 20:23:44 -0700 Subject: [PATCH 153/263] Fix more bustage. a=bustage --- js/src/jswrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 808d8cde5ba..a51d6dee4f7 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -310,7 +310,7 @@ TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, J { // Allow wrapping outer window proxies. JS_ASSERT(!obj->isWrapper() || obj->getClass()->ext.innerObject); - return JSWrapper::New(cx, obj, wrappedProto, NULL, &JSCrossCompartmentWrapper::singleton); + return JSWrapper::New(cx, obj, wrappedProto, parent, &JSCrossCompartmentWrapper::singleton); } } From 6b05c2d8aeedfeb1f394f884fcff0a6940d956ab Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 1 Nov 2010 20:55:43 -0700 Subject: [PATCH 154/263] Fix more bustage. a=bustage --- js/src/jsapi-tests/testBug604087.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jsapi-tests/testBug604087.cpp b/js/src/jsapi-tests/testBug604087.cpp index bdfab797b3d..8bb5c1a28cc 100644 --- a/js/src/jsapi-tests/testBug604087.cpp +++ b/js/src/jsapi-tests/testBug604087.cpp @@ -44,7 +44,7 @@ PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags) static JSObject * Wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, uintN flags) { - return JSWrapper::New(cx, obj, proto, NULL, &JSCrossCompartmentWrapper::singleton); + return JSWrapper::New(cx, obj, proto, parent, &JSCrossCompartmentWrapper::singleton); } BEGIN_TEST(testBug604087) From 8ce4f994ed4bc3bb9b8770318a569dead5144865 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Mon, 1 Nov 2010 22:24:24 -0700 Subject: [PATCH 155/263] A last attempt at fixing orange. a=orange --- dom/base/nsDOMClassInfo.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index de2fbe6a1cb..6af8b6b52c6 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -6180,16 +6180,16 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, { JSObject *winobj = aWin->FastGetGlobalJSObject(); - JSAutoEnterCompartment ac; - if (!ac.enter(cx, winobj)) { - return NS_ERROR_UNEXPECTED; - } - JSObject *proto = nsnull; if (class_parent_name) { jsval val; + JSAutoEnterCompartment ac; + if (!ac.enter(cx, winobj)) { + return NS_ERROR_UNEXPECTED; + } + if (!::JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) { return NS_ERROR_UNEXPECTED; } @@ -6213,7 +6213,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, if (proto && (!xpc_proto_proto || JS_GET_CLASS(cx, xpc_proto_proto) == sObjectClass)) { - if (!::JS_SetPrototype(cx, dot_prototype, proto)) { + if (!JS_WrapObject(cx, &proto) || + !JS_SetPrototype(cx, dot_prototype, proto)) { return NS_ERROR_UNEXPECTED; } } From 2e9595d37abc869c164f4dd6d414b6ff9c7666db Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Tue, 2 Nov 2010 00:06:54 -0700 Subject: [PATCH 156/263] Bug 608545 - Set cookie: unexpected "deleted" observer notification when cookie already exists. r=sdwilsh, a=b7+ --- netwerk/cookie/nsCookieService.cpp | 28 +++++++++++++++++----------- netwerk/cookie/nsICookieService.idl | 7 ++++--- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index 27bab495011..88e3ccf45e7 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -1314,7 +1314,7 @@ nsCookieService::NotifyRejected(nsIURI *aHostURI) // "added" means a cookie was added. aSubject is the added cookie. // "changed" means a cookie was altered. aSubject is the new cookie. // "cleared" means the entire cookie list was cleared. aSubject is null. -// "batch-deleted" means multiple cookies were deleted. aSubject is the list of +// "batch-deleted" means a set of cookies was purged. aSubject is the list of // cookies. void nsCookieService::NotifyChanged(nsISupports *aSubject, @@ -2334,10 +2334,13 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain, // Remove the stale cookie and notify. RemoveCookieFromList(matchIter); - COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, - "stale cookie was deleted"); - NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get()); + "stale cookie was purged"); + + nsCOMPtr removedList = + do_CreateInstance(NS_ARRAY_CONTRACTID); + removedList->AppendElement(oldCookie, PR_FALSE); + NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get()); // We've done all we need to wrt removing and notifying the stale cookie. // From here on out, we pretend pretend it didn't exist, so that we @@ -2352,16 +2355,15 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain, return; } - // Remove the old cookie and notify. + // Remove the old cookie. RemoveCookieFromList(matchIter); - COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, - "previously stored cookie was deleted"); - NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get()); - // If the new cookie has expired -- i.e. the intent was simply to delete // the old cookie -- then we're done. if (aCookie->Expiry() <= currentTime) { + COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, + "previously stored cookie was deleted"); + NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get()); return; } @@ -2382,12 +2384,16 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain, if (entry && entry->GetCookies().Length() >= mMaxCookiesPerHost) { nsListIter iter; FindStaleCookie(entry, currentTime, iter); + oldCookie = iter.Cookie(); // remove the oldest cookie from the domain - COOKIE_LOGEVICTED(iter.Cookie(), "Too many cookies for this domain"); RemoveCookieFromList(iter); + COOKIE_LOGEVICTED(oldCookie, "Too many cookies for this domain"); - NotifyChanged(iter.Cookie(), NS_LITERAL_STRING("deleted").get()); + nsCOMPtr removedList = + do_CreateInstance(NS_ARRAY_CONTRACTID); + removedList->AppendElement(oldCookie, PR_FALSE); + NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get()); } else if (mDBState->cookieCount >= ADD_TEN_PERCENT(mMaxNumberOfCookies)) { PRInt64 maxAge = aCurrentTimeInUsec - mDBState->cookieOldestTime; diff --git a/netwerk/cookie/nsICookieService.idl b/netwerk/cookie/nsICookieService.idl index b5720d83886..ce2a0344d2d 100644 --- a/netwerk/cookie/nsICookieService.idl +++ b/netwerk/cookie/nsICookieService.idl @@ -66,9 +66,10 @@ interface nsIChannel; * the new cookie. (note that host, path, and name are invariant * for a given cookie; other parameters may change.) * "batch-deleted" - * a batch of cookies was deleted (for instance, as part of a purging - * operation). the subject is an nsIArray of nsICookie2's representing - * the deleted cookies. + * a set of cookies was purged (typically, because they have either + * expired or because the cookie list has grown too large). The subject + * is an nsIArray of nsICookie2's representing the deleted cookies. + * Note that the array could contain a single cookie. * "cleared" * the entire cookie list was cleared. the subject is null. * "reload" From acf5c7df2d195f894a1f9eb0fc2f2308b995b18d Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Tue, 2 Nov 2010 11:32:15 +0100 Subject: [PATCH 157/263] bug 596087, update shipped-locales for beta7, adding rm. a=blocker --- browser/locales/shipped-locales | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/locales/shipped-locales b/browser/locales/shipped-locales index 416af29c188..cbb6fc07b37 100644 --- a/browser/locales/shipped-locales +++ b/browser/locales/shipped-locales @@ -42,6 +42,7 @@ pa-IN pl pt-BR pt-PT +rm ro ru sk From 07142483c922bf8a1e434e217a37219d14e68e7c Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Mon, 1 Nov 2010 14:47:16 -0400 Subject: [PATCH 158/263] bug 607946 - Allow specifying a post-upload command for uploadsymbols. r=catlee a=bsmedberg --HG-- extra : rebase_source : c613fcbdc37f2154dd0f8029068584ccdf867b44 --- Makefile.in | 2 +- js/src/jit-test/README | 74 --- js/src/jit-test/lib/prolog.js | 48 -- js/src/jit-test/tests/arguments/args6.js | 22 - js/src/jit-test/tests/arguments/args8.js | 14 - js/src/jit-test/tests/arguments/argsx-4.js | 23 - js/src/jit-test/tests/basic/arith.js | 11 - js/src/jit-test/tests/basic/bug520498.js | 9 - js/src/jit-test/tests/basic/bug522136.js | 10 - js/src/jit-test/tests/basic/bug528644.js | 16 - js/src/jit-test/tests/basic/bug578041.js | 3 - js/src/jit-test/tests/basic/bug584565.js | 10 - .../tests/basic/delete-named-names.js | 17 - .../jit-test/tests/basic/jitstatsArchFlags.js | 14 - js/src/jit-test/tests/basic/parseIntTests.js | 23 - .../tests/basic/strictParseIntOctal.js | 16 - .../testAssignmentThatIgnoresSetterRetval.js | 10 - js/src/jit-test/tests/basic/testBug458838.js | 19 - js/src/jit-test/tests/basic/testBug504520.js | 11 - .../tests/basic/testBug504520Harder.js | 33 -- js/src/jit-test/tests/basic/testBug552248.js | 36 -- js/src/jit-test/tests/basic/testBug579602.js | 21 - js/src/jit-test/tests/basic/testBug579646.js | 22 - js/src/jit-test/tests/basic/testBug584650.js | 9 - js/src/jit-test/tests/basic/testBug597736.js | 32 -- .../basic/testEliminatedGuardWithinAnchor.js | 12 - .../tests/basic/testHoleInDenseArray.js | 18 - .../jit-test/tests/basic/testIntOverflow.js | 15 - .../tests/basic/testMethodInitSafety.js | 14 - .../tests/basic/testNativeArgsRooting.js | 14 - .../tests/basic/testNestedDeepBail.js | 20 - .../tests/basic/testNestedExitStackOuter.js | 29 -- .../jit-test/tests/basic/testNewArrayCount.js | 12 - .../tests/basic/testNewArrayCount2.js | 8 - .../tests/basic/testProxyConstructors.js | 9 - .../jit-test/tests/basic/testRebranding2.js | 21 - .../basic/testReconstructImacroPCStack.js | 28 -- js/src/jit-test/tests/basic/testRegExpTest.js | 10 - .../basic/testScriptGetter_JSOP_CALLPROP.js | 11 - js/src/jit-test/tests/basic/testShiftLeft.js | 38 -- .../tests/basic/testShiftRightArithmetic.js | 44 -- .../tests/basic/testSideExitInConstructor.js | 39 -- .../tests/basic/testSlowNativeBail.js | 10 - .../tests/basic/testStackQuotaExhausted.js | 29 -- js/src/jit-test/tests/closures/bug540136.js | 17 - js/src/jit-test/tests/closures/bug540242.js | 17 - js/src/jit-test/tests/closures/bug540243.js | 10 - js/src/jit-test/tests/closures/bug541239.js | 16 - js/src/jit-test/tests/closures/lambda.js | 27 -- .../tests/closures/setname-inner-heavy.js | 18 - js/src/jit-test/tests/jaeger/bug554580-5.js | 20 - js/src/jit-test/tests/jaeger/bug555155.js | 12 - js/src/jit-test/tests/jaeger/bug555543.js | 8 - js/src/jit-test/tests/jaeger/bug556525.js | 5 - .../tests/jaeger/bug563000/eif-trap-newvar.js | 9 - .../jaeger/bug563000/eif-trap-typechange.js | 10 - .../tests/jaeger/bug563000/eif-trap.js | 10 - .../tests/jaeger/bug563000/simple-trap-1.js | 9 - .../tests/jaeger/bug563000/simple-trap-2.js | 10 - .../tests/jaeger/bug563000/simple-untrap.js | 11 - .../jaeger/bug563000/trap-force-return-1.js | 7 - .../jaeger/bug563000/trap-force-return-2.js | 7 - .../jaeger/bug563000/trap-own-callsite.js | 15 - .../jaeger/bug563000/trap-parent-from-trap.js | 21 - .../tests/jaeger/bug563000/trap-parent.js | 16 - .../jaeger/bug563000/trap-self-as-parent.js | 18 - .../jaeger/bug563000/trap-self-from-trap.js | 23 - .../tests/jaeger/bug563000/trap-self.js | 11 - .../jaeger/bug563000/untrap-own-trapsite.js | 15 - .../tests/jaeger/bug563000/untrap-self.js | 13 - js/src/jit-test/tests/jaeger/bug573433.js | 7 - js/src/jit-test/tests/jaeger/bug580884.js | 8 - js/src/jit-test/tests/jaeger/bug582286.js | 3 - js/src/jit-test/tests/jaeger/bug583158.js | 9 - js/src/jit-test/tests/jaeger/bug585341.js | 6 - js/src/jit-test/tests/jaeger/bug588338.js | 14 - js/src/jit-test/tests/jaeger/bug588363-2.js | 7 - .../jit-test/tests/jaeger/crash-on-compare.js | 1 - js/src/jit-test/tests/jaeger/fused-eq-ifeq.js | 6 - js/src/jit-test/tests/pic/bug558099.js | 60 --- .../sunspider/check-date-format-xparb.js | 422 ------------------ .../sunspider/check-math-partial-sums.js | 41 -- .../tests/sunspider/check-string-tagcloud.js | 270 ----------- js/src/tests/js1_8_1/jit/jstests.list | 24 - js/src/tests/js1_8_1/jit/regress-451673.js | 115 ----- js/src/tests/js1_8_1/jit/regress-451974-01.js | 86 ---- js/src/tests/js1_8_1/jit/regress-451974-02.js | 97 ---- js/src/tests/js1_8_1/jit/regress-452498-01.js | 105 ----- js/src/tests/js1_8_1/jit/regress-458838.js | 97 ---- js/src/tests/js1_8_1/jit/regress-462459-01.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-02.js | 106 ----- js/src/tests/js1_8_1/jit/regress-462459-03.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-04.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-05.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-06.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-07.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-08.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-09.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-10.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-11.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-12.js | 107 ----- js/src/tests/js1_8_1/jit/regress-469927.js | 78 ---- js/src/tests/js1_8_1/jit/regress-470739.js | 80 ---- js/src/tests/js1_8_1/jit/regress-471635.js | 90 ---- js/src/tests/js1_8_1/jit/regress-489682.js | 65 --- js/src/tests/js1_8_1/jit/shell.js | 4 - toolkit/crashreporter/tools/upload_symbols.sh | 10 + 107 files changed, 11 insertions(+), 4218 deletions(-) delete mode 100644 js/src/jit-test/README delete mode 100644 js/src/jit-test/lib/prolog.js delete mode 100644 js/src/jit-test/tests/arguments/args6.js delete mode 100644 js/src/jit-test/tests/arguments/args8.js delete mode 100644 js/src/jit-test/tests/arguments/argsx-4.js delete mode 100644 js/src/jit-test/tests/basic/arith.js delete mode 100644 js/src/jit-test/tests/basic/bug520498.js delete mode 100644 js/src/jit-test/tests/basic/bug522136.js delete mode 100644 js/src/jit-test/tests/basic/bug528644.js delete mode 100644 js/src/jit-test/tests/basic/bug578041.js delete mode 100644 js/src/jit-test/tests/basic/bug584565.js delete mode 100644 js/src/jit-test/tests/basic/delete-named-names.js delete mode 100644 js/src/jit-test/tests/basic/jitstatsArchFlags.js delete mode 100644 js/src/jit-test/tests/basic/parseIntTests.js delete mode 100644 js/src/jit-test/tests/basic/strictParseIntOctal.js delete mode 100644 js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js delete mode 100644 js/src/jit-test/tests/basic/testBug458838.js delete mode 100644 js/src/jit-test/tests/basic/testBug504520.js delete mode 100644 js/src/jit-test/tests/basic/testBug504520Harder.js delete mode 100644 js/src/jit-test/tests/basic/testBug552248.js delete mode 100644 js/src/jit-test/tests/basic/testBug579602.js delete mode 100644 js/src/jit-test/tests/basic/testBug579646.js delete mode 100644 js/src/jit-test/tests/basic/testBug584650.js delete mode 100644 js/src/jit-test/tests/basic/testBug597736.js delete mode 100644 js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js delete mode 100644 js/src/jit-test/tests/basic/testHoleInDenseArray.js delete mode 100644 js/src/jit-test/tests/basic/testIntOverflow.js delete mode 100644 js/src/jit-test/tests/basic/testMethodInitSafety.js delete mode 100644 js/src/jit-test/tests/basic/testNativeArgsRooting.js delete mode 100644 js/src/jit-test/tests/basic/testNestedDeepBail.js delete mode 100644 js/src/jit-test/tests/basic/testNestedExitStackOuter.js delete mode 100644 js/src/jit-test/tests/basic/testNewArrayCount.js delete mode 100644 js/src/jit-test/tests/basic/testNewArrayCount2.js delete mode 100644 js/src/jit-test/tests/basic/testProxyConstructors.js delete mode 100644 js/src/jit-test/tests/basic/testRebranding2.js delete mode 100644 js/src/jit-test/tests/basic/testReconstructImacroPCStack.js delete mode 100644 js/src/jit-test/tests/basic/testRegExpTest.js delete mode 100644 js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js delete mode 100644 js/src/jit-test/tests/basic/testShiftLeft.js delete mode 100644 js/src/jit-test/tests/basic/testShiftRightArithmetic.js delete mode 100644 js/src/jit-test/tests/basic/testSideExitInConstructor.js delete mode 100644 js/src/jit-test/tests/basic/testSlowNativeBail.js delete mode 100644 js/src/jit-test/tests/basic/testStackQuotaExhausted.js delete mode 100644 js/src/jit-test/tests/closures/bug540136.js delete mode 100644 js/src/jit-test/tests/closures/bug540242.js delete mode 100644 js/src/jit-test/tests/closures/bug540243.js delete mode 100644 js/src/jit-test/tests/closures/bug541239.js delete mode 100644 js/src/jit-test/tests/closures/lambda.js delete mode 100644 js/src/jit-test/tests/closures/setname-inner-heavy.js delete mode 100644 js/src/jit-test/tests/jaeger/bug554580-5.js delete mode 100644 js/src/jit-test/tests/jaeger/bug555155.js delete mode 100644 js/src/jit-test/tests/jaeger/bug555543.js delete mode 100644 js/src/jit-test/tests/jaeger/bug556525.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-self.js delete mode 100644 js/src/jit-test/tests/jaeger/bug573433.js delete mode 100644 js/src/jit-test/tests/jaeger/bug580884.js delete mode 100644 js/src/jit-test/tests/jaeger/bug582286.js delete mode 100644 js/src/jit-test/tests/jaeger/bug583158.js delete mode 100644 js/src/jit-test/tests/jaeger/bug585341.js delete mode 100644 js/src/jit-test/tests/jaeger/bug588338.js delete mode 100644 js/src/jit-test/tests/jaeger/bug588363-2.js delete mode 100644 js/src/jit-test/tests/jaeger/crash-on-compare.js delete mode 100644 js/src/jit-test/tests/jaeger/fused-eq-ifeq.js delete mode 100644 js/src/jit-test/tests/pic/bug558099.js delete mode 100644 js/src/jit-test/tests/sunspider/check-date-format-xparb.js delete mode 100644 js/src/jit-test/tests/sunspider/check-math-partial-sums.js delete mode 100644 js/src/jit-test/tests/sunspider/check-string-tagcloud.js delete mode 100644 js/src/tests/js1_8_1/jit/jstests.list delete mode 100644 js/src/tests/js1_8_1/jit/regress-451673.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-451974-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-451974-02.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-452498-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-458838.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-02.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-03.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-04.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-05.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-06.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-07.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-08.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-09.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-10.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-11.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-12.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-469927.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-470739.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-471635.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-489682.js delete mode 100644 js/src/tests/js1_8_1/jit/shell.js diff --git a/Makefile.in b/Makefile.in index b13e00a2032..aeaf6ad4453 100644 --- a/Makefile.in +++ b/Makefile.in @@ -171,7 +171,7 @@ ifdef MOZ_SYMBOLS_EXTRA_BUILDID EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID) endif -SYMBOL_INDEX_NAME = \ +export SYMBOL_INDEX_NAME = \ $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt buildsymbols: diff --git a/js/src/jit-test/README b/js/src/jit-test/README deleted file mode 100644 index ddde38dc962..00000000000 --- a/js/src/jit-test/README +++ /dev/null @@ -1,74 +0,0 @@ -JS Trace Test Suite - -* PURPOSE - -This is a test suite for testing TraceMonkey. All tests are run in the JS shell -with tracing enabled (-j). - -* REQUIREMENTS - -Python 2.5. This is already a standard requirement for building our tree. - -* RUNNING THE TESTS - -Basic usage: - - python jit_test.py - -The progress bar shows [#tests passed, #tests failed, #tests run] at the left. -If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted -at any time with Ctrl+C and partial results will be printed. - -To run only the basic tests, not including the slow tests: - - python jit_test.py basic - -For more options: - - python jit_test.py -h - -* CREATING NEW TESTS - -Simply create a JS file under the 'tests/' directory. Most tests should go in -'tests/basic/'. - -All tests are run with 'lib/prolog.js' included first on the command line. The -command line also creates a global variable 'libdir' that is set to the path -of the 'lib' directory. To include a file 'foo.js' from the lib directory in a -test case: - - load(libdir + 'foo.js') - -* TEST METALINES - -The first line of a test case can contain a special comment controlling how the -test is run. For example: - - // |jit-test| allow-oom; - -The general format in EBNF is: - - metaline ::= cookie { item ";" } - cookie ::= "|jit-test|" - item ::= flag | attribute - - flag ::= "slow" | "allow-oom" - - attribute ::= name ":" value - name ::= "TMFLAGS" | "error" - value ::= - -The metaline may appear anywhere in the first line of the file: this allows it -to be placed inside any kind of comment. - -The meaning of the items: - - slow Test runs slowly. Do not run if the --no-slow option is given. - allow-oom If the test runs out of memory, it counts as passing. - valgrind Run test under valgrind. - - error The test should be considered to pass iff it throws the - given JS exception. - TMFLAGS Set the environment variable TMFLAGS to the given value. - -* END diff --git a/js/src/jit-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js deleted file mode 100644 index 5d577b39bda..00000000000 --- a/js/src/jit-test/lib/prolog.js +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -const HAVE_TM = 'tracemonkey' in this; - -const HOTLOOP = HAVE_TM ? tracemonkey.HOTLOOP : 8; -const RECORDLOOP = HOTLOOP; -const RUNLOOP = HOTLOOP + 1; - -var checkStats; -if (HAVE_TM) { - checkStats = function(stats) - { - // Temporarily disabled while we work on heuristics. - return; - function jit(on) - { - if (on && !options().match(/tracejit/)) - { - options('tracejit'); - } - else if (!on && options().match(/tracejit/)) - { - options('tracejit'); - } - } - - jit(false); - for (var name in stats) { - var expected = stats[name]; - var actual = tracemonkey[name]; - if (expected != actual) { - print('Trace stats check failed: got ' + actual + ', expected ' + expected + ' for ' + name); - } - } - jit(true); - }; -} else { - checkStats = function() {}; -} - -var appendToActual = function(s) { - actual += s + ','; -} - -if (!("gczeal" in this)) { - gczeal = function() { } -} - diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js deleted file mode 100644 index a2fc60d36a8..00000000000 --- a/js/src/jit-test/tests/arguments/args6.js +++ /dev/null @@ -1,22 +0,0 @@ -actual = ''; -expected = '6,'; - -// tracing length - -var g = 0; - -function h(args) { - g = args.length; -} - -function f() { - h(arguments); -} - -for (var i = 0; i < 5; ++i) { - f(10, 20, 30, 40, 50, 60); -} -appendToActual(g); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js deleted file mode 100644 index 57938d9e231..00000000000 --- a/js/src/jit-test/tests/arguments/args8.js +++ /dev/null @@ -1,14 +0,0 @@ -actual = ''; -expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],'; - -function h() { - return arguments; -} - -for (var i = 0; i < 5; ++i) { - var p = h(i, i*2); - appendToActual(p); -} - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js deleted file mode 100644 index b52b14853cf..00000000000 --- a/js/src/jit-test/tests/arguments/argsx-4.js +++ /dev/null @@ -1,23 +0,0 @@ -actual = ''; -expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,'; - -function f() { - g(arguments); -} - -function g(a, b, c) { - h(arguments); - a = 1; - b = 2; - c = 3; - h(arguments); -} - -function h(a, b, c) { - appendToActual(a + ' ' + b + ' ' + c); -} - -f(4, 5, 6); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/basic/arith.js b/js/src/jit-test/tests/basic/arith.js deleted file mode 100644 index b7f551dccd0..00000000000 --- a/js/src/jit-test/tests/basic/arith.js +++ /dev/null @@ -1,11 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis - -function arith() -{ - var accum = 0; - for (var i = 0; i < 100; i++) { - accum += (i * 2) - 1; - } - return accum; -} -assertEq(arith(), 9800); diff --git a/js/src/jit-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js deleted file mode 100644 index 55324f6f30d..00000000000 --- a/js/src/jit-test/tests/basic/bug520498.js +++ /dev/null @@ -1,9 +0,0 @@ -var Q = 0; -try { - (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) -} catch (e) { -} - -if (Q == 100000) - assertEq(Q, "fail"); - diff --git a/js/src/jit-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js deleted file mode 100644 index 9267c99ccfa..00000000000 --- a/js/src/jit-test/tests/basic/bug522136.js +++ /dev/null @@ -1,10 +0,0 @@ -var Q = 0; -try { - (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) -} catch (e) { -} - -// Exact behavior of recursion check depends on which JIT we use. -var ok = (Q == 3000 || Q == 3001); -assertEq(ok, true); - diff --git a/js/src/jit-test/tests/basic/bug528644.js b/js/src/jit-test/tests/basic/bug528644.js deleted file mode 100644 index 260e0d99590..00000000000 --- a/js/src/jit-test/tests/basic/bug528644.js +++ /dev/null @@ -1,16 +0,0 @@ -// Don't crash - -function g(foo) { - for (a in foo) { - } -} - -var makegen = eval("\n\ - (function(b) {\n\ - var h = \n\ - eval(\"new function() { yield print(b) }\" ); \n\ - return h\n\ - })\n\ -"); - -g(makegen()); diff --git a/js/src/jit-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js deleted file mode 100644 index 7a81feb1800..00000000000 --- a/js/src/jit-test/tests/basic/bug578041.js +++ /dev/null @@ -1,3 +0,0 @@ -__defineGetter__('x', Float32Array); -with(this) - x; diff --git a/js/src/jit-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js deleted file mode 100644 index ad7d4b47577..00000000000 --- a/js/src/jit-test/tests/basic/bug584565.js +++ /dev/null @@ -1,10 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ -// Contributor: Luke Wagner - -var x, f; -for (var i = 0; i < 100; i++) { - f = function() {}; - f.foo; - x = f.length; -} diff --git a/js/src/jit-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js deleted file mode 100644 index 1e0ac407321..00000000000 --- a/js/src/jit-test/tests/basic/delete-named-names.js +++ /dev/null @@ -1,17 +0,0 @@ -var a = ['p', 'q', 'r', 's', 't']; -var o = {p:1, q:2, r:3, s:4, t:5}; -for (var i in o) { - delete o.p; - delete o.q; - delete o.r; - delete o.s; - delete o.t; -} -for each (var i in a) - assertEq(o.hasOwnProperty(i), false); - -checkStats({ - recorderAborted:0, - traceCompleted:1, - sideExitIntoInterpreter:1 -}); diff --git a/js/src/jit-test/tests/basic/jitstatsArchFlags.js b/js/src/jit-test/tests/basic/jitstatsArchFlags.js deleted file mode 100644 index a4ec0c4ee4b..00000000000 --- a/js/src/jit-test/tests/basic/jitstatsArchFlags.js +++ /dev/null @@ -1,14 +0,0 @@ -// Make sure the arch flags are valid on startup, even if nothing has -// been traced yet. We don't know what arch the user is building on, -// but presumably we want at least 1 flag to be set on all supported -// platforms. - -if (HAVE_TM) { - assertEq(jitstats.archIsIA32 || - jitstats.archIs64BIT || - jitstats.archIsARM || - jitstats.archIsSPARC || - jitstats.archIsPPC || - jitstats.archIsAMD64, - 1); - } diff --git a/js/src/jit-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js deleted file mode 100644 index c8ecb366556..00000000000 --- a/js/src/jit-test/tests/basic/parseIntTests.js +++ /dev/null @@ -1,23 +0,0 @@ -function parseIntHelper(n) { - var a; - for (var i = 0; i < 5; i++) - a = parseInt(n); - return a; -} -function doParseIntTests() { - var inputs = [0, -0, .1, -.1, .7, -.7, 1.3, -1.3]; - var outputs = new Array(8); - //avoid jit, unrolled - outputs[0] = outputs[1] = outputs[2] = outputs[4] = 0; - outputs[3] = outputs[5] = -0; - outputs[6] = 1; - outputs[7] = -1; - for (var i = 0; i < 8; i++) { - var testfn = new Function('return parseIntHelper(' + uneval(inputs[i]) + ');'); - assertEq(testfn(), outputs[i]); - } -} -doParseIntTests(); - -assertEq(parseInt("08"), 0); -assertEq(parseInt("09"), 0); diff --git a/js/src/jit-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js deleted file mode 100644 index 536d2d7dd0c..00000000000 --- a/js/src/jit-test/tests/basic/strictParseIntOctal.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -assertEq(parseInt("08"), 0); -assertEq(parseInt("09"), 0); -assertEq(parseInt("014"), 12); -assertEq(parseInt("0xA"), 10); -assertEq(parseInt("00123"), 83); - -for (var i = 0; i < 5; i++) -{ - assertEq(parseInt("08"), 0); - assertEq(parseInt("09"), 0); - assertEq(parseInt("014"), 12); - assertEq(parseInt("0xA"), 10); - assertEq(parseInt("00123"), 83); -} diff --git a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js deleted file mode 100644 index 1c59113482d..00000000000 --- a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js +++ /dev/null @@ -1,10 +0,0 @@ -var o = { - set x(v) { - return 42; - } -}; - -for (var i = 0; i < 10; ++i) { - var z = o.x = "choose me"; - assertEq(z, "choose me"); -} diff --git a/js/src/jit-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js deleted file mode 100644 index cd1e05cf77b..00000000000 --- a/js/src/jit-test/tests/basic/testBug458838.js +++ /dev/null @@ -1,19 +0,0 @@ -var escape; -function testBug458838() { - var a = 1; - function g() { - var b = 0 - for (var i = 0; i < 10; ++i) { - b += a; - } - return b; - } - - return g(); -} -assertEq(testBug458838(), 10); -checkStats({ - recorderStarted: 1, - recorderAborted: 0, - traceCompleted: 1 -}); diff --git a/js/src/jit-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js deleted file mode 100644 index 73e2e3013fb..00000000000 --- a/js/src/jit-test/tests/basic/testBug504520.js +++ /dev/null @@ -1,11 +0,0 @@ -function testBug504520() { - // A bug involving comparisons. - var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 0]; - assertEq(arr.length > RUNLOOP, true); - - var s = ''; - for (var i = 0; i < arr.length; i++) - arr[i] >= 1/0 ? null : (s += i); - assertEq(s, '9'); -} -testBug504520(); diff --git a/js/src/jit-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js deleted file mode 100644 index 0a63ebf4075..00000000000 --- a/js/src/jit-test/tests/basic/testBug504520Harder.js +++ /dev/null @@ -1,33 +0,0 @@ -function testBug504520Harder() { - // test 1024 similar cases - var vals = [1/0, -1/0, 0, 0/0]; - var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; - for each (var x in vals) { - for each (var y in vals) { - for each (var op in ops) { - for each (var z in vals) { - // Assume eval is correct. This depends on the global - // Infinity property not having been reassigned. - var xz = eval(x + op + z); - var yz = eval(y + op + z); - - var arr = [x, x, x, x, x, x, x, x, x, y]; - assertEq(arr.length > RUNLOOP, true); - var expected = [xz, xz, xz, xz, xz, xz, xz, xz, xz, yz]; - - // ?: looks superfluous but that's what we're testing here - var fun = eval( - '(function (arr, results) {\n' + - ' for (let i = 0; i < arr.length; i++)\n' + - ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + - '});\n'); - var actual = []; - fun(arr, actual); - print(x, y, op, z); - assertEq("" + actual, "" + expected); - } - } - } - } -} -testBug504520Harder(); diff --git a/js/src/jit-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js deleted file mode 100644 index 28782b665bb..00000000000 --- a/js/src/jit-test/tests/basic/testBug552248.js +++ /dev/null @@ -1,36 +0,0 @@ -setDebug(true); -var a = new Array(); - -function i(save) { - var x = 9; - evalInFrame(0, "a.push(x)", save); - evalInFrame(1, "a.push(z)", save); - evalInFrame(2, "a.push(z)", save); - evalInFrame(3, "a.push(y)", save); - evalInFrame(4, "a.push(x)", save); -} - -function h() { - var z = 5; - evalInFrame(0, "a.push(z)"); - evalInFrame(1, "a.push(y)"); - evalInFrame(2, "a.push(x)"); - evalInFrame(0, "i(false)"); - evalInFrame(0, "a.push(z)", true); - evalInFrame(1, "a.push(y)", true); - evalInFrame(2, "a.push(x)", true); - evalInFrame(0, "i(true)", true); -} - -function g() { - var y = 4; - h(); -} - -function f() { - var x = 3; - g(); -} - -f(); -assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+''); diff --git a/js/src/jit-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js deleted file mode 100644 index 5871c24d46e..00000000000 --- a/js/src/jit-test/tests/basic/testBug579602.js +++ /dev/null @@ -1,21 +0,0 @@ -// don't panic - -f = function() { - x = yield -} -rv = f() -for (a in rv) (function() {}) -x = Proxy.create((function() { - return { - defineProperty: gc - } -})(), x) -with({ - d: (({ - x: Object.defineProperty(x, "", ({ - set: Array.e - })) - })) -}) {} - -// don't crash diff --git a/js/src/jit-test/tests/basic/testBug579646.js b/js/src/jit-test/tests/basic/testBug579646.js deleted file mode 100644 index d034410f9cc..00000000000 --- a/js/src/jit-test/tests/basic/testBug579646.js +++ /dev/null @@ -1,22 +0,0 @@ -if (typeof gczeal != "function") - gczeal = function() {} - -for (a = 0; a < 9; a++) - for (b = 0; b < 1; b++) - for (c = 0; c < 2; c++) - gczeal(); - -for each(e in [NaN]) - for (d = 0; d < 1; d++) - z = 0; - -for (w in [0, 0]) - {} - -x = 0; - -for (e = 0; e < 3; e++) - for (f = 0; f < 4; f++) - x = -x - -// don't crash diff --git a/js/src/jit-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js deleted file mode 100644 index b6c9d8ab7fd..00000000000 --- a/js/src/jit-test/tests/basic/testBug584650.js +++ /dev/null @@ -1,9 +0,0 @@ -if (typeof gczeal != "function") - gczeal = function() {} - -// don't crash -x = (evalcx('lazy')) -x.watch("", function () {}) -gczeal(1) -for (w in x) {} - diff --git a/js/src/jit-test/tests/basic/testBug597736.js b/js/src/jit-test/tests/basic/testBug597736.js deleted file mode 100644 index ded33842776..00000000000 --- a/js/src/jit-test/tests/basic/testBug597736.js +++ /dev/null @@ -1,32 +0,0 @@ -function leak_test() { - // Create a reference loop function->script->traceFragment->object->function - // that GC must be able to break. To embedd object into the fragment the - // code use prototype chain of depth 2 which caches obj.__proto__.__proto__ - // into the fragment. - - // To make sure that we have no references to the function f after this - // function returns due via the conservative scan of the native stack we - // loop here multiple times overwriting the stack and registers with new garabge. - for (var j = 0; j != 8; ++j) { - var f = Function("a", "var s = 0; for (var i = 0; i != 100; ++i) s += a.b; return s;"); - var c = {b: 1, f: f, leakDetection: makeFinalizeObserver()}; - f({ __proto__: { __proto__: c}}); - f = c = a = null; - gc(); - } -} - -function test() -{ - if (typeof finalizeCount != "function") - return; - - var base = finalizeCount(); - leak_test(); - gc(); - gc(); - var n = finalizeCount(); - assertEq(base + 4 < finalizeCount(), true, "Some finalizations must happen"); -} - -test(); diff --git a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js deleted file mode 100644 index cc80e779c37..00000000000 --- a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js +++ /dev/null @@ -1,12 +0,0 @@ -function testEliminatedGuardWithinAnchor() { - for (let i = 0; i < 5; ++i) { i / (i * i); } - return "ok"; -} - -assertEq(testEliminatedGuardWithinAnchor(), "ok"); - -if (HAVE_TM) { - checkStats({ - sideExitIntoInterpreter: (jitstats.archIsARM ? 1 : 3) - }); -} diff --git a/js/src/jit-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js deleted file mode 100644 index ba7a2c01e16..00000000000 --- a/js/src/jit-test/tests/basic/testHoleInDenseArray.js +++ /dev/null @@ -1,18 +0,0 @@ -var s; - -function f(i) { - if (i > 4) /* side exit when arr[i] changes from bool to undefined (via a hole) */ - assertEq(s, undefined); - else - assertEq(s, false); - return 1; -} - -/* trailing 'true' ensures array has capacity >= 10 */ -var arr = [ false, false, false, false, false, , , , , , true ]; - -for (var i = 0; i < 10; ++i) { - (s = arr[i]) + f(i); -} - -checkStats({ traceTriggered: 2, sideExitIntoInterpreter: 2 }) diff --git a/js/src/jit-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js deleted file mode 100644 index 712ef0c6529..00000000000 --- a/js/src/jit-test/tests/basic/testIntOverflow.js +++ /dev/null @@ -1,15 +0,0 @@ -function testIntOverflow() { - // int32_max - 7 - var ival = 2147483647 - 7; - for (var i = 0; i < 30; i++) { - ival += 30; - } - return (ival < 2147483647); -} -assertEq(testIntOverflow(), false); -checkStats({ - recorderStarted: 1, - recorderAborted: 0, - traceCompleted: 1, - traceTriggered: 1, -}); diff --git a/js/src/jit-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js deleted file mode 100644 index ebd6309bdf9..00000000000 --- a/js/src/jit-test/tests/basic/testMethodInitSafety.js +++ /dev/null @@ -1,14 +0,0 @@ -function testMethodInitSafety() { - function f() { return 'fail'; } - function g() { return 'ok'; } - - var s; - var arr = [f, f, f, f, g]; - //assertEq(arr.length > RUNLOOP, true); - for (var i = 0; i < arr.length; i++) { - var x = {m: arr[i]}; - s = x.m(); - } - return s; -} -assertEq(testMethodInitSafety(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js deleted file mode 100644 index 1ce8259f2d4..00000000000 --- a/js/src/jit-test/tests/basic/testNativeArgsRooting.js +++ /dev/null @@ -1,14 +0,0 @@ -if ('gczeal' in this) -(function () { - (eval("\ - (function () {\ - for (var y = 0; y < 16; ++y) {\ - if (y % 3 == 2) {\ - gczeal(1);\ - } else {\ - print(0 / 0);\ - }\ - }\ - });\ - "))() -})(); diff --git a/js/src/jit-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js deleted file mode 100644 index 8e59b04cdaa..00000000000 --- a/js/src/jit-test/tests/basic/testNestedDeepBail.js +++ /dev/null @@ -1,20 +0,0 @@ -var _quit; -function testNestedDeepBail() -{ - _quit = false; - function loop() { - for (var i = 0; i < 4; i++) - ; - } - loop(); - - function f() { - loop(); - _quit = true; - } - - var stk = [[1], [], [], [], []]; - while (!_quit) - stk.pop().forEach(f); -} -testNestedDeepBail(); diff --git a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js deleted file mode 100644 index 88b795e7cbc..00000000000 --- a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js +++ /dev/null @@ -1,29 +0,0 @@ -// Test stack reconstruction after a nested exit -function testNestedExitStackInner(j, counter) { - ++counter; - var b = 0; - for (var i = 1; i <= RUNLOOP; i++) { - ++b; - var a; - // Make sure that once everything has been traced we suddenly switch to - // a different control flow the first time we run the outermost tree, - // triggering a side exit. - if (j < RUNLOOP) - a = 1; - else - a = 0; - ++b; - b += a; - } - return counter + b; -} -function testNestedExitStackOuter() { - var counter = 0; - for (var j = 1; j <= RUNLOOP; ++j) { - for (var k = 1; k <= RUNLOOP; ++k) { - counter = testNestedExitStackInner(j, counter); - } - } - return counter; -} -//assertEq(testNestedExitStackOuter(), 81); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js deleted file mode 100644 index cb7e6d9843c..00000000000 --- a/js/src/jit-test/tests/basic/testNewArrayCount.js +++ /dev/null @@ -1,12 +0,0 @@ -function testNewArrayCount() -{ - function count(a) { var n = 0; for (var p in a) n++; return n; } - var a = []; - for (var i = 0; i < 5; i++) - a = [0]; - assertEq(count(a), 1); - for (var i = 0; i < 5; i++) - a = [0, , 2]; - assertEq(count(a), 2); -} -testNewArrayCount(); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js deleted file mode 100644 index 6318e4c25f3..00000000000 --- a/js/src/jit-test/tests/basic/testNewArrayCount2.js +++ /dev/null @@ -1,8 +0,0 @@ -function testNewArrayCount2() { - function count(a) { var n = 0; for (var p in a) n++; return n; } - var x = 0; - for (var i = 0; i < 10; ++i) - x = count(new Array(1,2,3)); - return x; -} -assertEq(testNewArrayCount2(), 3); diff --git a/js/src/jit-test/tests/basic/testProxyConstructors.js b/js/src/jit-test/tests/basic/testProxyConstructors.js deleted file mode 100644 index e716b361ef0..00000000000 --- a/js/src/jit-test/tests/basic/testProxyConstructors.js +++ /dev/null @@ -1,9 +0,0 @@ -// proxies can return primitives -assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined); - -x = Proxy.createFunction((function () {}), Uint16Array, wrap) -new(wrap(x)) - -// proxies can return the callee -var x = Proxy.createFunction({}, function (q) { return q; }); -new x(x); diff --git a/js/src/jit-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js deleted file mode 100644 index 2bf26eeaff5..00000000000 --- a/js/src/jit-test/tests/basic/testRebranding2.js +++ /dev/null @@ -1,21 +0,0 @@ -delete q; -delete g; -delete h; -delete a; -delete f; - -function testRebranding2() { - // Same as testRebranding, but the object to be rebranded isn't the global. - var x = "FAIL"; - function g(){} - function h(){ x = "ok"; } - var obj = {m: g}; - var arr = [g, g, g, g, h]; - //assertEq(arr.length > RUNLOOP, true); - for (var i = 0; i < 5; i++) { - obj.m = arr[i]; - obj.m(); - } - return x; -} -assertEq(testRebranding2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js deleted file mode 100644 index 2dc51508d4f..00000000000 --- a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js +++ /dev/null @@ -1,28 +0,0 @@ -x = Proxy.create((function () { - return { - get: function () {} - } -}()), Object.e) - -var hit = false; - -try { - Function("\ - for(var a = 0; a < 2; ++a) {\ - if (a == 0) {}\ - else {\ - x > x\ - }\ - }\ - ")() -} catch (e) { - hit = true; - - var str = String(e); - var match = (str == "TypeError: x is not a function" || - str == "TypeError: can't convert x to number"); - - assertEq(match, true); -} - -assertEq(hit, true); diff --git a/js/src/jit-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js deleted file mode 100644 index 78917ba9be3..00000000000 --- a/js/src/jit-test/tests/basic/testRegExpTest.js +++ /dev/null @@ -1,10 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -function testRegExpTest() { - var r = /abc/; - var flag = false; - for (var i = 0; i < 10; ++i) - flag = r.test("abc"); - return flag; -} -assertEq(testRegExpTest(), true); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js deleted file mode 100644 index 14574b146bf..00000000000 --- a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js +++ /dev/null @@ -1,11 +0,0 @@ -var a = {_val: 'q', - get p() { return f; }}; - -function f() { return this._val; } - -var g = ''; -for (var i = 0; i < 9; i++) - g += a.p(); -assertEq(g, 'qqqqqqqqq'); - -checkStats({recorderStarted: 1, recorderAborted: 0, traceCompleted: 1, traceTriggered: 1}); diff --git a/js/src/jit-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js deleted file mode 100644 index 4a7f5d98289..00000000000 --- a/js/src/jit-test/tests/basic/testShiftLeft.js +++ /dev/null @@ -1,38 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -/* Test the proper operation of the left shift operator. This is especially - * important on ARM as an explicit mask is required at the native instruction - * level. */ - -load(libdir + 'range.js'); - -function testShiftLeft() -{ - var r = []; - var i = 0; - var j = 0; - - var shifts = [0,1,7,8,15,16,23,24,31]; - - /* Samples from the simple shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << shifts[i]; - - /* Samples outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 32); - - /* Samples far outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 224); - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 256); - - return r.join(","); -} - -assertEq(testShiftLeft(), - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648"); diff --git a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js deleted file mode 100644 index 7268dc0bad3..00000000000 --- a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Test the proper operation of the arithmetic right shift operator. This is - * especially important on ARM as an explicit mask is required at the native - * instruction level. */ - -load(libdir + 'range.js'); - -/* Test different combinations of literals/variables. */ -var s = 4; -var t = 100; -assertEq(42 >> s, 2); -assertEq(s >> 1, 2); -assertEq(23 >> 3, 2); -assertEq(t >> s, 6); - - -function testShiftRightArithmetic() -{ - var r = []; - var i = 0; - var j = 0; - - var shifts = [0,1,7,8,15,16,23,24,31]; - - /* Samples from the simple shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> shifts[i]; - - /* Samples outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 32); - - /* Samples far outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 224); - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 256); - - return r.join(","); -} -assertEq(testShiftRightArithmetic(), - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"); diff --git a/js/src/jit-test/tests/basic/testSideExitInConstructor.js b/js/src/jit-test/tests/basic/testSideExitInConstructor.js deleted file mode 100644 index d46543ef7bd..00000000000 --- a/js/src/jit-test/tests/basic/testSideExitInConstructor.js +++ /dev/null @@ -1,39 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -function testSideExitInConstructor() { - var FCKConfig = {}; - FCKConfig.CoreStyles = - { - 'Bold': { }, - 'Italic': { }, - 'FontFace': { }, - 'Size' : - { - Overrides: [ ] - }, - - 'Color' : - { - Element: '', - Styles: { }, - Overrides: [ ] - }, - 'BackColor': { - Element : '', - Styles : { 'background-color' : '' } - }, - - }; - var FCKStyle = function(A) { - A.Element; - }; - - var pass = true; - for (var s in FCKConfig.CoreStyles) { - var x = new FCKStyle(FCKConfig.CoreStyles[s]); - if (!x) - pass = false; - } - return pass; -} -assertEq(testSideExitInConstructor(), true); diff --git a/js/src/jit-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js deleted file mode 100644 index f7a1443a71a..00000000000 --- a/js/src/jit-test/tests/basic/testSlowNativeBail.js +++ /dev/null @@ -1,10 +0,0 @@ -function testSlowNativeBail() { - var a = ['0', '1', '2', '3', '+']; - try { - for (var i = 0; i < a.length; i++) - new RegExp(a[i]); - } catch (exc) { - assertEq(""+exc, "SyntaxError: invalid quantifier"); - } -} -testSlowNativeBail(); diff --git a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js deleted file mode 100644 index f65957a74b7..00000000000 --- a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js +++ /dev/null @@ -1,29 +0,0 @@ -const numFatArgs = Math.pow(2,19) - 1024; - -function fun(x) { - if (x <= 0) - return 0; - return fun(x-1); -} - -function fatStack() { - return fun(10000); -} - -function assertRightFailure(e) { - assertEq(e.toString() == "InternalError: script stack space quota is exhausted" || - e.toString() == "InternalError: too much recursion", - true); -} - -exception = false; -try { - fatStack.apply(null, new Array(numFatArgs)); -} catch (e) { - assertRightFailure(e); - exception = true; -} -assertEq(exception, true); - -// No more trace recursion w/ JM -checkStats({traceCompleted:0}); diff --git a/js/src/jit-test/tests/closures/bug540136.js b/js/src/jit-test/tests/closures/bug540136.js deleted file mode 100644 index 54b57713a7f..00000000000 --- a/js/src/jit-test/tests/closures/bug540136.js +++ /dev/null @@ -1,17 +0,0 @@ -// |jit-test| error: TypeError - -(eval("\ - (function () {\ - for (var[x] = function(){} in \ - (function m(a) {\ - if (a < 1) {\ - x;\ - return\ - }\ - return m(a - 1) + m(a - 2)\ - })(7)\ - (eval(\"\"))\ - )\ - ([])\ - })\ -"))() diff --git a/js/src/jit-test/tests/closures/bug540242.js b/js/src/jit-test/tests/closures/bug540242.js deleted file mode 100644 index 56c1a5a3143..00000000000 --- a/js/src/jit-test/tests/closures/bug540242.js +++ /dev/null @@ -1,17 +0,0 @@ -for (j = 0; j < 1; j++) { - var f = eval("\ - (function() {\ - for (var a = 0; a < 8; ++a) {\ - if (a % 3 == 2) {\ - eval(\"\ - for(b in[0,0,0,0]) {\ - print()\ - }\ - \")\ - }\ - gc()\ - }\ - })\ - "); - f() -} diff --git a/js/src/jit-test/tests/closures/bug540243.js b/js/src/jit-test/tests/closures/bug540243.js deleted file mode 100644 index 07faa26b6e7..00000000000 --- a/js/src/jit-test/tests/closures/bug540243.js +++ /dev/null @@ -1,10 +0,0 @@ -for (a in (eval("\ - (function() {\ - return function() {\ - yield ((function() {\ - return d\ - })())\ - } ();\ - var d = []\ - })\ -"))()); diff --git a/js/src/jit-test/tests/closures/bug541239.js b/js/src/jit-test/tests/closures/bug541239.js deleted file mode 100644 index 32e3af1565b..00000000000 --- a/js/src/jit-test/tests/closures/bug541239.js +++ /dev/null @@ -1,16 +0,0 @@ -function m() { - var d = 73; - - return (eval("\n\ - (function() {\n\ - return function() {\n\ - yield ((function() {\n\ - print(d);\n\ - return d\n\ - })())\n\ - } ();\n\ - })\n\ - "))(); -} - -m().next(); diff --git a/js/src/jit-test/tests/closures/lambda.js b/js/src/jit-test/tests/closures/lambda.js deleted file mode 100644 index fd7cbd16ed7..00000000000 --- a/js/src/jit-test/tests/closures/lambda.js +++ /dev/null @@ -1,27 +0,0 @@ -function f() { - var k = 0; - - var g = function() { - return ++k; - } - - return g; -} - -function h() { - for (var i = 0; i < 10; ++i) { - var vf = f(); - assertEq(vf(), 1); - assertEq(vf(), 2); - for (var j = 0; j < 10; ++j) { - assertEq(vf(), j + 3); - } - } -} - -h(); - -checkStats({ - recorderAborted: 8, // Inner tree is trying to grow -}); - diff --git a/js/src/jit-test/tests/closures/setname-inner-heavy.js b/js/src/jit-test/tests/closures/setname-inner-heavy.js deleted file mode 100644 index 9c1919dc2f3..00000000000 --- a/js/src/jit-test/tests/closures/setname-inner-heavy.js +++ /dev/null @@ -1,18 +0,0 @@ -actual = ''; -expected = 'undefined,'; - -function f() { - (eval("\ - (function () {\ - for (var z = 0; z < 2; ++z) {\ - x = ''\ - }\ - })\ - "))(); -} -__defineSetter__("x", eval) -f() -appendToActual(x); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/jaeger/bug554580-5.js b/js/src/jit-test/tests/jaeger/bug554580-5.js deleted file mode 100644 index 1d3ee522b07..00000000000 --- a/js/src/jit-test/tests/jaeger/bug554580-5.js +++ /dev/null @@ -1,20 +0,0 @@ -(function() { - (function g(m, n) { - if (m = n) { - return eval("x=this") - } - g(m, 1)[[]] - })() -})() -Function("\ - for (let b in [0]) {\ - for (var k = 0; k < 6; ++k) {\ - if (k == 1) {\ - print(x)\ - }\ - }\ - }\ -")() - -/* Don't crash/assert. */ - diff --git a/js/src/jit-test/tests/jaeger/bug555155.js b/js/src/jit-test/tests/jaeger/bug555155.js deleted file mode 100644 index db7b57aa1bc..00000000000 --- a/js/src/jit-test/tests/jaeger/bug555155.js +++ /dev/null @@ -1,12 +0,0 @@ -// |jit-test| error: undefined -(function() { - throw (function f(a, b) { - if (a.h == b) { - return eval("((function(){return 1})())!=this") - } - f(b) - })([], 0) -})() - -/* Don't assert/crash. */ - diff --git a/js/src/jit-test/tests/jaeger/bug555543.js b/js/src/jit-test/tests/jaeger/bug555543.js deleted file mode 100644 index b641c1b5832..00000000000 --- a/js/src/jit-test/tests/jaeger/bug555543.js +++ /dev/null @@ -1,8 +0,0 @@ -(function() { - for each(let z in [new String(''), new String('q'), new String('')]) { - if (uneval() < z) (function(){}) - } -})() - -/* Don't assert/crash. */ - diff --git a/js/src/jit-test/tests/jaeger/bug556525.js b/js/src/jit-test/tests/jaeger/bug556525.js deleted file mode 100644 index 0b59f3274b0..00000000000 --- a/js/src/jit-test/tests/jaeger/bug556525.js +++ /dev/null @@ -1,5 +0,0 @@ -for each(x in [new Number]) - x.__proto__ = [] -++x[x] - -// don't assert diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js deleted file mode 100644 index 2cde4fde8a9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js +++ /dev/null @@ -1,9 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - return x; -} -trap(caller, 7, "var x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js deleted file mode 100644 index 11f2ff0a659..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - var x = ({ dana : "zuul" }); - return x; -} -trap(caller, 23, "x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js deleted file mode 100644 index 9eeb76d07eb..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - var x = "failure"; - return x; -} -trap(caller, 14, "x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js deleted file mode 100644 index 266db65090d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js +++ /dev/null @@ -1,9 +0,0 @@ -setDebug(true); -var x = "failure"; -function main() { x = "success"; } - -/* The JSOP_STOP in a. */ -trap(main, 8, ""); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js deleted file mode 100644 index db7e4b82b2a..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); -var x = "notset"; -function main() { x = "failure"; } -function success() { x = "success"; } - -/* The JSOP_STOP in a. */ -trap(main, 7, "success()"); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js deleted file mode 100644 index 2f89f58bc3d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js +++ /dev/null @@ -1,11 +0,0 @@ -setDebug(true); -var x = "notset"; -function main() { x = "success"; } -function failure() { x = "failure"; } - -/* The JSOP_STOP in a. */ -trap(main, 8, "failure()"); -untrap(main, 8); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js deleted file mode 100644 index 1d19aeebeb1..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js +++ /dev/null @@ -1,7 +0,0 @@ -setDebug(true); -function main() { - return "failure"; -} -/* JSOP_RETURN in main. */ -trap(main, 3, "'success'"); -assertEq(main(), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js deleted file mode 100644 index b2b516826a9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js +++ /dev/null @@ -1,7 +0,0 @@ -setDebug(true); -function main() { - return 1; -} -/* JSOP_RETURN in main. */ -trap(main, 1, "0"); -assertEq(main(), 0); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js deleted file mode 100644 index 18378b7808f..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js +++ /dev/null @@ -1,15 +0,0 @@ -setDebug(true); -x = "notset"; -function myparent(nested) { - if (nested) { - /* myparent call in myparent. */ - trap(myparent, 39, "failure()"); - } else { - x = "success"; - myparent(true); - } -} -function failure() { x = "failure"; } - -myparent(false); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js deleted file mode 100644 index d6ded288128..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js +++ /dev/null @@ -1,21 +0,0 @@ -setDebug(true); -x = "notset"; - -function child() { - x = "failure1"; - /* JSOP_STOP in parent. */ - trap(parent, 10, "success()"); -} - -function parent() { - x = "failure2"; -} -/* First op in parent. */ -trap(parent, 0, "child()"); - -function success() { - x = "success"; -} - -parent(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js deleted file mode 100644 index 2209f946af9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js +++ /dev/null @@ -1,16 +0,0 @@ -setDebug(true); -x = "notset"; -function child() { - /* JSOP_STOP in parent. */ - trap(parent, 17, "success()"); -} -function parent() { - child(); - x = "failure"; -} -function success() { - x = "success"; -} - -parent() -assertEq(x, "success"); diff --git 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 deleted file mode 100644 index 65d3e73135e..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js +++ /dev/null @@ -1,18 +0,0 @@ -setDebug(true); -x = "notset"; - -function myparent(nested) { - if (nested) { - /* noop call in myparent */ - trap(myparent, 50, "success()"); - } else { - myparent(true); - x = "failure"; - noop(); - } -} -function noop() { } -function success() { x = "success"; } - -myparent(); -assertEq(x, "success"); diff --git 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 deleted file mode 100644 index 8a9caaaafda..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js +++ /dev/null @@ -1,23 +0,0 @@ -setDebug(true); -x = "notset"; - -function doNothing() { } - -function myparent(nested) { - if (nested) { - /* JSOP_CALL to doNothing in myparent with nested = true. */ - trap(myparent, 24, "success()"); - doNothing(); - } else { - doNothing(); - } -} -/* JSOP_CALL to doNothing in myparent with nested = false. */ -trap(myparent, 35, "myparent(true)"); - -function success() { - x = "success"; -} - -myparent(false); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js deleted file mode 100644 index 9b94fd1c8cc..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js +++ /dev/null @@ -1,11 +0,0 @@ -setDebug(true); -x = "notset"; -function main() { - /* The JSOP_STOP in a. */ - trap(main, 25, "success()"); - x = "failure"; -} -function success() { x = "success"; } - -main(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js deleted file mode 100644 index e4dd9d7dc97..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js +++ /dev/null @@ -1,15 +0,0 @@ -setDebug(true); -x = "notset"; -function child() { - /* JSOP_STOP in parent */ - untrap(parent, 10); - x = "success"; -} -function parent() { - x = "failure"; -} -/* JSOP_STOP in parent */ -trap(parent, 10, "child()"); - -parent(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js deleted file mode 100644 index 4c18db52e8e..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js +++ /dev/null @@ -1,13 +0,0 @@ -setDebug(true); -x = "notset"; -function main() { - /* JSOP_STOP in main. */ - untrap(main, 23); - x = "success"; -} -function failure() { x = "failure"; } - -/* JSOP_STOP in main. */ -trap(main, 23, "failure()"); -main(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug573433.js b/js/src/jit-test/tests/jaeger/bug573433.js deleted file mode 100644 index aa39022bb74..00000000000 --- a/js/src/jit-test/tests/jaeger/bug573433.js +++ /dev/null @@ -1,7 +0,0 @@ -// |jit-test| error: TypeError -function f() { - eval("(function() \n{\nfor(x in[])\n{}\n})"); - ("")() -} -f() - diff --git a/js/src/jit-test/tests/jaeger/bug580884.js b/js/src/jit-test/tests/jaeger/bug580884.js deleted file mode 100644 index b7a26f70566..00000000000 --- a/js/src/jit-test/tests/jaeger/bug580884.js +++ /dev/null @@ -1,8 +0,0 @@ -// |jit-test| error: ReferenceError -for (let a in [0]) -a = e -for (let a in [0]) -(function () { - a -}) - diff --git a/js/src/jit-test/tests/jaeger/bug582286.js b/js/src/jit-test/tests/jaeger/bug582286.js deleted file mode 100644 index 094366a3c79..00000000000 --- a/js/src/jit-test/tests/jaeger/bug582286.js +++ /dev/null @@ -1,3 +0,0 @@ -evalcx("function s(){}",evalcx('lazy')) - - diff --git a/js/src/jit-test/tests/jaeger/bug583158.js b/js/src/jit-test/tests/jaeger/bug583158.js deleted file mode 100644 index 6d8c124487d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug583158.js +++ /dev/null @@ -1,9 +0,0 @@ -// |jit-test| error: ReferenceError -function g() { - var rv = (function() { - this << 1 - })() - if (a) (function() {}) -} -g() - diff --git a/js/src/jit-test/tests/jaeger/bug585341.js b/js/src/jit-test/tests/jaeger/bug585341.js deleted file mode 100644 index fb96b92c3c3..00000000000 --- a/js/src/jit-test/tests/jaeger/bug585341.js +++ /dev/null @@ -1,6 +0,0 @@ -__defineGetter__("x", Float64Array) -Function("\ - with(this) {\ - eval(\"x\")\ - }\ -")() diff --git a/js/src/jit-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js deleted file mode 100644 index 65c30952077..00000000000 --- a/js/src/jit-test/tests/jaeger/bug588338.js +++ /dev/null @@ -1,14 +0,0 @@ -// |jit-test| error: is not a function -function f() { (e) -} (x = Proxy.createFunction((function(x) { - return { - get: function(r, b) { - return x[b] - } - } -})(/x/), wrap)) -for (z = 0; z < 100; x.unwatch(), z++) -for (e in [0]) { - gczeal(2) -} ( )("") - diff --git a/js/src/jit-test/tests/jaeger/bug588363-2.js b/js/src/jit-test/tests/jaeger/bug588363-2.js deleted file mode 100644 index 5550be3ea8d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug588363-2.js +++ /dev/null @@ -1,7 +0,0 @@ -with(evalcx('')) { - delete eval; - eval("x", this.__defineGetter__("x", Function)); -} - -/* Don't assert or crash. */ - diff --git a/js/src/jit-test/tests/jaeger/crash-on-compare.js b/js/src/jit-test/tests/jaeger/crash-on-compare.js deleted file mode 100644 index 5abd7aa045e..00000000000 --- a/js/src/jit-test/tests/jaeger/crash-on-compare.js +++ /dev/null @@ -1 +0,0 @@ -assertEq(Infinity >= Infinity ? true : false, true); diff --git a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js deleted file mode 100644 index b5d2bf2f61b..00000000000 --- a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js +++ /dev/null @@ -1,6 +0,0 @@ -function ack(m,n){ - if (m==0) { return n+1; } - if (n==0) { return ack(m-1,1); } - return ack(m-1, ack(m,n-1) ); -} -assertEq(ack(3, 3), 61); diff --git a/js/src/jit-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js deleted file mode 100644 index 5d8c68fa590..00000000000 --- a/js/src/jit-test/tests/pic/bug558099.js +++ /dev/null @@ -1,60 +0,0 @@ -(function()[function() function() function() function() function() function() {}]); -foo = [{ - text: "(function(){if(d){(1)}})", - s: function() {}, - test: function() { - try { - f - } catch(e) {} - } -}, -{ - text: "(function(){t})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){if(0){}})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){if(1){}(2)})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){g})", - b: function() {}, - test: function() {} -}, -{ - text: "(function(){})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){1})", - s: function() {}, - test: function() {} -}]; (function() { - for (i = 0; i < foo.length; ++i) { - a = foo[i] - text = a.text - eval(text.replace(/@/, "")); - if (a.test()) {} - } -} ()); -s = [function() function() function() function() function() function() {}] -[function() function() function() function() {}]; -(function() { [function() function() {}] }); -(function() {}); -(eval("\ - (function(){\ - for each(d in[\ - 0,0,0,0,0,0,0,0,0,0,0,0,0,null,NaN,1,Boolean(false),Boolean(false)\ - ]){\ - [].filter(new Function,gczeal(2))\ - }\ - })\ -"))(); diff --git a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js deleted file mode 100644 index 41f44fed50c..00000000000 --- a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2004 Baron Schwartz - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, version 2.1. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - */ - -Date.parseFunctions = {count:0}; -Date.parseRegexes = []; -Date.formatFunctions = {count:0}; - -Date.prototype.dateFormat = function(format) { - if (Date.formatFunctions[format] == null) { - Date.createNewFormat(format); - } - var func = Date.formatFunctions[format]; - return this[func](); -} - -Date.createNewFormat = function(format) { - var funcName = "format" + Date.formatFunctions.count++; - Date.formatFunctions[format] = funcName; - var code = "Date.prototype." + funcName + " = function(){return "; - var special = false; - var ch = ''; - for (var i = 0; i < format.length; ++i) { - ch = format.charAt(i); - if (!special && ch == "\\") { - special = true; - } - else if (special) { - special = false; - code += "'" + String.escape(ch) + "' + "; - } - else { - code += Date.getFormatCode(ch); - } - } - eval(code.substring(0, code.length - 3) + ";}"); -} - -Date.getFormatCode = function(character) { - switch (character) { - case "d": - return "String.leftPad(this.getDate(), 2, '0') + "; - case "D": - return "Date.dayNames[this.getDay()].substring(0, 3) + "; - case "j": - return "this.getDate() + "; - case "l": - return "Date.dayNames[this.getDay()] + "; - case "S": - return "this.getSuffix() + "; - case "w": - return "this.getDay() + "; - case "z": - return "this.getDayOfYear() + "; - case "W": - return "this.getWeekOfYear() + "; - case "F": - return "Date.monthNames[this.getMonth()] + "; - case "m": - return "String.leftPad(this.getMonth() + 1, 2, '0') + "; - case "M": - return "Date.monthNames[this.getMonth()].substring(0, 3) + "; - case "n": - return "(this.getMonth() + 1) + "; - case "t": - return "this.getDaysInMonth() + "; - case "L": - return "(this.isLeapYear() ? 1 : 0) + "; - case "Y": - return "this.getFullYear() + "; - case "y": - return "('' + this.getFullYear()).substring(2, 4) + "; - case "a": - return "(this.getHours() < 12 ? 'am' : 'pm') + "; - case "A": - return "(this.getHours() < 12 ? 'AM' : 'PM') + "; - case "g": - return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; - case "G": - return "this.getHours() + "; - case "h": - return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; - case "H": - return "String.leftPad(this.getHours(), 2, '0') + "; - case "i": - return "String.leftPad(this.getMinutes(), 2, '0') + "; - case "s": - return "String.leftPad(this.getSeconds(), 2, '0') + "; - case "O": - return "this.getGMTOffset() + "; - case "T": - return "this.getTimezone() + "; - case "Z": - return "(this.getTimezoneOffset() * -60) + "; - default: - return "'" + String.escape(character) + "' + "; - } -} - -Date.parseDate = function(input, format) { - if (Date.parseFunctions[format] == null) { - Date.createParser(format); - } - var func = Date.parseFunctions[format]; - return Date[func](input); -} - -Date.createParser = function(format) { - var funcName = "parse" + Date.parseFunctions.count++; - var regexNum = Date.parseRegexes.length; - var currentGroup = 1; - Date.parseFunctions[format] = funcName; - - var code = "Date." + funcName + " = function(input){\n" - + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" - + "var d = new Date();\n" - + "y = d.getFullYear();\n" - + "m = d.getMonth();\n" - + "d = d.getDate();\n" - + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" - + "if (results && results.length > 0) {" - var regex = ""; - - var special = false; - var ch = ''; - for (var i = 0; i < format.length; ++i) { - ch = format.charAt(i); - if (!special && ch == "\\") { - special = true; - } - else if (special) { - special = false; - regex += String.escape(ch); - } - else { - obj = Date.formatCodeToRegex(ch, currentGroup); - currentGroup += obj.g; - regex += obj.s; - if (obj.g && obj.c) { - code += obj.c; - } - } - } - - code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" - + "{return new Date(y, m, d, h, i, s);}\n" - + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" - + "{return new Date(y, m, d, h, i);}\n" - + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" - + "{return new Date(y, m, d, h);}\n" - + "else if (y > 0 && m >= 0 && d > 0)\n" - + "{return new Date(y, m, d);}\n" - + "else if (y > 0 && m >= 0)\n" - + "{return new Date(y, m);}\n" - + "else if (y > 0)\n" - + "{return new Date(y);}\n" - + "}return null;}"; - - Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); - eval(code); -} - -Date.formatCodeToRegex = function(character, currentGroup) { - switch (character) { - case "D": - return {g:0, - c:null, - s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; - case "j": - case "d": - return {g:1, - c:"d = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{1,2})"}; - case "l": - return {g:0, - c:null, - s:"(?:" + Date.dayNames.join("|") + ")"}; - case "S": - return {g:0, - c:null, - s:"(?:st|nd|rd|th)"}; - case "w": - return {g:0, - c:null, - s:"\\d"}; - case "z": - return {g:0, - c:null, - s:"(?:\\d{1,3})"}; - case "W": - return {g:0, - c:null, - s:"(?:\\d{2})"}; - case "F": - return {g:1, - c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", - s:"(" + Date.monthNames.join("|") + ")"}; - case "M": - return {g:1, - c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", - s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; - case "n": - case "m": - return {g:1, - c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", - s:"(\\d{1,2})"}; - case "t": - return {g:0, - c:null, - s:"\\d{1,2}"}; - case "L": - return {g:0, - c:null, - s:"(?:1|0)"}; - case "Y": - return {g:1, - c:"y = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{4})"}; - case "y": - return {g:1, - c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" - + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", - s:"(\\d{1,2})"}; - case "a": - return {g:1, - c:"if (results[" + currentGroup + "] == 'am') {\n" - + "if (h == 12) { h = 0; }\n" - + "} else { if (h < 12) { h += 12; }}", - s:"(am|pm)"}; - case "A": - return {g:1, - c:"if (results[" + currentGroup + "] == 'AM') {\n" - + "if (h == 12) { h = 0; }\n" - + "} else { if (h < 12) { h += 12; }}", - s:"(AM|PM)"}; - case "g": - case "G": - case "h": - case "H": - return {g:1, - c:"h = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{1,2})"}; - case "i": - return {g:1, - c:"i = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{2})"}; - case "s": - return {g:1, - c:"s = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{2})"}; - case "O": - return {g:0, - c:null, - s:"[+-]\\d{4}"}; - case "T": - return {g:0, - c:null, - s:"[A-Z]{3}"}; - case "Z": - return {g:0, - c:null, - s:"[+-]\\d{1,5}"}; - default: - return {g:0, - c:null, - s:String.escape(character)}; - } -} - -Date.prototype.getTimezone = function() { - return this.toString().replace( - /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( - /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); -} - -Date.prototype.getGMTOffset = function() { - return (this.getTimezoneOffset() > 0 ? "-" : "+") - + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") - + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); -} - -Date.prototype.getDayOfYear = function() { - var num = 0; - Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; - for (var i = 0; i < this.getMonth(); ++i) { - num += Date.daysInMonth[i]; - } - return num + this.getDate() - 1; -} - -Date.prototype.getWeekOfYear = function() { - // Skip to Thursday of this week - var now = this.getDayOfYear() + (4 - this.getDay()); - // Find the first Thursday of the year - var jan1 = new Date(this.getFullYear(), 0, 1); - var then = (7 - jan1.getDay() + 4); - document.write(then); - return String.leftPad(((now - then) / 7) + 1, 2, "0"); -} - -Date.prototype.isLeapYear = function() { - var year = this.getFullYear(); - return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); -} - -Date.prototype.getFirstDayOfMonth = function() { - var day = (this.getDay() - (this.getDate() - 1)) % 7; - return (day < 0) ? (day + 7) : day; -} - -Date.prototype.getLastDayOfMonth = function() { - var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; - return (day < 0) ? (day + 7) : day; -} - -Date.prototype.getDaysInMonth = function() { - Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; - return Date.daysInMonth[this.getMonth()]; -} - -Date.prototype.getSuffix = function() { - switch (this.getDate()) { - case 1: - case 21: - case 31: - return "st"; - case 2: - case 22: - return "nd"; - case 3: - case 23: - return "rd"; - default: - return "th"; - } -} - -String.escape = function(string) { - return string.replace(/('|\\)/g, "\\$1"); -} - -String.leftPad = function (val, size, ch) { - var result = new String(val); - if (ch == null) { - ch = " "; - } - while (result.length < size) { - result = ch + result; - } - return result; -} - -Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; -Date.monthNames = - ["January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December"]; -Date.dayNames = - ["Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday"]; -Date.y2kYear = 50; -Date.monthNumbers = { - Jan:0, - Feb:1, - Mar:2, - Apr:3, - May:4, - Jun:5, - Jul:6, - Aug:7, - Sep:8, - Oct:9, - Nov:10, - Dec:11}; -Date.patterns = { - ISO8601LongPattern:"Y-m-d H:i:s", - ISO8601ShortPattern:"Y-m-d", - ShortDatePattern: "n/j/Y", - LongDatePattern: "l, F d, Y", - FullDateTimePattern: "l, F d, Y g:i:s A", - MonthDayPattern: "F d", - ShortTimePattern: "g:i A", - LongTimePattern: "g:i:s A", - SortableDateTimePattern: "Y-m-d\\TH:i:s", - UniversalSortableDateTimePattern: "Y-m-d H:i:sO", - YearMonthPattern: "F, Y"}; - -var date = new Date("1/1/2007 1:11:11"); - -var ret; -for (i = 0; i < 4000; ++i) { - var shortFormat = date.dateFormat("Y-m-d"); - var longFormat = date.dateFormat("l, F d, Y g:i:s A"); - ret = shortFormat + longFormat; - date.setTime(date.getTime() + 84266956); -} - -// No exact match because the output depends on the locale's time zone. See bug 524490. -assertEq(/^2017-09-05Tuesday, September 05, 2017 [0-9:]* AM$/.exec(ret) != null, true); diff --git a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js deleted file mode 100644 index a9082702ccf..00000000000 --- a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js +++ /dev/null @@ -1,41 +0,0 @@ -// The Computer Language Shootout -// http://shootout.alioth.debian.org/ -// contributed by Isaac Gouy - -function partial(n){ - var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; - var twothirds = 2.0/3.0; - var alt = -1.0; - var k2 = k3 = sk = ck = 0.0; - - for (var k = 1; k <= n; k++){ - k2 = k*k; - k3 = k2*k; - sk = Math.sin(k); - ck = Math.cos(k); - alt = -alt; - - a1 += Math.pow(twothirds,k-1); - a2 += Math.pow(k,-0.5); - a3 += 1.0/(k*(k+1.0)); - a4 += 1.0/(k3 * sk*sk); - a5 += 1.0/(k3 * ck*ck); - a6 += 1.0/k; - a7 += 1.0/k2; - a8 += alt/k; - a9 += alt/(2*k -1); - } - - return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ]; -} - -var actual = []; -for (var i = 1024; i <= 16384; i *= 2) - Array.prototype.push.apply(actual, partial(i)); - -var eps = 1e-12; -var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998]; - -assertEq(actual.length, expect.length); -for (var i = 0; i < expect.length; ++i) - assertEq(Math.abs(actual[i] - expect[i]) < eps, true); diff --git a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js deleted file mode 100644 index f446e46ed5c..00000000000 --- a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js +++ /dev/null @@ -1,270 +0,0 @@ - -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Portions from: - json.js - 2007-10-10 - - Public Domain -*/ - -// This test parses a JSON string giving tag names and popularity, and -// generates html markup for a "tagcloud" view. - -if (!Object.prototype.toJSONString) { - - Array.prototype.toJSONString = function (w) { - var a = [], // The array holding the partial texts. - i, // Loop counter. - l = this.length, - v; // The value to be stringified. - - for (i = 0; i < l; i += 1) { - v = this[i]; - switch (typeof v) { - case 'object': - - if (v && typeof v.toJSONString === 'function') { - a.push(v.toJSONString(w)); - } else { - a.push('null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(v.toJSONString()); - break; - default: - a.push('null'); - } - } - - return '[' + a.join(',') + ']'; - }; - - - Boolean.prototype.toJSONString = function () { - return String(this); - }; - - - Date.prototype.toJSONString = function () { - - function f(n) { - - return n < 10 ? '0' + n : n; - } - - return '"' + this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z"'; - }; - - - Number.prototype.toJSONString = function () { - - return isFinite(this) ? String(this) : 'null'; - }; - - - Object.prototype.toJSONString = function (w) { - var a = [], // The array holding the partial texts. - k, // The current key. - i, // The loop counter. - v; // The current value. - - if (w) { - for (i = 0; i < w.length; i += 1) { - k = w[i]; - if (typeof k === 'string') { - v = this[k]; - switch (typeof v) { - case 'object': - - if (v) { - if (typeof v.toJSONString === 'function') { - a.push(k.toJSONString() + ':' + - v.toJSONString(w)); - } - } else { - a.push(k.toJSONString() + ':null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(k.toJSONString() + ':' + v.toJSONString()); - - } - } - } - } else { - - for (k in this) { - if (typeof k === 'string' && - Object.prototype.hasOwnProperty.apply(this, [k])) { - v = this[k]; - switch (typeof v) { - case 'object': - - if (v) { - if (typeof v.toJSONString === 'function') { - a.push(k.toJSONString() + ':' + - v.toJSONString()); - } - } else { - a.push(k.toJSONString() + ':null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(k.toJSONString() + ':' + v.toJSONString()); - - } - } - } - } - - return '{' + a.join(',') + '}'; - }; - - - (function (s) { - - var m = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }; - - - s.parseJSON = function (filter) { - var j; - - function walk(k, v) { - var i, n; - if (v && typeof v === 'object') { - for (i in v) { - if (Object.prototype.hasOwnProperty.apply(v, [i])) { - n = walk(i, v[i]); - if (n !== undefined) { - v[i] = n; - } - } - } - } - return filter(k, v); - } - - if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@'). - replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). - replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - - j = eval('(' + this + ')'); - - return typeof filter === 'function' ? walk('', j) : j; - } - - throw new SyntaxError('parseJSON'); - }; - - - s.toJSONString = function () { - - if (/["\\\x00-\x1f]/.test(this)) { - return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) { - var c = m[a]; - if (c) { - return c; - } - c = a.charCodeAt(); - return '\\u00' + Math.floor(c / 16).toString(16) + - (c % 16).toString(16); - }) + '"'; - } - return '"' + this + '"'; - }; - })(String.prototype); -} - -var tagInfoJSON = '[\n {\n \"tag\": "titillation",\n \"popularity\": 4294967296\n },\n {\n \"tag\": "foamless",\n \"popularity\": 1257718401\n },\n {\n \"tag\": "snarler",\n \"popularity\": 613166183\n },\n {\n \"tag\": "multangularness",\n \"popularity\": 368304452\n },\n {\n \"tag\": "Fesapo unventurous",\n \"popularity\": 248026512\n },\n {\n \"tag\": "esthesioblast",\n \"popularity\": 179556755\n },\n {\n \"tag\": "echeneidoid",\n \"popularity\": 136641578\n },\n {\n \"tag\": "embryoctony",\n \"popularity\": 107852576\n },\n {\n \"tag\": "undilatory",\n \"popularity\": 87537981\n },\n {\n \"tag\": "predisregard",\n \"popularity\": 72630939\n },\n {\n \"tag\": "allergenic",\n \"popularity\": 61345190\n },\n {\n \"tag\": "uncloudy",\n \"popularity\": 52580571\n },\n {\n \"tag\": "unforeseeably",\n \"popularity\": 45628109\n },\n {\n \"tag\": "sturniform",\n \"popularity\": 40013489\n },\n {\n \"tag\": "anesthetize",\n \"popularity\": 35409226\n },\n {\n \"tag\": "ametabolia",\n \"popularity\": 31583050\n },\n {\n \"tag\": "angiopathy",\n \"popularity\": 28366350\n },\n {\n \"tag\": "sultanaship",\n \"popularity\": 25634218\n },\n {\n \"tag\": "Frenchwise",\n \"popularity\": 23292461\n },\n {\n \"tag\": "cerviconasal",\n \"popularity\": 21268909\n },\n {\n \"tag\": "mercurialness",\n \"popularity\": 19507481\n },\n {\n \"tag\": "glutelin venditate",\n \"popularity\": 17964042\n },\n {\n \"tag\": "acred overblack",\n \"popularity\": 16603454\n },\n {\n \"tag\": "Atik",\n \"popularity\": 15397451\n },\n {\n \"tag\": "puncturer",\n \"popularity\": 14323077\n },\n {\n \"tag\": "pukatea",\n \"popularity\": 13361525\n },\n {\n \"tag\": "suberize",\n \"popularity\": 12497261\n },\n {\n \"tag\": "Godfrey",\n \"popularity\": 11717365\n },\n {\n \"tag\": "tetraptote",\n \"popularity\": 11011011\n },\n {\n \"tag\": "lucidness",\n \"popularity\": 10369074\n },\n {\n \"tag\": "tartness",\n \"popularity\": 9783815\n },\n {\n \"tag\": "axfetch",\n \"popularity\": 9248634\n },\n {\n \"tag\": "preacquittal",\n \"popularity\": 8757877\n },\n {\n \"tag\": "matris",\n \"popularity\": 8306671\n },\n {\n \"tag\": "hyphenate",\n \"popularity\": 7890801\n },\n {\n \"tag\": "semifabulous",\n \"popularity\": 7506606\n },\n {\n \"tag\": "oppressiveness",\n \"popularity\": 7150890\n },\n {\n \"tag\": "Protococcales",\n \"popularity\": 6820856\n },\n {\n \"tag\": "unpreventive",\n \"popularity\": 6514045\n },\n {\n \"tag\": "Cordia",\n \"popularity\": 6228289\n },\n {\n \"tag\": "Wakamba leaflike",\n \"popularity\": 5961668\n },\n {\n \"tag\": "dacryoma",\n \"popularity\": 5712480\n },\n {\n \"tag\": "inguinal",\n \"popularity\": 5479211\n },\n {\n \"tag\": "responseless",\n \"popularity\": 5260507\n },\n {\n \"tag\": "supplementarily",\n \"popularity\": 5055158\n },\n {\n \"tag\": "emu",\n \"popularity\": 4862079\n },\n {\n \"tag\": "countermeet",\n \"popularity\": 4680292\n },\n {\n \"tag\": "purrer",\n \"popularity\": 4508918\n },\n {\n \"tag\": "Corallinaceae",\n \"popularity\": 4347162\n },\n {\n \"tag\": "speculum",\n \"popularity\": 4194304\n },\n {\n \"tag\": "crimpness",\n \"popularity\": 4049690\n },\n {\n \"tag\": "antidetonant",\n \"popularity\": 3912727\n },\n {\n \"tag\": "topeewallah",\n \"popularity\": 3782875\n },\n {\n \"tag\": "fidalgo ballant",\n \"popularity\": 3659640\n },\n {\n \"tag\": "utriculose",\n \"popularity\": 3542572\n },\n {\n \"tag\": "testata",\n \"popularity\": 3431259\n },\n {\n \"tag\": "beltmaking",\n \"popularity\": 3325322\n },\n {\n \"tag\": "necrotype",\n \"popularity\": 3224413\n },\n {\n \"tag\": "ovistic",\n \"popularity\": 3128215\n },\n {\n \"tag\": "swindlership",\n \"popularity\": 3036431\n },\n {\n \"tag\": "augustal",\n \"popularity\": 2948792\n },\n {\n \"tag\": "Titoist",\n \"popularity\": 2865047\n },\n {\n \"tag\": "trisoctahedral",\n \"popularity\": 2784963\n },\n {\n \"tag\": "sequestrator",\n \"popularity\": 2708327\n },\n {\n \"tag\": "sideburns",\n \"popularity\": 2634939\n },\n {\n \"tag\": "paraphrasia",\n \"popularity\": 2564616\n },\n {\n \"tag\": "graminology unbay",\n \"popularity\": 2497185\n },\n {\n \"tag\": "acaridomatium emargination",\n \"popularity\": 2432487\n },\n {\n \"tag\": "roofward",\n \"popularity\": 2370373\n },\n {\n \"tag\": "lauder",\n \"popularity\": 2310705\n },\n {\n \"tag\": "subjunctive",\n \"popularity\": 2253354\n },\n {\n \"tag\": "subelongate",\n \"popularity\": 2198199\n },\n {\n \"tag\": "guacimo",\n \"popularity\": 2145128\n },\n {\n \"tag\": "cockade",\n \"popularity\": 2094033\n },\n {\n \"tag\": "misgauge",\n \"popularity\": 2044818\n },\n {\n \"tag\": "unexpensive",\n \"popularity\": 1997388\n },\n {\n \"tag\": "chebel",\n \"popularity\": 1951657\n },\n {\n \"tag\": "unpursuing",\n \"popularity\": 1907543\n },\n {\n \"tag\": "kilobar",\n \"popularity\": 1864969\n },\n {\n \"tag\": "obsecration",\n \"popularity\": 1823863\n },\n {\n \"tag\": "nacarine",\n \"popularity\": 1784157\n },\n {\n \"tag\": "spirituosity",\n \"popularity\": 1745787\n },\n {\n \"tag\": "movableness deity",\n \"popularity\": 1708692\n },\n {\n \"tag\": "exostracism",\n \"popularity\": 1672816\n },\n {\n \"tag\": "archipterygium",\n \"popularity\": 1638104\n },\n {\n \"tag\": "monostrophic",\n \"popularity\": 1604506\n },\n {\n \"tag\": "gynecide",\n \"popularity\": 1571974\n },\n {\n \"tag\": "gladden",\n \"popularity\": 1540462\n },\n {\n \"tag\": "throughbred",\n \"popularity\": 1509927\n },\n {\n \"tag\": "groper",\n \"popularity\": 1480329\n },\n {\n \"tag\": "Xenosaurus",\n \"popularity\": 1451628\n },\n {\n \"tag\": "photoetcher",\n \"popularity\": 1423788\n },\n {\n \"tag\": "glucosid",\n \"popularity\": 1396775\n },\n {\n \"tag\": "Galtonian",\n \"popularity\": 1370555\n },\n {\n \"tag\": "mesosporic",\n \"popularity\": 1345097\n },\n {\n \"tag\": "theody",\n \"popularity\": 1320370\n },\n {\n \"tag\": "zaffer",\n \"popularity\": 1296348\n },\n {\n \"tag\": "probiology",\n \"popularity\": 1273003\n },\n {\n \"tag\": "rhizomic",\n \"popularity\": 1250308\n },\n {\n \"tag\": "superphosphate",\n \"popularity\": 1228240\n },\n {\n \"tag\": "Hippolytan",\n \"popularity\": 1206776\n },\n {\n \"tag\": "garget",\n \"popularity\": 1185892\n },\n {\n \"tag\": "diploplacula",\n \"popularity\": 1165568\n },\n {\n \"tag\": "orohydrographical",\n \"popularity\": 1145785\n },\n {\n \"tag\": "enhypostatize",\n \"popularity\": 1126521\n },\n {\n \"tag\": "polisman",\n \"popularity\": 1107759\n },\n {\n \"tag\": "acetometer",\n \"popularity\": 1089482\n },\n {\n \"tag\": "unsnatched",\n \"popularity\": 1071672\n },\n {\n \"tag\": "yabber",\n \"popularity\": 1054313\n },\n {\n \"tag\": "demiwolf",\n \"popularity\": 1037390\n },\n {\n \"tag\": "chromascope",\n \"popularity\": 1020888\n },\n {\n \"tag\": "seamanship",\n \"popularity\": 1004794\n },\n {\n \"tag\": "nonfenestrated",\n \"popularity\": 989092\n },\n {\n \"tag\": "hydrophytism",\n \"popularity\": 973771\n },\n {\n \"tag\": "dotter",\n \"popularity\": 958819\n },\n {\n \"tag\": "thermoperiodism",\n \"popularity\": 944222\n },\n {\n \"tag\": "unlawyerlike",\n \"popularity\": 929970\n },\n {\n \"tag\": "enantiomeride citywards",\n \"popularity\": 916052\n },\n {\n \"tag\": "unmetallurgical",\n \"popularity\": 902456\n },\n {\n \"tag\": "prickled",\n \"popularity\": 889174\n },\n {\n \"tag\": "strangerwise manioc",\n \"popularity\": 876195\n },\n {\n \"tag\": "incisorial",\n \"popularity\": 863510\n },\n {\n \"tag\": "irrationalize",\n \"popularity\": 851110\n },\n {\n \"tag\": "nasology",\n \"popularity\": 838987\n },\n {\n \"tag\": "fatuism",\n \"popularity\": 827131\n },\n {\n \"tag\": "Huk",\n \"popularity\": 815535\n },\n {\n \"tag\": "properispomenon",\n \"popularity\": 804192\n },\n {\n \"tag\": "unpummelled",\n \"popularity\": 793094\n },\n {\n \"tag\": "technographically",\n \"popularity\": 782233\n },\n {\n \"tag\": "underfurnish",\n \"popularity\": 771603\n },\n {\n \"tag\": "sinter",\n \"popularity\": 761198\n },\n {\n \"tag\": "lateroanterior",\n \"popularity\": 751010\n },\n {\n \"tag\": "nonpersonification",\n \"popularity\": 741034\n },\n {\n \"tag\": "Sitophilus",\n \"popularity\": 731264\n },\n {\n \"tag\": "unstudded overexerted",\n \"popularity\": 721694\n },\n {\n \"tag\": "tracheation",\n \"popularity\": 712318\n },\n {\n \"tag\": "thirteenth begloze",\n \"popularity\": 703131\n },\n {\n \"tag\": "bespice",\n \"popularity\": 694129\n },\n {\n \"tag\": "doppia",\n \"popularity\": 685305\n },\n {\n \"tag\": "unadorned",\n \"popularity\": 676656\n },\n {\n \"tag\": "dovelet engraff",\n \"popularity\": 668176\n },\n {\n \"tag\": "diphyozooid",\n \"popularity\": 659862\n },\n {\n \"tag\": "mure",\n \"popularity\": 651708\n },\n {\n \"tag\": "Tripitaka",\n \"popularity\": 643710\n },\n {\n \"tag\": "Billjim",\n \"popularity\": 635865\n },\n {\n \"tag\": "pyramidical",\n \"popularity\": 628169\n },\n {\n \"tag\": "circumlocutionist",\n \"popularity\": 620617\n },\n {\n \"tag\": "slapstick",\n \"popularity\": 613207\n },\n {\n \"tag\": "preobedience",\n \"popularity\": 605934\n },\n {\n \"tag\": "unfriarlike",\n \"popularity\": 598795\n },\n {\n \"tag\": "microchromosome",\n \"popularity\": 591786\n },\n {\n \"tag\": "Orphicism",\n \"popularity\": 584905\n },\n {\n \"tag\": "peel",\n \"popularity\": 578149\n },\n {\n \"tag\": "obediential",\n \"popularity\": 571514\n },\n {\n \"tag\": "Peripatidea",\n \"popularity\": 564997\n },\n {\n \"tag\": "undoubtful",\n \"popularity\": 558596\n },\n {\n \"tag\": "lodgeable",\n \"popularity\": 552307\n },\n {\n \"tag\": "pustulated woodchat",\n \"popularity\": 546129\n },\n {\n \"tag\": "antepast",\n \"popularity\": 540057\n },\n {\n \"tag\": "sagittoid matrimoniously",\n \"popularity\": 534091\n },\n {\n \"tag\": "Albizzia",\n \"popularity\": 528228\n },\n {\n \"tag\": "Elateridae unnewness",\n \"popularity\": 522464\n },\n {\n \"tag\": "convertingness",\n \"popularity\": 516798\n },\n {\n \"tag\": "Pelew",\n \"popularity\": 511228\n },\n {\n \"tag\": "recapitulation",\n \"popularity\": 505751\n },\n {\n \"tag\": "shack",\n \"popularity\": 500365\n },\n {\n \"tag\": "unmellowed",\n \"popularity\": 495069\n },\n {\n \"tag\": "pavis capering",\n \"popularity\": 489859\n },\n {\n \"tag\": "fanfare",\n \"popularity\": 484735\n },\n {\n \"tag\": "sole",\n \"popularity\": 479695\n },\n {\n \"tag\": "subarcuate",\n \"popularity\": 474735\n },\n {\n \"tag\": "multivious",\n \"popularity\": 469856\n },\n {\n \"tag\": "squandermania",\n \"popularity\": 465054\n },\n {\n \"tag\": "scintle",\n \"popularity\": 460329\n },\n {\n \"tag\": "hash chirognomic",\n \"popularity\": 455679\n },\n {\n \"tag\": "linseed",\n \"popularity\": 451101\n },\n {\n \"tag\": "redoubtable",\n \"popularity\": 446596\n },\n {\n \"tag\": "poachy reimpact",\n \"popularity\": 442160\n },\n {\n \"tag\": "limestone",\n \"popularity\": 437792\n },\n {\n \"tag\": "serranid",\n \"popularity\": 433492\n },\n {\n \"tag\": "pohna",\n \"popularity\": 429258\n },\n {\n \"tag\": "warwolf",\n \"popularity\": 425088\n },\n {\n \"tag\": "ruthenous",\n \"popularity\": 420981\n },\n {\n \"tag\": "dover",\n \"popularity\": 416935\n },\n {\n \"tag\": "deuteroalbumose",\n \"popularity\": 412950\n },\n {\n \"tag\": "pseudoprophetic",\n \"popularity\": 409025\n },\n {\n \"tag\": "dissoluteness",\n \"popularity\": 405157\n },\n {\n \"tag\": "preinvention",\n \"popularity\": 401347\n },\n {\n \"tag\": "swagbellied",\n \"popularity\": 397592\n },\n {\n \"tag\": "Ophidia",\n \"popularity\": 393892\n },\n {\n \"tag\": "equanimity",\n \"popularity\": 390245\n },\n {\n \"tag\": "troutful",\n \"popularity\": 386651\n },\n {\n \"tag\": "uke",\n \"popularity\": 383108\n },\n {\n \"tag\": "preacquaint",\n \"popularity\": 379616\n },\n {\n \"tag\": "shoq",\n \"popularity\": 376174\n },\n {\n \"tag\": "yox",\n \"popularity\": 372780\n },\n {\n \"tag\": "unelemental",\n \"popularity\": 369434\n },\n {\n \"tag\": "Yavapai",\n \"popularity\": 366134\n },\n {\n \"tag\": "joulean",\n \"popularity\": 362880\n },\n {\n \"tag\": "dracontine",\n \"popularity\": 359672\n },\n {\n \"tag\": "hardmouth",\n \"popularity\": 356507\n },\n {\n \"tag\": "sylvanize",\n \"popularity\": 353386\n },\n {\n \"tag\": "intraparenchymatous meadowbur",\n \"popularity\": 350308\n },\n {\n \"tag\": "uncharily",\n \"popularity\": 347271\n },\n {\n \"tag\": "redtab flexibly",\n \"popularity\": 344275\n },\n {\n \"tag\": "centervelic",\n \"popularity\": 341319\n },\n {\n \"tag\": "unravellable",\n \"popularity\": 338403\n },\n {\n \"tag\": "infortunately",\n \"popularity\": 335526\n },\n {\n \"tag\": "cannel",\n \"popularity\": 332687\n },\n {\n \"tag\": "oxyblepsia",\n \"popularity\": 329885\n },\n {\n \"tag\": "Damon",\n \"popularity\": 327120\n },\n {\n \"tag\": "etherin",\n \"popularity\": 324391\n },\n {\n \"tag\": "luminal",\n \"popularity\": 321697\n },\n {\n \"tag\": "interrogatorily presbyte",\n \"popularity\": 319038\n },\n {\n \"tag\": "hemiclastic",\n \"popularity\": 316414\n },\n {\n \"tag\": "poh flush",\n \"popularity\": 313823\n },\n {\n \"tag\": "Psoroptes",\n \"popularity\": 311265\n },\n {\n \"tag\": "dispirit",\n \"popularity\": 308740\n },\n {\n \"tag\": "nashgab",\n \"popularity\": 306246\n },\n {\n \"tag\": "Aphidiinae",\n \"popularity\": 303784\n },\n {\n \"tag\": "rhapsody nonconstruction",\n \"popularity\": 301353\n },\n {\n \"tag\": "Osmond",\n \"popularity\": 298952\n },\n {\n \"tag\": "Leonis",\n \"popularity\": 296581\n },\n {\n \"tag\": "Lemnian",\n \"popularity\": 294239\n },\n {\n \"tag\": "acetonic gnathonic",\n \"popularity\": 291926\n },\n {\n \"tag\": "surculus",\n \"popularity\": 289641\n },\n {\n \"tag\": "diagonally",\n \"popularity\": 287384\n },\n {\n \"tag\": "counterpenalty",\n \"popularity\": 285154\n },\n {\n \"tag\": "Eugenie",\n \"popularity\": 282952\n },\n {\n \"tag\": "hornbook",\n \"popularity\": 280776\n },\n {\n \"tag\": "miscoin",\n \"popularity\": 278626\n },\n {\n \"tag\": "admi",\n \"popularity\": 276501\n },\n {\n \"tag\": "Tarmac",\n \"popularity\": 274402\n },\n {\n \"tag\": "inexplicable",\n \"popularity\": 272328\n },\n {\n \"tag\": "rascallion",\n \"popularity\": 270278\n },\n {\n \"tag\": "dusterman",\n \"popularity\": 268252\n },\n {\n \"tag\": "osteostomous unhoroscopic",\n \"popularity\": 266250\n },\n {\n \"tag\": "spinibulbar",\n \"popularity\": 264271\n },\n {\n \"tag\": "phototelegraphically",\n \"popularity\": 262315\n },\n {\n \"tag\": "Manihot",\n \"popularity\": 260381\n },\n {\n \"tag\": "neighborhood",\n \"popularity\": 258470\n },\n {\n \"tag\": "Vincetoxicum",\n \"popularity\": 256581\n },\n {\n \"tag\": "khirka",\n \"popularity\": 254713\n },\n {\n \"tag\": "conscriptive",\n \"popularity\": 252866\n },\n {\n \"tag\": "synechthran",\n \"popularity\": 251040\n },\n {\n \"tag\": "Guttiferales",\n \"popularity\": 249235\n },\n {\n \"tag\": "roomful",\n \"popularity\": 247450\n },\n {\n \"tag\": "germinal",\n \"popularity\": 245685\n },\n {\n \"tag\": "untraitorous",\n \"popularity\": 243939\n },\n {\n \"tag\": "nondissenting",\n \"popularity\": 242213\n },\n {\n \"tag\": "amotion",\n \"popularity\": 240506\n },\n {\n \"tag\": "badious",\n \"popularity\": 238817\n },\n {\n \"tag\": "sumpit",\n \"popularity\": 237147\n },\n {\n \"tag\": "ectozoic",\n \"popularity\": 235496\n },\n {\n \"tag\": "elvet",\n \"popularity\": 233862\n },\n {\n \"tag\": "underclerk",\n \"popularity\": 232246\n },\n {\n \"tag\": "reticency",\n \"popularity\": 230647\n },\n {\n \"tag\": "neutroclusion",\n \"popularity\": 229065\n },\n {\n \"tag\": "unbelieving",\n \"popularity\": 227500\n },\n {\n \"tag\": "histogenetic",\n \"popularity\": 225952\n },\n {\n \"tag\": "dermamyiasis",\n \"popularity\": 224421\n },\n {\n \"tag\": "telenergy",\n \"popularity\": 222905\n },\n {\n \"tag\": "axiomatic",\n \"popularity\": 221406\n },\n {\n \"tag\": "undominoed",\n \"popularity\": 219922\n },\n {\n \"tag\": "periosteoma",\n \"popularity\": 218454\n },\n {\n \"tag\": "justiciaryship",\n \"popularity\": 217001\n },\n {\n \"tag\": "autoluminescence",\n \"popularity\": 215563\n },\n {\n \"tag\": "osmous",\n \"popularity\": 214140\n },\n {\n \"tag\": "borgh",\n \"popularity\": 212731\n },\n {\n \"tag\": "bedebt",\n \"popularity\": 211337\n },\n {\n \"tag\": "considerableness adenoidism",\n \"popularity\": 209957\n },\n {\n \"tag\": "sailorizing",\n \"popularity\": 208592\n },\n {\n \"tag\": "Montauk",\n \"popularity\": 207240\n },\n {\n \"tag\": "Bridget",\n \"popularity\": 205901\n },\n {\n \"tag\": "Gekkota",\n \"popularity\": 204577\n },\n {\n \"tag\": "subcorymbose",\n \"popularity\": 203265\n },\n {\n \"tag\": "undersap",\n \"popularity\": 201967\n },\n {\n \"tag\": "poikilothermic",\n \"popularity\": 200681\n },\n {\n \"tag\": "enneatical",\n \"popularity\": 199409\n },\n {\n \"tag\": "martinetism",\n \"popularity\": 198148\n },\n {\n \"tag\": "sustanedly",\n \"popularity\": 196901\n },\n {\n \"tag\": "declaration",\n \"popularity\": 195665\n },\n {\n \"tag\": "myringoplasty",\n \"popularity\": 194442\n },\n {\n \"tag\": "Ginkgo",\n \"popularity\": 193230\n },\n {\n \"tag\": "unrecurrent",\n \"popularity\": 192031\n },\n {\n \"tag\": "proprecedent",\n \"popularity\": 190843\n },\n {\n \"tag\": "roadman",\n \"popularity\": 189666\n },\n {\n \"tag\": "elemin",\n \"popularity\": 188501\n },\n {\n \"tag\": "maggot",\n \"popularity\": 187347\n },\n {\n \"tag\": "alitrunk",\n \"popularity\": 186204\n },\n {\n \"tag\": "introspection",\n \"popularity\": 185071\n },\n {\n \"tag\": "batiker",\n \"popularity\": 183950\n },\n {\n \"tag\": "backhatch oversettle",\n \"popularity\": 182839\n },\n {\n \"tag\": "thresherman",\n \"popularity\": 181738\n },\n {\n \"tag\": "protemperance",\n \"popularity\": 180648\n },\n {\n \"tag\": "undern",\n \"popularity\": 179568\n },\n {\n \"tag\": "tweeg",\n \"popularity\": 178498\n },\n {\n \"tag\": "crosspath",\n \"popularity\": 177438\n },\n {\n \"tag\": "Tangaridae",\n \"popularity\": 176388\n },\n {\n \"tag\": "scrutation",\n \"popularity\": 175348\n },\n {\n \"tag\": "piecemaker",\n \"popularity\": 174317\n },\n {\n \"tag\": "paster",\n \"popularity\": 173296\n },\n {\n \"tag\": "unpretendingness",\n \"popularity\": 172284\n },\n {\n \"tag\": "inframundane",\n \"popularity\": 171281\n },\n {\n \"tag\": "kiblah",\n \"popularity\": 170287\n },\n {\n \"tag\": "playwrighting",\n \"popularity\": 169302\n },\n {\n \"tag\": "gonepoiesis snowslip",\n \"popularity\": 168326\n },\n {\n \"tag\": "hoodwise",\n \"popularity\": 167359\n },\n {\n \"tag\": "postseason",\n \"popularity\": 166401\n },\n {\n \"tag\": "equivocality",\n \"popularity\": 165451\n },\n {\n \"tag\": "Opiliaceae nuclease",\n \"popularity\": 164509\n },\n {\n \"tag\": "sextipara",\n \"popularity\": 163576\n },\n {\n \"tag\": "weeper",\n \"popularity\": 162651\n },\n {\n \"tag\": "frambesia",\n \"popularity\": 161735\n },\n {\n \"tag\": "answerable",\n \"popularity\": 160826\n },\n {\n \"tag\": "Trichosporum",\n \"popularity\": 159925\n },\n {\n \"tag\": "cajuputol",\n \"popularity\": 159033\n },\n {\n \"tag\": "pleomorphous",\n \"popularity\": 158148\n },\n {\n \"tag\": "aculeolate",\n \"popularity\": 157270\n },\n {\n \"tag\": "wherever",\n \"popularity\": 156400\n },\n {\n \"tag\": "collapse",\n \"popularity\": 155538\n },\n {\n \"tag\": "porky",\n \"popularity\": 154683\n },\n {\n \"tag\": "perule",\n \"popularity\": 153836\n },\n {\n \"tag\": "Nevada",\n \"popularity\": 152996\n },\n {\n \"tag\": "conalbumin",\n \"popularity\": 152162\n },\n {\n \"tag\": "tsunami",\n \"popularity\": 151336\n },\n {\n \"tag\": "Gulf",\n \"popularity\": 150517\n },\n {\n \"tag\": "hertz",\n \"popularity\": 149705\n },\n {\n \"tag\": "limmock",\n \"popularity\": 148900\n },\n {\n \"tag\": "Tartarize",\n \"popularity\": 148101\n },\n {\n \"tag\": "entosphenoid",\n \"popularity\": 147310\n },\n {\n \"tag\": "ibis",\n \"popularity\": 146524\n },\n {\n \"tag\": "unyeaned",\n \"popularity\": 145746\n },\n {\n \"tag\": "tritural",\n \"popularity\": 144973\n },\n {\n \"tag\": "hundredary",\n \"popularity\": 144207\n },\n {\n \"tag\": "stolonlike",\n \"popularity\": 143448\n },\n {\n \"tag\": "chorister",\n \"popularity\": 142694\n },\n {\n \"tag\": "mismove",\n \"popularity\": 141947\n },\n {\n \"tag\": "Andine",\n \"popularity\": 141206\n },\n {\n \"tag\": "Annette proneur escribe",\n \"popularity\": 140471\n },\n {\n \"tag\": "exoperidium",\n \"popularity\": 139742\n },\n {\n \"tag\": "disedge",\n \"popularity\": 139019\n },\n {\n \"tag\": "hypochloruria",\n \"popularity\": 138302\n },\n {\n \"tag\": "prepupa",\n \"popularity\": 137590\n },\n {\n \"tag\": "assent",\n \"popularity\": 136884\n },\n {\n \"tag\": "hydrazobenzene",\n \"popularity\": 136184\n },\n {\n \"tag\": "emballonurid",\n \"popularity\": 135489\n },\n {\n \"tag\": "roselle",\n \"popularity\": 134800\n },\n {\n \"tag\": "unifiedly",\n \"popularity\": 134117\n },\n {\n \"tag\": "clang",\n \"popularity\": 133439\n },\n {\n \"tag\": "acetolytic",\n \"popularity\": 132766\n },\n {\n \"tag\": "cladodont",\n \"popularity\": 132098\n },\n {\n \"tag\": "recoast",\n \"popularity\": 131436\n },\n {\n \"tag\": "celebrated tydie Eocarboniferous",\n \"popularity\": 130779\n },\n {\n \"tag\": "superconsciousness",\n \"popularity\": 130127\n },\n {\n \"tag\": "soberness",\n \"popularity\": 129480\n },\n {\n \"tag\": "panoramist",\n \"popularity\": 128838\n },\n {\n \"tag\": "Orbitolina",\n \"popularity\": 128201\n },\n {\n \"tag\": "overlewd",\n \"popularity\": 127569\n },\n {\n \"tag\": "demiquaver",\n \"popularity\": 126942\n },\n {\n \"tag\": "kamelaukion",\n \"popularity\": 126319\n },\n {\n \"tag\": "flancard",\n \"popularity\": 125702\n },\n {\n \"tag\": "tricuspid",\n \"popularity\": 125089\n },\n {\n \"tag\": "bepelt",\n \"popularity\": 124480\n },\n {\n \"tag\": "decuplet",\n \"popularity\": 123877\n },\n {\n \"tag\": "Rockies",\n \"popularity\": 123278\n },\n {\n \"tag\": "unforgeability",\n \"popularity\": 122683\n },\n {\n \"tag\": "mocha",\n \"popularity\": 122093\n },\n {\n \"tag\": "scrunge",\n \"popularity\": 121507\n },\n {\n \"tag\": "delighter",\n \"popularity\": 120926\n },\n {\n \"tag\": "willey Microtinae",\n \"popularity\": 120349\n },\n {\n \"tag\": "unhuntable",\n \"popularity\": 119777\n },\n {\n \"tag\": "historically",\n \"popularity\": 119208\n },\n {\n \"tag\": "vicegerentship",\n \"popularity\": 118644\n },\n {\n \"tag\": "hemangiosarcoma",\n \"popularity\": 118084\n },\n {\n \"tag\": "harpago",\n \"popularity\": 117528\n },\n {\n \"tag\": "unionoid",\n \"popularity\": 116976\n },\n {\n \"tag\": "wiseman",\n \"popularity\": 116429\n },\n {\n \"tag\": "diclinism",\n \"popularity\": 115885\n },\n {\n \"tag\": "Maud",\n \"popularity\": 115345\n },\n {\n \"tag\": "scaphocephalism",\n \"popularity\": 114809\n },\n {\n \"tag\": "obtenebration",\n \"popularity\": 114277\n },\n {\n \"tag\": "cymar predreadnought",\n \"popularity\": 113749\n },\n {\n \"tag\": "discommend",\n \"popularity\": 113225\n },\n {\n \"tag\": "crude",\n \"popularity\": 112704\n },\n {\n \"tag\": "upflash",\n \"popularity\": 112187\n },\n {\n \"tag\": "saltimbank",\n \"popularity\": 111674\n },\n {\n \"tag\": "posthysterical",\n \"popularity\": 111165\n },\n {\n \"tag\": "trample",\n \"popularity\": 110659\n },\n {\n \"tag\": "ungirthed",\n \"popularity\": 110157\n },\n {\n \"tag\": "unshakable",\n \"popularity\": 109658\n },\n {\n \"tag\": "hepatocystic",\n \"popularity\": 109163\n },\n {\n \"tag\": "psammophyte",\n \"popularity\": 108671\n },\n {\n \"tag\": "millionfold",\n \"popularity\": 108183\n },\n {\n \"tag\": "outtaste",\n \"popularity\": 107698\n },\n {\n \"tag\": "poppycockish",\n \"popularity\": 107217\n },\n {\n \"tag\": "viduine",\n \"popularity\": 106739\n },\n {\n \"tag\": "pleasureman",\n \"popularity\": 106264\n },\n {\n \"tag\": "cholesterolemia",\n \"popularity\": 105792\n },\n {\n \"tag\": "hostlerwife",\n \"popularity\": 105324\n },\n {\n \"tag\": "figure undergrass",\n \"popularity\": 104859\n },\n {\n \"tag\": "bedrape",\n \"popularity\": 104398\n },\n {\n \"tag\": "nuttishness",\n \"popularity\": 103939\n },\n {\n \"tag\": "fow",\n \"popularity\": 103484\n },\n {\n \"tag\": "rachianesthesia",\n \"popularity\": 103031\n },\n {\n \"tag\": "recruitable",\n \"popularity\": 102582\n },\n {\n \"tag\": "semianatomical Oenotheraceae",\n \"popularity\": 102136\n },\n {\n \"tag\": "extracapsular",\n \"popularity\": 101693\n },\n {\n \"tag\": "unsigneted",\n \"popularity\": 101253\n },\n {\n \"tag\": "fissural",\n \"popularity\": 100816\n },\n {\n \"tag\": "ayous",\n \"popularity\": 100381\n },\n {\n \"tag\": "crestfallenness odontograph",\n \"popularity\": 99950\n },\n {\n \"tag\": "monopodium",\n \"popularity\": 99522\n },\n {\n \"tag\": "germfree",\n \"popularity\": 99096\n },\n {\n \"tag\": "dauphin",\n \"popularity\": 98673\n },\n {\n \"tag\": "nonagesimal",\n \"popularity\": 98254\n },\n {\n \"tag\": "waterchat",\n \"popularity\": 97836\n },\n {\n \"tag\": "Entelodon",\n \"popularity\": 97422\n },\n {\n \"tag\": "semischolastic",\n \"popularity\": 97010\n },\n {\n \"tag\": "somata",\n \"popularity\": 96602\n },\n {\n \"tag\": "expositorily",\n \"popularity\": 96195\n },\n {\n \"tag\": "bass",\n \"popularity\": 95792\n },\n {\n \"tag\": "calorimetry",\n \"popularity\": 95391\n },\n {\n \"tag\": "entireness",\n \"popularity\": 94993\n },\n {\n \"tag\": "ratline soppiness",\n \"popularity\": 94597\n },\n {\n \"tag\": "shor",\n \"popularity\": 94204\n },\n {\n \"tag\": "coprecipitation",\n \"popularity\": 93813\n },\n {\n \"tag\": "unblushingly",\n \"popularity\": 93425\n },\n {\n \"tag\": "macarize",\n \"popularity\": 93040\n },\n {\n \"tag\": "scruplesomeness",\n \"popularity\": 92657\n },\n {\n \"tag\": "offsaddle",\n \"popularity\": 92276\n },\n {\n \"tag\": "hypertragical",\n \"popularity\": 91898\n },\n {\n \"tag\": "uncassock loined",\n \"popularity\": 91522\n },\n {\n \"tag\": "interlobate",\n \"popularity\": 91149\n },\n {\n \"tag\": "releasor orrisroot stoloniferously",\n \"popularity\": 90778\n },\n {\n \"tag\": "elementoid",\n \"popularity\": 90410\n },\n {\n \"tag\": "Lentilla",\n \"popularity\": 90043\n },\n {\n \"tag\": "distressing",\n \"popularity\": 89679\n },\n {\n \"tag\": "hydrodrome",\n \"popularity\": 89318\n },\n {\n \"tag\": "Jeannette",\n \"popularity\": 88958\n },\n {\n \"tag\": "Kuli",\n \"popularity\": 88601\n },\n {\n \"tag\": "taxinomist",\n \"popularity\": 88246\n },\n {\n \"tag\": "southwestwardly",\n \"popularity\": 87894\n },\n {\n \"tag\": "polyparia",\n \"popularity\": 87543\n },\n {\n \"tag\": "exmeridian",\n \"popularity\": 87195\n },\n {\n \"tag\": "splenius regimentaled",\n \"popularity\": 86849\n },\n {\n \"tag\": "Sphaeropsidaceae",\n \"popularity\": 86505\n },\n {\n \"tag\": "unbegun",\n \"popularity\": 86163\n },\n {\n \"tag\": "something",\n \"popularity\": 85823\n },\n {\n \"tag\": "contaminable nonexpulsion",\n \"popularity\": 85486\n },\n {\n \"tag\": "douser",\n \"popularity\": 85150\n },\n {\n \"tag\": "prostrike",\n \"popularity\": 84817\n },\n {\n \"tag\": "worky",\n \"popularity\": 84485\n },\n {\n \"tag\": "folliful",\n \"popularity\": 84156\n },\n {\n \"tag\": "prioracy",\n \"popularity\": 83828\n },\n {\n \"tag\": "undermentioned",\n \"popularity\": 83503\n },\n {\n \"tag\": "Judaica",\n \"popularity\": 83179\n },\n {\n \"tag\": "multifarious",\n \"popularity\": 82858\n },\n {\n \"tag\": "poogye",\n \"popularity\": 82538\n },\n {\n \"tag\": "Sparganium",\n \"popularity\": 82221\n },\n {\n \"tag\": "thurrock",\n \"popularity\": 81905\n },\n {\n \"tag\": "outblush",\n \"popularity\": 81591\n },\n {\n \"tag\": "Strophanthus supraordination",\n \"popularity\": 81279\n },\n {\n \"tag\": "gingerroot",\n \"popularity\": 80969\n },\n {\n \"tag\": "unconscient",\n \"popularity\": 80661\n },\n {\n \"tag\": "unconstitutionally",\n \"popularity\": 80354\n },\n {\n \"tag\": "plaguily",\n \"popularity\": 80050\n },\n {\n \"tag\": "waterily equatorwards",\n \"popularity\": 79747\n },\n {\n \"tag\": "nondeposition",\n \"popularity\": 79446\n },\n {\n \"tag\": "dronishly",\n \"popularity\": 79147\n },\n {\n \"tag\": "gateado",\n \"popularity\": 78849\n },\n {\n \"tag\": "dislink",\n \"popularity\": 78553\n },\n {\n \"tag\": "Joceline",\n \"popularity\": 78259\n },\n {\n \"tag\": "amphiboliferous",\n \"popularity\": 77967\n },\n {\n \"tag\": "bushrope",\n \"popularity\": 77676\n },\n {\n \"tag\": "plumicorn sulphosalicylic",\n \"popularity\": 77387\n },\n {\n \"tag\": "nonefficiency",\n \"popularity\": 77100\n },\n {\n \"tag\": "hieroscopy",\n \"popularity\": 76815\n },\n {\n \"tag\": "causativeness",\n \"popularity\": 76531\n },\n {\n \"tag\": "swird paleoeremology",\n \"popularity\": 76249\n },\n {\n \"tag\": "camphoric",\n \"popularity\": 75968\n },\n {\n \"tag\": "retaining",\n \"popularity\": 75689\n },\n {\n \"tag\": "thyreoprotein",\n \"popularity\": 75411\n },\n {\n \"tag\": "carbona",\n \"popularity\": 75136\n },\n {\n \"tag\": "protectively",\n \"popularity\": 74861\n },\n {\n \"tag\": "mosasaur",\n \"popularity\": 74589\n },\n {\n \"tag\": "reciprocator",\n \"popularity\": 74317\n },\n {\n \"tag\": "detentive",\n \"popularity\": 74048\n },\n {\n \"tag\": "supravital",\n \"popularity\": 73780\n },\n {\n \"tag\": "Vespertilionidae",\n \"popularity\": 73513\n },\n {\n \"tag\": "parka",\n \"popularity\": 73248\n },\n {\n \"tag\": "pickaway",\n \"popularity\": 72984\n },\n {\n \"tag\": "oleaceous",\n \"popularity\": 72722\n },\n {\n \"tag\": "anticogitative",\n \"popularity\": 72462\n },\n {\n \"tag\": "woe",\n \"popularity\": 72203\n },\n {\n \"tag\": "skeuomorph",\n \"popularity\": 71945\n },\n {\n \"tag\": "helpmeet",\n \"popularity\": 71689\n },\n {\n \"tag\": "Hexactinellida brickmaking",\n \"popularity\": 71434\n },\n {\n \"tag\": "resink",\n \"popularity\": 71180\n },\n {\n \"tag\": "diluter",\n \"popularity\": 70928\n },\n {\n \"tag\": "micromicron",\n \"popularity\": 70677\n },\n {\n \"tag\": "parentage",\n \"popularity\": 70428\n },\n {\n \"tag\": "galactorrhoea",\n \"popularity\": 70180\n },\n {\n \"tag\": "gey",\n \"popularity\": 69934\n },\n {\n \"tag\": "gesticulatory",\n \"popularity\": 69689\n },\n {\n \"tag\": "wergil",\n \"popularity\": 69445\n },\n {\n \"tag\": "Lecanora",\n \"popularity\": 69202\n },\n {\n \"tag\": "malanders karst",\n \"popularity\": 68961\n },\n {\n \"tag\": "vibetoite",\n \"popularity\": 68721\n },\n {\n \"tag\": "unrequitedness",\n \"popularity\": 68483\n },\n {\n \"tag\": "outwash",\n \"popularity\": 68245\n },\n {\n \"tag\": "unsacred",\n \"popularity\": 68009\n },\n {\n \"tag\": "unabetted dividend",\n \"popularity\": 67775\n },\n {\n \"tag\": "untraveling",\n \"popularity\": 67541\n },\n {\n \"tag\": "thermobattery",\n \"popularity\": 67309\n },\n {\n \"tag\": "polypragmist",\n \"popularity\": 67078\n },\n {\n \"tag\": "irrefutableness",\n \"popularity\": 66848\n },\n {\n \"tag\": "remiges",\n \"popularity\": 66620\n },\n {\n \"tag\": "implode",\n \"popularity\": 66393\n },\n {\n \"tag\": "superfluousness",\n \"popularity\": 66166\n },\n {\n \"tag\": "croakily unalleviated",\n \"popularity\": 65942\n },\n {\n \"tag\": "edicule",\n \"popularity\": 65718\n },\n {\n \"tag\": "entophytous",\n \"popularity\": 65495\n },\n {\n \"tag\": "benefactorship Toryish",\n \"popularity\": 65274\n },\n {\n \"tag\": "pseudoamateurish",\n \"popularity\": 65054\n },\n {\n \"tag\": "flueless Iguanodontoidea snipnose",\n \"popularity\": 64835\n },\n {\n \"tag\": "zealotical Zamicrus interpole",\n \"popularity\": 64617\n },\n {\n \"tag\": "whereabout",\n \"popularity\": 64401\n },\n {\n \"tag\": "benzazide",\n \"popularity\": 64185\n },\n {\n \"tag\": "pokeweed",\n \"popularity\": 63971\n },\n {\n \"tag\": "calamitoid",\n \"popularity\": 63757\n },\n {\n \"tag\": "sporozoal",\n \"popularity\": 63545\n },\n {\n \"tag\": "physcioid Welshwoman",\n \"popularity\": 63334\n },\n {\n \"tag\": "wanting",\n \"popularity\": 63124\n },\n {\n \"tag\": "unencumbering",\n \"popularity\": 62915\n },\n {\n \"tag\": "Tupi",\n \"popularity\": 62707\n },\n {\n \"tag\": "potbank",\n \"popularity\": 62501\n },\n {\n \"tag\": "bulked",\n \"popularity\": 62295\n },\n {\n \"tag\": "uparise",\n \"popularity\": 62090\n },\n {\n \"tag\": "Sudra",\n \"popularity\": 61887\n },\n {\n \"tag\": "hyperscrupulosity",\n \"popularity\": 61684\n },\n {\n \"tag\": "subterraneously unmaid",\n \"popularity\": 61483\n },\n {\n \"tag\": "poisonousness",\n \"popularity\": 61282\n },\n {\n \"tag\": "phare",\n \"popularity\": 61083\n },\n {\n \"tag\": "dicynodont",\n \"popularity\": 60884\n },\n {\n \"tag\": "chewer",\n \"popularity\": 60687\n },\n {\n \"tag\": "uliginous",\n \"popularity\": 60490\n },\n {\n \"tag\": "tinman",\n \"popularity\": 60295\n },\n {\n \"tag\": "coconut",\n \"popularity\": 60100\n },\n {\n \"tag\": "phryganeoid",\n \"popularity\": 59907\n },\n {\n \"tag\": "bismillah",\n \"popularity\": 59714\n },\n {\n \"tag\": "tautomeric",\n \"popularity\": 59523\n },\n {\n \"tag\": "jerquer",\n \"popularity\": 59332\n },\n {\n \"tag\": "Dryopithecinae",\n \"popularity\": 59143\n },\n {\n \"tag\": "ghizite",\n \"popularity\": 58954\n },\n {\n \"tag\": "unliveable",\n \"popularity\": 58766\n },\n {\n \"tag\": "craftsmaster",\n \"popularity\": 58579\n },\n {\n \"tag\": "semiscenic",\n \"popularity\": 58394\n },\n {\n \"tag\": "danaid",\n \"popularity\": 58209\n },\n {\n \"tag\": "flawful",\n \"popularity\": 58025\n },\n {\n \"tag\": "risibleness",\n \"popularity\": 57841\n },\n {\n \"tag\": "Muscovite",\n \"popularity\": 57659\n },\n {\n \"tag\": "snaringly",\n \"popularity\": 57478\n },\n {\n \"tag\": "brilliantwise",\n \"popularity\": 57297\n },\n {\n \"tag\": "plebeity",\n \"popularity\": 57118\n },\n {\n \"tag\": "historicalness",\n \"popularity\": 56939\n },\n {\n \"tag\": "piecemeal",\n \"popularity\": 56761\n },\n {\n \"tag\": "maxillipedary",\n \"popularity\": 56584\n },\n {\n \"tag\": "Hypenantron",\n \"popularity\": 56408\n },\n {\n \"tag\": "quaintness avigate",\n \"popularity\": 56233\n },\n {\n \"tag\": "ave",\n \"popularity\": 56059\n },\n {\n \"tag\": "mediaevally",\n \"popularity\": 55885\n },\n {\n \"tag\": "brucite",\n \"popularity\": 55712\n },\n {\n \"tag\": "Schwendenerian",\n \"popularity\": 55541\n },\n {\n \"tag\": "julole",\n \"popularity\": 55370\n },\n {\n \"tag\": "palaeolith",\n \"popularity\": 55199\n },\n {\n \"tag\": "cotyledonary",\n \"popularity\": 55030\n },\n {\n \"tag\": "rond",\n \"popularity\": 54861\n },\n {\n \"tag\": "boomster tassoo",\n \"popularity\": 54694\n },\n {\n \"tag\": "cattishly",\n \"popularity\": 54527\n },\n {\n \"tag\": "tonguefence",\n \"popularity\": 54360\n },\n {\n \"tag\": "hexastylar triskele",\n \"popularity\": 54195\n },\n {\n \"tag\": "ariot",\n \"popularity\": 54030\n },\n {\n \"tag\": "intarsist",\n \"popularity\": 53867\n },\n {\n \"tag\": "Oscines",\n \"popularity\": 53704\n },\n {\n \"tag\": "Spaniolize",\n \"popularity\": 53541\n },\n {\n \"tag\": "smellfungus",\n \"popularity\": 53380\n },\n {\n \"tag\": "redisplay",\n \"popularity\": 53219\n },\n {\n \"tag\": "phosphene",\n \"popularity\": 53059\n },\n {\n \"tag\": "phycomycete",\n \"popularity\": 52900\n },\n {\n \"tag\": "prophetic",\n \"popularity\": 52741\n },\n {\n \"tag\": "overtrustful",\n \"popularity\": 52584\n },\n {\n \"tag\": "pinitol",\n \"popularity\": 52427\n },\n {\n \"tag\": "asthmatic",\n \"popularity\": 52270\n },\n {\n \"tag\": "convulsive",\n \"popularity\": 52115\n },\n {\n \"tag\": "draughtswoman",\n \"popularity\": 51960\n },\n {\n \"tag\": "unetymologizable",\n \"popularity\": 51806\n },\n {\n \"tag\": "centrarchoid",\n \"popularity\": 51652\n },\n {\n \"tag\": "mesioincisal",\n \"popularity\": 51500\n },\n {\n \"tag\": "transbaikal",\n \"popularity\": 51348\n },\n {\n \"tag\": "silveriness",\n \"popularity\": 51196\n },\n {\n \"tag\": "costotomy",\n \"popularity\": 51046\n },\n {\n \"tag\": "caracore",\n \"popularity\": 50896\n },\n {\n \"tag\": "depotentiation",\n \"popularity\": 50747\n },\n {\n \"tag\": "glossoepiglottidean",\n \"popularity\": 50598\n },\n {\n \"tag\": "upswell",\n \"popularity\": 50450\n },\n {\n \"tag\": "flecnodal",\n \"popularity\": 50303\n },\n {\n \"tag\": "coventrate",\n \"popularity\": 50157\n },\n {\n \"tag\": "duchesse",\n \"popularity\": 50011\n },\n {\n \"tag\": "excisemanship trophied",\n \"popularity\": 49866\n },\n {\n \"tag\": "cytinaceous",\n \"popularity\": 49721\n },\n {\n \"tag\": "assuringly",\n \"popularity\": 49577\n },\n {\n \"tag\": "unconducted upliftitis",\n \"popularity\": 49434\n },\n {\n \"tag\": "rachicentesis",\n \"popularity\": 49292\n },\n {\n \"tag\": "antiangular",\n \"popularity\": 49150\n },\n {\n \"tag\": "advisal",\n \"popularity\": 49008\n },\n {\n \"tag\": "birdcatcher",\n \"popularity\": 48868\n },\n {\n \"tag\": "secularistic",\n \"popularity\": 48728\n },\n {\n \"tag\": "grandeeism superinformal",\n \"popularity\": 48588\n },\n {\n \"tag\": "unapprehension",\n \"popularity\": 48449\n },\n {\n \"tag\": "excipulum",\n \"popularity\": 48311\n },\n {\n \"tag\": "decimole",\n \"popularity\": 48174\n },\n {\n \"tag\": "semidrachm",\n \"popularity\": 48037\n },\n {\n \"tag\": "uvulotome",\n \"popularity\": 47901\n },\n {\n \"tag\": "Lemaneaceae",\n \"popularity\": 47765\n },\n {\n \"tag\": "corrade",\n \"popularity\": 47630\n },\n {\n \"tag\": "Kuroshio",\n \"popularity\": 47495\n },\n {\n \"tag\": "Araliophyllum",\n \"popularity\": 47361\n },\n {\n \"tag\": "victoriousness cardiosphygmograph",\n \"popularity\": 47228\n },\n {\n \"tag\": "reinvent",\n \"popularity\": 47095\n },\n {\n \"tag\": "Macrotolagus",\n \"popularity\": 46963\n },\n {\n \"tag\": "strenuousness",\n \"popularity\": 46831\n },\n {\n \"tag\": "deviability",\n \"popularity\": 46700\n },\n {\n \"tag\": "phyllospondylous",\n \"popularity\": 46570\n },\n {\n \"tag\": "bisect rudderhole",\n \"popularity\": 46440\n },\n {\n \"tag\": "crownwork",\n \"popularity\": 46311\n },\n {\n \"tag\": "Ascalabota",\n \"popularity\": 46182\n },\n {\n \"tag\": "prostatomyomectomy",\n \"popularity\": 46054\n },\n {\n \"tag\": "neurosyphilis",\n \"popularity\": 45926\n },\n {\n \"tag\": "tabloid scraplet",\n \"popularity\": 45799\n },\n {\n \"tag\": "nonmedullated servility",\n \"popularity\": 45673\n },\n {\n \"tag\": "melopoeic practicalization",\n \"popularity\": 45547\n },\n {\n \"tag\": "nonrhythmic",\n \"popularity\": 45421\n },\n {\n \"tag\": "deplorer",\n \"popularity\": 45296\n },\n {\n \"tag\": "Ophion",\n \"popularity\": 45172\n },\n {\n \"tag\": "subprioress",\n \"popularity\": 45048\n },\n {\n \"tag\": "semiregular",\n \"popularity\": 44925\n },\n {\n \"tag\": "praelection",\n \"popularity\": 44802\n },\n {\n \"tag\": "discinct",\n \"popularity\": 44680\n },\n {\n \"tag\": "preplace",\n \"popularity\": 44558\n },\n {\n \"tag\": "paternoster",\n \"popularity\": 44437\n },\n {\n \"tag\": "suboccipital",\n \"popularity\": 44316\n },\n {\n \"tag\": "Teutophil",\n \"popularity\": 44196\n },\n {\n \"tag\": "tracheole",\n \"popularity\": 44076\n },\n {\n \"tag\": "subsmile",\n \"popularity\": 43957\n },\n {\n \"tag\": "nonapostatizing",\n \"popularity\": 43839\n },\n {\n \"tag\": "cleidotomy",\n \"popularity\": 43720\n },\n {\n \"tag\": "hingle",\n \"popularity\": 43603\n },\n {\n \"tag\": "jocoque",\n \"popularity\": 43486\n },\n {\n \"tag\": "trundler notidanian",\n \"popularity\": 43369\n },\n {\n \"tag\": "strangling misdaub",\n \"popularity\": 43253\n },\n {\n \"tag\": "noncancellable",\n \"popularity\": 43137\n },\n {\n \"tag\": "lavabo",\n \"popularity\": 43022\n },\n {\n \"tag\": "lanterloo",\n \"popularity\": 42907\n },\n {\n \"tag\": "uncitizenly",\n \"popularity\": 42793\n },\n {\n \"tag\": "autoturning",\n \"popularity\": 42679\n },\n {\n \"tag\": "Haganah",\n \"popularity\": 42566\n },\n {\n \"tag\": "Glecoma",\n \"popularity\": 42453\n },\n {\n \"tag\": "membered",\n \"popularity\": 42341\n },\n {\n \"tag\": "consuetudinal",\n \"popularity\": 42229\n },\n {\n \"tag\": "gatehouse",\n \"popularity\": 42117\n },\n {\n \"tag\": "tetherball",\n \"popularity\": 42006\n },\n {\n \"tag\": "counterrevolutionist numismatical",\n \"popularity\": 41896\n },\n {\n \"tag\": "pagehood plateiasmus",\n \"popularity\": 41786\n },\n {\n \"tag\": "pelterer",\n \"popularity\": 41676\n },\n {\n \"tag\": "splenemphraxis",\n \"popularity\": 41567\n },\n {\n \"tag\": "Crypturidae",\n \"popularity\": 41458\n },\n {\n \"tag\": "caboodle",\n \"popularity\": 41350\n },\n {\n \"tag\": "Filaria",\n \"popularity\": 41242\n },\n {\n \"tag\": "noninvincibility",\n \"popularity\": 41135\n },\n {\n \"tag\": "preadvertisement",\n \"popularity\": 41028\n },\n {\n \"tag\": "bathrobe",\n \"popularity\": 40921\n },\n {\n \"tag\": "nitrifier",\n \"popularity\": 40815\n },\n {\n \"tag\": "furthermore",\n \"popularity\": 40709\n },\n {\n \"tag\": "recrate",\n \"popularity\": 40604\n },\n {\n \"tag\": "inexist",\n \"popularity\": 40499\n },\n {\n \"tag\": "Mocoan",\n \"popularity\": 40395\n },\n {\n \"tag\": "forint",\n \"popularity\": 40291\n },\n {\n \"tag\": "cardiomyoliposis",\n \"popularity\": 40187\n },\n {\n \"tag\": "channeling",\n \"popularity\": 40084\n },\n {\n \"tag\": "quebrachine",\n \"popularity\": 39981\n },\n {\n \"tag\": "magistery",\n \"popularity\": 39879\n },\n {\n \"tag\": "koko",\n \"popularity\": 39777\n },\n {\n \"tag\": "nobilify",\n \"popularity\": 39676\n },\n {\n \"tag\": "articulate taprooted",\n \"popularity\": 39575\n },\n {\n \"tag\": "cardiotonic Nicaragua",\n \"popularity\": 39474\n },\n {\n \"tag\": "assertiveness",\n \"popularity\": 39374\n },\n {\n \"tag\": "springtail",\n \"popularity\": 39274\n },\n {\n \"tag\": "spontoon",\n \"popularity\": 39174\n },\n {\n \"tag\": "plesiobiosis",\n \"popularity\": 39075\n },\n {\n \"tag\": "rooinek",\n \"popularity\": 38976\n },\n {\n \"tag\": "hairif falsehood",\n \"popularity\": 38878\n },\n {\n \"tag\": "synodally",\n \"popularity\": 38780\n },\n {\n \"tag\": "biodynamics",\n \"popularity\": 38683\n },\n {\n \"tag\": "trickling",\n \"popularity\": 38585\n },\n {\n \"tag\": "oxfly daystar",\n \"popularity\": 38489\n },\n {\n \"tag\": "epicycloidal",\n \"popularity\": 38392\n },\n {\n \"tag\": "shorthand",\n \"popularity\": 38296\n },\n {\n \"tag\": "herpolhode",\n \"popularity\": 38201\n },\n {\n \"tag\": "polysynthesism",\n \"popularity\": 38105\n },\n {\n \"tag\": "cany",\n \"popularity\": 38010\n },\n {\n \"tag\": "sideage",\n \"popularity\": 37916\n },\n {\n \"tag\": "strainableness",\n \"popularity\": 37822\n },\n {\n \"tag\": "superformidable",\n \"popularity\": 37728\n },\n {\n \"tag\": "slendang",\n \"popularity\": 37634\n },\n {\n \"tag\": "impropriation",\n \"popularity\": 37541\n },\n {\n \"tag\": "ficklehearted",\n \"popularity\": 37449\n },\n {\n \"tag\": "wintrify",\n \"popularity\": 37356\n },\n {\n \"tag\": "geomorphogenist",\n \"popularity\": 37264\n },\n {\n \"tag\": "smuggleable",\n \"popularity\": 37173\n },\n {\n \"tag\": "delapsion",\n \"popularity\": 37081\n },\n {\n \"tag\": "projective",\n \"popularity\": 36990\n },\n {\n \"tag\": "unglue exfoliation",\n \"popularity\": 36900\n },\n {\n \"tag\": "Acerae",\n \"popularity\": 36810\n },\n {\n \"tag\": "unstaged",\n \"popularity\": 36720\n },\n {\n \"tag\": "ranal",\n \"popularity\": 36630\n },\n {\n \"tag\": "worrier",\n \"popularity\": 36541\n },\n {\n \"tag\": "unhid",\n \"popularity\": 36452\n },\n {\n \"tag\": "adequation",\n \"popularity\": 36363\n },\n {\n \"tag\": "strongylid Sokotri",\n \"popularity\": 36275\n },\n {\n \"tag\": "fumingly",\n \"popularity\": 36187\n },\n {\n \"tag\": "gynosporangium phaenogenetic",\n \"popularity\": 36100\n },\n {\n \"tag\": "uniunguiculate",\n \"popularity\": 36012\n },\n {\n \"tag\": "prudelike",\n \"popularity\": 35926\n },\n {\n \"tag\": "seminomata",\n \"popularity\": 35839\n },\n {\n \"tag\": "trinklet",\n \"popularity\": 35753\n },\n {\n \"tag\": "risorial",\n \"popularity\": 35667\n },\n {\n \"tag\": "pericardiocentesis",\n \"popularity\": 35581\n },\n {\n \"tag\": "filmist",\n \"popularity\": 35496\n },\n {\n \"tag\": "Nana",\n \"popularity\": 35411\n },\n {\n \"tag\": "cynipoid",\n \"popularity\": 35326\n },\n {\n \"tag\": "cteniform",\n \"popularity\": 35242\n },\n {\n \"tag\": "semiflex",\n \"popularity\": 35158\n },\n {\n \"tag\": "solstitially",\n \"popularity\": 35074\n },\n {\n \"tag\": "Algarsife",\n \"popularity\": 34991\n },\n {\n \"tag\": "noncriminal",\n \"popularity\": 34908\n },\n {\n \"tag\": "compassion",\n \"popularity\": 34825\n },\n {\n \"tag\": "Buddhic",\n \"popularity\": 34743\n },\n {\n \"tag\": "vellicative dactylically hotfoot",\n \"popularity\": 34661\n },\n {\n \"tag\": "chicory",\n \"popularity\": 34579\n },\n {\n \"tag\": "transperitoneally",\n \"popularity\": 34497\n },\n {\n \"tag\": "pennae",\n \"popularity\": 34416\n },\n {\n \"tag\": "Flamandize",\n \"popularity\": 34335\n },\n {\n \"tag\": "underviewer",\n \"popularity\": 34254\n },\n {\n \"tag\": "assoil",\n \"popularity\": 34174\n },\n {\n \"tag\": "saccharobacillus",\n \"popularity\": 34094\n },\n {\n \"tag\": "biacetylene",\n \"popularity\": 34014\n },\n {\n \"tag\": "mouchardism",\n \"popularity\": 33935\n },\n {\n \"tag\": "anisomeric",\n \"popularity\": 33856\n },\n {\n \"tag\": "digestive",\n \"popularity\": 33777\n },\n {\n \"tag\": "darlingly",\n \"popularity\": 33698\n },\n {\n \"tag\": "liman",\n \"popularity\": 33620\n },\n {\n \"tag\": "soldanrie",\n \"popularity\": 33542\n },\n {\n \"tag\": "sully",\n \"popularity\": 33464\n },\n {\n \"tag\": "brightsmith",\n \"popularity\": 33387\n },\n {\n \"tag\": "inwrap antiliturgist ureterocervical",\n \"popularity\": 33309\n },\n {\n \"tag\": "discommodity",\n \"popularity\": 33232\n },\n {\n \"tag\": "typical aggrandizer",\n \"popularity\": 33156\n },\n {\n \"tag\": "xenogeny",\n \"popularity\": 33079\n },\n {\n \"tag\": "uncountrified",\n \"popularity\": 33003\n },\n {\n \"tag\": "Podarge",\n \"popularity\": 32928\n },\n {\n \"tag\": "uninterviewed",\n \"popularity\": 32852\n },\n {\n \"tag\": "underprior",\n \"popularity\": 32777\n },\n {\n \"tag\": "leiomyomatous",\n \"popularity\": 32702\n },\n {\n \"tag\": "postdysenteric",\n \"popularity\": 32627\n },\n {\n \"tag\": "Fusicladium",\n \"popularity\": 32553\n },\n {\n \"tag\": "Dulcinea",\n \"popularity\": 32478\n },\n {\n \"tag\": "interspersion",\n \"popularity\": 32404\n },\n {\n \"tag\": "preobligate",\n \"popularity\": 32331\n },\n {\n \"tag\": "subaggregate",\n \"popularity\": 32257\n },\n {\n \"tag\": "grammarianism",\n \"popularity\": 32184\n },\n {\n \"tag\": "palikar",\n \"popularity\": 32111\n },\n {\n \"tag\": "facileness",\n \"popularity\": 32039\n },\n {\n \"tag\": "deuterofibrinose",\n \"popularity\": 31966\n },\n {\n \"tag\": "pseudesthesia",\n \"popularity\": 31894\n },\n {\n \"tag\": "sedimentary",\n \"popularity\": 31822\n },\n {\n \"tag\": "typewrite",\n \"popularity\": 31751\n },\n {\n \"tag\": "immemorable",\n \"popularity\": 31679\n },\n {\n \"tag\": "Myrtus",\n \"popularity\": 31608\n },\n {\n \"tag\": "hauchecornite",\n \"popularity\": 31537\n },\n {\n \"tag\": "galleylike",\n \"popularity\": 31467\n },\n {\n \"tag\": "thimber",\n \"popularity\": 31396\n },\n {\n \"tag\": "Hegelianism",\n \"popularity\": 31326\n },\n {\n \"tag\": "strig",\n \"popularity\": 31256\n },\n {\n \"tag\": "skyre",\n \"popularity\": 31187\n },\n {\n \"tag\": "eupepticism",\n \"popularity\": 31117\n },\n {\n \"tag\": "eponymism",\n \"popularity\": 31048\n },\n {\n \"tag\": "flunkeyhood",\n \"popularity\": 30979\n },\n {\n \"tag\": "Abama",\n \"popularity\": 30911\n },\n {\n \"tag\": "adiadochokinesis",\n \"popularity\": 30842\n },\n {\n \"tag\": "spendthrifty",\n \"popularity\": 30774\n },\n {\n \"tag\": "chalcedony",\n \"popularity\": 30706\n },\n {\n \"tag\": "authorism",\n \"popularity\": 30638\n },\n {\n \"tag\": "nasturtium",\n \"popularity\": 30571\n },\n {\n \"tag\": "Acanthocereus",\n \"popularity\": 30504\n },\n {\n \"tag\": "uncollapsible",\n \"popularity\": 30437\n },\n {\n \"tag\": "excursionist",\n \"popularity\": 30370\n },\n {\n \"tag\": "fogbow",\n \"popularity\": 30303\n },\n {\n \"tag\": "overlie",\n \"popularity\": 30237\n },\n {\n \"tag\": "velours",\n \"popularity\": 30171\n },\n {\n \"tag\": "zoodendria madrigal stagbush",\n \"popularity\": 30105\n },\n {\n \"tag\": "imi",\n \"popularity\": 30039\n },\n {\n \"tag\": "cojudge",\n \"popularity\": 29974\n },\n {\n \"tag\": "depurate argal",\n \"popularity\": 29909\n },\n {\n \"tag\": "unrecognition",\n \"popularity\": 29844\n },\n {\n \"tag\": "paunchful",\n \"popularity\": 29779\n },\n {\n \"tag\": "invalued",\n \"popularity\": 29714\n },\n {\n \"tag\": "probang",\n \"popularity\": 29650\n },\n {\n \"tag\": "chetvert",\n \"popularity\": 29586\n },\n {\n \"tag\": "enactable",\n \"popularity\": 29522\n },\n {\n \"tag\": "detoxicate adhibit",\n \"popularity\": 29458\n },\n {\n \"tag\": "kullaite",\n \"popularity\": 29395\n },\n {\n \"tag\": "undazzling",\n \"popularity\": 29332\n },\n {\n \"tag\": "excalation",\n \"popularity\": 29269\n },\n {\n \"tag\": "sievings",\n \"popularity\": 29206\n },\n {\n \"tag\": "disenthral",\n \"popularity\": 29143\n },\n {\n \"tag\": "disinterestedly",\n \"popularity\": 29081\n },\n {\n \"tag\": "stanner",\n \"popularity\": 29018\n },\n {\n \"tag\": "recapitulative",\n \"popularity\": 28956\n },\n {\n \"tag\": "objectivist",\n \"popularity\": 28895\n },\n {\n \"tag\": "hypermetropia",\n \"popularity\": 28833\n },\n {\n \"tag\": "incumbency",\n \"popularity\": 28772\n },\n {\n \"tag\": "protegee",\n \"popularity\": 28711\n },\n {\n \"tag\": "zealotic",\n \"popularity\": 28650\n },\n {\n \"tag\": "predebit",\n \"popularity\": 28589\n },\n {\n \"tag\": "cupolar",\n \"popularity\": 28528\n },\n {\n \"tag\": "unattributed",\n \"popularity\": 28468\n },\n {\n \"tag\": "louisine",\n \"popularity\": 28408\n },\n {\n \"tag\": "illustrate",\n \"popularity\": 28348\n },\n {\n \"tag\": "inofficiousness",\n \"popularity\": 28288\n },\n {\n \"tag\": "Americawards",\n \"popularity\": 28228\n },\n {\n \"tag\": "foreflap",\n \"popularity\": 28169\n },\n {\n \"tag\": "eruditeness",\n \"popularity\": 28110\n },\n {\n \"tag\": "copiopsia",\n \"popularity\": 28051\n },\n {\n \"tag\": "sporuliferous",\n \"popularity\": 27992\n },\n {\n \"tag\": "muttering",\n \"popularity\": 27934\n },\n {\n \"tag\": "prepsychology adrip",\n \"popularity\": 27875\n },\n {\n \"tag\": "unfriendly",\n \"popularity\": 27817\n },\n {\n \"tag\": "sulphanilic",\n \"popularity\": 27759\n },\n {\n \"tag\": "Coelococcus",\n \"popularity\": 27701\n },\n {\n \"tag\": "undoubtfulness",\n \"popularity\": 27643\n },\n {\n \"tag\": "flaringly",\n \"popularity\": 27586\n },\n {\n \"tag\": "unordain",\n \"popularity\": 27529\n },\n {\n \"tag\": "fratchety",\n \"popularity\": 27472\n },\n {\n \"tag\": "decadentism dolefully",\n \"popularity\": 27415\n },\n {\n \"tag\": "synthronus",\n \"popularity\": 27358\n },\n {\n \"tag\": "maiid",\n \"popularity\": 27301\n },\n {\n \"tag\": "rhinobyon",\n \"popularity\": 27245\n },\n {\n \"tag\": "Didynamia",\n \"popularity\": 27189\n },\n {\n \"tag\": "millionairedom",\n \"popularity\": 27133\n },\n {\n \"tag\": "mulierine",\n \"popularity\": 27077\n },\n {\n \"tag\": "Mayo",\n \"popularity\": 27021\n },\n {\n \"tag\": "perceivedness",\n \"popularity\": 26966\n },\n {\n \"tag\": "unadoration",\n \"popularity\": 26911\n },\n {\n \"tag\": "regraft",\n \"popularity\": 26856\n },\n {\n \"tag\": "witch",\n \"popularity\": 26801\n },\n {\n \"tag\": "ungrow",\n \"popularity\": 26746\n },\n {\n \"tag\": "glossopharyngeus",\n \"popularity\": 26691\n },\n {\n \"tag\": "unstirrable",\n \"popularity\": 26637\n },\n {\n \"tag\": "synodsman",\n \"popularity\": 26583\n },\n {\n \"tag\": "placentalian",\n \"popularity\": 26529\n },\n {\n \"tag\": "corpulently",\n \"popularity\": 26475\n },\n {\n \"tag\": "photochromoscope",\n \"popularity\": 26421\n },\n {\n \"tag\": "indusiate retinasphaltum chokestrap",\n \"popularity\": 26368\n },\n {\n \"tag\": "murdrum",\n \"popularity\": 26314\n },\n {\n \"tag\": "belatedness",\n \"popularity\": 26261\n },\n {\n \"tag\": "Cochin",\n \"popularity\": 26208\n },\n {\n \"tag\": "Leonist",\n \"popularity\": 26155\n },\n {\n \"tag\": "keeker confined",\n \"popularity\": 26102\n },\n {\n \"tag\": "unintellectual",\n \"popularity\": 26050\n },\n {\n \"tag\": "nymphaline bait",\n \"popularity\": 25997\n },\n {\n \"tag\": "sarcosporidiosis",\n \"popularity\": 25945\n },\n {\n \"tag\": "catawamptiously",\n \"popularity\": 25893\n },\n {\n \"tag\": "outshame",\n \"popularity\": 25841\n },\n {\n \"tag\": "animalism",\n \"popularity\": 25790\n },\n {\n \"tag\": "epithalamial",\n \"popularity\": 25738\n },\n {\n \"tag\": "ganner",\n \"popularity\": 25687\n },\n {\n \"tag\": "desilicify",\n \"popularity\": 25635\n },\n {\n \"tag\": "dandyism",\n \"popularity\": 25584\n },\n {\n \"tag\": "hyleg",\n \"popularity\": 25533\n },\n {\n \"tag\": "photophysical",\n \"popularity\": 25483\n },\n {\n \"tag\": "underload",\n \"popularity\": 25432\n },\n {\n \"tag\": "unintrusive",\n \"popularity\": 25382\n },\n {\n \"tag\": "succinamic",\n \"popularity\": 25331\n },\n {\n \"tag\": "matchy",\n \"popularity\": 25281\n },\n {\n \"tag\": "concordal",\n \"popularity\": 25231\n },\n {\n \"tag\": "exteriority",\n \"popularity\": 25181\n },\n {\n \"tag\": "sterculiad",\n \"popularity\": 25132\n },\n {\n \"tag\": "sulfoxylic",\n \"popularity\": 25082\n },\n {\n \"tag\": "oversubscription",\n \"popularity\": 25033\n },\n {\n \"tag\": "chiasmic",\n \"popularity\": 24984\n },\n {\n \"tag\": "pseudoparthenogenesis",\n \"popularity\": 24935\n },\n {\n \"tag\": "indorse",\n \"popularity\": 24886\n },\n {\n \"tag\": "Krishnaite",\n \"popularity\": 24837\n },\n {\n \"tag\": "calcinize",\n \"popularity\": 24788\n },\n {\n \"tag\": "rhodium",\n \"popularity\": 24740\n },\n {\n \"tag\": "tragopan",\n \"popularity\": 24692\n },\n {\n \"tag\": "overwhelmingly",\n \"popularity\": 24643\n },\n {\n \"tag\": "procidence accorporate",\n \"popularity\": 24595\n },\n {\n \"tag\": "polemize speelless",\n \"popularity\": 24548\n },\n {\n \"tag\": "radiocarpal goran",\n \"popularity\": 24500\n },\n {\n \"tag\": "counteroffer Pelodytes",\n \"popularity\": 24452\n },\n {\n \"tag\": "lionhearted",\n \"popularity\": 24405\n },\n {\n \"tag\": "paramastoid",\n \"popularity\": 24358\n },\n {\n \"tag\": "murine",\n \"popularity\": 24310\n },\n {\n \"tag\": "woodbined",\n \"popularity\": 24263\n },\n {\n \"tag\": "packthread",\n \"popularity\": 24217\n },\n {\n \"tag\": "citreous",\n \"popularity\": 24170\n },\n {\n \"tag\": "unfallaciously",\n \"popularity\": 24123\n },\n {\n \"tag\": "tentwork reincarnadine",\n \"popularity\": 24077\n },\n {\n \"tag\": "verminousness",\n \"popularity\": 24030\n },\n {\n \"tag\": "sillometer",\n \"popularity\": 23984\n },\n {\n \"tag\": "jointy",\n \"popularity\": 23938\n },\n {\n \"tag\": "streptolysin",\n \"popularity\": 23892\n },\n {\n \"tag\": "Florentinism",\n \"popularity\": 23847\n },\n {\n \"tag\": "monosomatous",\n \"popularity\": 23801\n },\n {\n \"tag\": "capsulociliary",\n \"popularity\": 23756\n },\n {\n \"tag\": "organum",\n \"popularity\": 23710\n },\n {\n \"tag\": "overtly",\n \"popularity\": 23665\n },\n {\n \"tag\": "ophthalmoscopical",\n \"popularity\": 23620\n },\n {\n \"tag\": "supposititiously",\n \"popularity\": 23575\n },\n {\n \"tag\": "radiochemistry",\n \"popularity\": 23530\n },\n {\n \"tag\": "flaxtail",\n \"popularity\": 23486\n },\n {\n \"tag\": "pretympanic",\n \"popularity\": 23441\n },\n {\n \"tag\": "auscultation",\n \"popularity\": 23397\n },\n {\n \"tag\": "hairdresser",\n \"popularity\": 23352\n },\n {\n \"tag\": "chaffless",\n \"popularity\": 23308\n },\n {\n \"tag\": "polioencephalitis",\n \"popularity\": 23264\n },\n {\n \"tag\": "axolotl",\n \"popularity\": 23220\n },\n {\n \"tag\": "smous",\n \"popularity\": 23177\n },\n {\n \"tag\": "morgen disenamour toothed",\n \"popularity\": 23133\n },\n {\n \"tag\": "chaiseless",\n \"popularity\": 23089\n },\n {\n \"tag\": "frugally",\n \"popularity\": 23046\n },\n {\n \"tag\": "combustive antievolutionist cinenegative",\n \"popularity\": 23003\n },\n {\n \"tag\": "malacolite",\n \"popularity\": 22960\n },\n {\n \"tag\": "borne",\n \"popularity\": 22917\n },\n {\n \"tag\": "mercaptole",\n \"popularity\": 22874\n },\n {\n \"tag\": "judicatory",\n \"popularity\": 22831\n },\n {\n \"tag\": "noctivagation",\n \"popularity\": 22789\n },\n {\n \"tag\": "synthete",\n \"popularity\": 22746\n },\n {\n \"tag\": "tomboyism",\n \"popularity\": 22704\n },\n {\n \"tag\": "serranoid",\n \"popularity\": 22661\n },\n {\n \"tag\": "impostorism",\n \"popularity\": 22619\n },\n {\n \"tag\": "flagellosis Talitha",\n \"popularity\": 22577\n },\n {\n \"tag\": "pseudoviscous",\n \"popularity\": 22535\n },\n {\n \"tag\": "Galleriidae",\n \"popularity\": 22494\n },\n {\n \"tag\": "undulation didelph Comintern",\n \"popularity\": 22452\n },\n {\n \"tag\": "triangulopyramidal",\n \"popularity\": 22411\n },\n {\n \"tag\": "middlings",\n \"popularity\": 22369\n },\n {\n \"tag\": "piperazin",\n \"popularity\": 22328\n },\n {\n \"tag\": "endostitis",\n \"popularity\": 22287\n },\n {\n \"tag\": "swordlike",\n \"popularity\": 22246\n },\n {\n \"tag\": "forthwith",\n \"popularity\": 22205\n },\n {\n \"tag\": "menaceful",\n \"popularity\": 22164\n },\n {\n \"tag\": "explantation defective",\n \"popularity\": 22123\n },\n {\n \"tag\": "arrear",\n \"popularity\": 22083\n },\n {\n \"tag\": "engraft",\n \"popularity\": 22042\n },\n {\n \"tag\": "revolunteer",\n \"popularity\": 22002\n },\n {\n \"tag\": "foliaceous",\n \"popularity\": 21962\n },\n {\n \"tag\": "pseudograph",\n \"popularity\": 21922\n },\n {\n \"tag\": "maenaite",\n \"popularity\": 21882\n },\n {\n \"tag\": "interfinger",\n \"popularity\": 21842\n },\n {\n \"tag\": "macroscopically",\n \"popularity\": 21802\n },\n {\n \"tag\": "bluewood",\n \"popularity\": 21762\n },\n {\n \"tag\": "chikara",\n \"popularity\": 21723\n },\n {\n \"tag\": "reprehension diazeuxis nickelous",\n \"popularity\": 21683\n },\n {\n \"tag\": "vacuation",\n \"popularity\": 21644\n },\n {\n \"tag\": "Sartish",\n \"popularity\": 21605\n },\n {\n \"tag\": "pseudogyny",\n \"popularity\": 21566\n },\n {\n \"tag\": "friedcake",\n \"popularity\": 21527\n },\n {\n \"tag\": "thraw",\n \"popularity\": 21488\n },\n {\n \"tag\": "bifid",\n \"popularity\": 21449\n },\n {\n \"tag\": "truthlessly",\n \"popularity\": 21411\n },\n {\n \"tag\": "lungy",\n \"popularity\": 21372\n },\n {\n \"tag\": "fluoborite",\n \"popularity\": 21334\n },\n {\n \"tag\": "anthropolithic",\n \"popularity\": 21295\n },\n {\n \"tag\": "coachee straw",\n \"popularity\": 21257\n },\n {\n \"tag\": "dehorner Grecize",\n \"popularity\": 21219\n },\n {\n \"tag\": "spondylopyosis",\n \"popularity\": 21181\n },\n {\n \"tag\": "institutionary",\n \"popularity\": 21143\n },\n {\n \"tag\": "agentry",\n \"popularity\": 21105\n },\n {\n \"tag\": "musing bietle",\n \"popularity\": 21068\n },\n {\n \"tag\": "cormophyte",\n \"popularity\": 21030\n },\n {\n \"tag\": "semielliptic",\n \"popularity\": 20993\n },\n {\n \"tag\": "ependytes",\n \"popularity\": 20955\n },\n {\n \"tag\": "coachmaster",\n \"popularity\": 20918\n },\n {\n \"tag\": "overexuberant",\n \"popularity\": 20881\n },\n {\n \"tag\": "selectable",\n \"popularity\": 20844\n },\n {\n \"tag\": "saclike",\n \"popularity\": 20807\n },\n {\n \"tag\": "mullion",\n \"popularity\": 20770\n },\n {\n \"tag\": "pantheonize prevalency",\n \"popularity\": 20733\n },\n {\n \"tag\": "trophosperm",\n \"popularity\": 20697\n },\n {\n \"tag\": "paraphrasist",\n \"popularity\": 20660\n },\n {\n \"tag\": "undercarry",\n \"popularity\": 20624\n },\n {\n \"tag\": "thallogenic",\n \"popularity\": 20587\n },\n {\n \"tag\": "bulgy forbid",\n \"popularity\": 20551\n },\n {\n \"tag\": "proliquor gratulatory",\n \"popularity\": 20515\n },\n {\n \"tag\": "booker",\n \"popularity\": 20479\n },\n {\n \"tag\": "wizen",\n \"popularity\": 20443\n },\n {\n \"tag\": "synchondrosially",\n \"popularity\": 20407\n },\n {\n \"tag\": "herbless",\n \"popularity\": 20371\n },\n {\n \"tag\": "arfvedsonite",\n \"popularity\": 20336\n },\n {\n \"tag\": "Neuroptera",\n \"popularity\": 20300\n },\n {\n \"tag\": "fingerstone",\n \"popularity\": 20265\n },\n {\n \"tag\": "Odontoglossae",\n \"popularity\": 20229\n },\n {\n \"tag\": "transmigrator",\n \"popularity\": 20194\n },\n {\n \"tag\": "Dehaites",\n \"popularity\": 20159\n },\n {\n \"tag\": "Molinist",\n \"popularity\": 20124\n },\n {\n \"tag\": "novelistic",\n \"popularity\": 20089\n },\n {\n \"tag\": "astelic",\n \"popularity\": 20054\n },\n {\n \"tag\": "pyelometry",\n \"popularity\": 20019\n },\n {\n \"tag\": "pigmentation",\n \"popularity\": 19984\n },\n {\n \"tag\": "epinaos",\n \"popularity\": 19950\n },\n {\n \"tag\": "outdare",\n \"popularity\": 19915\n },\n {\n \"tag\": "Funje philaristocracy",\n \"popularity\": 19881\n },\n {\n \"tag\": "keddah",\n \"popularity\": 19846\n },\n {\n \"tag\": "axoidean",\n \"popularity\": 19812\n },\n {\n \"tag\": "ovule",\n \"popularity\": 19778\n },\n {\n \"tag\": "solidify",\n \"popularity\": 19744\n },\n {\n \"tag\": "noncelestial",\n \"popularity\": 19710\n },\n {\n \"tag\": "overmultiplication",\n \"popularity\": 19676\n },\n {\n \"tag\": "hexatetrahedron",\n \"popularity\": 19642\n },\n {\n \"tag\": "pliciform",\n \"popularity\": 19609\n },\n {\n \"tag\": "zimbalon",\n \"popularity\": 19575\n },\n {\n \"tag\": "annexational",\n \"popularity\": 19542\n },\n {\n \"tag\": "eurhodol",\n \"popularity\": 19508\n },\n {\n \"tag\": "yark",\n \"popularity\": 19475\n },\n {\n \"tag\": "illegality nitroalizarin",\n \"popularity\": 19442\n },\n {\n \"tag\": "quadratum",\n \"popularity\": 19409\n },\n {\n \"tag\": "saccharine",\n \"popularity\": 19376\n },\n {\n \"tag\": "unemploy",\n \"popularity\": 19343\n },\n {\n \"tag\": "uniclinal unipotent",\n \"popularity\": 19310\n },\n {\n \"tag\": "turbo",\n \"popularity\": 19277\n },\n {\n \"tag\": "sybarism",\n \"popularity\": 19244\n },\n {\n \"tag\": "motacilline",\n \"popularity\": 19212\n },\n {\n \"tag\": "weaselly",\n \"popularity\": 19179\n },\n {\n \"tag\": "plastid",\n \"popularity\": 19147\n },\n {\n \"tag\": "wasting",\n \"popularity\": 19114\n },\n {\n \"tag\": "begrime fluting",\n \"popularity\": 19082\n },\n {\n \"tag\": "Nephilinae",\n \"popularity\": 19050\n },\n {\n \"tag\": "disregardance",\n \"popularity\": 19018\n },\n {\n \"tag\": "Shakerlike",\n \"popularity\": 18986\n },\n {\n \"tag\": "uniped",\n \"popularity\": 18954\n },\n {\n \"tag\": "knap",\n \"popularity\": 18922\n },\n {\n \"tag\": "electivism undergardener",\n \"popularity\": 18890\n },\n {\n \"tag\": "hulverheaded",\n \"popularity\": 18858\n },\n {\n \"tag\": "unruptured",\n \"popularity\": 18827\n },\n {\n \"tag\": "solemnize credently",\n \"popularity\": 18795\n },\n {\n \"tag\": "pentastomoid possessingly",\n \"popularity\": 18764\n },\n {\n \"tag\": "octose",\n \"popularity\": 18733\n },\n {\n \"tag\": "psithurism indefensibility",\n \"popularity\": 18701\n },\n {\n \"tag\": "torrentuous cyanometer subcrenate",\n \"popularity\": 18670\n },\n {\n \"tag\": "photoplaywright tapaculo",\n \"popularity\": 18639\n },\n {\n \"tag\": "univalence",\n \"popularity\": 18608\n },\n {\n \"tag\": "Porthetria",\n \"popularity\": 18577\n },\n {\n \"tag\": "funambulo",\n \"popularity\": 18546\n },\n {\n \"tag\": "pedion",\n \"popularity\": 18515\n },\n {\n \"tag\": "horticulturally",\n \"popularity\": 18485\n },\n {\n \"tag\": "marennin",\n \"popularity\": 18454\n },\n {\n \"tag\": "horselaugh",\n \"popularity\": 18423\n },\n {\n \"tag\": "semiexecutive",\n \"popularity\": 18393\n },\n {\n \"tag\": "Monopteridae",\n \"popularity\": 18363\n },\n {\n \"tag\": "commonable",\n \"popularity\": 18332\n },\n {\n \"tag\": "dreariment",\n \"popularity\": 18302\n },\n {\n \"tag\": "disbud",\n \"popularity\": 18272\n },\n {\n \"tag\": "monocled",\n \"popularity\": 18242\n },\n {\n \"tag\": "hurlbarrow",\n \"popularity\": 18212\n },\n {\n \"tag\": "opiateproof",\n \"popularity\": 18182\n },\n {\n \"tag\": "Fahrenheit",\n \"popularity\": 18152\n },\n {\n \"tag\": "writhed",\n \"popularity\": 18122\n },\n {\n \"tag\": "Volstead",\n \"popularity\": 18093\n },\n {\n \"tag\": "yesternight",\n \"popularity\": 18063\n },\n {\n \"tag\": "readmittance",\n \"popularity\": 18033\n },\n {\n \"tag\": "reiterable",\n \"popularity\": 18004\n },\n {\n \"tag\": "triquetral",\n \"popularity\": 17975\n },\n {\n \"tag\": "guillotinement",\n \"popularity\": 17945\n },\n {\n \"tag\": "repermission",\n \"popularity\": 17916\n },\n {\n \"tag\": "assishly",\n \"popularity\": 17887\n },\n {\n \"tag\": "daidle",\n \"popularity\": 17858\n },\n {\n \"tag\": "prismatoid",\n \"popularity\": 17829\n },\n {\n \"tag\": "irreptitious",\n \"popularity\": 17800\n },\n {\n \"tag\": "sourdeline",\n \"popularity\": 17771\n },\n {\n \"tag\": "Austrian",\n \"popularity\": 17742\n },\n {\n \"tag\": "psychorrhagic",\n \"popularity\": 17713\n },\n {\n \"tag\": "Monumbo",\n \"popularity\": 17685\n },\n {\n \"tag\": "cloiochoanitic",\n \"popularity\": 17656\n },\n {\n \"tag\": "hant",\n \"popularity\": 17628\n },\n {\n \"tag\": "roily pulldown",\n \"popularity\": 17599\n },\n {\n \"tag\": "recongratulation",\n \"popularity\": 17571\n },\n {\n \"tag\": "Peking",\n \"popularity\": 17543\n },\n {\n \"tag\": "erdvark",\n \"popularity\": 17514\n },\n {\n \"tag\": "antimnemonic",\n \"popularity\": 17486\n },\n {\n \"tag\": "noncapillarity",\n \"popularity\": 17458\n },\n {\n \"tag\": "irrepressive",\n \"popularity\": 17430\n },\n {\n \"tag\": "Petromyzontes",\n \"popularity\": 17402\n },\n {\n \"tag\": "piscatorially",\n \"popularity\": 17374\n },\n {\n \"tag\": "cholesterosis",\n \"popularity\": 17346\n },\n {\n \"tag\": "denunciate",\n \"popularity\": 17319\n },\n {\n \"tag\": "unmetalled",\n \"popularity\": 17291\n },\n {\n \"tag\": "Tigris enruin",\n \"popularity\": 17263\n },\n {\n \"tag\": "anaspalin",\n \"popularity\": 17236\n },\n {\n \"tag\": "monodromy",\n \"popularity\": 17208\n },\n {\n \"tag\": "Canichanan",\n \"popularity\": 17181\n },\n {\n \"tag\": "mesolabe",\n \"popularity\": 17154\n },\n {\n \"tag\": "trichothallic overcunningness",\n \"popularity\": 17127\n },\n {\n \"tag\": "spinsterishly",\n \"popularity\": 17099\n },\n {\n \"tag\": "sensilla",\n \"popularity\": 17072\n },\n {\n \"tag\": "wifelkin",\n \"popularity\": 17045\n },\n {\n \"tag\": "suppositionless",\n \"popularity\": 17018\n },\n {\n \"tag\": "irksomeness",\n \"popularity\": 16991\n },\n {\n \"tag\": "sanbenito",\n \"popularity\": 16964\n },\n {\n \"tag\": "nonstatement",\n \"popularity\": 16938\n },\n {\n \"tag\": "phenoloid",\n \"popularity\": 16911\n },\n {\n \"tag\": "Steinberger",\n \"popularity\": 16884\n },\n {\n \"tag\": "replicated boom",\n \"popularity\": 16858\n },\n {\n \"tag\": "sciomachiology",\n \"popularity\": 16831\n },\n {\n \"tag\": "starwise",\n \"popularity\": 16805\n },\n {\n \"tag\": "prerich",\n \"popularity\": 16778\n },\n {\n \"tag\": "unspawned",\n \"popularity\": 16752\n },\n {\n \"tag\": "unindentable",\n \"popularity\": 16726\n },\n {\n \"tag\": "stromatic",\n \"popularity\": 16700\n },\n {\n \"tag\": "fetishize",\n \"popularity\": 16673\n },\n {\n \"tag\": "dihydroxy",\n \"popularity\": 16647\n },\n {\n \"tag\": "precaudal",\n \"popularity\": 16621\n },\n {\n \"tag\": "Madagascar",\n \"popularity\": 16595\n },\n {\n \"tag\": "repinement",\n \"popularity\": 16570\n },\n {\n \"tag\": "noncathedral wenzel",\n \"popularity\": 16544\n },\n {\n \"tag\": "corollike",\n \"popularity\": 16518\n },\n {\n \"tag\": "pubes unamortization",\n \"popularity\": 16492\n },\n {\n \"tag\": "brickcroft",\n \"popularity\": 16467\n },\n {\n \"tag\": "intertrabecular",\n \"popularity\": 16441\n },\n {\n \"tag\": "formulaic",\n \"popularity\": 16416\n },\n {\n \"tag\": "arienzo",\n \"popularity\": 16390\n },\n {\n \"tag\": "Mazzinian",\n \"popularity\": 16365\n },\n {\n \"tag\": "wallowishly",\n \"popularity\": 16339\n },\n {\n \"tag\": "sysselman",\n \"popularity\": 16314\n },\n {\n \"tag\": "seligmannite",\n \"popularity\": 16289\n },\n {\n \"tag\": "harlequinery",\n \"popularity\": 16264\n },\n {\n \"tag\": "zucchetto",\n \"popularity\": 16239\n },\n {\n \"tag\": "malonyl",\n \"popularity\": 16214\n },\n {\n \"tag\": "patwari",\n \"popularity\": 16189\n },\n {\n \"tag\": "neoholmia venturesomeness",\n \"popularity\": 16164\n },\n {\n \"tag\": "Dehwar",\n \"popularity\": 16139\n },\n {\n \"tag\": "fetiferous",\n \"popularity\": 16114\n },\n {\n \"tag\": "chromatophore",\n \"popularity\": 16090\n },\n {\n \"tag\": "reregistration",\n \"popularity\": 16065\n },\n {\n \"tag\": "alienor",\n \"popularity\": 16040\n },\n {\n \"tag\": "Hexagynia",\n \"popularity\": 16016\n },\n {\n \"tag\": "cerebrotonia",\n \"popularity\": 15991\n },\n {\n \"tag\": "deedbox",\n \"popularity\": 15967\n },\n {\n \"tag\": "staab",\n \"popularity\": 15943\n },\n {\n \"tag\": "uratemia",\n \"popularity\": 15918\n },\n {\n \"tag\": "flaunt",\n \"popularity\": 15894\n },\n {\n \"tag\": "bogy",\n \"popularity\": 15870\n },\n {\n \"tag\": "subcartilaginous",\n \"popularity\": 15846\n },\n {\n \"tag\": "protonephridial",\n \"popularity\": 15822\n },\n {\n \"tag\": "Boswellia",\n \"popularity\": 15798\n },\n {\n \"tag\": "relaxant untiaraed protoepiphyte",\n \"popularity\": 15774\n },\n {\n \"tag\": "nesslerization",\n \"popularity\": 15750\n },\n {\n \"tag\": "precession",\n \"popularity\": 15726\n },\n {\n \"tag\": "peat",\n \"popularity\": 15702\n },\n {\n \"tag\": "unbit",\n \"popularity\": 15678\n },\n {\n \"tag\": "snailish",\n \"popularity\": 15655\n },\n {\n \"tag\": "porismatical",\n \"popularity\": 15631\n },\n {\n \"tag\": "hooflike",\n \"popularity\": 15608\n },\n {\n \"tag\": "resuppose phene cranic",\n \"popularity\": 15584\n },\n {\n \"tag\": "peptonization kipskin",\n \"popularity\": 15561\n },\n {\n \"tag\": "birdstone",\n \"popularity\": 15537\n },\n {\n \"tag\": "empty inferoanterior",\n \"popularity\": 15514\n },\n {\n \"tag\": "androtauric",\n \"popularity\": 15491\n },\n {\n \"tag\": "triamide",\n \"popularity\": 15467\n },\n {\n \"tag\": "showmanry",\n \"popularity\": 15444\n },\n {\n \"tag\": "doing",\n \"popularity\": 15421\n },\n {\n \"tag\": "bouchaleen",\n \"popularity\": 15398\n },\n {\n \"tag\": "precollude",\n \"popularity\": 15375\n },\n {\n \"tag\": "finger",\n \"popularity\": 15352\n },\n {\n \"tag\": "limnetic intermessenger",\n \"popularity\": 15329\n },\n {\n \"tag\": "uncharitable picrotoxic",\n \"popularity\": 15306\n },\n {\n \"tag\": "nationalizer Phasmidae",\n \"popularity\": 15283\n },\n {\n \"tag\": "laughingstock",\n \"popularity\": 15261\n },\n {\n \"tag\": "nondeferential",\n \"popularity\": 15238\n },\n {\n \"tag\": "uproariously",\n \"popularity\": 15215\n },\n {\n \"tag\": "manzanilla",\n \"popularity\": 15193\n },\n {\n \"tag\": "khahoon",\n \"popularity\": 15170\n },\n {\n \"tag\": "olericulturally longshanks",\n \"popularity\": 15148\n },\n {\n \"tag\": "enthusiastically methionic",\n \"popularity\": 15125\n },\n {\n \"tag\": "pobs",\n \"popularity\": 15103\n },\n {\n \"tag\": "tricarpellate",\n \"popularity\": 15081\n },\n {\n \"tag\": "souterrain",\n \"popularity\": 15058\n },\n {\n \"tag\": "tethelin",\n \"popularity\": 15036\n },\n {\n \"tag\": "tartle",\n \"popularity\": 15014\n },\n {\n \"tag\": "tidelike",\n \"popularity\": 14992\n },\n {\n \"tag\": "cosmoramic",\n \"popularity\": 14970\n },\n {\n \"tag\": "pretardiness",\n \"popularity\": 14948\n },\n {\n \"tag\": "insoul",\n \"popularity\": 14926\n },\n {\n \"tag\": "anthroxan",\n \"popularity\": 14904\n },\n {\n \"tag\": "jilter",\n \"popularity\": 14882\n },\n {\n \"tag\": "pectinibranchian trematode",\n \"popularity\": 14860\n },\n {\n \"tag\": "Renaissancist",\n \"popularity\": 14838\n },\n {\n \"tag\": "imaginant",\n \"popularity\": 14817\n },\n {\n \"tag\": "supercensure",\n \"popularity\": 14795\n },\n {\n \"tag\": "festilogy",\n \"popularity\": 14773\n },\n {\n \"tag\": "regression",\n \"popularity\": 14752\n },\n {\n \"tag\": "mesobregmate languorously",\n \"popularity\": 14730\n },\n {\n \"tag\": "unsupernaturalized",\n \"popularity\": 14709\n },\n {\n \"tag\": "boobyish",\n \"popularity\": 14687\n },\n {\n \"tag\": "scopolamine",\n \"popularity\": 14666\n },\n {\n \"tag\": "reamputation unchristianly",\n \"popularity\": 14645\n },\n {\n \"tag\": "cuneatic",\n \"popularity\": 14623\n },\n {\n \"tag\": "heathberry",\n \"popularity\": 14602\n },\n {\n \"tag\": "hate",\n \"popularity\": 14581\n },\n {\n \"tag\": "redeemableness",\n \"popularity\": 14560\n },\n {\n \"tag\": "damasse",\n \"popularity\": 14539\n },\n {\n \"tag\": "thrillsome",\n \"popularity\": 14518\n },\n {\n \"tag\": "disseverment",\n \"popularity\": 14497\n },\n {\n \"tag\": "underbishopric Ostyak",\n \"popularity\": 14476\n },\n {\n \"tag\": "Exoascales",\n \"popularity\": 14455\n },\n {\n \"tag\": "soiled",\n \"popularity\": 14434\n },\n {\n \"tag\": "Cain",\n \"popularity\": 14413\n },\n {\n \"tag\": "mismanageable arenae",\n \"popularity\": 14392\n },\n {\n \"tag\": "manducate unhinderably",\n \"popularity\": 14372\n },\n {\n \"tag\": "peregrin",\n \"popularity\": 14351\n },\n {\n \"tag\": "musicianly",\n \"popularity\": 14330\n },\n {\n \"tag\": "aln",\n \"popularity\": 14310\n },\n {\n \"tag\": "intercentrum",\n \"popularity\": 14289\n },\n {\n \"tag\": "roothold",\n \"popularity\": 14269\n },\n {\n \"tag\": "jane aneurism",\n \"popularity\": 14248\n },\n {\n \"tag\": "insinuatively forefeel phytolatrous",\n \"popularity\": 14228\n },\n {\n \"tag\": "kanchil",\n \"popularity\": 14208\n },\n {\n \"tag\": "Austrophile",\n \"popularity\": 14187\n },\n {\n \"tag\": "unterrorized",\n \"popularity\": 14167\n },\n {\n \"tag\": "admeasure",\n \"popularity\": 14147\n },\n {\n \"tag\": "electrodissolution",\n \"popularity\": 14127\n },\n {\n \"tag\": "unweddedly",\n \"popularity\": 14107\n },\n {\n \"tag\": "unannoying",\n \"popularity\": 14087\n },\n {\n \"tag\": "uningenuous",\n \"popularity\": 14067\n },\n {\n \"tag\": "omnibenevolent",\n \"popularity\": 14047\n },\n {\n \"tag\": "commissure",\n \"popularity\": 14027\n },\n {\n \"tag\": "tellureted",\n \"popularity\": 14007\n },\n {\n \"tag\": "suffragan",\n \"popularity\": 13987\n },\n {\n \"tag\": "sphaeriaceous",\n \"popularity\": 13967\n },\n {\n \"tag\": "unfearing",\n \"popularity\": 13947\n },\n {\n \"tag\": "stentoriousness precounsellor",\n \"popularity\": 13928\n },\n {\n \"tag\": "haemaspectroscope",\n \"popularity\": 13908\n },\n {\n \"tag\": "teras",\n \"popularity\": 13888\n },\n {\n \"tag\": "pulicine",\n \"popularity\": 13869\n },\n {\n \"tag\": "colicystopyelitis",\n \"popularity\": 13849\n },\n {\n \"tag\": "Physalia",\n \"popularity\": 13830\n },\n {\n \"tag\": "Saxicolidae",\n \"popularity\": 13810\n },\n {\n \"tag\": "peritonital",\n \"popularity\": 13791\n },\n {\n \"tag\": "dysphotic",\n \"popularity\": 13771\n },\n {\n \"tag\": "unabandoned",\n \"popularity\": 13752\n },\n {\n \"tag\": "rashful",\n \"popularity\": 13733\n },\n {\n \"tag\": "goodyness Manobo",\n \"popularity\": 13714\n },\n {\n \"tag\": "glaring",\n \"popularity\": 13694\n },\n {\n \"tag\": "horrorful",\n \"popularity\": 13675\n },\n {\n \"tag\": "intercepting",\n \"popularity\": 13656\n },\n {\n \"tag\": "semifine",\n \"popularity\": 13637\n },\n {\n \"tag\": "Gaypoo",\n \"popularity\": 13618\n },\n {\n \"tag\": "Metrosideros",\n \"popularity\": 13599\n },\n {\n \"tag\": "thoracicolumbar",\n \"popularity\": 13580\n },\n {\n \"tag\": "unserried",\n \"popularity\": 13561\n },\n {\n \"tag\": "keeperess cauterization",\n \"popularity\": 13542\n },\n {\n \"tag\": "administrant",\n \"popularity\": 13523\n },\n {\n \"tag\": "unpropitiatedness",\n \"popularity\": 13505\n },\n {\n \"tag\": "pensileness",\n \"popularity\": 13486\n },\n {\n \"tag\": "quinaldic unreceivable",\n \"popularity\": 13467\n },\n {\n \"tag\": "Carnaria",\n \"popularity\": 13448\n },\n {\n \"tag\": "azothionium wurrus",\n \"popularity\": 13430\n },\n {\n \"tag\": "mistresshood",\n \"popularity\": 13411\n },\n {\n \"tag\": "Savara",\n \"popularity\": 13393\n },\n {\n \"tag\": "dasyurine",\n \"popularity\": 13374\n },\n {\n \"tag\": "superideal",\n \"popularity\": 13356\n },\n {\n \"tag\": "Parisianize",\n \"popularity\": 13337\n },\n {\n \"tag\": "underearth",\n \"popularity\": 13319\n },\n {\n \"tag\": "athrogenic",\n \"popularity\": 13301\n },\n {\n \"tag\": "communicate",\n \"popularity\": 13282\n },\n {\n \"tag\": "denervation enworthed",\n \"popularity\": 13264\n },\n {\n \"tag\": "subbromide",\n \"popularity\": 13246\n },\n {\n \"tag\": "stenocoriasis",\n \"popularity\": 13228\n },\n {\n \"tag\": "facetiousness",\n \"popularity\": 13209\n },\n {\n \"tag\": "twaddling",\n \"popularity\": 13191\n },\n {\n \"tag\": "tetartoconid",\n \"popularity\": 13173\n },\n {\n \"tag\": "audiophile",\n \"popularity\": 13155\n },\n {\n \"tag\": "fustigate",\n \"popularity\": 13137\n },\n {\n \"tag\": "Sorbian cacophonia",\n \"popularity\": 13119\n },\n {\n \"tag\": "fondish",\n \"popularity\": 13101\n },\n {\n \"tag\": "endomastoiditis",\n \"popularity\": 13084\n },\n {\n \"tag\": "sniptious",\n \"popularity\": 13066\n },\n {\n \"tag\": "glochidiate",\n \"popularity\": 13048\n },\n {\n \"tag\": "polycarboxylic",\n \"popularity\": 13030\n },\n {\n \"tag\": "stamp",\n \"popularity\": 13012\n },\n {\n \"tag\": "tritonymph endotoxoid",\n \"popularity\": 12995\n },\n {\n \"tag\": "wolfskin",\n \"popularity\": 12977\n },\n {\n \"tag\": "oncosimeter",\n \"popularity\": 12959\n },\n {\n \"tag\": "outward",\n \"popularity\": 12942\n },\n {\n \"tag\": "circumscribed",\n \"popularity\": 12924\n },\n {\n \"tag\": "autohemolytic",\n \"popularity\": 12907\n },\n {\n \"tag\": "isorhamnose",\n \"popularity\": 12889\n },\n {\n \"tag\": "monarchomachic",\n \"popularity\": 12872\n },\n {\n \"tag\": "phaenomenon",\n \"popularity\": 12855\n },\n {\n \"tag\": "angiopressure",\n \"popularity\": 12837\n },\n {\n \"tag\": "similarize",\n \"popularity\": 12820\n },\n {\n \"tag\": "unseeable",\n \"popularity\": 12803\n },\n {\n \"tag\": "Toryize",\n \"popularity\": 12785\n },\n {\n \"tag\": "fruitling",\n \"popularity\": 12768\n },\n {\n \"tag\": "axle",\n \"popularity\": 12751\n },\n {\n \"tag\": "priestal cocked",\n \"popularity\": 12734\n },\n {\n \"tag\": "serotoxin",\n \"popularity\": 12717\n },\n {\n \"tag\": "unmovably",\n \"popularity\": 12700\n },\n {\n \"tag\": "darbha",\n \"popularity\": 12683\n },\n {\n \"tag\": "Mongolize",\n \"popularity\": 12666\n },\n {\n \"tag\": "clusteringly",\n \"popularity\": 12649\n },\n {\n \"tag\": "tendence",\n \"popularity\": 12632\n },\n {\n \"tag\": "foziness",\n \"popularity\": 12615\n },\n {\n \"tag\": "brickkiln lithify",\n \"popularity\": 12598\n },\n {\n \"tag\": "unpriest",\n \"popularity\": 12581\n },\n {\n \"tag\": "convincer",\n \"popularity\": 12564\n },\n {\n \"tag\": "mornlike",\n \"popularity\": 12548\n },\n {\n \"tag\": "overaddiction ostentatiousness",\n \"popularity\": 12531\n },\n {\n \"tag\": "diffusively moccasin pendom",\n \"popularity\": 12514\n },\n {\n \"tag\": "boose",\n \"popularity\": 12498\n },\n {\n \"tag\": "myonosus",\n \"popularity\": 12481\n },\n {\n \"tag\": "handsome",\n \"popularity\": 12464\n },\n {\n \"tag\": "paroxysmic",\n \"popularity\": 12448\n },\n {\n \"tag\": "Ulidian",\n \"popularity\": 12431\n },\n {\n \"tag\": "heartache",\n \"popularity\": 12415\n },\n {\n \"tag\": "torporize",\n \"popularity\": 12398\n },\n {\n \"tag\": "hippish",\n \"popularity\": 12382\n },\n {\n \"tag\": "stigmal militation",\n \"popularity\": 12366\n },\n {\n \"tag\": "matmaker",\n \"popularity\": 12349\n },\n {\n \"tag\": "marantaceous bivoluminous",\n \"popularity\": 12333\n },\n {\n \"tag\": "Uraniidae",\n \"popularity\": 12317\n },\n {\n \"tag\": "risper",\n \"popularity\": 12301\n },\n {\n \"tag\": "tintinnabulation",\n \"popularity\": 12284\n },\n {\n \"tag\": "tributorian",\n \"popularity\": 12268\n },\n {\n \"tag\": "ashamedly",\n \"popularity\": 12252\n },\n {\n \"tag\": "Macrourus",\n \"popularity\": 12236\n },\n {\n \"tag\": "Chora",\n \"popularity\": 12220\n },\n {\n \"tag\": "caul",\n \"popularity\": 12204\n },\n {\n \"tag\": "exsector",\n \"popularity\": 12188\n },\n {\n \"tag\": "acutish",\n \"popularity\": 12172\n },\n {\n \"tag\": "amphichrome",\n \"popularity\": 12156\n },\n {\n \"tag\": "guarder",\n \"popularity\": 12140\n },\n {\n \"tag\": "sculpturally",\n \"popularity\": 12124\n },\n {\n \"tag\": "benightmare",\n \"popularity\": 12108\n },\n {\n \"tag\": "chucky",\n \"popularity\": 12093\n },\n {\n \"tag\": "Venetian",\n \"popularity\": 12077\n },\n {\n \"tag\": "autotheater",\n \"popularity\": 12061\n },\n {\n \"tag\": "planarioid",\n \"popularity\": 12045\n },\n {\n \"tag\": "handkerchiefful",\n \"popularity\": 12030\n },\n {\n \"tag\": "fuliginousness potentize",\n \"popularity\": 12014\n },\n {\n \"tag\": "pantheum",\n \"popularity\": 11998\n },\n {\n \"tag\": "heavyweight",\n \"popularity\": 11983\n },\n {\n \"tag\": "unbrick",\n \"popularity\": 11967\n },\n {\n \"tag\": "duomachy",\n \"popularity\": 11952\n },\n {\n \"tag\": "polyphyodont",\n \"popularity\": 11936\n },\n {\n \"tag\": "hibernacle",\n \"popularity\": 11921\n },\n {\n \"tag\": "undistend",\n \"popularity\": 11905\n },\n {\n \"tag\": "hystericky",\n \"popularity\": 11890\n },\n {\n \"tag\": "paleolimnology",\n \"popularity\": 11875\n },\n {\n \"tag\": "cedarware",\n \"popularity\": 11859\n },\n {\n \"tag\": "overwrested",\n \"popularity\": 11844\n },\n {\n \"tag\": "Syriacism",\n \"popularity\": 11829\n },\n {\n \"tag\": "pretan",\n \"popularity\": 11813\n },\n {\n \"tag\": "formant",\n \"popularity\": 11798\n },\n {\n \"tag\": "pharmacopoeist Fedia",\n \"popularity\": 11783\n },\n {\n \"tag\": "exorcist eerisome",\n \"popularity\": 11768\n },\n {\n \"tag\": "separation",\n \"popularity\": 11753\n },\n {\n \"tag\": "infancy",\n \"popularity\": 11738\n },\n {\n \"tag\": "ecrasite",\n \"popularity\": 11723\n },\n {\n \"tag\": "propolize",\n \"popularity\": 11708\n },\n {\n \"tag\": "uncram phyllin",\n \"popularity\": 11693\n },\n {\n \"tag\": "thymopathy",\n \"popularity\": 11678\n },\n {\n \"tag\": "omniscient",\n \"popularity\": 11663\n },\n {\n \"tag\": "coussinet hazer",\n \"popularity\": 11648\n },\n {\n \"tag\": "contributiveness",\n \"popularity\": 11633\n },\n {\n \"tag\": "septifluous",\n \"popularity\": 11618\n },\n {\n \"tag\": "halfness",\n \"popularity\": 11603\n },\n {\n \"tag\": "tocher",\n \"popularity\": 11589\n },\n {\n \"tag\": "monotonist",\n \"popularity\": 11574\n },\n {\n \"tag\": "headchair",\n \"popularity\": 11559\n },\n {\n \"tag\": "everywhence",\n \"popularity\": 11544\n },\n {\n \"tag\": "gerate",\n \"popularity\": 11530\n },\n {\n \"tag\": "unrepellent",\n \"popularity\": 11515\n },\n {\n \"tag\": "inidoneous",\n \"popularity\": 11500\n },\n {\n \"tag\": "Rifi",\n \"popularity\": 11486\n },\n {\n \"tag\": "unstop",\n \"popularity\": 11471\n },\n {\n \"tag\": "conformer",\n \"popularity\": 11457\n },\n {\n \"tag\": "vivisectionally",\n \"popularity\": 11442\n },\n {\n \"tag\": "nonfinishing",\n \"popularity\": 11428\n },\n {\n \"tag\": "tyranness",\n \"popularity\": 11413\n },\n {\n \"tag\": "shepherdage havoc",\n \"popularity\": 11399\n },\n {\n \"tag\": "coronale",\n \"popularity\": 11385\n },\n {\n \"tag\": "airmarker",\n \"popularity\": 11370\n },\n {\n \"tag\": "subpanel",\n \"popularity\": 11356\n },\n {\n \"tag\": "conciliation",\n \"popularity\": 11342\n },\n {\n \"tag\": "supergun",\n \"popularity\": 11327\n },\n {\n \"tag\": "photoheliography",\n \"popularity\": 11313\n },\n {\n \"tag\": "cacosmia",\n \"popularity\": 11299\n },\n {\n \"tag\": "caressant",\n \"popularity\": 11285\n },\n {\n \"tag\": "swivet",\n \"popularity\": 11270\n },\n {\n \"tag\": "coddler",\n \"popularity\": 11256\n },\n {\n \"tag\": "rakehellish",\n \"popularity\": 11242\n },\n {\n \"tag\": "recohabitation",\n \"popularity\": 11228\n },\n {\n \"tag\": "postillator",\n \"popularity\": 11214\n },\n {\n \"tag\": "receipt",\n \"popularity\": 11200\n },\n {\n \"tag\": "nonconformistical",\n \"popularity\": 11186\n },\n {\n \"tag\": "unglorified",\n \"popularity\": 11172\n },\n {\n \"tag\": "unordinariness",\n \"popularity\": 11158\n },\n {\n \"tag\": "tetrahydroxy",\n \"popularity\": 11144\n },\n {\n \"tag\": "haploperistomic corporeity",\n \"popularity\": 11130\n },\n {\n \"tag\": "varical",\n \"popularity\": 11117\n },\n {\n \"tag\": "pilferment",\n \"popularity\": 11103\n },\n {\n \"tag\": "reverentially playcraft",\n \"popularity\": 11089\n },\n {\n \"tag\": "unretentive",\n \"popularity\": 11075\n },\n {\n \"tag\": "readiness",\n \"popularity\": 11061\n },\n {\n \"tag\": "thermomagnetism",\n \"popularity\": 11048\n },\n {\n \"tag\": "spotless",\n \"popularity\": 11034\n },\n {\n \"tag\": "semishrubby",\n \"popularity\": 11020\n },\n {\n \"tag\": "metrotomy",\n \"popularity\": 11007\n },\n {\n \"tag\": "hocker",\n \"popularity\": 10993\n },\n {\n \"tag\": "anecdotal",\n \"popularity\": 10979\n },\n {\n \"tag\": "tetrabelodont",\n \"popularity\": 10966\n },\n {\n \"tag\": "Ramillied",\n \"popularity\": 10952\n },\n {\n \"tag\": "sympatheticism",\n \"popularity\": 10939\n },\n {\n \"tag\": "kiskatom",\n \"popularity\": 10925\n },\n {\n \"tag\": "concyclically",\n \"popularity\": 10912\n },\n {\n \"tag\": "tunicless",\n \"popularity\": 10899\n },\n {\n \"tag\": "formalistic",\n \"popularity\": 10885\n },\n {\n \"tag\": "thermacogenesis",\n \"popularity\": 10872\n },\n {\n \"tag\": "multimotored",\n \"popularity\": 10858\n },\n {\n \"tag\": "inversive",\n \"popularity\": 10845\n },\n {\n \"tag\": "Jatki",\n \"popularity\": 10832\n },\n {\n \"tag\": "highest",\n \"popularity\": 10818\n },\n {\n \"tag\": "rubidic",\n \"popularity\": 10805\n },\n {\n \"tag\": "acranial",\n \"popularity\": 10792\n },\n {\n \"tag\": "pulvinulus",\n \"popularity\": 10779\n },\n {\n \"tag\": "nattiness",\n \"popularity\": 10766\n },\n {\n \"tag\": "antisimoniacal",\n \"popularity\": 10752\n },\n {\n \"tag\": "tetanize",\n \"popularity\": 10739\n },\n {\n \"tag\": "spectrophobia",\n \"popularity\": 10726\n },\n {\n \"tag\": "monopolitical",\n \"popularity\": 10713\n },\n {\n \"tag\": "teallite",\n \"popularity\": 10700\n },\n {\n \"tag\": "alicyclic interpellator",\n \"popularity\": 10687\n },\n {\n \"tag\": "nonsynthesized",\n \"popularity\": 10674\n },\n {\n \"tag\": "wheelwrighting",\n \"popularity\": 10661\n },\n {\n \"tag\": "pelliculate",\n \"popularity\": 10648\n },\n {\n \"tag\": "Euphyllopoda",\n \"popularity\": 10635\n },\n {\n \"tag\": "graver",\n \"popularity\": 10622\n },\n {\n \"tag\": "automorph",\n \"popularity\": 10609\n },\n {\n \"tag\": "underhanded",\n \"popularity\": 10597\n },\n {\n \"tag\": "causal",\n \"popularity\": 10584\n },\n {\n \"tag\": "odoom",\n \"popularity\": 10571\n },\n {\n \"tag\": "apodictical",\n \"popularity\": 10558\n },\n {\n \"tag\": "foundery",\n \"popularity\": 10545\n },\n {\n \"tag\": "unneighbored",\n \"popularity\": 10533\n },\n {\n \"tag\": "woolshearing",\n \"popularity\": 10520\n },\n {\n \"tag\": "boschveld",\n \"popularity\": 10507\n },\n {\n \"tag\": "unhardened lipopod",\n \"popularity\": 10495\n },\n {\n \"tag\": "unenriching",\n \"popularity\": 10482\n },\n {\n \"tag\": "spak",\n \"popularity\": 10469\n },\n {\n \"tag\": "yogasana",\n \"popularity\": 10457\n },\n {\n \"tag\": "depoetize",\n \"popularity\": 10444\n },\n {\n \"tag\": "parousiamania",\n \"popularity\": 10432\n },\n {\n \"tag\": "longlegs",\n \"popularity\": 10419\n },\n {\n \"tag\": "gelatinizability",\n \"popularity\": 10407\n },\n {\n \"tag\": "edeology",\n \"popularity\": 10394\n },\n {\n \"tag\": "sodwork",\n \"popularity\": 10382\n },\n {\n \"tag\": "somnambule",\n \"popularity\": 10369\n },\n {\n \"tag\": "antiquing",\n \"popularity\": 10357\n },\n {\n \"tag\": "intaker",\n \"popularity\": 10344\n },\n {\n \"tag\": "Gerberia",\n \"popularity\": 10332\n },\n {\n \"tag\": "preadmit",\n \"popularity\": 10320\n },\n {\n \"tag\": "bullhorn",\n \"popularity\": 10307\n },\n {\n \"tag\": "sororal",\n \"popularity\": 10295\n },\n {\n \"tag\": "phaeophyceous",\n \"popularity\": 10283\n },\n {\n \"tag\": "omphalopsychite",\n \"popularity\": 10271\n },\n {\n \"tag\": "substantious",\n \"popularity\": 10258\n },\n {\n \"tag\": "undemonstratively",\n \"popularity\": 10246\n },\n {\n \"tag\": "corallike blackit",\n \"popularity\": 10234\n },\n {\n \"tag\": "amoebous",\n \"popularity\": 10222\n },\n {\n \"tag\": "Polypodium",\n \"popularity\": 10210\n },\n {\n \"tag\": "blodite",\n \"popularity\": 10198\n },\n {\n \"tag\": "hordarian",\n \"popularity\": 10186\n },\n {\n \"tag\": "nonmoral",\n \"popularity\": 10174\n },\n {\n \"tag\": "dredgeful",\n \"popularity\": 10162\n },\n {\n \"tag\": "nourishingly",\n \"popularity\": 10150\n },\n {\n \"tag\": "seamy",\n \"popularity\": 10138\n },\n {\n \"tag\": "vara",\n \"popularity\": 10126\n },\n {\n \"tag\": "incorruptibleness",\n \"popularity\": 10114\n },\n {\n \"tag\": "manipulator",\n \"popularity\": 10102\n },\n {\n \"tag\": "chromodiascope uncountably",\n \"popularity\": 10090\n },\n {\n \"tag\": "typhemia",\n \"popularity\": 10078\n },\n {\n \"tag\": "Smalcaldic",\n \"popularity\": 10066\n },\n {\n \"tag\": "precontrive",\n \"popularity\": 10054\n },\n {\n \"tag\": "sowarry",\n \"popularity\": 10042\n },\n {\n \"tag\": "monopodic",\n \"popularity\": 10031\n },\n {\n \"tag\": "recodify",\n \"popularity\": 10019\n },\n {\n \"tag\": "phosphowolframic rimple",\n \"popularity\": 10007\n },\n {\n \"tag\": "triconch",\n \"popularity\": 9995\n },\n {\n \"tag\": "pycnodontoid",\n \"popularity\": 9984\n },\n {\n \"tag\": "bradyspermatism",\n \"popularity\": 9972\n },\n {\n \"tag\": "extensionist",\n \"popularity\": 9960\n },\n {\n \"tag\": "characterize",\n \"popularity\": 9949\n },\n {\n \"tag\": "anatreptic proteolytic",\n \"popularity\": 9937\n },\n {\n \"tag\": "waterboard",\n \"popularity\": 9925\n },\n {\n \"tag\": "allopathically",\n \"popularity\": 9914\n },\n {\n \"tag\": "arithmetician",\n \"popularity\": 9902\n },\n {\n \"tag\": "subsist",\n \"popularity\": 9891\n },\n {\n \"tag\": "Islamitish",\n \"popularity\": 9879\n },\n {\n \"tag\": "biddy",\n \"popularity\": 9868\n },\n {\n \"tag\": "reverberation",\n \"popularity\": 9856\n },\n {\n \"tag\": "Zaporogue",\n \"popularity\": 9845\n },\n {\n \"tag\": "soapberry",\n \"popularity\": 9833\n },\n {\n \"tag\": "physiognomics",\n \"popularity\": 9822\n },\n {\n \"tag\": "hospitalization",\n \"popularity\": 9810\n },\n {\n \"tag\": "dissembler",\n \"popularity\": 9799\n },\n {\n \"tag\": "festinate",\n \"popularity\": 9788\n },\n {\n \"tag\": "angiectopia",\n \"popularity\": 9776\n },\n {\n \"tag\": "Pulicidae",\n \"popularity\": 9765\n },\n {\n \"tag\": "beslimer",\n \"popularity\": 9754\n },\n {\n \"tag\": "nontreaty",\n \"popularity\": 9743\n },\n {\n \"tag\": "unhaggled",\n \"popularity\": 9731\n },\n {\n \"tag\": "catfall",\n \"popularity\": 9720\n },\n {\n \"tag\": "stola",\n \"popularity\": 9709\n },\n {\n \"tag\": "pataco",\n \"popularity\": 9698\n },\n {\n \"tag\": "ontologistic",\n \"popularity\": 9686\n },\n {\n \"tag\": "aerosphere",\n \"popularity\": 9675\n },\n {\n \"tag\": "deobstruent",\n \"popularity\": 9664\n },\n {\n \"tag\": "threepence",\n \"popularity\": 9653\n },\n {\n \"tag\": "cyprinoid",\n \"popularity\": 9642\n },\n {\n \"tag\": "overbank",\n \"popularity\": 9631\n },\n {\n \"tag\": "prostyle",\n \"popularity\": 9620\n },\n {\n \"tag\": "photoactivation",\n \"popularity\": 9609\n },\n {\n \"tag\": "homothetic",\n \"popularity\": 9598\n },\n {\n \"tag\": "roguedom",\n \"popularity\": 9587\n },\n {\n \"tag\": "underschool",\n \"popularity\": 9576\n },\n {\n \"tag\": "tractility",\n \"popularity\": 9565\n },\n {\n \"tag\": "gardenin",\n \"popularity\": 9554\n },\n {\n \"tag\": "Micromastictora",\n \"popularity\": 9543\n },\n {\n \"tag\": "gossypine",\n \"popularity\": 9532\n },\n {\n \"tag\": "amylodyspepsia",\n \"popularity\": 9521\n },\n {\n \"tag\": "Luciana",\n \"popularity\": 9510\n },\n {\n \"tag\": "meetly nonfisherman",\n \"popularity\": 9500\n },\n {\n \"tag\": "backhanded",\n \"popularity\": 9489\n },\n {\n \"tag\": "decrustation",\n \"popularity\": 9478\n },\n {\n \"tag\": "pinrail",\n \"popularity\": 9467\n },\n {\n \"tag\": "Mahori",\n \"popularity\": 9456\n },\n {\n \"tag\": "unsizable",\n \"popularity\": 9446\n },\n {\n \"tag\": "disawa",\n \"popularity\": 9435\n },\n {\n \"tag\": "launderability inconsidered",\n \"popularity\": 9424\n },\n {\n \"tag\": "unclassical",\n \"popularity\": 9414\n },\n {\n \"tag\": "inobtrusiveness",\n \"popularity\": 9403\n },\n {\n \"tag\": "sialogenous",\n \"popularity\": 9392\n },\n {\n \"tag\": "sulphonamide",\n \"popularity\": 9382\n },\n {\n \"tag\": "diluvion",\n \"popularity\": 9371\n },\n {\n \"tag\": "deuteranope",\n \"popularity\": 9361\n },\n {\n \"tag\": "addition",\n \"popularity\": 9350\n },\n {\n \"tag\": "bockeret",\n \"popularity\": 9339\n },\n {\n \"tag\": "unidentified",\n \"popularity\": 9329\n },\n {\n \"tag\": "caryatic",\n \"popularity\": 9318\n },\n {\n \"tag\": "misattribution",\n \"popularity\": 9308\n },\n {\n \"tag\": "outray",\n \"popularity\": 9297\n },\n {\n \"tag\": "areometrical",\n \"popularity\": 9287\n },\n {\n \"tag\": "antilogism",\n \"popularity\": 9277\n },\n {\n \"tag\": "inadjustable",\n \"popularity\": 9266\n },\n {\n \"tag\": "byssus",\n \"popularity\": 9256\n },\n {\n \"tag\": "trun",\n \"popularity\": 9245\n },\n {\n \"tag\": "thereology",\n \"popularity\": 9235\n },\n {\n \"tag\": "extort",\n \"popularity\": 9225\n },\n {\n \"tag\": "bumpkin",\n \"popularity\": 9214\n },\n {\n \"tag\": "sulphobenzide",\n \"popularity\": 9204\n },\n {\n \"tag\": "hydrogeology",\n \"popularity\": 9194\n },\n {\n \"tag\": "nidulariaceous",\n \"popularity\": 9183\n },\n {\n \"tag\": "propodiale",\n \"popularity\": 9173\n },\n {\n \"tag\": "fierily",\n \"popularity\": 9163\n },\n {\n \"tag\": "aerotonometry",\n \"popularity\": 9153\n },\n {\n \"tag\": "pelobatid oversuperstitious",\n \"popularity\": 9142\n },\n {\n \"tag\": "restringent",\n \"popularity\": 9132\n },\n {\n \"tag\": "tetrapodic",\n \"popularity\": 9122\n },\n {\n \"tag\": "heroicness Vendidad",\n \"popularity\": 9112\n },\n {\n \"tag\": "Sphingurus",\n \"popularity\": 9102\n },\n {\n \"tag\": "sclerote",\n \"popularity\": 9092\n },\n {\n \"tag\": "unkeyed",\n \"popularity\": 9082\n },\n {\n \"tag\": "superparliamentary",\n \"popularity\": 9072\n },\n {\n \"tag\": "hetericism",\n \"popularity\": 9061\n },\n {\n \"tag\": "hucklebone",\n \"popularity\": 9051\n },\n {\n \"tag\": "yojan",\n \"popularity\": 9041\n },\n {\n \"tag\": "bossed",\n \"popularity\": 9031\n },\n {\n \"tag\": "spiderwork",\n \"popularity\": 9021\n },\n {\n \"tag\": "millfeed dullery",\n \"popularity\": 9011\n },\n {\n \"tag\": "adnoun",\n \"popularity\": 9001\n },\n {\n \"tag\": "mesometric",\n \"popularity\": 8992\n },\n {\n \"tag\": "doublehandedness",\n \"popularity\": 8982\n },\n {\n \"tag\": "suppurant",\n \"popularity\": 8972\n },\n {\n \"tag\": "Berlinize",\n \"popularity\": 8962\n },\n {\n \"tag\": "sontag",\n \"popularity\": 8952\n },\n {\n \"tag\": "biplane",\n \"popularity\": 8942\n },\n {\n \"tag\": "insula",\n \"popularity\": 8932\n },\n {\n \"tag\": "unbrand",\n \"popularity\": 8922\n },\n {\n \"tag\": "Basilosaurus",\n \"popularity\": 8913\n },\n {\n \"tag\": "prenomination",\n \"popularity\": 8903\n },\n {\n \"tag\": "untextual",\n \"popularity\": 8893\n },\n {\n \"tag\": "coleslaw",\n \"popularity\": 8883\n },\n {\n \"tag\": "langsyne",\n \"popularity\": 8874\n },\n {\n \"tag\": "impede",\n \"popularity\": 8864\n },\n {\n \"tag\": "irrigator",\n \"popularity\": 8854\n },\n {\n \"tag\": "deflocculation",\n \"popularity\": 8844\n },\n {\n \"tag\": "narghile",\n \"popularity\": 8835\n },\n {\n \"tag\": "unguardedly ebenaceous",\n \"popularity\": 8825\n },\n {\n \"tag\": "conversantly subocular",\n \"popularity\": 8815\n },\n {\n \"tag\": "hydroponic",\n \"popularity\": 8806\n },\n {\n \"tag\": "anthropopsychism",\n \"popularity\": 8796\n },\n {\n \"tag\": "panoptic",\n \"popularity\": 8787\n },\n {\n \"tag\": "insufferable",\n \"popularity\": 8777\n },\n {\n \"tag\": "salema",\n \"popularity\": 8768\n },\n {\n \"tag\": "Myriapoda",\n \"popularity\": 8758\n },\n {\n \"tag\": "regarrison",\n \"popularity\": 8748\n },\n {\n \"tag\": "overlearned",\n \"popularity\": 8739\n },\n {\n \"tag\": "ultraroyalist conventical bureaucratical",\n \"popularity\": 8729\n },\n {\n \"tag\": "epicaridan",\n \"popularity\": 8720\n },\n {\n \"tag\": "poetastress",\n \"popularity\": 8711\n },\n {\n \"tag\": "monophthalmus",\n \"popularity\": 8701\n },\n {\n \"tag\": "simnel",\n \"popularity\": 8692\n },\n {\n \"tag\": "compotor",\n \"popularity\": 8682\n },\n {\n \"tag\": "hydrolase",\n \"popularity\": 8673\n },\n {\n \"tag\": "attemptless",\n \"popularity\": 8663\n },\n {\n \"tag\": "visceroptosis",\n \"popularity\": 8654\n },\n {\n \"tag\": "unpreparedly",\n \"popularity\": 8645\n },\n {\n \"tag\": "mastage",\n \"popularity\": 8635\n },\n {\n \"tag\": "preinfluence",\n \"popularity\": 8626\n },\n {\n \"tag\": "Siwan",\n \"popularity\": 8617\n },\n {\n \"tag\": "ceratotheca belvedere",\n \"popularity\": 8607\n },\n {\n \"tag\": "disenablement",\n \"popularity\": 8598\n },\n {\n \"tag\": "nine",\n \"popularity\": 8589\n },\n {\n \"tag\": "spellingdown abridgment",\n \"popularity\": 8580\n },\n {\n \"tag\": "twilightless",\n \"popularity\": 8571\n },\n {\n \"tag\": "overflow",\n \"popularity\": 8561\n },\n {\n \"tag\": "mismeasurement",\n \"popularity\": 8552\n },\n {\n \"tag\": "nawabship",\n \"popularity\": 8543\n },\n {\n \"tag\": "Phrynosoma",\n \"popularity\": 8534\n },\n {\n \"tag\": "unanticipatingly",\n \"popularity\": 8525\n },\n {\n \"tag\": "blankite",\n \"popularity\": 8516\n },\n {\n \"tag\": "role",\n \"popularity\": 8506\n },\n {\n \"tag\": "peperine edelweiss",\n \"popularity\": 8497\n },\n {\n \"tag\": "unhysterical",\n \"popularity\": 8488\n },\n {\n \"tag\": "attentiveness",\n \"popularity\": 8479\n },\n {\n \"tag\": "scintillant",\n \"popularity\": 8470\n },\n {\n \"tag\": "stenostomatous",\n \"popularity\": 8461\n },\n {\n \"tag\": "pectinite",\n \"popularity\": 8452\n },\n {\n \"tag\": "herring",\n \"popularity\": 8443\n },\n {\n \"tag\": "interroom",\n \"popularity\": 8434\n },\n {\n \"tag\": "laccol",\n \"popularity\": 8425\n },\n {\n \"tag\": "unpartably kylite",\n \"popularity\": 8416\n },\n {\n \"tag\": "spirivalve",\n \"popularity\": 8407\n },\n {\n \"tag\": "hoosegow",\n \"popularity\": 8398\n },\n {\n \"tag\": "doat",\n \"popularity\": 8389\n },\n {\n \"tag\": "amphibian",\n \"popularity\": 8380\n },\n {\n \"tag\": "exposit",\n \"popularity\": 8371\n },\n {\n \"tag\": "canopy",\n \"popularity\": 8363\n },\n {\n \"tag\": "houndlike",\n \"popularity\": 8354\n },\n {\n \"tag\": "spikebill",\n \"popularity\": 8345\n },\n {\n \"tag\": "wiseacre pyrotechnic",\n \"popularity\": 8336\n },\n {\n \"tag\": "confessingly woodman",\n \"popularity\": 8327\n },\n {\n \"tag\": "overside",\n \"popularity\": 8318\n },\n {\n \"tag\": "oftwhiles",\n \"popularity\": 8310\n },\n {\n \"tag\": "Musophagidae",\n \"popularity\": 8301\n },\n {\n \"tag\": "slumberer",\n \"popularity\": 8292\n },\n {\n \"tag\": "leiotrichy",\n \"popularity\": 8283\n },\n {\n \"tag\": "Mantispidae",\n \"popularity\": 8275\n },\n {\n \"tag\": "perceptually",\n \"popularity\": 8266\n },\n {\n \"tag\": "biller",\n \"popularity\": 8257\n },\n {\n \"tag\": "eudaemonical",\n \"popularity\": 8249\n },\n {\n \"tag\": "underfiend",\n \"popularity\": 8240\n },\n {\n \"tag\": "impartible",\n \"popularity\": 8231\n },\n {\n \"tag\": "saxicavous",\n \"popularity\": 8223\n },\n {\n \"tag\": "yapster",\n \"popularity\": 8214\n },\n {\n \"tag\": "aliseptal",\n \"popularity\": 8205\n },\n {\n \"tag\": "omniparient",\n \"popularity\": 8197\n },\n {\n \"tag\": "nishiki",\n \"popularity\": 8188\n },\n {\n \"tag\": "yuzluk",\n \"popularity\": 8180\n },\n {\n \"tag\": "solderer",\n \"popularity\": 8171\n },\n {\n \"tag\": "Pinna",\n \"popularity\": 8162\n },\n {\n \"tag\": "reinterfere",\n \"popularity\": 8154\n },\n {\n \"tag\": "superepic",\n \"popularity\": 8145\n },\n {\n \"tag\": "ronquil",\n \"popularity\": 8137\n },\n {\n \"tag\": "bratstvo",\n \"popularity\": 8128\n },\n {\n \"tag\": "Thea",\n \"popularity\": 8120\n },\n {\n \"tag\": "hermaphroditical",\n \"popularity\": 8111\n },\n {\n \"tag\": "enlief",\n \"popularity\": 8103\n },\n {\n \"tag\": "Jesuate",\n \"popularity\": 8095\n },\n {\n \"tag\": "gaysome",\n \"popularity\": 8086\n },\n {\n \"tag\": "iliohypogastric",\n \"popularity\": 8078\n },\n {\n \"tag\": "regardance",\n \"popularity\": 8069\n },\n {\n \"tag\": "cumulately",\n \"popularity\": 8061\n },\n {\n \"tag\": "haustorial nucleolocentrosome",\n \"popularity\": 8053\n },\n {\n \"tag\": "cosmocrat",\n \"popularity\": 8044\n },\n {\n \"tag\": "onyxitis",\n \"popularity\": 8036\n },\n {\n \"tag\": "Cabinda",\n \"popularity\": 8028\n },\n {\n \"tag\": "coresort",\n \"popularity\": 8019\n },\n {\n \"tag\": "drusy preformant",\n \"popularity\": 8011\n },\n {\n \"tag\": "piningly",\n \"popularity\": 8003\n },\n {\n \"tag\": "bootlessly",\n \"popularity\": 7994\n },\n {\n \"tag\": "talari",\n \"popularity\": 7986\n },\n {\n \"tag\": "amidoacetal",\n \"popularity\": 7978\n },\n {\n \"tag\": "pschent",\n \"popularity\": 7970\n },\n {\n \"tag\": "consumptional scarer titivate",\n \"popularity\": 7962\n },\n {\n \"tag\": "Anserinae",\n \"popularity\": 7953\n },\n {\n \"tag\": "flaunter",\n \"popularity\": 7945\n },\n {\n \"tag\": "reindeer",\n \"popularity\": 7937\n },\n {\n \"tag\": "disparage",\n \"popularity\": 7929\n },\n {\n \"tag\": "superheat",\n \"popularity\": 7921\n },\n {\n \"tag\": "Chromatium",\n \"popularity\": 7912\n },\n {\n \"tag\": "Tina",\n \"popularity\": 7904\n },\n {\n \"tag\": "rededicatory",\n \"popularity\": 7896\n },\n {\n \"tag\": "nontransient",\n \"popularity\": 7888\n },\n {\n \"tag\": "Phocaean brinkless",\n \"popularity\": 7880\n },\n {\n \"tag\": "ventriculose",\n \"popularity\": 7872\n },\n {\n \"tag\": "upplough",\n \"popularity\": 7864\n },\n {\n \"tag\": "succorless",\n \"popularity\": 7856\n },\n {\n \"tag\": "hayrake",\n \"popularity\": 7848\n },\n {\n \"tag\": "merriness amorphia",\n \"popularity\": 7840\n },\n {\n \"tag\": "merycism",\n \"popularity\": 7832\n },\n {\n \"tag\": "checkrow",\n \"popularity\": 7824\n },\n {\n \"tag\": "scry",\n \"popularity\": 7816\n },\n {\n \"tag\": "obvolve",\n \"popularity\": 7808\n },\n {\n \"tag\": "orchard",\n \"popularity\": 7800\n },\n {\n \"tag\": "isomerize",\n \"popularity\": 7792\n },\n {\n \"tag\": "competitrix",\n \"popularity\": 7784\n },\n {\n \"tag\": "unbannered",\n \"popularity\": 7776\n },\n {\n \"tag\": "undoctrined",\n \"popularity\": 7768\n },\n {\n \"tag\": "theologian",\n \"popularity\": 7760\n },\n {\n \"tag\": "nebby",\n \"popularity\": 7752\n },\n {\n \"tag\": "Cardiazol",\n \"popularity\": 7745\n },\n {\n \"tag\": "phagedenic",\n \"popularity\": 7737\n },\n {\n \"tag\": "nostalgic",\n \"popularity\": 7729\n },\n {\n \"tag\": "orthodoxy",\n \"popularity\": 7721\n },\n {\n \"tag\": "oversanguine",\n \"popularity\": 7713\n },\n {\n \"tag\": "lish",\n \"popularity\": 7705\n },\n {\n \"tag\": "ketogenic",\n \"popularity\": 7698\n },\n {\n \"tag\": "syndicalize",\n \"popularity\": 7690\n },\n {\n \"tag\": "leeftail",\n \"popularity\": 7682\n },\n {\n \"tag\": "bulbomedullary",\n \"popularity\": 7674\n },\n {\n \"tag\": "reletter",\n \"popularity\": 7667\n },\n {\n \"tag\": "bitterly",\n \"popularity\": 7659\n },\n {\n \"tag\": "participatory",\n \"popularity\": 7651\n },\n {\n \"tag\": "baldberry",\n \"popularity\": 7643\n },\n {\n \"tag\": "prowaterpower",\n \"popularity\": 7636\n },\n {\n \"tag\": "lexicographical",\n \"popularity\": 7628\n },\n {\n \"tag\": "Anisodactyli",\n \"popularity\": 7620\n },\n {\n \"tag\": "amphipodous",\n \"popularity\": 7613\n },\n {\n \"tag\": "triglandular",\n \"popularity\": 7605\n },\n {\n \"tag\": "xanthopsin",\n \"popularity\": 7597\n },\n {\n \"tag\": "indefinitude",\n \"popularity\": 7590\n },\n {\n \"tag\": "bookworm",\n \"popularity\": 7582\n },\n {\n \"tag\": "suffocative",\n \"popularity\": 7574\n },\n {\n \"tag\": "uncongested tyrant",\n \"popularity\": 7567\n },\n {\n \"tag\": "alow harmoniously Pamir",\n \"popularity\": 7559\n },\n {\n \"tag\": "monander",\n \"popularity\": 7552\n },\n {\n \"tag\": "bagatelle",\n \"popularity\": 7544\n },\n {\n \"tag\": "membranology",\n \"popularity\": 7537\n },\n {\n \"tag\": "parturifacient",\n \"popularity\": 7529\n },\n {\n \"tag\": "excitovascular",\n \"popularity\": 7522\n },\n {\n \"tag\": "homopolar",\n \"popularity\": 7514\n },\n {\n \"tag\": "phobiac",\n \"popularity\": 7507\n },\n {\n \"tag\": "clype",\n \"popularity\": 7499\n },\n {\n \"tag\": "unsubversive",\n \"popularity\": 7492\n },\n {\n \"tag\": "bostrychoidal scorpionwort",\n \"popularity\": 7484\n },\n {\n \"tag\": "biliteralism",\n \"popularity\": 7477\n },\n {\n \"tag\": "dentatocostate",\n \"popularity\": 7469\n },\n {\n \"tag\": "Pici",\n \"popularity\": 7462\n },\n {\n \"tag\": "sideritic",\n \"popularity\": 7454\n },\n {\n \"tag\": "syntaxis",\n \"popularity\": 7447\n },\n {\n \"tag\": "ingest",\n \"popularity\": 7440\n },\n {\n \"tag\": "rigmarolish",\n \"popularity\": 7432\n },\n {\n \"tag\": "ocreaceous",\n \"popularity\": 7425\n },\n {\n \"tag\": "hyperbrachyskelic",\n \"popularity\": 7418\n },\n {\n \"tag\": "basophobia",\n \"popularity\": 7410\n },\n {\n \"tag\": "substantialness",\n \"popularity\": 7403\n },\n {\n \"tag\": "agglutinoid",\n \"popularity\": 7396\n },\n {\n \"tag\": "longleaf",\n \"popularity\": 7388\n },\n {\n \"tag\": "electroengraving",\n \"popularity\": 7381\n },\n {\n \"tag\": "laparoenterotomy",\n \"popularity\": 7374\n },\n {\n \"tag\": "oxalylurea",\n \"popularity\": 7366\n },\n {\n \"tag\": "unattaintedly",\n \"popularity\": 7359\n },\n {\n \"tag\": "pennystone",\n \"popularity\": 7352\n },\n {\n \"tag\": "Plumbaginaceae",\n \"popularity\": 7345\n },\n {\n \"tag\": "horntip",\n \"popularity\": 7337\n },\n {\n \"tag\": "begrudge",\n \"popularity\": 7330\n },\n {\n \"tag\": "bechignoned",\n \"popularity\": 7323\n },\n {\n \"tag\": "hologonidium",\n \"popularity\": 7316\n },\n {\n \"tag\": "Pulian",\n \"popularity\": 7309\n },\n {\n \"tag\": "gratulation",\n \"popularity\": 7301\n },\n {\n \"tag\": "Sebright",\n \"popularity\": 7294\n },\n {\n \"tag\": "coinstantaneous emotionally",\n \"popularity\": 7287\n },\n {\n \"tag\": "thoracostracan",\n \"popularity\": 7280\n },\n {\n \"tag\": "saurodont",\n \"popularity\": 7273\n },\n {\n \"tag\": "coseat",\n \"popularity\": 7266\n },\n {\n \"tag\": "irascibility",\n \"popularity\": 7259\n },\n {\n \"tag\": "occlude",\n \"popularity\": 7251\n },\n {\n \"tag\": "metallurgist",\n \"popularity\": 7244\n },\n {\n \"tag\": "extraviolet",\n \"popularity\": 7237\n },\n {\n \"tag\": "clinic",\n \"popularity\": 7230\n },\n {\n \"tag\": "skater",\n \"popularity\": 7223\n },\n {\n \"tag\": "linguistic",\n \"popularity\": 7216\n },\n {\n \"tag\": "attacheship",\n \"popularity\": 7209\n },\n {\n \"tag\": "Rachianectes",\n \"popularity\": 7202\n },\n {\n \"tag\": "foliolose",\n \"popularity\": 7195\n },\n {\n \"tag\": "claudetite",\n \"popularity\": 7188\n },\n {\n \"tag\": "aphidian scratching",\n \"popularity\": 7181\n },\n {\n \"tag\": "Carida",\n \"popularity\": 7174\n },\n {\n \"tag\": "tiepin polymicroscope",\n \"popularity\": 7167\n },\n {\n \"tag\": "telpherage",\n \"popularity\": 7160\n },\n {\n \"tag\": "meek",\n \"popularity\": 7153\n },\n {\n \"tag\": "swiftness",\n \"popularity\": 7146\n },\n {\n \"tag\": "gentes",\n \"popularity\": 7139\n },\n {\n \"tag\": "uncommemorated",\n \"popularity\": 7132\n },\n {\n \"tag\": "Lazarus",\n \"popularity\": 7125\n },\n {\n \"tag\": "redivive",\n \"popularity\": 7119\n },\n {\n \"tag\": "nonfebrile",\n \"popularity\": 7112\n },\n {\n \"tag\": "nymphet",\n \"popularity\": 7105\n },\n {\n \"tag\": "areologically",\n \"popularity\": 7098\n },\n {\n \"tag\": "undonkey",\n \"popularity\": 7091\n },\n {\n \"tag\": "projecting",\n \"popularity\": 7084\n },\n {\n \"tag\": "pinnigrade",\n \"popularity\": 7077\n },\n {\n \"tag\": "butylation",\n \"popularity\": 7071\n },\n {\n \"tag\": "philologistic lenticle",\n \"popularity\": 7064\n },\n {\n \"tag\": "nooky",\n \"popularity\": 7057\n },\n {\n \"tag\": "incestuousness",\n \"popularity\": 7050\n },\n {\n \"tag\": "palingenetically",\n \"popularity\": 7043\n },\n {\n \"tag\": "mitochondria",\n \"popularity\": 7037\n },\n {\n \"tag\": "truthify",\n \"popularity\": 7030\n },\n {\n \"tag\": "titanyl",\n \"popularity\": 7023\n },\n {\n \"tag\": "bestride",\n \"popularity\": 7016\n },\n {\n \"tag\": "chende",\n \"popularity\": 7010\n },\n {\n \"tag\": "Chaucerian monophote",\n \"popularity\": 7003\n },\n {\n \"tag\": "cutback",\n \"popularity\": 6996\n },\n {\n \"tag\": "unpatiently",\n \"popularity\": 6989\n },\n {\n \"tag\": "subvitreous",\n \"popularity\": 6983\n },\n {\n \"tag\": "organizable",\n \"popularity\": 6976\n },\n {\n \"tag\": "anniverse uncomprehensible",\n \"popularity\": 6969\n },\n {\n \"tag\": "hyalescence",\n \"popularity\": 6963\n },\n {\n \"tag\": "amniochorial",\n \"popularity\": 6956\n },\n {\n \"tag\": "Corybantian",\n \"popularity\": 6949\n },\n {\n \"tag\": "genocide Scaphitidae",\n \"popularity\": 6943\n },\n {\n \"tag\": "accordionist",\n \"popularity\": 6936\n },\n {\n \"tag\": "becheck",\n \"popularity\": 6930\n },\n {\n \"tag\": "overproduce",\n \"popularity\": 6923\n },\n {\n \"tag\": "unmaniac frijolillo",\n \"popularity\": 6916\n },\n {\n \"tag\": "multisulcated",\n \"popularity\": 6910\n },\n {\n \"tag\": "wennebergite",\n \"popularity\": 6903\n },\n {\n \"tag\": "tautousious mowth",\n \"popularity\": 6897\n },\n {\n \"tag\": "marigold",\n \"popularity\": 6890\n },\n {\n \"tag\": "affray",\n \"popularity\": 6884\n },\n {\n \"tag\": "nonidolatrous",\n \"popularity\": 6877\n },\n {\n \"tag\": "aphrasia",\n \"popularity\": 6871\n },\n {\n \"tag\": "muddlingly",\n \"popularity\": 6864\n },\n {\n \"tag\": "clear",\n \"popularity\": 6858\n },\n {\n \"tag\": "Clitoria",\n \"popularity\": 6851\n },\n {\n \"tag\": "apportionment underwaist",\n \"popularity\": 6845\n },\n {\n \"tag\": "kodakist",\n \"popularity\": 6838\n },\n {\n \"tag\": "Momotidae",\n \"popularity\": 6832\n },\n {\n \"tag\": "cryptovalency",\n \"popularity\": 6825\n },\n {\n \"tag\": "floe",\n \"popularity\": 6819\n },\n {\n \"tag\": "aphagia",\n \"popularity\": 6812\n },\n {\n \"tag\": "brontograph",\n \"popularity\": 6806\n },\n {\n \"tag\": "tubulous",\n \"popularity\": 6799\n },\n {\n \"tag\": "unhorse",\n \"popularity\": 6793\n },\n {\n \"tag\": "chlordane",\n \"popularity\": 6787\n },\n {\n \"tag\": "colloquy brochan",\n \"popularity\": 6780\n },\n {\n \"tag\": "sloosh",\n \"popularity\": 6774\n },\n {\n \"tag\": "battered",\n \"popularity\": 6767\n },\n {\n \"tag\": "monocularity pluriguttulate",\n \"popularity\": 6761\n },\n {\n \"tag\": "chiastoneury",\n \"popularity\": 6755\n },\n {\n \"tag\": "Sanguinaria",\n \"popularity\": 6748\n },\n {\n \"tag\": "confessionary",\n \"popularity\": 6742\n },\n {\n \"tag\": "enzymic",\n \"popularity\": 6736\n },\n {\n \"tag\": "cord",\n \"popularity\": 6729\n },\n {\n \"tag\": "oviducal",\n \"popularity\": 6723\n },\n {\n \"tag\": "crozzle outsea",\n \"popularity\": 6717\n },\n {\n \"tag\": "balladical",\n \"popularity\": 6710\n },\n {\n \"tag\": "uncollectibleness",\n \"popularity\": 6704\n },\n {\n \"tag\": "predorsal",\n \"popularity\": 6698\n },\n {\n \"tag\": "reauthenticate",\n \"popularity\": 6692\n },\n {\n \"tag\": "ravissant",\n \"popularity\": 6685\n },\n {\n \"tag\": "advantageousness",\n \"popularity\": 6679\n },\n {\n \"tag\": "rung",\n \"popularity\": 6673\n },\n {\n \"tag\": "duncedom",\n \"popularity\": 6667\n },\n {\n \"tag\": "hematolite",\n \"popularity\": 6660\n },\n {\n \"tag\": "thisness",\n \"popularity\": 6654\n },\n {\n \"tag\": "mapau",\n \"popularity\": 6648\n },\n {\n \"tag\": "Hecatic",\n \"popularity\": 6642\n },\n {\n \"tag\": "meningoencephalocele",\n \"popularity\": 6636\n },\n {\n \"tag\": "confection sorra",\n \"popularity\": 6630\n },\n {\n \"tag\": "unsedate",\n \"popularity\": 6623\n },\n {\n \"tag\": "meningocerebritis",\n \"popularity\": 6617\n },\n {\n \"tag\": "biopsychological",\n \"popularity\": 6611\n },\n {\n \"tag\": "clavicithern",\n \"popularity\": 6605\n },\n {\n \"tag\": "resun",\n \"popularity\": 6599\n },\n {\n \"tag\": "bayamo",\n \"popularity\": 6593\n },\n {\n \"tag\": "seeableness",\n \"popularity\": 6587\n },\n {\n \"tag\": "hypsidolichocephalism",\n \"popularity\": 6581\n },\n {\n \"tag\": "salivous",\n \"popularity\": 6574\n },\n {\n \"tag\": "neumatize",\n \"popularity\": 6568\n },\n {\n \"tag\": "stree",\n \"popularity\": 6562\n },\n {\n \"tag\": "markshot",\n \"popularity\": 6556\n },\n {\n \"tag\": "phraseologically",\n \"popularity\": 6550\n },\n {\n \"tag\": "yealing",\n \"popularity\": 6544\n },\n {\n \"tag\": "puggy",\n \"popularity\": 6538\n },\n {\n \"tag\": "sexadecimal",\n \"popularity\": 6532\n },\n {\n \"tag\": "unofficerlike",\n \"popularity\": 6526\n },\n {\n \"tag\": "curiosa",\n \"popularity\": 6520\n },\n {\n \"tag\": "pedomotor",\n \"popularity\": 6514\n },\n {\n \"tag\": "astrally",\n \"popularity\": 6508\n },\n {\n \"tag\": "prosomatic",\n \"popularity\": 6502\n },\n {\n \"tag\": "bulletheaded",\n \"popularity\": 6496\n },\n {\n \"tag\": "fortuned",\n \"popularity\": 6490\n },\n {\n \"tag\": "pixy",\n \"popularity\": 6484\n },\n {\n \"tag\": "protectrix",\n \"popularity\": 6478\n },\n {\n \"tag\": "arthritical",\n \"popularity\": 6472\n },\n {\n \"tag\": "coction",\n \"popularity\": 6466\n },\n {\n \"tag\": "Anthropos",\n \"popularity\": 6460\n },\n {\n \"tag\": "runer",\n \"popularity\": 6454\n },\n {\n \"tag\": "prenotify",\n \"popularity\": 6449\n },\n {\n \"tag\": "microspheric gastroparalysis",\n \"popularity\": 6443\n },\n {\n \"tag\": "Jovicentrical",\n \"popularity\": 6437\n },\n {\n \"tag\": "ceratopsid",\n \"popularity\": 6431\n },\n {\n \"tag\": "Theodoric",\n \"popularity\": 6425\n },\n {\n \"tag\": "Pactolus",\n \"popularity\": 6419\n },\n {\n \"tag\": "spawning",\n \"popularity\": 6413\n },\n {\n \"tag\": "nonconfidential",\n \"popularity\": 6407\n },\n {\n \"tag\": "halotrichite infumate",\n \"popularity\": 6402\n },\n {\n \"tag\": "undiscriminatingly",\n \"popularity\": 6396\n },\n {\n \"tag\": "unexasperated",\n \"popularity\": 6390\n },\n {\n \"tag\": "isoeugenol",\n \"popularity\": 6384\n },\n {\n \"tag\": "pressboard",\n \"popularity\": 6378\n },\n {\n \"tag\": "unshrew",\n \"popularity\": 6372\n },\n {\n \"tag\": "huffingly",\n \"popularity\": 6367\n },\n {\n \"tag\": "wagaun",\n \"popularity\": 6361\n },\n {\n \"tag\": "squirt Philistine",\n \"popularity\": 6355\n },\n {\n \"tag\": "kryptic",\n \"popularity\": 6349\n },\n {\n \"tag\": "paraform",\n \"popularity\": 6344\n },\n {\n \"tag\": "preverify",\n \"popularity\": 6338\n },\n {\n \"tag\": "dalar",\n \"popularity\": 6332\n },\n {\n \"tag\": "interdictor appraisingly",\n \"popularity\": 6326\n },\n {\n \"tag\": "chipped",\n \"popularity\": 6321\n },\n {\n \"tag\": "Pteropoda",\n \"popularity\": 6315\n },\n {\n \"tag\": "Bohairic",\n \"popularity\": 6309\n },\n {\n \"tag\": "felting",\n \"popularity\": 6303\n },\n {\n \"tag\": "compurgatorial",\n \"popularity\": 6298\n },\n {\n \"tag\": "unclead",\n \"popularity\": 6292\n },\n {\n \"tag\": "stockish",\n \"popularity\": 6286\n },\n {\n \"tag\": "mulligatawny",\n \"popularity\": 6281\n },\n {\n \"tag\": "Monotheletism",\n \"popularity\": 6275\n },\n {\n \"tag\": "lutanist",\n \"popularity\": 6269\n },\n {\n \"tag\": "gluttonize",\n \"popularity\": 6264\n },\n {\n \"tag\": "hackneyed",\n \"popularity\": 6258\n },\n {\n \"tag\": "yield",\n \"popularity\": 6253\n },\n {\n \"tag\": "sulphonamido",\n \"popularity\": 6247\n },\n {\n \"tag\": "granulative",\n \"popularity\": 6241\n },\n {\n \"tag\": "swingy",\n \"popularity\": 6236\n },\n {\n \"tag\": "Desmidiales",\n \"popularity\": 6230\n },\n {\n \"tag\": "tootlish",\n \"popularity\": 6224\n },\n {\n \"tag\": "unsatisfiedly",\n \"popularity\": 6219\n },\n {\n \"tag\": "burucha",\n \"popularity\": 6213\n },\n {\n \"tag\": "premeditatingly",\n \"popularity\": 6208\n },\n {\n \"tag\": "cowrie",\n \"popularity\": 6202\n },\n {\n \"tag\": "pleurolysis",\n \"popularity\": 6197\n },\n {\n \"tag\": "nationalist",\n \"popularity\": 6191\n },\n {\n \"tag\": "Pholadacea",\n \"popularity\": 6186\n },\n {\n \"tag\": "anakrousis",\n \"popularity\": 6180\n },\n {\n \"tag\": "proctorial",\n \"popularity\": 6175\n },\n {\n \"tag\": "cavillation",\n \"popularity\": 6169\n },\n {\n \"tag\": "cervicobregmatic",\n \"popularity\": 6163\n },\n {\n \"tag\": "interspecific",\n \"popularity\": 6158\n },\n {\n \"tag\": "Teutonity",\n \"popularity\": 6152\n },\n {\n \"tag\": "snakeholing",\n \"popularity\": 6147\n },\n {\n \"tag\": "balcony",\n \"popularity\": 6142\n },\n {\n \"tag\": "latchless",\n \"popularity\": 6136\n },\n {\n \"tag\": "Mithraea",\n \"popularity\": 6131\n },\n {\n \"tag\": "pseudepigraph",\n \"popularity\": 6125\n },\n {\n \"tag\": "flosser",\n \"popularity\": 6120\n },\n {\n \"tag\": "kotyle",\n \"popularity\": 6114\n },\n {\n \"tag\": "outdo",\n \"popularity\": 6109\n },\n {\n \"tag\": "interclerical",\n \"popularity\": 6103\n },\n {\n \"tag\": "aurar",\n \"popularity\": 6098\n },\n {\n \"tag\": "apophyseal",\n \"popularity\": 6093\n },\n {\n \"tag\": "Miro",\n \"popularity\": 6087\n },\n {\n \"tag\": "Priscillian",\n \"popularity\": 6082\n },\n {\n \"tag\": "alluvia",\n \"popularity\": 6076\n },\n {\n \"tag\": "exordize",\n \"popularity\": 6071\n },\n {\n \"tag\": "breakage",\n \"popularity\": 6066\n },\n {\n \"tag\": "unclosable",\n \"popularity\": 6060\n },\n {\n \"tag\": "monocondylous",\n \"popularity\": 6055\n },\n {\n \"tag\": "dyarchy",\n \"popularity\": 6050\n },\n {\n \"tag\": "subchelate",\n \"popularity\": 6044\n },\n {\n \"tag\": "hearsay",\n \"popularity\": 6039\n },\n {\n \"tag\": "prestigiously",\n \"popularity\": 6034\n },\n {\n \"tag\": "unimuscular",\n \"popularity\": 6028\n },\n {\n \"tag\": "lingwort",\n \"popularity\": 6023\n },\n {\n \"tag\": "jealous",\n \"popularity\": 6018\n },\n {\n \"tag\": "artilleryman",\n \"popularity\": 6012\n },\n {\n \"tag\": "phantasmagorially",\n \"popularity\": 6007\n },\n {\n \"tag\": "stagnum",\n \"popularity\": 6002\n },\n {\n \"tag\": "organotropism shatteringly",\n \"popularity\": 5997\n },\n {\n \"tag\": "Mytilus Hebraist",\n \"popularity\": 5991\n },\n {\n \"tag\": "returf",\n \"popularity\": 5986\n },\n {\n \"tag\": "townfolk",\n \"popularity\": 5981\n },\n {\n \"tag\": "propitiative",\n \"popularity\": 5976\n },\n {\n \"tag\": "Anita unsullied",\n \"popularity\": 5970\n },\n {\n \"tag\": "bandoleered",\n \"popularity\": 5965\n },\n {\n \"tag\": "cubby",\n \"popularity\": 5960\n },\n {\n \"tag\": "Hexanchus",\n \"popularity\": 5955\n },\n {\n \"tag\": "circuminsular",\n \"popularity\": 5949\n },\n {\n \"tag\": "chamberletted eumycete",\n \"popularity\": 5944\n },\n {\n \"tag\": "secure",\n \"popularity\": 5939\n },\n {\n \"tag\": "Edwardean",\n \"popularity\": 5934\n },\n {\n \"tag\": "strenth",\n \"popularity\": 5929\n },\n {\n \"tag\": "exhaustless",\n \"popularity\": 5923\n },\n {\n \"tag\": "electioneerer",\n \"popularity\": 5918\n },\n {\n \"tag\": "estoile",\n \"popularity\": 5913\n },\n {\n \"tag\": "redden",\n \"popularity\": 5908\n },\n {\n \"tag\": "solicitee",\n \"popularity\": 5903\n },\n {\n \"tag\": "nonpatented",\n \"popularity\": 5898\n },\n {\n \"tag\": "lemming",\n \"popularity\": 5893\n },\n {\n \"tag\": "marled subalate",\n \"popularity\": 5887\n },\n {\n \"tag\": "premial horizonward",\n \"popularity\": 5882\n },\n {\n \"tag\": "nonrefueling",\n \"popularity\": 5877\n },\n {\n \"tag\": "rupturewort",\n \"popularity\": 5872\n },\n {\n \"tag\": "unfed",\n \"popularity\": 5867\n },\n {\n \"tag\": "empanelment",\n \"popularity\": 5862\n },\n {\n \"tag\": "isoosmosis",\n \"popularity\": 5857\n },\n {\n \"tag\": "jipijapa",\n \"popularity\": 5852\n },\n {\n \"tag\": "Fiji",\n \"popularity\": 5847\n },\n {\n \"tag\": "interferant",\n \"popularity\": 5842\n },\n {\n \"tag\": "reconstitution",\n \"popularity\": 5837\n },\n {\n \"tag\": "dockyardman",\n \"popularity\": 5832\n },\n {\n \"tag\": "dolichopodous",\n \"popularity\": 5826\n },\n {\n \"tag\": "whiteworm",\n \"popularity\": 5821\n },\n {\n \"tag\": "atheistically",\n \"popularity\": 5816\n },\n {\n \"tag\": "nonconcern",\n \"popularity\": 5811\n },\n {\n \"tag\": "scarabaeidoid",\n \"popularity\": 5806\n },\n {\n \"tag\": "triumviri",\n \"popularity\": 5801\n },\n {\n \"tag\": "rakit",\n \"popularity\": 5796\n },\n {\n \"tag\": "leecheater",\n \"popularity\": 5791\n },\n {\n \"tag\": "Arthrostraca",\n \"popularity\": 5786\n },\n {\n \"tag\": "upknit",\n \"popularity\": 5781\n },\n {\n \"tag\": "tymbalon",\n \"popularity\": 5776\n },\n {\n \"tag\": "inventurous",\n \"popularity\": 5771\n },\n {\n \"tag\": "perradiate",\n \"popularity\": 5766\n },\n {\n \"tag\": "seer",\n \"popularity\": 5762\n },\n {\n \"tag\": "Auricularia",\n \"popularity\": 5757\n },\n {\n \"tag\": "wettish exclusivity",\n \"popularity\": 5752\n },\n {\n \"tag\": "arteriosympathectomy",\n \"popularity\": 5747\n },\n {\n \"tag\": "tunlike",\n \"popularity\": 5742\n },\n {\n \"tag\": "cephalocercal",\n \"popularity\": 5737\n },\n {\n \"tag\": "meaninglessness",\n \"popularity\": 5732\n },\n {\n \"tag\": "fountful",\n \"popularity\": 5727\n },\n {\n \"tag\": "appraisement",\n \"popularity\": 5722\n },\n {\n \"tag\": "geniculated",\n \"popularity\": 5717\n },\n {\n \"tag\": "rotator",\n \"popularity\": 5712\n },\n {\n \"tag\": "foremarch biography",\n \"popularity\": 5707\n },\n {\n \"tag\": "arid",\n \"popularity\": 5703\n },\n {\n \"tag\": "inapprehensible",\n \"popularity\": 5698\n },\n {\n \"tag\": "chlorosulphonic",\n \"popularity\": 5693\n },\n {\n \"tag\": "braguette",\n \"popularity\": 5688\n },\n {\n \"tag\": "panophthalmitis",\n \"popularity\": 5683\n },\n {\n \"tag\": "pro objurgatorily",\n \"popularity\": 5678\n },\n {\n \"tag\": "zooplasty",\n \"popularity\": 5673\n },\n {\n \"tag\": "Terebratulidae",\n \"popularity\": 5669\n },\n {\n \"tag\": "Mahran",\n \"popularity\": 5664\n },\n {\n \"tag\": "anthologize merocele",\n \"popularity\": 5659\n },\n {\n \"tag\": "firecracker chiropractic",\n \"popularity\": 5654\n },\n {\n \"tag\": "tenorist",\n \"popularity\": 5649\n },\n {\n \"tag\": "amphitene",\n \"popularity\": 5645\n },\n {\n \"tag\": "silverbush toadstone",\n \"popularity\": 5640\n },\n {\n \"tag\": "entozoological",\n \"popularity\": 5635\n },\n {\n \"tag\": "trustlessness",\n \"popularity\": 5630\n },\n {\n \"tag\": "reassay",\n \"popularity\": 5625\n },\n {\n \"tag\": "chrysalides",\n \"popularity\": 5621\n },\n {\n \"tag\": "truncation",\n \"popularity\": 5616\n },\n {\n \"tag\": "unwavered mausoleal",\n \"popularity\": 5611\n },\n {\n \"tag\": "unserrated",\n \"popularity\": 5606\n },\n {\n \"tag\": "frampler",\n \"popularity\": 5602\n },\n {\n \"tag\": "celestial",\n \"popularity\": 5597\n },\n {\n \"tag\": "depreter",\n \"popularity\": 5592\n },\n {\n \"tag\": "retaliate",\n \"popularity\": 5588\n },\n {\n \"tag\": "decempunctate",\n \"popularity\": 5583\n },\n {\n \"tag\": "submitter",\n \"popularity\": 5578\n },\n {\n \"tag\": "phenothiazine",\n \"popularity\": 5573\n },\n {\n \"tag\": "hobbledehoyish",\n \"popularity\": 5569\n },\n {\n \"tag\": "erraticness",\n \"popularity\": 5564\n },\n {\n \"tag\": "ovariodysneuria",\n \"popularity\": 5559\n },\n {\n \"tag\": "puja",\n \"popularity\": 5555\n },\n {\n \"tag\": "cesspool",\n \"popularity\": 5550\n },\n {\n \"tag\": "sonation",\n \"popularity\": 5545\n },\n {\n \"tag\": "moggan",\n \"popularity\": 5541\n },\n {\n \"tag\": "overjutting",\n \"popularity\": 5536\n },\n {\n \"tag\": "cohobate",\n \"popularity\": 5531\n },\n {\n \"tag\": "Distoma",\n \"popularity\": 5527\n },\n {\n \"tag\": "Plectognathi",\n \"popularity\": 5522\n },\n {\n \"tag\": "dumple caliphate",\n \"popularity\": 5517\n },\n {\n \"tag\": "shiko",\n \"popularity\": 5513\n },\n {\n \"tag\": "downness",\n \"popularity\": 5508\n },\n {\n \"tag\": "whippletree",\n \"popularity\": 5504\n },\n {\n \"tag\": "nymphaeum",\n \"popularity\": 5499\n },\n {\n \"tag\": "there trest",\n \"popularity\": 5494\n },\n {\n \"tag\": "psychrometer",\n \"popularity\": 5490\n },\n {\n \"tag\": "pyelograph",\n \"popularity\": 5485\n },\n {\n \"tag\": "unsalvable",\n \"popularity\": 5481\n },\n {\n \"tag\": "bescreen",\n \"popularity\": 5476\n },\n {\n \"tag\": "cushy",\n \"popularity\": 5471\n },\n {\n \"tag\": "plicatolobate",\n \"popularity\": 5467\n },\n {\n \"tag\": "lakie",\n \"popularity\": 5462\n },\n {\n \"tag\": "anthropodeoxycholic",\n \"popularity\": 5458\n },\n {\n \"tag\": "resatisfaction",\n \"popularity\": 5453\n },\n {\n \"tag\": "unravelment unaccidental",\n \"popularity\": 5449\n },\n {\n \"tag\": "telewriter monogeneous",\n \"popularity\": 5444\n },\n {\n \"tag\": "unsabred",\n \"popularity\": 5440\n },\n {\n \"tag\": "startlingly",\n \"popularity\": 5435\n },\n {\n \"tag\": "Aralia",\n \"popularity\": 5431\n },\n {\n \"tag\": "alamonti",\n \"popularity\": 5426\n },\n {\n \"tag\": "Franklinization",\n \"popularity\": 5422\n },\n {\n \"tag\": "parliament",\n \"popularity\": 5417\n },\n {\n \"tag\": "schoolkeeper",\n \"popularity\": 5413\n },\n {\n \"tag\": "nonsociety",\n \"popularity\": 5408\n },\n {\n \"tag\": "parenthetic",\n \"popularity\": 5404\n },\n {\n \"tag\": "stog",\n \"popularity\": 5399\n },\n {\n \"tag\": "Pristipomidae",\n \"popularity\": 5395\n },\n {\n \"tag\": "exocarp",\n \"popularity\": 5390\n },\n {\n \"tag\": "monaxonial",\n \"popularity\": 5386\n },\n {\n \"tag\": "tramroad",\n \"popularity\": 5381\n },\n {\n \"tag\": "hookah",\n \"popularity\": 5377\n },\n {\n \"tag\": "saccharonic",\n \"popularity\": 5372\n },\n {\n \"tag\": "perimetrium",\n \"popularity\": 5368\n },\n {\n \"tag\": "libelluloid",\n \"popularity\": 5364\n },\n {\n \"tag\": "overrunningly",\n \"popularity\": 5359\n },\n {\n \"tag\": "untwister",\n \"popularity\": 5355\n },\n {\n \"tag\": "ninnyhammer",\n \"popularity\": 5350\n },\n {\n \"tag\": "metranate",\n \"popularity\": 5346\n },\n {\n \"tag\": "sarcoblast",\n \"popularity\": 5341\n },\n {\n \"tag\": "porkish",\n \"popularity\": 5337\n },\n {\n \"tag\": "chauvinistic",\n \"popularity\": 5333\n },\n {\n \"tag\": "sexagesimal",\n \"popularity\": 5328\n },\n {\n \"tag\": "hematogenic",\n \"popularity\": 5324\n },\n {\n \"tag\": "selfpreservatory",\n \"popularity\": 5320\n },\n {\n \"tag\": "myelauxe",\n \"popularity\": 5315\n },\n {\n \"tag\": "triply",\n \"popularity\": 5311\n },\n {\n \"tag\": "metaphysicous",\n \"popularity\": 5306\n },\n {\n \"tag\": "vitrinoid",\n \"popularity\": 5302\n },\n {\n \"tag\": "glabellae",\n \"popularity\": 5298\n },\n {\n \"tag\": "moonlighter",\n \"popularity\": 5293\n },\n {\n \"tag\": "monotheistically epexegetical",\n \"popularity\": 5289\n },\n {\n \"tag\": "pseudolateral",\n \"popularity\": 5285\n },\n {\n \"tag\": "heptamethylene",\n \"popularity\": 5280\n },\n {\n \"tag\": "salvadora",\n \"popularity\": 5276\n },\n {\n \"tag\": "unjovial diphenylthiourea",\n \"popularity\": 5272\n },\n {\n \"tag\": "thievishness",\n \"popularity\": 5268\n },\n {\n \"tag\": "unridable",\n \"popularity\": 5263\n },\n {\n \"tag\": "underhandedly",\n \"popularity\": 5259\n },\n {\n \"tag\": "fungiform",\n \"popularity\": 5255\n },\n {\n \"tag\": "scruffle",\n \"popularity\": 5250\n },\n {\n \"tag\": "preindisposition",\n \"popularity\": 5246\n },\n {\n \"tag\": "Amadis",\n \"popularity\": 5242\n },\n {\n \"tag\": "Culex",\n \"popularity\": 5238\n },\n {\n \"tag\": "churning",\n \"popularity\": 5233\n },\n {\n \"tag\": "imperite",\n \"popularity\": 5229\n },\n {\n \"tag\": "levorotation",\n \"popularity\": 5225\n },\n {\n \"tag\": "barbate",\n \"popularity\": 5221\n },\n {\n \"tag\": "knotwort",\n \"popularity\": 5216\n },\n {\n \"tag\": "gypsiferous",\n \"popularity\": 5212\n },\n {\n \"tag\": "tourmalinic",\n \"popularity\": 5208\n },\n {\n \"tag\": "helleboric",\n \"popularity\": 5204\n },\n {\n \"tag\": "pneumograph",\n \"popularity\": 5199\n },\n {\n \"tag\": "Peltigeraceae",\n \"popularity\": 5195\n },\n {\n \"tag\": "busine",\n \"popularity\": 5191\n },\n {\n \"tag\": "Ailuridae",\n \"popularity\": 5187\n },\n {\n \"tag\": "azotate",\n \"popularity\": 5183\n },\n {\n \"tag\": "unlikable",\n \"popularity\": 5178\n },\n {\n \"tag\": "sloyd",\n \"popularity\": 5174\n },\n {\n \"tag\": "biblioclasm",\n \"popularity\": 5170\n },\n {\n \"tag\": "Seres",\n \"popularity\": 5166\n },\n {\n \"tag\": "unaccurateness",\n \"popularity\": 5162\n },\n {\n \"tag\": "scrollwise",\n \"popularity\": 5157\n },\n {\n \"tag\": "flandowser",\n \"popularity\": 5153\n },\n {\n \"tag\": "unblackened",\n \"popularity\": 5149\n },\n {\n \"tag\": "schistosternia",\n \"popularity\": 5145\n },\n {\n \"tag\": "fuse",\n \"popularity\": 5141\n },\n {\n \"tag\": "narthecal",\n \"popularity\": 5137\n },\n {\n \"tag\": "Cueva",\n \"popularity\": 5133\n },\n {\n \"tag\": "appositeness",\n \"popularity\": 5128\n },\n {\n \"tag\": "proindustrial",\n \"popularity\": 5124\n },\n {\n \"tag\": "dermatorrhoea",\n \"popularity\": 5120\n },\n {\n \"tag\": "oxyurous tendential",\n \"popularity\": 5116\n },\n {\n \"tag\": "isopurpurin",\n \"popularity\": 5112\n },\n {\n \"tag\": "impose",\n \"popularity\": 5108\n },\n {\n \"tag\": "wordsmanship",\n \"popularity\": 5104\n },\n {\n \"tag\": "saturator",\n \"popularity\": 5100\n },\n {\n \"tag\": "Nordicity",\n \"popularity\": 5096\n },\n {\n \"tag\": "interaccuse",\n \"popularity\": 5092\n },\n {\n \"tag\": "acridinic",\n \"popularity\": 5087\n },\n {\n \"tag\": "scholion",\n \"popularity\": 5083\n },\n {\n \"tag\": "pseudoaconitine",\n \"popularity\": 5079\n },\n {\n \"tag\": "doctorial",\n \"popularity\": 5075\n },\n {\n \"tag\": "Etchimin",\n \"popularity\": 5071\n },\n {\n \"tag\": "oliviform",\n \"popularity\": 5067\n },\n {\n \"tag\": "Pele",\n \"popularity\": 5063\n },\n {\n \"tag\": "Chiromantis Progymnasium",\n \"popularity\": 5059\n },\n {\n \"tag\": "toxosis",\n \"popularity\": 5055\n },\n {\n \"tag\": "spadilla",\n \"popularity\": 5051\n },\n {\n \"tag\": "Actinopterygii",\n \"popularity\": 5047\n },\n {\n \"tag\": "untiring",\n \"popularity\": 5043\n },\n {\n \"tag\": "butyral",\n \"popularity\": 5039\n },\n {\n \"tag\": "Gymnoderinae",\n \"popularity\": 5035\n },\n {\n \"tag\": "testudo",\n \"popularity\": 5031\n },\n {\n \"tag\": "frigorify",\n \"popularity\": 5027\n },\n {\n \"tag\": "aliency",\n \"popularity\": 5023\n },\n {\n \"tag\": "jargon",\n \"popularity\": 5019\n },\n {\n \"tag\": "counterservice",\n \"popularity\": 5015\n },\n {\n \"tag\": "isostrychnine",\n \"popularity\": 5011\n },\n {\n \"tag\": "tellership",\n \"popularity\": 5007\n },\n {\n \"tag\": "miscegenetic",\n \"popularity\": 5003\n },\n {\n \"tag\": "sorcer",\n \"popularity\": 4999\n },\n {\n \"tag\": "tilewright",\n \"popularity\": 4995\n },\n {\n \"tag\": "cyanoplastid",\n \"popularity\": 4991\n },\n {\n \"tag\": "fluxionally",\n \"popularity\": 4987\n },\n {\n \"tag\": "proudhearted",\n \"popularity\": 4983\n },\n {\n \"tag\": "blithely",\n \"popularity\": 4979\n },\n {\n \"tag\": "jestproof",\n \"popularity\": 4975\n },\n {\n \"tag\": "jestwise",\n \"popularity\": 4971\n },\n {\n \"tag\": "nonassimilable",\n \"popularity\": 4967\n },\n {\n \"tag\": "compurgation",\n \"popularity\": 4964\n },\n {\n \"tag\": "unhate",\n \"popularity\": 4960\n },\n {\n \"tag\": "haplodonty",\n \"popularity\": 4956\n },\n {\n \"tag\": "cardholder",\n \"popularity\": 4952\n },\n {\n \"tag\": "rainlight megohmmeter overstout",\n \"popularity\": 4948\n },\n {\n \"tag\": "itchless",\n \"popularity\": 4944\n },\n {\n \"tag\": "begiggle",\n \"popularity\": 4940\n },\n {\n \"tag\": "chromatosphere",\n \"popularity\": 4936\n },\n {\n \"tag\": "typicality",\n \"popularity\": 4932\n },\n {\n \"tag\": "overgrown",\n \"popularity\": 4928\n },\n {\n \"tag\": "envolume",\n \"popularity\": 4925\n },\n {\n \"tag\": "pachycholia",\n \"popularity\": 4921\n },\n {\n \"tag\": "passageable",\n \"popularity\": 4917\n },\n {\n \"tag\": "pathopoiesis",\n \"popularity\": 4913\n },\n {\n \"tag\": "overbreak",\n \"popularity\": 4909\n },\n {\n \"tag\": "satyric",\n \"popularity\": 4905\n },\n {\n \"tag\": "unaudited",\n \"popularity\": 4901\n },\n {\n \"tag\": "whimble",\n \"popularity\": 4898\n },\n {\n \"tag\": "pressureless",\n \"popularity\": 4894\n },\n {\n \"tag\": "Selene",\n \"popularity\": 4890\n },\n {\n \"tag\": "slithery",\n \"popularity\": 4886\n },\n {\n \"tag\": "nondisfigurement",\n \"popularity\": 4882\n },\n {\n \"tag\": "overdelicious",\n \"popularity\": 4878\n },\n {\n \"tag\": "Perca",\n \"popularity\": 4875\n },\n {\n \"tag\": "Palladium",\n \"popularity\": 4871\n },\n {\n \"tag\": "insagacity",\n \"popularity\": 4867\n },\n {\n \"tag\": "peristoma",\n \"popularity\": 4863\n },\n {\n \"tag\": "uncreativeness",\n \"popularity\": 4859\n },\n {\n \"tag\": "incomparability surfboarding",\n \"popularity\": 4856\n },\n {\n \"tag\": "bacillar",\n \"popularity\": 4852\n },\n {\n \"tag\": "ulcerative",\n \"popularity\": 4848\n },\n {\n \"tag\": "stychomythia",\n \"popularity\": 4844\n },\n {\n \"tag\": "sesma somatics nonentry",\n \"popularity\": 4840\n },\n {\n \"tag\": "unsepulchred",\n \"popularity\": 4837\n },\n {\n \"tag\": "cephalanthium",\n \"popularity\": 4833\n },\n {\n \"tag\": "Asiaticization",\n \"popularity\": 4829\n },\n {\n \"tag\": "killeen",\n \"popularity\": 4825\n },\n {\n \"tag\": "Pseudococcus",\n \"popularity\": 4822\n },\n {\n \"tag\": "untractable",\n \"popularity\": 4818\n },\n {\n \"tag\": "apolegamic",\n \"popularity\": 4814\n },\n {\n \"tag\": "hyperpnea",\n \"popularity\": 4810\n },\n {\n \"tag\": "martyrolatry",\n \"popularity\": 4807\n },\n {\n \"tag\": "Sarmatic",\n \"popularity\": 4803\n },\n {\n \"tag\": "nonsurface",\n \"popularity\": 4799\n },\n {\n \"tag\": "adjoined",\n \"popularity\": 4796\n },\n {\n \"tag\": "vasiform",\n \"popularity\": 4792\n },\n {\n \"tag\": "tastelessness",\n \"popularity\": 4788\n },\n {\n \"tag\": "rumbo",\n \"popularity\": 4784\n },\n {\n \"tag\": "subdititious",\n \"popularity\": 4781\n },\n {\n \"tag\": "reparticipation",\n \"popularity\": 4777\n },\n {\n \"tag\": "Yorkshireism",\n \"popularity\": 4773\n },\n {\n \"tag\": "outcrow",\n \"popularity\": 4770\n },\n {\n \"tag\": "casserole",\n \"popularity\": 4766\n },\n {\n \"tag\": "semideltaic",\n \"popularity\": 4762\n },\n {\n \"tag\": "freemason",\n \"popularity\": 4759\n },\n {\n \"tag\": "catkin",\n \"popularity\": 4755\n },\n {\n \"tag\": "conscient",\n \"popularity\": 4751\n },\n {\n \"tag\": "reliably",\n \"popularity\": 4748\n },\n {\n \"tag\": "Telembi",\n \"popularity\": 4744\n },\n {\n \"tag\": "hide",\n \"popularity\": 4740\n },\n {\n \"tag\": "social",\n \"popularity\": 4737\n },\n {\n \"tag\": "ichneutic",\n \"popularity\": 4733\n },\n {\n \"tag\": "polypotome blouse pentagrammatic",\n \"popularity\": 4729\n },\n {\n \"tag\": "airdrome pesthole",\n \"popularity\": 4726\n },\n {\n \"tag\": "unportended",\n \"popularity\": 4722\n },\n {\n \"tag\": "sheerly",\n \"popularity\": 4719\n },\n {\n \"tag\": "acardiac",\n \"popularity\": 4715\n },\n {\n \"tag\": "fetor",\n \"popularity\": 4711\n },\n {\n \"tag\": "storax",\n \"popularity\": 4708\n },\n {\n \"tag\": "syndactylic",\n \"popularity\": 4704\n },\n {\n \"tag\": "otiatrics",\n \"popularity\": 4700\n },\n {\n \"tag\": "range",\n \"popularity\": 4697\n },\n {\n \"tag\": "branchway",\n \"popularity\": 4693\n },\n {\n \"tag\": "beatific",\n \"popularity\": 4690\n },\n {\n \"tag\": "Rugosa",\n \"popularity\": 4686\n },\n {\n \"tag\": "rafty",\n \"popularity\": 4682\n },\n {\n \"tag\": "gapy",\n \"popularity\": 4679\n },\n {\n \"tag\": "heterocercal",\n \"popularity\": 4675\n },\n {\n \"tag\": "actinopterygious",\n \"popularity\": 4672\n },\n {\n \"tag\": "glauconite",\n \"popularity\": 4668\n },\n {\n \"tag\": "limbless priest",\n \"popularity\": 4665\n },\n {\n \"tag\": "chrysene",\n \"popularity\": 4661\n },\n {\n \"tag\": "isentropic",\n \"popularity\": 4658\n },\n {\n \"tag\": "lairdess",\n \"popularity\": 4654\n },\n {\n \"tag\": "butterhead choliambic",\n \"popularity\": 4650\n },\n {\n \"tag\": "hexaseme",\n \"popularity\": 4647\n },\n {\n \"tag\": "treeify",\n \"popularity\": 4643\n },\n {\n \"tag\": "coronetted fructify",\n \"popularity\": 4640\n },\n {\n \"tag\": "admiralty",\n \"popularity\": 4636\n },\n {\n \"tag\": "Flosculariidae",\n \"popularity\": 4633\n },\n {\n \"tag\": "limaceous",\n \"popularity\": 4629\n },\n {\n \"tag\": "subterconscious",\n \"popularity\": 4626\n },\n {\n \"tag\": "stayless",\n \"popularity\": 4622\n },\n {\n \"tag\": "psha",\n \"popularity\": 4619\n },\n {\n \"tag\": "Mediterraneanize",\n \"popularity\": 4615\n },\n {\n \"tag\": "impenetrably",\n \"popularity\": 4612\n },\n {\n \"tag\": "Myrmeleonidae",\n \"popularity\": 4608\n },\n {\n \"tag\": "germander",\n \"popularity\": 4605\n },\n {\n \"tag\": "Buri",\n \"popularity\": 4601\n },\n {\n \"tag\": "papyrotamia",\n \"popularity\": 4598\n },\n {\n \"tag\": "Toxylon",\n \"popularity\": 4594\n },\n {\n \"tag\": "batatilla",\n \"popularity\": 4591\n },\n {\n \"tag\": "fabella assumer",\n \"popularity\": 4587\n },\n {\n \"tag\": "macromethod",\n \"popularity\": 4584\n },\n {\n \"tag\": "Blechnum",\n \"popularity\": 4580\n },\n {\n \"tag\": "pantography",\n \"popularity\": 4577\n },\n {\n \"tag\": "seminovel",\n \"popularity\": 4574\n },\n {\n \"tag\": "disembarrassment",\n \"popularity\": 4570\n },\n {\n \"tag\": "bushmaking",\n \"popularity\": 4567\n },\n {\n \"tag\": "neurosis",\n \"popularity\": 4563\n },\n {\n \"tag\": "Animalia",\n \"popularity\": 4560\n },\n {\n \"tag\": "Bernice",\n \"popularity\": 4556\n },\n {\n \"tag\": "wisen",\n \"popularity\": 4553\n },\n {\n \"tag\": "subhymenium",\n \"popularity\": 4549\n },\n {\n \"tag\": "esophagomycosis",\n \"popularity\": 4546\n },\n {\n \"tag\": "wireworks",\n \"popularity\": 4543\n },\n {\n \"tag\": "Sabellidae",\n \"popularity\": 4539\n },\n {\n \"tag\": "fustianish",\n \"popularity\": 4536\n },\n {\n \"tag\": "professively",\n \"popularity\": 4532\n },\n {\n \"tag\": "overcorruptly",\n \"popularity\": 4529\n },\n {\n \"tag\": "overcreep",\n \"popularity\": 4526\n },\n {\n \"tag\": "Castilloa",\n \"popularity\": 4522\n },\n {\n \"tag\": "forelady Georgie",\n \"popularity\": 4519\n },\n {\n \"tag\": "outsider",\n \"popularity\": 4515\n },\n {\n \"tag\": "Enukki",\n \"popularity\": 4512\n },\n {\n \"tag\": "gypsy",\n \"popularity\": 4509\n },\n {\n \"tag\": "Passamaquoddy",\n \"popularity\": 4505\n },\n {\n \"tag\": "reposit",\n \"popularity\": 4502\n },\n {\n \"tag\": "overtenderness",\n \"popularity\": 4499\n },\n {\n \"tag\": "keratome",\n \"popularity\": 4495\n },\n {\n \"tag\": "interclavicular hypermonosyllable Susanna",\n \"popularity\": 4492\n },\n {\n \"tag\": "mispropose",\n \"popularity\": 4489\n },\n {\n \"tag\": "Membranipora",\n \"popularity\": 4485\n },\n {\n \"tag\": "lampad",\n \"popularity\": 4482\n },\n {\n \"tag\": "header",\n \"popularity\": 4479\n },\n {\n \"tag\": "triseriate",\n \"popularity\": 4475\n },\n {\n \"tag\": "distrainment",\n \"popularity\": 4472\n },\n {\n \"tag\": "staphyloplastic",\n \"popularity\": 4469\n },\n {\n \"tag\": "outscour",\n \"popularity\": 4465\n },\n {\n \"tag\": "tallowmaking",\n \"popularity\": 4462\n },\n {\n \"tag\": "plugger",\n \"popularity\": 4459\n },\n {\n \"tag\": "fashionize",\n \"popularity\": 4455\n },\n {\n \"tag\": "puzzle",\n \"popularity\": 4452\n },\n {\n \"tag\": "imbrue",\n \"popularity\": 4449\n },\n {\n \"tag\": "osteoblast",\n \"popularity\": 4445\n },\n {\n \"tag\": "Hydrocores",\n \"popularity\": 4442\n },\n {\n \"tag\": "Lutra",\n \"popularity\": 4439\n },\n {\n \"tag\": "upridge scarfy",\n \"popularity\": 4435\n },\n {\n \"tag\": "ancon taffle",\n \"popularity\": 4432\n },\n {\n \"tag\": "impest",\n \"popularity\": 4429\n },\n {\n \"tag\": "uncollatedness",\n \"popularity\": 4426\n },\n {\n \"tag\": "hypersensitize",\n \"popularity\": 4422\n },\n {\n \"tag\": "autographically",\n \"popularity\": 4419\n },\n {\n \"tag\": "louther",\n \"popularity\": 4416\n },\n {\n \"tag\": "Ollie",\n \"popularity\": 4413\n },\n {\n \"tag\": "recompensate",\n \"popularity\": 4409\n },\n {\n \"tag\": "Shan",\n \"popularity\": 4406\n },\n {\n \"tag\": "brachycnemic",\n \"popularity\": 4403\n },\n {\n \"tag\": "Carinatae",\n \"popularity\": 4399\n },\n {\n \"tag\": "geotherm",\n \"popularity\": 4396\n },\n {\n \"tag\": "sawback",\n \"popularity\": 4393\n },\n {\n \"tag\": "Novatianist",\n \"popularity\": 4390\n },\n {\n \"tag\": "reapproach",\n \"popularity\": 4387\n },\n {\n \"tag\": "myelopoietic",\n \"popularity\": 4383\n },\n {\n \"tag\": "cyanin",\n \"popularity\": 4380\n },\n {\n \"tag\": "unsmutted",\n \"popularity\": 4377\n },\n {\n \"tag\": "nonpapist",\n \"popularity\": 4374\n },\n {\n \"tag\": "transbaikalian",\n \"popularity\": 4370\n },\n {\n \"tag\": "connately",\n \"popularity\": 4367\n },\n {\n \"tag\": "tenderize iterance",\n \"popularity\": 4364\n },\n {\n \"tag\": "hydrostatical",\n \"popularity\": 4361\n },\n {\n \"tag\": "unflag",\n \"popularity\": 4358\n },\n {\n \"tag\": "translate",\n \"popularity\": 4354\n },\n {\n \"tag\": "Scorzonera",\n \"popularity\": 4351\n },\n {\n \"tag\": "uncomforted",\n \"popularity\": 4348\n },\n {\n \"tag\": "risser varied",\n \"popularity\": 4345\n },\n {\n \"tag\": "plumbate",\n \"popularity\": 4342\n },\n {\n \"tag\": "Usneaceae",\n \"popularity\": 4338\n },\n {\n \"tag\": "fohat",\n \"popularity\": 4335\n },\n {\n \"tag\": "slagging",\n \"popularity\": 4332\n },\n {\n \"tag\": "superserious",\n \"popularity\": 4329\n },\n {\n \"tag\": "theocracy",\n \"popularity\": 4326\n },\n {\n \"tag\": "valonia",\n \"popularity\": 4323\n },\n {\n \"tag\": "Sapindales",\n \"popularity\": 4319\n },\n {\n \"tag\": "palaeozoologist",\n \"popularity\": 4316\n },\n {\n \"tag\": "yalb",\n \"popularity\": 4313\n },\n {\n \"tag\": "unviewed",\n \"popularity\": 4310\n },\n {\n \"tag\": "polyarteritis",\n \"popularity\": 4307\n },\n {\n \"tag\": "vectorial",\n \"popularity\": 4304\n },\n {\n \"tag\": "skimpingly",\n \"popularity\": 4301\n },\n {\n \"tag\": "athort",\n \"popularity\": 4297\n },\n {\n \"tag\": "tribofluorescence",\n \"popularity\": 4294\n },\n {\n \"tag\": "benzonitrol",\n \"popularity\": 4291\n },\n {\n \"tag\": "swiller subobtuse subjacency",\n \"popularity\": 4288\n },\n {\n \"tag\": "uncompassed",\n \"popularity\": 4285\n },\n {\n \"tag\": "cacochymia",\n \"popularity\": 4282\n },\n {\n \"tag\": "commensalist butadiene",\n \"popularity\": 4279\n },\n {\n \"tag\": "culpable",\n \"popularity\": 4276\n },\n {\n \"tag\": "contributive",\n \"popularity\": 4273\n },\n {\n \"tag\": "attemperately",\n \"popularity\": 4269\n },\n {\n \"tag\": "spelt",\n \"popularity\": 4266\n },\n {\n \"tag\": "exoneration",\n \"popularity\": 4263\n },\n {\n \"tag\": "antivivisectionist",\n \"popularity\": 4260\n },\n {\n \"tag\": "granitification",\n \"popularity\": 4257\n },\n {\n \"tag\": "palladize",\n \"popularity\": 4254\n },\n {\n \"tag\": "marksmanship",\n \"popularity\": 4251\n },\n {\n \"tag\": "bullydom",\n \"popularity\": 4248\n },\n {\n \"tag\": "spirality",\n \"popularity\": 4245\n },\n {\n \"tag\": "caliginous",\n \"popularity\": 4242\n },\n {\n \"tag\": "reportedly",\n \"popularity\": 4239\n },\n {\n \"tag\": "polyad",\n \"popularity\": 4236\n },\n {\n \"tag\": "arthroempyesis",\n \"popularity\": 4233\n },\n {\n \"tag\": "semibay facultatively",\n \"popularity\": 4229\n },\n {\n \"tag\": "metastatically",\n \"popularity\": 4226\n },\n {\n \"tag\": "prophetically",\n \"popularity\": 4223\n },\n {\n \"tag\": "Linguatula elapid",\n \"popularity\": 4220\n },\n {\n \"tag\": "pyknatom",\n \"popularity\": 4217\n },\n {\n \"tag\": "centimeter",\n \"popularity\": 4214\n },\n {\n \"tag\": "mensurate",\n \"popularity\": 4211\n },\n {\n \"tag\": "migraine",\n \"popularity\": 4208\n },\n {\n \"tag\": "pentagamist",\n \"popularity\": 4205\n },\n {\n \"tag\": "querken",\n \"popularity\": 4202\n },\n {\n \"tag\": "ambulance",\n \"popularity\": 4199\n },\n {\n \"tag\": "Stokavian",\n \"popularity\": 4196\n },\n {\n \"tag\": "malvasian",\n \"popularity\": 4193\n },\n {\n \"tag\": "uncouthsome",\n \"popularity\": 4190\n },\n {\n \"tag\": "readable",\n \"popularity\": 4187\n },\n {\n \"tag\": "enlodge",\n \"popularity\": 4184\n },\n {\n \"tag\": "plasterwise Appendiculariidae perspectograph",\n \"popularity\": 4181\n },\n {\n \"tag\": "inkweed",\n \"popularity\": 4178\n },\n {\n \"tag\": "streep",\n \"popularity\": 4175\n },\n {\n \"tag\": "diadelphian cultured",\n \"popularity\": 4172\n },\n {\n \"tag\": "hymenopterous",\n \"popularity\": 4169\n },\n {\n \"tag\": "unexorableness",\n \"popularity\": 4166\n },\n {\n \"tag\": "cascaron",\n \"popularity\": 4163\n },\n {\n \"tag\": "undaintiness",\n \"popularity\": 4160\n },\n {\n \"tag\": "Curtana",\n \"popularity\": 4157\n },\n {\n \"tag\": "scurvied",\n \"popularity\": 4154\n },\n {\n \"tag\": "molluscoidal",\n \"popularity\": 4151\n },\n {\n \"tag\": "yurt",\n \"popularity\": 4148\n },\n {\n \"tag\": "deciduitis",\n \"popularity\": 4145\n },\n {\n \"tag\": "creephole",\n \"popularity\": 4142\n },\n {\n \"tag\": "quatrefeuille",\n \"popularity\": 4139\n },\n {\n \"tag\": "bicapitate adenomatome",\n \"popularity\": 4136\n },\n {\n \"tag\": "damassin",\n \"popularity\": 4134\n },\n {\n \"tag\": "planching",\n \"popularity\": 4131\n },\n {\n \"tag\": "dashedly inferential",\n \"popularity\": 4128\n },\n {\n \"tag\": "lobe",\n \"popularity\": 4125\n },\n {\n \"tag\": "Hyrachyus",\n \"popularity\": 4122\n },\n {\n \"tag\": "knab",\n \"popularity\": 4119\n },\n {\n \"tag\": "discohexaster",\n \"popularity\": 4116\n },\n {\n \"tag\": "malign",\n \"popularity\": 4113\n },\n {\n \"tag\": "pedagoguism",\n \"popularity\": 4110\n },\n {\n \"tag\": "shrubbery",\n \"popularity\": 4107\n },\n {\n \"tag\": "undershrub",\n \"popularity\": 4104\n },\n {\n \"tag\": "bureaucrat",\n \"popularity\": 4101\n },\n {\n \"tag\": "pantaleon",\n \"popularity\": 4098\n },\n {\n \"tag\": "mesoventral",\n \"popularity\": 4096\n }]'; - -var log2 = Math.log(2); -var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); - -function makeTagCloud(tagInfo) -{ - var output = '
'; - - tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; }); - - for (var i = 0; i < tagInfo.length; i++) { - var tag = tagInfo[i].tag; - - var validates = true; - for (var j = 0; j < tag.length; j++) { - var ch = tag.charCodeAt(j); - if (ch < 0x20 || ch >= 0x7f) { - validates = false; - break; - } - } - - if (!validates) - continue; - - var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); - var popularity = tagInfo[i].popularity; - var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; - output += ' ' + tag + ' \n'; - } - - output += '
'; - output.replace(" ", " "); - - return output; -} - -var tagcloud = makeTagCloud(tagInfo); -tagInfo = null; - -// The result string embeds floating-point numbers, which can vary a bit on different platforms, -// so we truncate them a bit before comparing. -var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) -assertEq(tagcloud_norm.length, 295906) diff --git a/js/src/tests/js1_8_1/jit/jstests.list b/js/src/tests/js1_8_1/jit/jstests.list deleted file mode 100644 index d21cf7d0743..00000000000 --- a/js/src/tests/js1_8_1/jit/jstests.list +++ /dev/null @@ -1,24 +0,0 @@ -url-prefix ../../jsreftest.html?test=js1_8_1/jit/ -script math-jit-tests.js -skip script regress-451673.js # bogus perf test (bug 540512) -skip script regress-451974-01.js # bogus perf test (bug 540512) -skip script regress-451974-02.js # bogus perf test (bug 540512) -skip script regress-452498-01.js # bogus perf test (bug 540512) -script regress-458838.js -script regress-462459-01.js -script regress-462459-02.js -script regress-462459-03.js -script regress-462459-04.js -script regress-462459-05.js -script regress-462459-06.js -script regress-462459-07.js -script regress-462459-08.js -script regress-462459-09.js -script regress-462459-10.js -script regress-462459-11.js -script regress-462459-12.js -skip script regress-469927.js # bogus perf test (bug 540512) -skip script regress-470739.js # bogus perf test (bug 540512) -script regress-471635.js -script regress-489682.js -script testDeepBailFromNonNative.js diff --git a/js/src/tests/js1_8_1/jit/regress-451673.js b/js/src/tests/js1_8_1/jit/regress-451673.js deleted file mode 100644 index 5c7202fe039..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451673.js +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarsky - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451673; -var summary = 'TM: Tracing prime number generation'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function doTest(enablejit) - { - if (enablejit) - jit(true); - else - jit(false); - - var n = 1000000; - var start = new Date(); - var i=0; - var j=0; - var numprimes=0; - var limit=0; - numprimes = 1; // 2 is prime - var mceil = Math.floor; - var msqrt = Math.sqrt; - var isPrime = 1; - - for (i = 3; i<= n; i+=2) - { - isPrime=1; - limit = mceil(msqrt(i)+1) + 1; - - for (j = 3; j < limit; j+=2) - { - if (i % j == 0) - { - isPrime = 0; - break; - } - } - - if (isPrime) - { - numprimes ++; - } - } - - var end = new Date(); - - var timetaken = end - start; - timetaken = timetaken / 1000; - - if (enablejit) - jit(false); - - print((enablejit ? ' JIT' : 'Non-JIT') + ": Number of primes up to: " + n + " is " + numprimes + ", counted in " + timetaken + " secs."); - - return timetaken; - } - - var timenonjit = doTest(false); - var timejit = doTest(true); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-451974-01.js b/js/src/tests/js1_8_1/jit/regress-451974-01.js deleted file mode 100644 index 59fc1415da3..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451974-01.js +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451974; -var summary = 'TM: loops with anon functions should not be slower with jit enabled'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var chars = '0123456789abcdef'; -var size = 10000; -var mult = 1000; -var densearray = []; -var lsize = size; - -while (lsize--) -{ - densearray.push(chars); -} - -function loop() -{ - var start = new Date(); - - for (var a = 0; a < mult; a++) - { - var f = (function(x){}); - for (var i = 0, len = densearray.length; i < len; i++) - { - f(densearray[i]); - } - } - - var stop = new Date(); - return stop - start; -} - -jit(false); -var timenonjit = loop(); -jit(true); -var timejit = loop(); -jit(false); - -print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - -expect = true; -actual = timejit < timenonjit/2; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-451974-02.js b/js/src/tests/js1_8_1/jit/regress-451974-02.js deleted file mode 100644 index f0de29d49bf..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451974-02.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451974; -var summary = 'TM: loops with anon functions should not be slower with jit enabled'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var chars = '0123456789abcdef'; - var size = 10000; - var mult = 1000; - var densearray = []; - var lsize = size; - - while (lsize--) - { - densearray.push(chars); - } - - function loop() - { - var start = new Date(); - - for (var a = 0; a < mult; a++) - { - var f = (function(x){}); - for (var i = 0, len = densearray.length; i < len; i++) - { - f(densearray[i]); - } - } - - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = loop(); - jit(true); - var timejit = loop(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit/2; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-452498-01.js b/js/src/tests/js1_8_1/jit/regress-452498-01.js deleted file mode 100644 index c857e2087af..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-452498-01.js +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarsky - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 452498; -var summary = 'TM: upvar2: jit heavyweight functions'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -function complex(aReal, aImag) { - this.r = aReal; - this.i = aImag; - this.square = function() { - return new complex(this.r * this.r - this.i * this.i, - 2 * this.r * this.i); - } - this.dist = function() { - return Math.sqrt(this.r * this.r + this.i * this.i); - } - this.add = function(aComplex) { - return new complex(this.r + aComplex.r, this.i + aComplex.i); - } -} - -function mandelbrotValueOO (aC, aIterMax) { - let Z = new complex(0.0, 0.0); - for (var iter = 0; iter < aIterMax; iter++) { - Z = Z.square().add(aC); - if (Z.r * Z.r + Z.i * Z.i > 256) { break; } - } - return iter; -} - -function f(trace) { - jit(trace); - var start = Date.now(); - const width = 60; - const height = 60; - const max_iters = 50; - var output = []; - for (let img_x = 0; img_x < width; img_x++) { - for (let img_y = 0; img_y < height; img_y++) { - let C = new complex(-2 + (img_x / width) * 3, - -1.5 + (img_y / height) * 3); - var res = mandelbrotValueOO(C, max_iters); - if (output.length > 0 && output[output.length -1][0] == res) { - output[output.length-1][1]++; - } else { - output.push([res, 1]); - } - } - } - jit(false); - const reference = "[[2, 6], [3, 17], [4, 6], [5, 1], [50, 1], [5, 1], [4, 6], [3, 17], [2, 10], [3, 17], [4, 6], [5, 1], [6, 1], [50, 1], [6, 1], [5, 1], [4, 6], [3, 17], [2, 8], [3, 17], [4, 6], [5, 2], [6, 1], [50, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 6], [3, 17], [4, 6], [5, 2], [6, 1], [7, 1], [50, 1], [7, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 4], [3, 17], [4, 7], [5, 2], [6, 1], [8, 1], [50, 1], [8, 1], [6, 1], [5, 2], [4, 7], [3, 17], [2, 2], [3, 17], [4, 7], [5, 3], [6, 1], [9, 1], [50, 1], [9, 1], [6, 1], [5, 3], [4, 7], [3, 17], [2, 1], [3, 16], [4, 7], [5, 3], [6, 2], [8, 1], [50, 1], [8, 1], [6, 2], [5, 3], [4, 7], [3, 32], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 31], [4, 7], [5, 3], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 30], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 28], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [10, 1], [50, 1], [10, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 26], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [11, 1], [50, 1], [11, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 25], [4, 6], [5, 3], [6, 3], [7, 1], [8, 1], [18, 1], [13, 1], [15, 1], [50, 1], [15, 1], [13, 1], [18, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 6], [3, 24], [4, 7], [5, 2], [6, 2], [7, 3], [8, 1], [10, 1], [14, 1], [50, 3], [14, 1], [10, 1], [8, 1], [7, 3], [6, 2], [5, 2], [4, 7], [3, 23], [4, 6], [5, 3], [7, 1], [8, 1], [9, 1], [8, 2], [10, 1], [11, 1], [15, 1], [50, 3], [15, 1], [11, 1], [10, 1], [8, 2], [9, 1], [8, 1], [7, 1], [5, 3], [4, 6], [3, 22], [4, 7], [5, 2], [6, 1], [7, 1], [14, 1], [16, 1], [11, 1], [10, 1], [12, 1], [20, 1], [23, 1], [46, 1], [50, 1], [46, 1], [23, 1], [20, 1], [12, 1], [10, 1], [11, 1], [16, 1], [14, 1], [7, 1], [6, 1], [5, 2], [4, 7], [3, 20], [4, 7], [5, 3], [6, 1], [7, 1], [8, 1], [10, 1], [17, 1], [16, 1], [20, 1], [50, 7], [20, 1], [16, 1], [17, 1], [10, 1], [8, 1], [7, 1], [6, 1], [5, 3], [4, 7], [3, 19], [4, 7], [5, 3], [6, 2], [7, 1], [10, 1], [21, 1], [50, 11], [21, 1], [10, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 18], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [9, 1], [13, 1], [25, 1], [50, 9], [25, 1], [13, 1], [9, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 17], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [14, 2], [50, 11], [14, 2], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 16], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [11, 1], [36, 1], [50, 11], [36, 1], [11, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 15], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [14, 1], [50, 11], [14, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 14], [4, 7], [5, 4], [6, 3], [7, 1], [8, 1], [9, 1], [12, 1], [26, 1], [50, 9], [26, 1], [12, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 4], [4, 7], [3, 13], [4, 7], [5, 4], [6, 2], [7, 2], [8, 1], [9, 1], [10, 1], [15, 1], [50, 9], [15, 1], [10, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 4], [4, 7], [3, 12], [4, 7], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [10, 1], [12, 1], [16, 1], [50, 7], [16, 1], [12, 1], [10, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 7], [3, 11], [4, 6], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [11, 1], [12, 1], [14, 1], [17, 1], [23, 1], [34, 1], [50, 3], [34, 1], [23, 1], [17, 1], [14, 1], [12, 1], [11, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 6], [3, 10], [4, 7], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [22, 1], [12, 1], [50, 1], [25, 1], [50, 11], [25, 1], [50, 1], [12, 1], [22, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 7], [3, 9], [4, 6], [5, 4], [6, 1], [7, 1], [8, 2], [9, 1], [14, 1], [50, 1], [21, 1], [50, 15], [21, 1], [50, 1], [14, 1], [9, 1], [8, 2], [7, 1], [6, 1], [5, 4], [4, 6], [3, 8], [4, 7], [5, 3], [6, 2], [9, 1], [14, 1], [13, 1], [11, 1], [13, 1], [26, 1], [50, 17], [26, 1], [13, 1], [11, 1], [13, 1], [14, 1], [9, 1], [6, 2], [5, 3], [4, 7], [3, 7], [4, 6], [5, 4], [6, 1], [7, 1], [9, 1], [49, 1], [43, 1], [50, 23], [43, 1], [49, 1], [9, 1], [7, 1], [6, 1], [5, 4], [4, 6], [3, 7], [4, 5], [5, 4], [6, 2], [7, 1], [9, 1], [13, 1], [50, 25], [13, 1], [9, 1], [7, 1], [6, 2], [5, 4], [4, 5], [3, 6], [4, 6], [5, 3], [6, 2], [7, 2], [9, 1], [11, 1], [17, 1], [50, 23], [17, 1], [11, 1], [9, 1], [7, 2], [6, 2], [5, 3], [4, 6], [3, 5], [4, 5], [5, 3], [6, 3], [7, 1], [8, 1], [9, 1], [50, 1], [26, 1], [50, 23], [26, 1], [50, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 5], [4, 4], [5, 3], [6, 3], [7, 1], [8, 2], [10, 1], [21, 1], [50, 25], [21, 1], [10, 1], [8, 2], [7, 1], [6, 3], [5, 3], [4, 4], [3, 5], [4, 4], [5, 2], [6, 3], [7, 1], [12, 1], [9, 1], [10, 1], [11, 1], [50, 27], [11, 1], [10, 1], [9, 1], [12, 1], [7, 1], [6, 3], [5, 2], [4, 4], [3, 5], [4, 3], [5, 2], [6, 2], [7, 2], [9, 1], [42, 1], [15, 1], [23, 1], [14, 1], [50, 27], [14, 1], [23, 1], [15, 1], [42, 1], [9, 1], [7, 2], [6, 2], [5, 2], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [20, 1], [9, 1], [8, 1], [9, 1], [10, 1], [16, 1], [50, 33], [16, 1], [10, 1], [9, 1], [8, 1], [9, 1], [20, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [9, 1], [13, 1], [12, 1], [11, 1], [38, 1], [25, 1], [50, 33], [25, 1], [38, 1], [11, 1], [12, 1], [13, 1], [9, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 2], [6, 1], [7, 1], [10, 1], [24, 1], [25, 1], [50, 35], [25, 1], [24, 1], [10, 1], [7, 1], [6, 1], [5, 2], [4, 3], [3, 5], [4, 4], [5, 1], [6, 1], [7, 1], [11, 2], [13, 1], [19, 1], [50, 33], [19, 1], [13, 1], [11, 2], [7, 1], [6, 1], [5, 1], [4, 4], [3, 5], [4, 4], [5, 2], [6, 1], [50, 1], [8, 2], [17, 1], [19, 1], [35, 1], [14, 1], [24, 1], [50, 25], [24, 1], [14, 1], [35, 1], [19, 1], [17, 1], [8, 2], [50, 1], [6, 1], [5, 2], [4, 4], [3, 5], [4, 5], [5, 2], [6, 2], [7, 1], [8, 1], [9, 2], [11, 1], [38, 1], [50, 25], [38, 1], [11, 1], [9, 2], [8, 1], [7, 1], [6, 2], [5, 2], [4, 5], [3, 6], [4, 4], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [15, 1], [50, 25], [15, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 4], [3, 7], [4, 5], [5, 3], [6, 3], [7, 1], [9, 1], [42, 1], [21, 1], [50, 23], [21, 1], [42, 1], [9, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 8], [4, 5], [5, 3], [6, 2], [7, 1], [8, 1], [9, 1], [13, 1], [50, 23], [13, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 5], [3, 9], [4, 6], [5, 3], [6, 2], [7, 1], [9, 1], [14, 1], [50, 23], [14, 1], [9, 1], [7, 1], [6, 2], [5, 3], [4, 6], [3, 10], [4, 6], [5, 3], [6, 1], [7, 1], [9, 1], [16, 1], [50, 2], [35, 1], [50, 8], [13, 1], [50, 8], [35, 1], [50, 2], [16, 1], [9, 1], [7, 1], [6, 1], [5, 3], [4, 6], [3, 12], [4, 6], [5, 2], [6, 1], [19, 1], [16, 1], [17, 1], [25, 1], [21, 1], [13, 1], [18, 1], [50, 6], [11, 1], [9, 1], [11, 1], [50, 6], [18, 1], [13, 1], [21, 1], [25, 1], [17, 1], [16, 1], [19, 1], [6, 1], [5, 2], [4, 6], [3, 14], [4, 5], [5, 3], [6, 1], [8, 1], [16, 1], [10, 1], [8, 2], [11, 1], [50, 1], [16, 1], [15, 1], [32, 1], [29, 1], [9, 1], [8, 1], [7, 1], [8, 1], [9, 1], [29, 1], [32, 1], [15, 1], [16, 1], [50, 1], [11, 1], [8, 2], [10, 1], [16, 1], [8, 1], [6, 1], [5, 3], [4, 5], [3, 15], [4, 6], [5, 3], [6, 4], [7, 1], [20, 1], [19, 1], [9, 3], [7, 3], [6, 1], [7, 3], [9, 3], [19, 1], [20, 1], [7, 1], [6, 4], [5, 3], [4, 6], [3, 16], [4, 7], [5, 4], [6, 3], [7, 1], [6, 13], [7, 1], [6, 3], [5, 4], [4, 7], [3, 18], [4, 7], [5, 27], [4, 7], [3, 20], [4, 9], [5, 21], [4, 9], [3, 23], [4, 12], [5, 11], [4, 12], [3, 26], [4, 33], [3, 29], [4, 29], [3, 33], [4, 25], [3, 38], [4, 19], [3, 20], [2, 1], [3, 26], [4, 7], [3, 26], [2, 2], [3, 57], [2, 1]]"; - reportCompare(reference, output.toSource(), summary + ': correctness jit=' + trace); - return (Date.now() - start); -} - - -var timenonjit = f(false); -var timejit = f(true); - -expect = true; -actual = timejit < timenonjit; - -print('time nonjit: ' + timenonjit + ', time jit: ' + timejit); - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-458838.js b/js/src/tests/js1_8_1/jit/regress-458838.js deleted file mode 100644 index 0cc6991eb78..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-458838.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarksy - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 458838; -var summary = 'TM: do not fall off trace when nested function accesses var of outer function'; -var actual = ''; -var expect = ''; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - jit(true); - - function f() { - var a = 1; - function g() { - var b = 0 - for (var i = 0; i < 10; ++i) { - b += a; - } - return b; - } - - return g(); - } - - expect = 10; - actual = f(); - - var recorderStarted; - var recorderAborted; - var traceCompleted; - var skip = true; - - if (this.tracemonkey && !this.tracemonkey.profiler) - { - recorderStarted = this.tracemonkey.recorderStarted; - recorderAborted = this.tracemonkey.recorderAborted; - traceCompleted = this.tracemonkey.traceCompleted; - skip = false; - } - - jit(false); - - reportCompare(expect, actual, summary + ': return value 10'); - - if (!skip) - { - expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; - actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; - reportCompare(expect, actual, summary + ': trace'); - } - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-462459-01.js b/js/src/tests/js1_8_1/jit/regress-462459-01.js deleted file mode 100644 index 7cfe2a90ba4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-01.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array()'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-02.js b/js/src/tests/js1_8_1/jit/regress-462459-02.js deleted file mode 100644 index 14cc20198c4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-02.js +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-03.js b/js/src/tests/js1_8_1/jit/regress-462459-03.js deleted file mode 100644 index a1d3db47083..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-03.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1, 2)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1, 2); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-04.js b/js/src/tests/js1_8_1/jit/regress-462459-04.js deleted file mode 100644 index 3bfe7278b1e..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-04.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1, 2, 3)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1, 2, 3); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-05.js b/js/src/tests/js1_8_1/jit/regress-462459-05.js deleted file mode 100644 index 5513b078e44..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-05.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array()'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-06.js b/js/src/tests/js1_8_1/jit/regress-462459-06.js deleted file mode 100644 index aab4093ab5a..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-06.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-07.js b/js/src/tests/js1_8_1/jit/regress-462459-07.js deleted file mode 100644 index 0a9632a723d..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-07.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1, 2)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1, 2); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-08.js b/js/src/tests/js1_8_1/jit/regress-462459-08.js deleted file mode 100644 index 2c57b27fde4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-08.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1, 2, 3)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1, 2, 3); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-09.js b/js/src/tests/js1_8_1/jit/regress-462459-09.js deleted file mode 100644 index 221fc19c429..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-09.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace []'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - []; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-10.js b/js/src/tests/js1_8_1/jit/regress-462459-10.js deleted file mode 100644 index 4917d5cf31b..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-10.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-11.js b/js/src/tests/js1_8_1/jit/regress-462459-11.js deleted file mode 100644 index 2f7cb1c5945..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-11.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1, 2]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1, 2]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-12.js b/js/src/tests/js1_8_1/jit/regress-462459-12.js deleted file mode 100644 index 524a7e4ae4c..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-12.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1, 2, 3]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1, 2, 3]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-469927.js b/js/src/tests/js1_8_1/jit/regress-469927.js deleted file mode 100644 index 17b893674b1..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-469927.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 469927; -var summary = 'TM: jit should not slow down short loop with let'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function letitbe() { - var start = new Date(); - for (let i = 0; i < 500000; ++i) { - for (let j = 0; j < 4; ++j) { } - } - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = letitbe(); - jit(true); - var timejit = letitbe(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-470739.js b/js/src/tests/js1_8_1/jit/regress-470739.js deleted file mode 100644 index b6b0e64e0f2..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-470739.js +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 470739; -var summary = 'TM: never abort on =='; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function loop() - { - var i; - var start = new Date(); - - for(i=0;i<500000;++i) { var r = (void 0) == null; } - - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = loop(); - jit(true); - var timejit = loop(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-471635.js b/js/src/tests/js1_8_1/jit/regress-471635.js deleted file mode 100644 index 76078649204..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-471635.js +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarksy - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 471635; -var summary = 'TM: trace js shell print()'; -var actual = ''; -var expect = ''; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - jit(true); - - (function(){ - for (var i = 1; i < 20; ++i) { - print("#"); - } - })(); - - var recorderStarted; - var recorderAborted; - var traceCompleted; - var skip = true; - - if (this.tracemonkey && !this.tracemonkey.profiler) - { - recorderStarted = this.tracemonkey.recorderStarted; - recorderAborted = this.tracemonkey.recorderAborted; - traceCompleted = this.tracemonkey.traceCompleted; - skip = false; - } - - jit(false); - - if (!skip) - { - expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; - actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; - } - else - { - expect = actual = 'Test skipped due to lack of tracemonkey jitstats object.'; - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-489682.js b/js/src/tests/js1_8_1/jit/regress-489682.js deleted file mode 100644 index b8b73ec1ca7..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-489682.js +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 489682; -var summary = 'TM: wrong number with nested type-unstable loops'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -var v = 0; - -for each (var a in [0, {}, {}, {}]) { - print(v); - v = v >>> 0; - for each (var b in [{}, {}, new String(''), 42, new String(''), {}, 42]) - { - } - } -print(v); - -jit(false); - -expect = '0'; -actual = v + ''; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/shell.js b/js/src/tests/js1_8_1/jit/shell.js deleted file mode 100644 index 63f283b96f8..00000000000 --- a/js/src/tests/js1_8_1/jit/shell.js +++ /dev/null @@ -1,4 +0,0 @@ -// The loop count at which we trace -const RECORDLOOP = this.tracemonkey ? tracemonkey.HOTLOOP : 8; -// The loop count at which we run the trace -const RUNLOOP = RECORDLOOP + 1; diff --git a/toolkit/crashreporter/tools/upload_symbols.sh b/toolkit/crashreporter/tools/upload_symbols.sh index e3d6ebc35b9..d620fbf08ee 100755 --- a/toolkit/crashreporter/tools/upload_symbols.sh +++ b/toolkit/crashreporter/tools/upload_symbols.sh @@ -44,6 +44,9 @@ # And will use the following optional environment variables if set: # SYMBOL_SERVER_SSH_KEY : path to a ssh private key to use # SYMBOL_SERVER_PORT : port to use for ssh +# POST_SYMBOL_UPLOAD_CMD: a commandline to run on the remote host after +# uploading. The full path of the symbol index +# file will be appended to the commandline. # set -e @@ -63,4 +66,11 @@ ssh -2 ${SYMBOL_SERVER_PORT:+-p $SYMBOL_SERVER_PORT} \ cd ${SYMBOL_SERVER_PATH}; unzip -o '$archive'; rm -v '$archive';" +if test -n "$POST_SYMBOL_UPLOAD_CMD"; then + echo "${POST_SYMBOL_UPLOAD_CMD} \"${SYMBOL_SERVER_PATH}/${SYMBOL_INDEX_NAME}\"" + ssh -2 ${SYMBOL_SERVER_PORT:+-p $SYMBOL_SERVER_PORT} \ + ${SYMBOL_SERVER_SSH_KEY:+-i "$SYMBOL_SERVER_SSH_KEY"} \ + -l ${SYMBOL_SERVER_USER} ${SYMBOL_SERVER_HOST} \ + "${POST_SYMBOL_UPLOAD_CMD} \"${SYMBOL_SERVER_PATH}/${SYMBOL_INDEX_NAME}\"" +fi echo "Symbol transfer completed" From 7b82bfe9fcd661f731279efa72514106562dcc9e Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Tue, 2 Nov 2010 08:21:07 -0400 Subject: [PATCH 159/263] backout bug 607946, hg rebase did some bad things. a=bustage --- Makefile.in | 2 +- js/src/jit-test/README | 74 +++ js/src/jit-test/lib/prolog.js | 48 ++ js/src/jit-test/tests/arguments/args6.js | 22 + js/src/jit-test/tests/arguments/args8.js | 14 + js/src/jit-test/tests/arguments/argsx-4.js | 23 + js/src/jit-test/tests/basic/arith.js | 11 + js/src/jit-test/tests/basic/bug520498.js | 9 + js/src/jit-test/tests/basic/bug522136.js | 10 + js/src/jit-test/tests/basic/bug528644.js | 16 + js/src/jit-test/tests/basic/bug578041.js | 3 + js/src/jit-test/tests/basic/bug584565.js | 10 + .../tests/basic/delete-named-names.js | 17 + .../jit-test/tests/basic/jitstatsArchFlags.js | 14 + js/src/jit-test/tests/basic/parseIntTests.js | 23 + .../tests/basic/strictParseIntOctal.js | 16 + .../testAssignmentThatIgnoresSetterRetval.js | 10 + js/src/jit-test/tests/basic/testBug458838.js | 19 + js/src/jit-test/tests/basic/testBug504520.js | 11 + .../tests/basic/testBug504520Harder.js | 33 ++ js/src/jit-test/tests/basic/testBug552248.js | 36 ++ js/src/jit-test/tests/basic/testBug579602.js | 21 + js/src/jit-test/tests/basic/testBug579646.js | 22 + js/src/jit-test/tests/basic/testBug584650.js | 9 + js/src/jit-test/tests/basic/testBug597736.js | 32 ++ .../basic/testEliminatedGuardWithinAnchor.js | 12 + .../tests/basic/testHoleInDenseArray.js | 18 + .../jit-test/tests/basic/testIntOverflow.js | 15 + .../tests/basic/testMethodInitSafety.js | 14 + .../tests/basic/testNativeArgsRooting.js | 14 + .../tests/basic/testNestedDeepBail.js | 20 + .../tests/basic/testNestedExitStackOuter.js | 29 ++ .../jit-test/tests/basic/testNewArrayCount.js | 12 + .../tests/basic/testNewArrayCount2.js | 8 + .../tests/basic/testProxyConstructors.js | 9 + .../jit-test/tests/basic/testRebranding2.js | 21 + .../basic/testReconstructImacroPCStack.js | 28 ++ js/src/jit-test/tests/basic/testRegExpTest.js | 10 + .../basic/testScriptGetter_JSOP_CALLPROP.js | 11 + js/src/jit-test/tests/basic/testShiftLeft.js | 38 ++ .../tests/basic/testShiftRightArithmetic.js | 44 ++ .../tests/basic/testSideExitInConstructor.js | 39 ++ .../tests/basic/testSlowNativeBail.js | 10 + .../tests/basic/testStackQuotaExhausted.js | 29 ++ js/src/jit-test/tests/closures/bug540136.js | 17 + js/src/jit-test/tests/closures/bug540242.js | 17 + js/src/jit-test/tests/closures/bug540243.js | 10 + js/src/jit-test/tests/closures/bug541239.js | 16 + js/src/jit-test/tests/closures/lambda.js | 27 ++ .../tests/closures/setname-inner-heavy.js | 18 + js/src/jit-test/tests/jaeger/bug554580-5.js | 20 + js/src/jit-test/tests/jaeger/bug555155.js | 12 + js/src/jit-test/tests/jaeger/bug555543.js | 8 + js/src/jit-test/tests/jaeger/bug556525.js | 5 + .../tests/jaeger/bug563000/eif-trap-newvar.js | 9 + .../jaeger/bug563000/eif-trap-typechange.js | 10 + .../tests/jaeger/bug563000/eif-trap.js | 10 + .../tests/jaeger/bug563000/simple-trap-1.js | 9 + .../tests/jaeger/bug563000/simple-trap-2.js | 10 + .../tests/jaeger/bug563000/simple-untrap.js | 11 + .../jaeger/bug563000/trap-force-return-1.js | 7 + .../jaeger/bug563000/trap-force-return-2.js | 7 + .../jaeger/bug563000/trap-own-callsite.js | 15 + .../jaeger/bug563000/trap-parent-from-trap.js | 21 + .../tests/jaeger/bug563000/trap-parent.js | 16 + .../jaeger/bug563000/trap-self-as-parent.js | 18 + .../jaeger/bug563000/trap-self-from-trap.js | 23 + .../tests/jaeger/bug563000/trap-self.js | 11 + .../jaeger/bug563000/untrap-own-trapsite.js | 15 + .../tests/jaeger/bug563000/untrap-self.js | 13 + js/src/jit-test/tests/jaeger/bug573433.js | 7 + js/src/jit-test/tests/jaeger/bug580884.js | 8 + js/src/jit-test/tests/jaeger/bug582286.js | 3 + js/src/jit-test/tests/jaeger/bug583158.js | 9 + js/src/jit-test/tests/jaeger/bug585341.js | 6 + js/src/jit-test/tests/jaeger/bug588338.js | 14 + js/src/jit-test/tests/jaeger/bug588363-2.js | 7 + .../jit-test/tests/jaeger/crash-on-compare.js | 1 + js/src/jit-test/tests/jaeger/fused-eq-ifeq.js | 6 + js/src/jit-test/tests/pic/bug558099.js | 60 +++ .../sunspider/check-date-format-xparb.js | 422 ++++++++++++++++++ .../sunspider/check-math-partial-sums.js | 41 ++ .../tests/sunspider/check-string-tagcloud.js | 270 +++++++++++ js/src/tests/js1_8_1/jit/jstests.list | 24 + js/src/tests/js1_8_1/jit/regress-451673.js | 115 +++++ js/src/tests/js1_8_1/jit/regress-451974-01.js | 86 ++++ js/src/tests/js1_8_1/jit/regress-451974-02.js | 97 ++++ js/src/tests/js1_8_1/jit/regress-452498-01.js | 105 +++++ js/src/tests/js1_8_1/jit/regress-458838.js | 97 ++++ js/src/tests/js1_8_1/jit/regress-462459-01.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-02.js | 106 +++++ js/src/tests/js1_8_1/jit/regress-462459-03.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-04.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-05.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-06.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-07.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-08.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-09.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-10.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-11.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-12.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-469927.js | 78 ++++ js/src/tests/js1_8_1/jit/regress-470739.js | 80 ++++ js/src/tests/js1_8_1/jit/regress-471635.js | 90 ++++ js/src/tests/js1_8_1/jit/regress-489682.js | 65 +++ js/src/tests/js1_8_1/jit/shell.js | 4 + toolkit/crashreporter/tools/upload_symbols.sh | 10 - 107 files changed, 4218 insertions(+), 11 deletions(-) create mode 100644 js/src/jit-test/README create mode 100644 js/src/jit-test/lib/prolog.js create mode 100644 js/src/jit-test/tests/arguments/args6.js create mode 100644 js/src/jit-test/tests/arguments/args8.js create mode 100644 js/src/jit-test/tests/arguments/argsx-4.js create mode 100644 js/src/jit-test/tests/basic/arith.js create mode 100644 js/src/jit-test/tests/basic/bug520498.js create mode 100644 js/src/jit-test/tests/basic/bug522136.js create mode 100644 js/src/jit-test/tests/basic/bug528644.js create mode 100644 js/src/jit-test/tests/basic/bug578041.js create mode 100644 js/src/jit-test/tests/basic/bug584565.js create mode 100644 js/src/jit-test/tests/basic/delete-named-names.js create mode 100644 js/src/jit-test/tests/basic/jitstatsArchFlags.js create mode 100644 js/src/jit-test/tests/basic/parseIntTests.js create mode 100644 js/src/jit-test/tests/basic/strictParseIntOctal.js create mode 100644 js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js create mode 100644 js/src/jit-test/tests/basic/testBug458838.js create mode 100644 js/src/jit-test/tests/basic/testBug504520.js create mode 100644 js/src/jit-test/tests/basic/testBug504520Harder.js create mode 100644 js/src/jit-test/tests/basic/testBug552248.js create mode 100644 js/src/jit-test/tests/basic/testBug579602.js create mode 100644 js/src/jit-test/tests/basic/testBug579646.js create mode 100644 js/src/jit-test/tests/basic/testBug584650.js create mode 100644 js/src/jit-test/tests/basic/testBug597736.js create mode 100644 js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js create mode 100644 js/src/jit-test/tests/basic/testHoleInDenseArray.js create mode 100644 js/src/jit-test/tests/basic/testIntOverflow.js create mode 100644 js/src/jit-test/tests/basic/testMethodInitSafety.js create mode 100644 js/src/jit-test/tests/basic/testNativeArgsRooting.js create mode 100644 js/src/jit-test/tests/basic/testNestedDeepBail.js create mode 100644 js/src/jit-test/tests/basic/testNestedExitStackOuter.js create mode 100644 js/src/jit-test/tests/basic/testNewArrayCount.js create mode 100644 js/src/jit-test/tests/basic/testNewArrayCount2.js create mode 100644 js/src/jit-test/tests/basic/testProxyConstructors.js create mode 100644 js/src/jit-test/tests/basic/testRebranding2.js create mode 100644 js/src/jit-test/tests/basic/testReconstructImacroPCStack.js create mode 100644 js/src/jit-test/tests/basic/testRegExpTest.js create mode 100644 js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js create mode 100644 js/src/jit-test/tests/basic/testShiftLeft.js create mode 100644 js/src/jit-test/tests/basic/testShiftRightArithmetic.js create mode 100644 js/src/jit-test/tests/basic/testSideExitInConstructor.js create mode 100644 js/src/jit-test/tests/basic/testSlowNativeBail.js create mode 100644 js/src/jit-test/tests/basic/testStackQuotaExhausted.js create mode 100644 js/src/jit-test/tests/closures/bug540136.js create mode 100644 js/src/jit-test/tests/closures/bug540242.js create mode 100644 js/src/jit-test/tests/closures/bug540243.js create mode 100644 js/src/jit-test/tests/closures/bug541239.js create mode 100644 js/src/jit-test/tests/closures/lambda.js create mode 100644 js/src/jit-test/tests/closures/setname-inner-heavy.js create mode 100644 js/src/jit-test/tests/jaeger/bug554580-5.js create mode 100644 js/src/jit-test/tests/jaeger/bug555155.js create mode 100644 js/src/jit-test/tests/jaeger/bug555543.js create mode 100644 js/src/jit-test/tests/jaeger/bug556525.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-self.js create mode 100644 js/src/jit-test/tests/jaeger/bug573433.js create mode 100644 js/src/jit-test/tests/jaeger/bug580884.js create mode 100644 js/src/jit-test/tests/jaeger/bug582286.js create mode 100644 js/src/jit-test/tests/jaeger/bug583158.js create mode 100644 js/src/jit-test/tests/jaeger/bug585341.js create mode 100644 js/src/jit-test/tests/jaeger/bug588338.js create mode 100644 js/src/jit-test/tests/jaeger/bug588363-2.js create mode 100644 js/src/jit-test/tests/jaeger/crash-on-compare.js create mode 100644 js/src/jit-test/tests/jaeger/fused-eq-ifeq.js create mode 100644 js/src/jit-test/tests/pic/bug558099.js create mode 100644 js/src/jit-test/tests/sunspider/check-date-format-xparb.js create mode 100644 js/src/jit-test/tests/sunspider/check-math-partial-sums.js create mode 100644 js/src/jit-test/tests/sunspider/check-string-tagcloud.js create mode 100644 js/src/tests/js1_8_1/jit/jstests.list create mode 100644 js/src/tests/js1_8_1/jit/regress-451673.js create mode 100644 js/src/tests/js1_8_1/jit/regress-451974-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-451974-02.js create mode 100644 js/src/tests/js1_8_1/jit/regress-452498-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-458838.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-02.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-03.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-04.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-05.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-06.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-07.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-08.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-09.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-10.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-11.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-12.js create mode 100644 js/src/tests/js1_8_1/jit/regress-469927.js create mode 100644 js/src/tests/js1_8_1/jit/regress-470739.js create mode 100644 js/src/tests/js1_8_1/jit/regress-471635.js create mode 100644 js/src/tests/js1_8_1/jit/regress-489682.js create mode 100644 js/src/tests/js1_8_1/jit/shell.js diff --git a/Makefile.in b/Makefile.in index aeaf6ad4453..b13e00a2032 100644 --- a/Makefile.in +++ b/Makefile.in @@ -171,7 +171,7 @@ ifdef MOZ_SYMBOLS_EXTRA_BUILDID EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID) endif -export SYMBOL_INDEX_NAME = \ +SYMBOL_INDEX_NAME = \ $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt buildsymbols: diff --git a/js/src/jit-test/README b/js/src/jit-test/README new file mode 100644 index 00000000000..ddde38dc962 --- /dev/null +++ b/js/src/jit-test/README @@ -0,0 +1,74 @@ +JS Trace Test Suite + +* PURPOSE + +This is a test suite for testing TraceMonkey. All tests are run in the JS shell +with tracing enabled (-j). + +* REQUIREMENTS + +Python 2.5. This is already a standard requirement for building our tree. + +* RUNNING THE TESTS + +Basic usage: + + python jit_test.py + +The progress bar shows [#tests passed, #tests failed, #tests run] at the left. +If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted +at any time with Ctrl+C and partial results will be printed. + +To run only the basic tests, not including the slow tests: + + python jit_test.py basic + +For more options: + + python jit_test.py -h + +* CREATING NEW TESTS + +Simply create a JS file under the 'tests/' directory. Most tests should go in +'tests/basic/'. + +All tests are run with 'lib/prolog.js' included first on the command line. The +command line also creates a global variable 'libdir' that is set to the path +of the 'lib' directory. To include a file 'foo.js' from the lib directory in a +test case: + + load(libdir + 'foo.js') + +* TEST METALINES + +The first line of a test case can contain a special comment controlling how the +test is run. For example: + + // |jit-test| allow-oom; + +The general format in EBNF is: + + metaline ::= cookie { item ";" } + cookie ::= "|jit-test|" + item ::= flag | attribute + + flag ::= "slow" | "allow-oom" + + attribute ::= name ":" value + name ::= "TMFLAGS" | "error" + value ::= + +The metaline may appear anywhere in the first line of the file: this allows it +to be placed inside any kind of comment. + +The meaning of the items: + + slow Test runs slowly. Do not run if the --no-slow option is given. + allow-oom If the test runs out of memory, it counts as passing. + valgrind Run test under valgrind. + + error The test should be considered to pass iff it throws the + given JS exception. + TMFLAGS Set the environment variable TMFLAGS to the given value. + +* END diff --git a/js/src/jit-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js new file mode 100644 index 00000000000..5d577b39bda --- /dev/null +++ b/js/src/jit-test/lib/prolog.js @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +const HAVE_TM = 'tracemonkey' in this; + +const HOTLOOP = HAVE_TM ? tracemonkey.HOTLOOP : 8; +const RECORDLOOP = HOTLOOP; +const RUNLOOP = HOTLOOP + 1; + +var checkStats; +if (HAVE_TM) { + checkStats = function(stats) + { + // Temporarily disabled while we work on heuristics. + return; + function jit(on) + { + if (on && !options().match(/tracejit/)) + { + options('tracejit'); + } + else if (!on && options().match(/tracejit/)) + { + options('tracejit'); + } + } + + jit(false); + for (var name in stats) { + var expected = stats[name]; + var actual = tracemonkey[name]; + if (expected != actual) { + print('Trace stats check failed: got ' + actual + ', expected ' + expected + ' for ' + name); + } + } + jit(true); + }; +} else { + checkStats = function() {}; +} + +var appendToActual = function(s) { + actual += s + ','; +} + +if (!("gczeal" in this)) { + gczeal = function() { } +} + diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js new file mode 100644 index 00000000000..a2fc60d36a8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args6.js @@ -0,0 +1,22 @@ +actual = ''; +expected = '6,'; + +// tracing length + +var g = 0; + +function h(args) { + g = args.length; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 5; ++i) { + f(10, 20, 30, 40, 50, 60); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js new file mode 100644 index 00000000000..57938d9e231 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args8.js @@ -0,0 +1,14 @@ +actual = ''; +expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],'; + +function h() { + return arguments; +} + +for (var i = 0; i < 5; ++i) { + var p = h(i, i*2); + appendToActual(p); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js new file mode 100644 index 00000000000..b52b14853cf --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-4.js @@ -0,0 +1,23 @@ +actual = ''; +expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,'; + +function f() { + g(arguments); +} + +function g(a, b, c) { + h(arguments); + a = 1; + b = 2; + c = 3; + h(arguments); +} + +function h(a, b, c) { + appendToActual(a + ' ' + b + ' ' + c); +} + +f(4, 5, 6); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/basic/arith.js b/js/src/jit-test/tests/basic/arith.js new file mode 100644 index 00000000000..b7f551dccd0 --- /dev/null +++ b/js/src/jit-test/tests/basic/arith.js @@ -0,0 +1,11 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis + +function arith() +{ + var accum = 0; + for (var i = 0; i < 100; i++) { + accum += (i * 2) - 1; + } + return accum; +} +assertEq(arith(), 9800); diff --git a/js/src/jit-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js new file mode 100644 index 00000000000..55324f6f30d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug520498.js @@ -0,0 +1,9 @@ +var Q = 0; +try { + (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) +} catch (e) { +} + +if (Q == 100000) + assertEq(Q, "fail"); + diff --git a/js/src/jit-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js new file mode 100644 index 00000000000..9267c99ccfa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug522136.js @@ -0,0 +1,10 @@ +var Q = 0; +try { + (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) +} catch (e) { +} + +// Exact behavior of recursion check depends on which JIT we use. +var ok = (Q == 3000 || Q == 3001); +assertEq(ok, true); + diff --git a/js/src/jit-test/tests/basic/bug528644.js b/js/src/jit-test/tests/basic/bug528644.js new file mode 100644 index 00000000000..260e0d99590 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug528644.js @@ -0,0 +1,16 @@ +// Don't crash + +function g(foo) { + for (a in foo) { + } +} + +var makegen = eval("\n\ + (function(b) {\n\ + var h = \n\ + eval(\"new function() { yield print(b) }\" ); \n\ + return h\n\ + })\n\ +"); + +g(makegen()); diff --git a/js/src/jit-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js new file mode 100644 index 00000000000..7a81feb1800 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug578041.js @@ -0,0 +1,3 @@ +__defineGetter__('x', Float32Array); +with(this) + x; diff --git a/js/src/jit-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js new file mode 100644 index 00000000000..ad7d4b47577 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584565.js @@ -0,0 +1,10 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ +// Contributor: Luke Wagner + +var x, f; +for (var i = 0; i < 100; i++) { + f = function() {}; + f.foo; + x = f.length; +} diff --git a/js/src/jit-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js new file mode 100644 index 00000000000..1e0ac407321 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-named-names.js @@ -0,0 +1,17 @@ +var a = ['p', 'q', 'r', 's', 't']; +var o = {p:1, q:2, r:3, s:4, t:5}; +for (var i in o) { + delete o.p; + delete o.q; + delete o.r; + delete o.s; + delete o.t; +} +for each (var i in a) + assertEq(o.hasOwnProperty(i), false); + +checkStats({ + recorderAborted:0, + traceCompleted:1, + sideExitIntoInterpreter:1 +}); diff --git a/js/src/jit-test/tests/basic/jitstatsArchFlags.js b/js/src/jit-test/tests/basic/jitstatsArchFlags.js new file mode 100644 index 00000000000..a4ec0c4ee4b --- /dev/null +++ b/js/src/jit-test/tests/basic/jitstatsArchFlags.js @@ -0,0 +1,14 @@ +// Make sure the arch flags are valid on startup, even if nothing has +// been traced yet. We don't know what arch the user is building on, +// but presumably we want at least 1 flag to be set on all supported +// platforms. + +if (HAVE_TM) { + assertEq(jitstats.archIsIA32 || + jitstats.archIs64BIT || + jitstats.archIsARM || + jitstats.archIsSPARC || + jitstats.archIsPPC || + jitstats.archIsAMD64, + 1); + } diff --git a/js/src/jit-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js new file mode 100644 index 00000000000..c8ecb366556 --- /dev/null +++ b/js/src/jit-test/tests/basic/parseIntTests.js @@ -0,0 +1,23 @@ +function parseIntHelper(n) { + var a; + for (var i = 0; i < 5; i++) + a = parseInt(n); + return a; +} +function doParseIntTests() { + var inputs = [0, -0, .1, -.1, .7, -.7, 1.3, -1.3]; + var outputs = new Array(8); + //avoid jit, unrolled + outputs[0] = outputs[1] = outputs[2] = outputs[4] = 0; + outputs[3] = outputs[5] = -0; + outputs[6] = 1; + outputs[7] = -1; + for (var i = 0; i < 8; i++) { + var testfn = new Function('return parseIntHelper(' + uneval(inputs[i]) + ');'); + assertEq(testfn(), outputs[i]); + } +} +doParseIntTests(); + +assertEq(parseInt("08"), 0); +assertEq(parseInt("09"), 0); diff --git a/js/src/jit-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js new file mode 100644 index 00000000000..536d2d7dd0c --- /dev/null +++ b/js/src/jit-test/tests/basic/strictParseIntOctal.js @@ -0,0 +1,16 @@ +"use strict"; + +assertEq(parseInt("08"), 0); +assertEq(parseInt("09"), 0); +assertEq(parseInt("014"), 12); +assertEq(parseInt("0xA"), 10); +assertEq(parseInt("00123"), 83); + +for (var i = 0; i < 5; i++) +{ + assertEq(parseInt("08"), 0); + assertEq(parseInt("09"), 0); + assertEq(parseInt("014"), 12); + assertEq(parseInt("0xA"), 10); + assertEq(parseInt("00123"), 83); +} diff --git a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js new file mode 100644 index 00000000000..1c59113482d --- /dev/null +++ b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js @@ -0,0 +1,10 @@ +var o = { + set x(v) { + return 42; + } +}; + +for (var i = 0; i < 10; ++i) { + var z = o.x = "choose me"; + assertEq(z, "choose me"); +} diff --git a/js/src/jit-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js new file mode 100644 index 00000000000..cd1e05cf77b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug458838.js @@ -0,0 +1,19 @@ +var escape; +function testBug458838() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); +} +assertEq(testBug458838(), 10); +checkStats({ + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1 +}); diff --git a/js/src/jit-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js new file mode 100644 index 00000000000..73e2e3013fb --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520.js @@ -0,0 +1,11 @@ +function testBug504520() { + // A bug involving comparisons. + var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 0]; + assertEq(arr.length > RUNLOOP, true); + + var s = ''; + for (var i = 0; i < arr.length; i++) + arr[i] >= 1/0 ? null : (s += i); + assertEq(s, '9'); +} +testBug504520(); diff --git a/js/src/jit-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js new file mode 100644 index 00000000000..0a63ebf4075 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520Harder.js @@ -0,0 +1,33 @@ +function testBug504520Harder() { + // test 1024 similar cases + var vals = [1/0, -1/0, 0, 0/0]; + var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; + for each (var x in vals) { + for each (var y in vals) { + for each (var op in ops) { + for each (var z in vals) { + // Assume eval is correct. This depends on the global + // Infinity property not having been reassigned. + var xz = eval(x + op + z); + var yz = eval(y + op + z); + + var arr = [x, x, x, x, x, x, x, x, x, y]; + assertEq(arr.length > RUNLOOP, true); + var expected = [xz, xz, xz, xz, xz, xz, xz, xz, xz, yz]; + + // ?: looks superfluous but that's what we're testing here + var fun = eval( + '(function (arr, results) {\n' + + ' for (let i = 0; i < arr.length; i++)\n' + + ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + + '});\n'); + var actual = []; + fun(arr, actual); + print(x, y, op, z); + assertEq("" + actual, "" + expected); + } + } + } + } +} +testBug504520Harder(); diff --git a/js/src/jit-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js new file mode 100644 index 00000000000..28782b665bb --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug552248.js @@ -0,0 +1,36 @@ +setDebug(true); +var a = new Array(); + +function i(save) { + var x = 9; + evalInFrame(0, "a.push(x)", save); + evalInFrame(1, "a.push(z)", save); + evalInFrame(2, "a.push(z)", save); + evalInFrame(3, "a.push(y)", save); + evalInFrame(4, "a.push(x)", save); +} + +function h() { + var z = 5; + evalInFrame(0, "a.push(z)"); + evalInFrame(1, "a.push(y)"); + evalInFrame(2, "a.push(x)"); + evalInFrame(0, "i(false)"); + evalInFrame(0, "a.push(z)", true); + evalInFrame(1, "a.push(y)", true); + evalInFrame(2, "a.push(x)", true); + evalInFrame(0, "i(true)", true); +} + +function g() { + var y = 4; + h(); +} + +function f() { + var x = 3; + g(); +} + +f(); +assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+''); diff --git a/js/src/jit-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js new file mode 100644 index 00000000000..5871c24d46e --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug579602.js @@ -0,0 +1,21 @@ +// don't panic + +f = function() { + x = yield +} +rv = f() +for (a in rv) (function() {}) +x = Proxy.create((function() { + return { + defineProperty: gc + } +})(), x) +with({ + d: (({ + x: Object.defineProperty(x, "", ({ + set: Array.e + })) + })) +}) {} + +// don't crash diff --git a/js/src/jit-test/tests/basic/testBug579646.js b/js/src/jit-test/tests/basic/testBug579646.js new file mode 100644 index 00000000000..d034410f9cc --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug579646.js @@ -0,0 +1,22 @@ +if (typeof gczeal != "function") + gczeal = function() {} + +for (a = 0; a < 9; a++) + for (b = 0; b < 1; b++) + for (c = 0; c < 2; c++) + gczeal(); + +for each(e in [NaN]) + for (d = 0; d < 1; d++) + z = 0; + +for (w in [0, 0]) + {} + +x = 0; + +for (e = 0; e < 3; e++) + for (f = 0; f < 4; f++) + x = -x + +// don't crash diff --git a/js/src/jit-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js new file mode 100644 index 00000000000..b6c9d8ab7fd --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug584650.js @@ -0,0 +1,9 @@ +if (typeof gczeal != "function") + gczeal = function() {} + +// don't crash +x = (evalcx('lazy')) +x.watch("", function () {}) +gczeal(1) +for (w in x) {} + diff --git a/js/src/jit-test/tests/basic/testBug597736.js b/js/src/jit-test/tests/basic/testBug597736.js new file mode 100644 index 00000000000..ded33842776 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug597736.js @@ -0,0 +1,32 @@ +function leak_test() { + // Create a reference loop function->script->traceFragment->object->function + // that GC must be able to break. To embedd object into the fragment the + // code use prototype chain of depth 2 which caches obj.__proto__.__proto__ + // into the fragment. + + // To make sure that we have no references to the function f after this + // function returns due via the conservative scan of the native stack we + // loop here multiple times overwriting the stack and registers with new garabge. + for (var j = 0; j != 8; ++j) { + var f = Function("a", "var s = 0; for (var i = 0; i != 100; ++i) s += a.b; return s;"); + var c = {b: 1, f: f, leakDetection: makeFinalizeObserver()}; + f({ __proto__: { __proto__: c}}); + f = c = a = null; + gc(); + } +} + +function test() +{ + if (typeof finalizeCount != "function") + return; + + var base = finalizeCount(); + leak_test(); + gc(); + gc(); + var n = finalizeCount(); + assertEq(base + 4 < finalizeCount(), true, "Some finalizations must happen"); +} + +test(); diff --git a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js new file mode 100644 index 00000000000..cc80e779c37 --- /dev/null +++ b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js @@ -0,0 +1,12 @@ +function testEliminatedGuardWithinAnchor() { + for (let i = 0; i < 5; ++i) { i / (i * i); } + return "ok"; +} + +assertEq(testEliminatedGuardWithinAnchor(), "ok"); + +if (HAVE_TM) { + checkStats({ + sideExitIntoInterpreter: (jitstats.archIsARM ? 1 : 3) + }); +} diff --git a/js/src/jit-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js new file mode 100644 index 00000000000..ba7a2c01e16 --- /dev/null +++ b/js/src/jit-test/tests/basic/testHoleInDenseArray.js @@ -0,0 +1,18 @@ +var s; + +function f(i) { + if (i > 4) /* side exit when arr[i] changes from bool to undefined (via a hole) */ + assertEq(s, undefined); + else + assertEq(s, false); + return 1; +} + +/* trailing 'true' ensures array has capacity >= 10 */ +var arr = [ false, false, false, false, false, , , , , , true ]; + +for (var i = 0; i < 10; ++i) { + (s = arr[i]) + f(i); +} + +checkStats({ traceTriggered: 2, sideExitIntoInterpreter: 2 }) diff --git a/js/src/jit-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js new file mode 100644 index 00000000000..712ef0c6529 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIntOverflow.js @@ -0,0 +1,15 @@ +function testIntOverflow() { + // int32_max - 7 + var ival = 2147483647 - 7; + for (var i = 0; i < 30; i++) { + ival += 30; + } + return (ival < 2147483647); +} +assertEq(testIntOverflow(), false); +checkStats({ + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1, + traceTriggered: 1, +}); diff --git a/js/src/jit-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js new file mode 100644 index 00000000000..ebd6309bdf9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodInitSafety.js @@ -0,0 +1,14 @@ +function testMethodInitSafety() { + function f() { return 'fail'; } + function g() { return 'ok'; } + + var s; + var arr = [f, f, f, f, g]; + //assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < arr.length; i++) { + var x = {m: arr[i]}; + s = x.m(); + } + return s; +} +assertEq(testMethodInitSafety(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js new file mode 100644 index 00000000000..1ce8259f2d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeArgsRooting.js @@ -0,0 +1,14 @@ +if ('gczeal' in this) +(function () { + (eval("\ + (function () {\ + for (var y = 0; y < 16; ++y) {\ + if (y % 3 == 2) {\ + gczeal(1);\ + } else {\ + print(0 / 0);\ + }\ + }\ + });\ + "))() +})(); diff --git a/js/src/jit-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js new file mode 100644 index 00000000000..8e59b04cdaa --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedDeepBail.js @@ -0,0 +1,20 @@ +var _quit; +function testNestedDeepBail() +{ + _quit = false; + function loop() { + for (var i = 0; i < 4; i++) + ; + } + loop(); + + function f() { + loop(); + _quit = true; + } + + var stk = [[1], [], [], [], []]; + while (!_quit) + stk.pop().forEach(f); +} +testNestedDeepBail(); diff --git a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js new file mode 100644 index 00000000000..88b795e7cbc --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js @@ -0,0 +1,29 @@ +// Test stack reconstruction after a nested exit +function testNestedExitStackInner(j, counter) { + ++counter; + var b = 0; + for (var i = 1; i <= RUNLOOP; i++) { + ++b; + var a; + // Make sure that once everything has been traced we suddenly switch to + // a different control flow the first time we run the outermost tree, + // triggering a side exit. + if (j < RUNLOOP) + a = 1; + else + a = 0; + ++b; + b += a; + } + return counter + b; +} +function testNestedExitStackOuter() { + var counter = 0; + for (var j = 1; j <= RUNLOOP; ++j) { + for (var k = 1; k <= RUNLOOP; ++k) { + counter = testNestedExitStackInner(j, counter); + } + } + return counter; +} +//assertEq(testNestedExitStackOuter(), 81); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js new file mode 100644 index 00000000000..cb7e6d9843c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount.js @@ -0,0 +1,12 @@ +function testNewArrayCount() +{ + function count(a) { var n = 0; for (var p in a) n++; return n; } + var a = []; + for (var i = 0; i < 5; i++) + a = [0]; + assertEq(count(a), 1); + for (var i = 0; i < 5; i++) + a = [0, , 2]; + assertEq(count(a), 2); +} +testNewArrayCount(); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js new file mode 100644 index 00000000000..6318e4c25f3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount2.js @@ -0,0 +1,8 @@ +function testNewArrayCount2() { + function count(a) { var n = 0; for (var p in a) n++; return n; } + var x = 0; + for (var i = 0; i < 10; ++i) + x = count(new Array(1,2,3)); + return x; +} +assertEq(testNewArrayCount2(), 3); diff --git a/js/src/jit-test/tests/basic/testProxyConstructors.js b/js/src/jit-test/tests/basic/testProxyConstructors.js new file mode 100644 index 00000000000..e716b361ef0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testProxyConstructors.js @@ -0,0 +1,9 @@ +// proxies can return primitives +assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined); + +x = Proxy.createFunction((function () {}), Uint16Array, wrap) +new(wrap(x)) + +// proxies can return the callee +var x = Proxy.createFunction({}, function (q) { return q; }); +new x(x); diff --git a/js/src/jit-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js new file mode 100644 index 00000000000..2bf26eeaff5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRebranding2.js @@ -0,0 +1,21 @@ +delete q; +delete g; +delete h; +delete a; +delete f; + +function testRebranding2() { + // Same as testRebranding, but the object to be rebranded isn't the global. + var x = "FAIL"; + function g(){} + function h(){ x = "ok"; } + var obj = {m: g}; + var arr = [g, g, g, g, h]; + //assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < 5; i++) { + obj.m = arr[i]; + obj.m(); + } + return x; +} +assertEq(testRebranding2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js new file mode 100644 index 00000000000..2dc51508d4f --- /dev/null +++ b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js @@ -0,0 +1,28 @@ +x = Proxy.create((function () { + return { + get: function () {} + } +}()), Object.e) + +var hit = false; + +try { + Function("\ + for(var a = 0; a < 2; ++a) {\ + if (a == 0) {}\ + else {\ + x > x\ + }\ + }\ + ")() +} catch (e) { + hit = true; + + var str = String(e); + var match = (str == "TypeError: x is not a function" || + str == "TypeError: can't convert x to number"); + + assertEq(match, true); +} + +assertEq(hit, true); diff --git a/js/src/jit-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js new file mode 100644 index 00000000000..78917ba9be3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRegExpTest.js @@ -0,0 +1,10 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +function testRegExpTest() { + var r = /abc/; + var flag = false; + for (var i = 0; i < 10; ++i) + flag = r.test("abc"); + return flag; +} +assertEq(testRegExpTest(), true); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js new file mode 100644 index 00000000000..14574b146bf --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js @@ -0,0 +1,11 @@ +var a = {_val: 'q', + get p() { return f; }}; + +function f() { return this._val; } + +var g = ''; +for (var i = 0; i < 9; i++) + g += a.p(); +assertEq(g, 'qqqqqqqqq'); + +checkStats({recorderStarted: 1, recorderAborted: 0, traceCompleted: 1, traceTriggered: 1}); diff --git a/js/src/jit-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js new file mode 100644 index 00000000000..4a7f5d98289 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftLeft.js @@ -0,0 +1,38 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +/* Test the proper operation of the left shift operator. This is especially + * important on ARM as an explicit mask is required at the native instruction + * level. */ + +load(libdir + 'range.js'); + +function testShiftLeft() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 256); + + return r.join(","); +} + +assertEq(testShiftLeft(), + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648"); diff --git a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js new file mode 100644 index 00000000000..7268dc0bad3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js @@ -0,0 +1,44 @@ +/* Test the proper operation of the arithmetic right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ + +load(libdir + 'range.js'); + +/* Test different combinations of literals/variables. */ +var s = 4; +var t = 100; +assertEq(42 >> s, 2); +assertEq(s >> 1, 2); +assertEq(23 >> 3, 2); +assertEq(t >> s, 6); + + +function testShiftRightArithmetic() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 256); + + return r.join(","); +} +assertEq(testShiftRightArithmetic(), + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"); diff --git a/js/src/jit-test/tests/basic/testSideExitInConstructor.js b/js/src/jit-test/tests/basic/testSideExitInConstructor.js new file mode 100644 index 00000000000..d46543ef7bd --- /dev/null +++ b/js/src/jit-test/tests/basic/testSideExitInConstructor.js @@ -0,0 +1,39 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +function testSideExitInConstructor() { + var FCKConfig = {}; + FCKConfig.CoreStyles = + { + 'Bold': { }, + 'Italic': { }, + 'FontFace': { }, + 'Size' : + { + Overrides: [ ] + }, + + 'Color' : + { + Element: '', + Styles: { }, + Overrides: [ ] + }, + 'BackColor': { + Element : '', + Styles : { 'background-color' : '' } + }, + + }; + var FCKStyle = function(A) { + A.Element; + }; + + var pass = true; + for (var s in FCKConfig.CoreStyles) { + var x = new FCKStyle(FCKConfig.CoreStyles[s]); + if (!x) + pass = false; + } + return pass; +} +assertEq(testSideExitInConstructor(), true); diff --git a/js/src/jit-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js new file mode 100644 index 00000000000..f7a1443a71a --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowNativeBail.js @@ -0,0 +1,10 @@ +function testSlowNativeBail() { + var a = ['0', '1', '2', '3', '+']; + try { + for (var i = 0; i < a.length; i++) + new RegExp(a[i]); + } catch (exc) { + assertEq(""+exc, "SyntaxError: invalid quantifier"); + } +} +testSlowNativeBail(); diff --git a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js new file mode 100644 index 00000000000..f65957a74b7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js @@ -0,0 +1,29 @@ +const numFatArgs = Math.pow(2,19) - 1024; + +function fun(x) { + if (x <= 0) + return 0; + return fun(x-1); +} + +function fatStack() { + return fun(10000); +} + +function assertRightFailure(e) { + assertEq(e.toString() == "InternalError: script stack space quota is exhausted" || + e.toString() == "InternalError: too much recursion", + true); +} + +exception = false; +try { + fatStack.apply(null, new Array(numFatArgs)); +} catch (e) { + assertRightFailure(e); + exception = true; +} +assertEq(exception, true); + +// No more trace recursion w/ JM +checkStats({traceCompleted:0}); diff --git a/js/src/jit-test/tests/closures/bug540136.js b/js/src/jit-test/tests/closures/bug540136.js new file mode 100644 index 00000000000..54b57713a7f --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540136.js @@ -0,0 +1,17 @@ +// |jit-test| error: TypeError + +(eval("\ + (function () {\ + for (var[x] = function(){} in \ + (function m(a) {\ + if (a < 1) {\ + x;\ + return\ + }\ + return m(a - 1) + m(a - 2)\ + })(7)\ + (eval(\"\"))\ + )\ + ([])\ + })\ +"))() diff --git a/js/src/jit-test/tests/closures/bug540242.js b/js/src/jit-test/tests/closures/bug540242.js new file mode 100644 index 00000000000..56c1a5a3143 --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540242.js @@ -0,0 +1,17 @@ +for (j = 0; j < 1; j++) { + var f = eval("\ + (function() {\ + for (var a = 0; a < 8; ++a) {\ + if (a % 3 == 2) {\ + eval(\"\ + for(b in[0,0,0,0]) {\ + print()\ + }\ + \")\ + }\ + gc()\ + }\ + })\ + "); + f() +} diff --git a/js/src/jit-test/tests/closures/bug540243.js b/js/src/jit-test/tests/closures/bug540243.js new file mode 100644 index 00000000000..07faa26b6e7 --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540243.js @@ -0,0 +1,10 @@ +for (a in (eval("\ + (function() {\ + return function() {\ + yield ((function() {\ + return d\ + })())\ + } ();\ + var d = []\ + })\ +"))()); diff --git a/js/src/jit-test/tests/closures/bug541239.js b/js/src/jit-test/tests/closures/bug541239.js new file mode 100644 index 00000000000..32e3af1565b --- /dev/null +++ b/js/src/jit-test/tests/closures/bug541239.js @@ -0,0 +1,16 @@ +function m() { + var d = 73; + + return (eval("\n\ + (function() {\n\ + return function() {\n\ + yield ((function() {\n\ + print(d);\n\ + return d\n\ + })())\n\ + } ();\n\ + })\n\ + "))(); +} + +m().next(); diff --git a/js/src/jit-test/tests/closures/lambda.js b/js/src/jit-test/tests/closures/lambda.js new file mode 100644 index 00000000000..fd7cbd16ed7 --- /dev/null +++ b/js/src/jit-test/tests/closures/lambda.js @@ -0,0 +1,27 @@ +function f() { + var k = 0; + + var g = function() { + return ++k; + } + + return g; +} + +function h() { + for (var i = 0; i < 10; ++i) { + var vf = f(); + assertEq(vf(), 1); + assertEq(vf(), 2); + for (var j = 0; j < 10; ++j) { + assertEq(vf(), j + 3); + } + } +} + +h(); + +checkStats({ + recorderAborted: 8, // Inner tree is trying to grow +}); + diff --git a/js/src/jit-test/tests/closures/setname-inner-heavy.js b/js/src/jit-test/tests/closures/setname-inner-heavy.js new file mode 100644 index 00000000000..9c1919dc2f3 --- /dev/null +++ b/js/src/jit-test/tests/closures/setname-inner-heavy.js @@ -0,0 +1,18 @@ +actual = ''; +expected = 'undefined,'; + +function f() { + (eval("\ + (function () {\ + for (var z = 0; z < 2; ++z) {\ + x = ''\ + }\ + })\ + "))(); +} +__defineSetter__("x", eval) +f() +appendToActual(x); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/jaeger/bug554580-5.js b/js/src/jit-test/tests/jaeger/bug554580-5.js new file mode 100644 index 00000000000..1d3ee522b07 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug554580-5.js @@ -0,0 +1,20 @@ +(function() { + (function g(m, n) { + if (m = n) { + return eval("x=this") + } + g(m, 1)[[]] + })() +})() +Function("\ + for (let b in [0]) {\ + for (var k = 0; k < 6; ++k) {\ + if (k == 1) {\ + print(x)\ + }\ + }\ + }\ +")() + +/* Don't crash/assert. */ + diff --git a/js/src/jit-test/tests/jaeger/bug555155.js b/js/src/jit-test/tests/jaeger/bug555155.js new file mode 100644 index 00000000000..db7b57aa1bc --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug555155.js @@ -0,0 +1,12 @@ +// |jit-test| error: undefined +(function() { + throw (function f(a, b) { + if (a.h == b) { + return eval("((function(){return 1})())!=this") + } + f(b) + })([], 0) +})() + +/* Don't assert/crash. */ + diff --git a/js/src/jit-test/tests/jaeger/bug555543.js b/js/src/jit-test/tests/jaeger/bug555543.js new file mode 100644 index 00000000000..b641c1b5832 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug555543.js @@ -0,0 +1,8 @@ +(function() { + for each(let z in [new String(''), new String('q'), new String('')]) { + if (uneval() < z) (function(){}) + } +})() + +/* Don't assert/crash. */ + diff --git a/js/src/jit-test/tests/jaeger/bug556525.js b/js/src/jit-test/tests/jaeger/bug556525.js new file mode 100644 index 00000000000..0b59f3274b0 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug556525.js @@ -0,0 +1,5 @@ +for each(x in [new Number]) + x.__proto__ = [] +++x[x] + +// don't assert diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js new file mode 100644 index 00000000000..2cde4fde8a9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js @@ -0,0 +1,9 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + return x; +} +trap(caller, 7, "var x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js new file mode 100644 index 00000000000..11f2ff0a659 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js @@ -0,0 +1,10 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + var x = ({ dana : "zuul" }); + return x; +} +trap(caller, 23, "x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js new file mode 100644 index 00000000000..9eeb76d07eb --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js @@ -0,0 +1,10 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + var x = "failure"; + return x; +} +trap(caller, 14, "x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js new file mode 100644 index 00000000000..266db65090d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js @@ -0,0 +1,9 @@ +setDebug(true); +var x = "failure"; +function main() { x = "success"; } + +/* The JSOP_STOP in a. */ +trap(main, 8, ""); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js new file mode 100644 index 00000000000..db7e4b82b2a --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js @@ -0,0 +1,10 @@ +setDebug(true); +var x = "notset"; +function main() { x = "failure"; } +function success() { x = "success"; } + +/* The JSOP_STOP in a. */ +trap(main, 7, "success()"); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js new file mode 100644 index 00000000000..2f89f58bc3d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js @@ -0,0 +1,11 @@ +setDebug(true); +var x = "notset"; +function main() { x = "success"; } +function failure() { x = "failure"; } + +/* The JSOP_STOP in a. */ +trap(main, 8, "failure()"); +untrap(main, 8); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js new file mode 100644 index 00000000000..1d19aeebeb1 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js @@ -0,0 +1,7 @@ +setDebug(true); +function main() { + return "failure"; +} +/* JSOP_RETURN in main. */ +trap(main, 3, "'success'"); +assertEq(main(), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js new file mode 100644 index 00000000000..b2b516826a9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js @@ -0,0 +1,7 @@ +setDebug(true); +function main() { + return 1; +} +/* JSOP_RETURN in main. */ +trap(main, 1, "0"); +assertEq(main(), 0); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js new file mode 100644 index 00000000000..18378b7808f --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js @@ -0,0 +1,15 @@ +setDebug(true); +x = "notset"; +function myparent(nested) { + if (nested) { + /* myparent call in myparent. */ + trap(myparent, 39, "failure()"); + } else { + x = "success"; + myparent(true); + } +} +function failure() { x = "failure"; } + +myparent(false); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js new file mode 100644 index 00000000000..d6ded288128 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js @@ -0,0 +1,21 @@ +setDebug(true); +x = "notset"; + +function child() { + x = "failure1"; + /* JSOP_STOP in parent. */ + trap(parent, 10, "success()"); +} + +function parent() { + x = "failure2"; +} +/* First op in parent. */ +trap(parent, 0, "child()"); + +function success() { + x = "success"; +} + +parent(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js new file mode 100644 index 00000000000..2209f946af9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js @@ -0,0 +1,16 @@ +setDebug(true); +x = "notset"; +function child() { + /* JSOP_STOP in parent. */ + trap(parent, 17, "success()"); +} +function parent() { + child(); + x = "failure"; +} +function success() { + x = "success"; +} + +parent() +assertEq(x, "success"); diff --git 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 new file mode 100644 index 00000000000..65d3e73135e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js @@ -0,0 +1,18 @@ +setDebug(true); +x = "notset"; + +function myparent(nested) { + if (nested) { + /* noop call in myparent */ + trap(myparent, 50, "success()"); + } else { + myparent(true); + x = "failure"; + noop(); + } +} +function noop() { } +function success() { x = "success"; } + +myparent(); +assertEq(x, "success"); diff --git 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 new file mode 100644 index 00000000000..8a9caaaafda --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js @@ -0,0 +1,23 @@ +setDebug(true); +x = "notset"; + +function doNothing() { } + +function myparent(nested) { + if (nested) { + /* JSOP_CALL to doNothing in myparent with nested = true. */ + trap(myparent, 24, "success()"); + doNothing(); + } else { + doNothing(); + } +} +/* JSOP_CALL to doNothing in myparent with nested = false. */ +trap(myparent, 35, "myparent(true)"); + +function success() { + x = "success"; +} + +myparent(false); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js new file mode 100644 index 00000000000..9b94fd1c8cc --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js @@ -0,0 +1,11 @@ +setDebug(true); +x = "notset"; +function main() { + /* The JSOP_STOP in a. */ + trap(main, 25, "success()"); + x = "failure"; +} +function success() { x = "success"; } + +main(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js new file mode 100644 index 00000000000..e4dd9d7dc97 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js @@ -0,0 +1,15 @@ +setDebug(true); +x = "notset"; +function child() { + /* JSOP_STOP in parent */ + untrap(parent, 10); + x = "success"; +} +function parent() { + x = "failure"; +} +/* JSOP_STOP in parent */ +trap(parent, 10, "child()"); + +parent(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js new file mode 100644 index 00000000000..4c18db52e8e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js @@ -0,0 +1,13 @@ +setDebug(true); +x = "notset"; +function main() { + /* JSOP_STOP in main. */ + untrap(main, 23); + x = "success"; +} +function failure() { x = "failure"; } + +/* JSOP_STOP in main. */ +trap(main, 23, "failure()"); +main(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug573433.js b/js/src/jit-test/tests/jaeger/bug573433.js new file mode 100644 index 00000000000..aa39022bb74 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug573433.js @@ -0,0 +1,7 @@ +// |jit-test| error: TypeError +function f() { + eval("(function() \n{\nfor(x in[])\n{}\n})"); + ("")() +} +f() + diff --git a/js/src/jit-test/tests/jaeger/bug580884.js b/js/src/jit-test/tests/jaeger/bug580884.js new file mode 100644 index 00000000000..b7a26f70566 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug580884.js @@ -0,0 +1,8 @@ +// |jit-test| error: ReferenceError +for (let a in [0]) +a = e +for (let a in [0]) +(function () { + a +}) + diff --git a/js/src/jit-test/tests/jaeger/bug582286.js b/js/src/jit-test/tests/jaeger/bug582286.js new file mode 100644 index 00000000000..094366a3c79 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug582286.js @@ -0,0 +1,3 @@ +evalcx("function s(){}",evalcx('lazy')) + + diff --git a/js/src/jit-test/tests/jaeger/bug583158.js b/js/src/jit-test/tests/jaeger/bug583158.js new file mode 100644 index 00000000000..6d8c124487d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug583158.js @@ -0,0 +1,9 @@ +// |jit-test| error: ReferenceError +function g() { + var rv = (function() { + this << 1 + })() + if (a) (function() {}) +} +g() + diff --git a/js/src/jit-test/tests/jaeger/bug585341.js b/js/src/jit-test/tests/jaeger/bug585341.js new file mode 100644 index 00000000000..fb96b92c3c3 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug585341.js @@ -0,0 +1,6 @@ +__defineGetter__("x", Float64Array) +Function("\ + with(this) {\ + eval(\"x\")\ + }\ +")() diff --git a/js/src/jit-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js new file mode 100644 index 00000000000..65c30952077 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug588338.js @@ -0,0 +1,14 @@ +// |jit-test| error: is not a function +function f() { (e) +} (x = Proxy.createFunction((function(x) { + return { + get: function(r, b) { + return x[b] + } + } +})(/x/), wrap)) +for (z = 0; z < 100; x.unwatch(), z++) +for (e in [0]) { + gczeal(2) +} ( )("") + diff --git a/js/src/jit-test/tests/jaeger/bug588363-2.js b/js/src/jit-test/tests/jaeger/bug588363-2.js new file mode 100644 index 00000000000..5550be3ea8d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug588363-2.js @@ -0,0 +1,7 @@ +with(evalcx('')) { + delete eval; + eval("x", this.__defineGetter__("x", Function)); +} + +/* Don't assert or crash. */ + diff --git a/js/src/jit-test/tests/jaeger/crash-on-compare.js b/js/src/jit-test/tests/jaeger/crash-on-compare.js new file mode 100644 index 00000000000..5abd7aa045e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/crash-on-compare.js @@ -0,0 +1 @@ +assertEq(Infinity >= Infinity ? true : false, true); diff --git a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js new file mode 100644 index 00000000000..b5d2bf2f61b --- /dev/null +++ b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js @@ -0,0 +1,6 @@ +function ack(m,n){ + if (m==0) { return n+1; } + if (n==0) { return ack(m-1,1); } + return ack(m-1, ack(m,n-1) ); +} +assertEq(ack(3, 3), 61); diff --git a/js/src/jit-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js new file mode 100644 index 00000000000..5d8c68fa590 --- /dev/null +++ b/js/src/jit-test/tests/pic/bug558099.js @@ -0,0 +1,60 @@ +(function()[function() function() function() function() function() function() {}]); +foo = [{ + text: "(function(){if(d){(1)}})", + s: function() {}, + test: function() { + try { + f + } catch(e) {} + } +}, +{ + text: "(function(){t})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){if(0){}})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){if(1){}(2)})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){g})", + b: function() {}, + test: function() {} +}, +{ + text: "(function(){})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){1})", + s: function() {}, + test: function() {} +}]; (function() { + for (i = 0; i < foo.length; ++i) { + a = foo[i] + text = a.text + eval(text.replace(/@/, "")); + if (a.test()) {} + } +} ()); +s = [function() function() function() function() function() function() {}] +[function() function() function() function() {}]; +(function() { [function() function() {}] }); +(function() {}); +(eval("\ + (function(){\ + for each(d in[\ + 0,0,0,0,0,0,0,0,0,0,0,0,0,null,NaN,1,Boolean(false),Boolean(false)\ + ]){\ + [].filter(new Function,gczeal(2))\ + }\ + })\ +"))(); diff --git a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js new file mode 100644 index 00000000000..41f44fed50c --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2004 Baron Schwartz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, version 2.1. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ + +Date.parseFunctions = {count:0}; +Date.parseRegexes = []; +Date.formatFunctions = {count:0}; + +Date.prototype.dateFormat = function(format) { + if (Date.formatFunctions[format] == null) { + Date.createNewFormat(format); + } + var func = Date.formatFunctions[format]; + return this[func](); +} + +Date.createNewFormat = function(format) { + var funcName = "format" + Date.formatFunctions.count++; + Date.formatFunctions[format] = funcName; + var code = "Date.prototype." + funcName + " = function(){return "; + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + code += "'" + String.escape(ch) + "' + "; + } + else { + code += Date.getFormatCode(ch); + } + } + eval(code.substring(0, code.length - 3) + ";}"); +} + +Date.getFormatCode = function(character) { + switch (character) { + case "d": + return "String.leftPad(this.getDate(), 2, '0') + "; + case "D": + return "Date.dayNames[this.getDay()].substring(0, 3) + "; + case "j": + return "this.getDate() + "; + case "l": + return "Date.dayNames[this.getDay()] + "; + case "S": + return "this.getSuffix() + "; + case "w": + return "this.getDay() + "; + case "z": + return "this.getDayOfYear() + "; + case "W": + return "this.getWeekOfYear() + "; + case "F": + return "Date.monthNames[this.getMonth()] + "; + case "m": + return "String.leftPad(this.getMonth() + 1, 2, '0') + "; + case "M": + return "Date.monthNames[this.getMonth()].substring(0, 3) + "; + case "n": + return "(this.getMonth() + 1) + "; + case "t": + return "this.getDaysInMonth() + "; + case "L": + return "(this.isLeapYear() ? 1 : 0) + "; + case "Y": + return "this.getFullYear() + "; + case "y": + return "('' + this.getFullYear()).substring(2, 4) + "; + case "a": + return "(this.getHours() < 12 ? 'am' : 'pm') + "; + case "A": + return "(this.getHours() < 12 ? 'AM' : 'PM') + "; + case "g": + return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; + case "G": + return "this.getHours() + "; + case "h": + return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; + case "H": + return "String.leftPad(this.getHours(), 2, '0') + "; + case "i": + return "String.leftPad(this.getMinutes(), 2, '0') + "; + case "s": + return "String.leftPad(this.getSeconds(), 2, '0') + "; + case "O": + return "this.getGMTOffset() + "; + case "T": + return "this.getTimezone() + "; + case "Z": + return "(this.getTimezoneOffset() * -60) + "; + default: + return "'" + String.escape(character) + "' + "; + } +} + +Date.parseDate = function(input, format) { + if (Date.parseFunctions[format] == null) { + Date.createParser(format); + } + var func = Date.parseFunctions[format]; + return Date[func](input); +} + +Date.createParser = function(format) { + var funcName = "parse" + Date.parseFunctions.count++; + var regexNum = Date.parseRegexes.length; + var currentGroup = 1; + Date.parseFunctions[format] = funcName; + + var code = "Date." + funcName + " = function(input){\n" + + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" + + "var d = new Date();\n" + + "y = d.getFullYear();\n" + + "m = d.getMonth();\n" + + "d = d.getDate();\n" + + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" + + "if (results && results.length > 0) {" + var regex = ""; + + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + regex += String.escape(ch); + } + else { + obj = Date.formatCodeToRegex(ch, currentGroup); + currentGroup += obj.g; + regex += obj.s; + if (obj.g && obj.c) { + code += obj.c; + } + } + } + + code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" + + "{return new Date(y, m, d, h, i, s);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" + + "{return new Date(y, m, d, h, i);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" + + "{return new Date(y, m, d, h);}\n" + + "else if (y > 0 && m >= 0 && d > 0)\n" + + "{return new Date(y, m, d);}\n" + + "else if (y > 0 && m >= 0)\n" + + "{return new Date(y, m);}\n" + + "else if (y > 0)\n" + + "{return new Date(y);}\n" + + "}return null;}"; + + Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); + eval(code); +} + +Date.formatCodeToRegex = function(character, currentGroup) { + switch (character) { + case "D": + return {g:0, + c:null, + s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; + case "j": + case "d": + return {g:1, + c:"d = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "l": + return {g:0, + c:null, + s:"(?:" + Date.dayNames.join("|") + ")"}; + case "S": + return {g:0, + c:null, + s:"(?:st|nd|rd|th)"}; + case "w": + return {g:0, + c:null, + s:"\\d"}; + case "z": + return {g:0, + c:null, + s:"(?:\\d{1,3})"}; + case "W": + return {g:0, + c:null, + s:"(?:\\d{2})"}; + case "F": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", + s:"(" + Date.monthNames.join("|") + ")"}; + case "M": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", + s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; + case "n": + case "m": + return {g:1, + c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", + s:"(\\d{1,2})"}; + case "t": + return {g:0, + c:null, + s:"\\d{1,2}"}; + case "L": + return {g:0, + c:null, + s:"(?:1|0)"}; + case "Y": + return {g:1, + c:"y = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{4})"}; + case "y": + return {g:1, + c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" + + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", + s:"(\\d{1,2})"}; + case "a": + return {g:1, + c:"if (results[" + currentGroup + "] == 'am') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(am|pm)"}; + case "A": + return {g:1, + c:"if (results[" + currentGroup + "] == 'AM') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(AM|PM)"}; + case "g": + case "G": + case "h": + case "H": + return {g:1, + c:"h = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "i": + return {g:1, + c:"i = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "s": + return {g:1, + c:"s = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "O": + return {g:0, + c:null, + s:"[+-]\\d{4}"}; + case "T": + return {g:0, + c:null, + s:"[A-Z]{3}"}; + case "Z": + return {g:0, + c:null, + s:"[+-]\\d{1,5}"}; + default: + return {g:0, + c:null, + s:String.escape(character)}; + } +} + +Date.prototype.getTimezone = function() { + return this.toString().replace( + /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( + /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); +} + +Date.prototype.getGMTOffset = function() { + return (this.getTimezoneOffset() > 0 ? "-" : "+") + + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") + + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); +} + +Date.prototype.getDayOfYear = function() { + var num = 0; + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + for (var i = 0; i < this.getMonth(); ++i) { + num += Date.daysInMonth[i]; + } + return num + this.getDate() - 1; +} + +Date.prototype.getWeekOfYear = function() { + // Skip to Thursday of this week + var now = this.getDayOfYear() + (4 - this.getDay()); + // Find the first Thursday of the year + var jan1 = new Date(this.getFullYear(), 0, 1); + var then = (7 - jan1.getDay() + 4); + document.write(then); + return String.leftPad(((now - then) / 7) + 1, 2, "0"); +} + +Date.prototype.isLeapYear = function() { + var year = this.getFullYear(); + return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); +} + +Date.prototype.getFirstDayOfMonth = function() { + var day = (this.getDay() - (this.getDate() - 1)) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getLastDayOfMonth = function() { + var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getDaysInMonth = function() { + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + return Date.daysInMonth[this.getMonth()]; +} + +Date.prototype.getSuffix = function() { + switch (this.getDate()) { + case 1: + case 21: + case 31: + return "st"; + case 2: + case 22: + return "nd"; + case 3: + case 23: + return "rd"; + default: + return "th"; + } +} + +String.escape = function(string) { + return string.replace(/('|\\)/g, "\\$1"); +} + +String.leftPad = function (val, size, ch) { + var result = new String(val); + if (ch == null) { + ch = " "; + } + while (result.length < size) { + result = ch + result; + } + return result; +} + +Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; +Date.monthNames = + ["January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"]; +Date.dayNames = + ["Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday"]; +Date.y2kYear = 50; +Date.monthNumbers = { + Jan:0, + Feb:1, + Mar:2, + Apr:3, + May:4, + Jun:5, + Jul:6, + Aug:7, + Sep:8, + Oct:9, + Nov:10, + Dec:11}; +Date.patterns = { + ISO8601LongPattern:"Y-m-d H:i:s", + ISO8601ShortPattern:"Y-m-d", + ShortDatePattern: "n/j/Y", + LongDatePattern: "l, F d, Y", + FullDateTimePattern: "l, F d, Y g:i:s A", + MonthDayPattern: "F d", + ShortTimePattern: "g:i A", + LongTimePattern: "g:i:s A", + SortableDateTimePattern: "Y-m-d\\TH:i:s", + UniversalSortableDateTimePattern: "Y-m-d H:i:sO", + YearMonthPattern: "F, Y"}; + +var date = new Date("1/1/2007 1:11:11"); + +var ret; +for (i = 0; i < 4000; ++i) { + var shortFormat = date.dateFormat("Y-m-d"); + var longFormat = date.dateFormat("l, F d, Y g:i:s A"); + ret = shortFormat + longFormat; + date.setTime(date.getTime() + 84266956); +} + +// No exact match because the output depends on the locale's time zone. See bug 524490. +assertEq(/^2017-09-05Tuesday, September 05, 2017 [0-9:]* AM$/.exec(ret) != null, true); diff --git a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js new file mode 100644 index 00000000000..a9082702ccf --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js @@ -0,0 +1,41 @@ +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// contributed by Isaac Gouy + +function partial(n){ + var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; + var twothirds = 2.0/3.0; + var alt = -1.0; + var k2 = k3 = sk = ck = 0.0; + + for (var k = 1; k <= n; k++){ + k2 = k*k; + k3 = k2*k; + sk = Math.sin(k); + ck = Math.cos(k); + alt = -alt; + + a1 += Math.pow(twothirds,k-1); + a2 += Math.pow(k,-0.5); + a3 += 1.0/(k*(k+1.0)); + a4 += 1.0/(k3 * sk*sk); + a5 += 1.0/(k3 * ck*ck); + a6 += 1.0/k; + a7 += 1.0/k2; + a8 += alt/k; + a9 += alt/(2*k -1); + } + + return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ]; +} + +var actual = []; +for (var i = 1024; i <= 16384; i *= 2) + Array.prototype.push.apply(actual, partial(i)); + +var eps = 1e-12; +var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998]; + +assertEq(actual.length, expect.length); +for (var i = 0; i < expect.length; ++i) + assertEq(Math.abs(actual[i] - expect[i]) < eps, true); diff --git a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js new file mode 100644 index 00000000000..f446e46ed5c --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js @@ -0,0 +1,270 @@ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + Portions from: + json.js + 2007-10-10 + + Public Domain +*/ + +// This test parses a JSON string giving tag names and popularity, and +// generates html markup for a "tagcloud" view. + +if (!Object.prototype.toJSONString) { + + Array.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + i, // Loop counter. + l = this.length, + v; // The value to be stringified. + + for (i = 0; i < l; i += 1) { + v = this[i]; + switch (typeof v) { + case 'object': + + if (v && typeof v.toJSONString === 'function') { + a.push(v.toJSONString(w)); + } else { + a.push('null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(v.toJSONString()); + break; + default: + a.push('null'); + } + } + + return '[' + a.join(',') + ']'; + }; + + + Boolean.prototype.toJSONString = function () { + return String(this); + }; + + + Date.prototype.toJSONString = function () { + + function f(n) { + + return n < 10 ? '0' + n : n; + } + + return '"' + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z"'; + }; + + + Number.prototype.toJSONString = function () { + + return isFinite(this) ? String(this) : 'null'; + }; + + + Object.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + k, // The current key. + i, // The loop counter. + v; // The current value. + + if (w) { + for (i = 0; i < w.length; i += 1) { + k = w[i]; + if (typeof k === 'string') { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString(w)); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } else { + + for (k in this) { + if (typeof k === 'string' && + Object.prototype.hasOwnProperty.apply(this, [k])) { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString()); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } + + return '{' + a.join(',') + '}'; + }; + + + (function (s) { + + var m = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }; + + + s.parseJSON = function (filter) { + var j; + + function walk(k, v) { + var i, n; + if (v && typeof v === 'object') { + for (i in v) { + if (Object.prototype.hasOwnProperty.apply(v, [i])) { + n = walk(i, v[i]); + if (n !== undefined) { + v[i] = n; + } + } + } + } + return filter(k, v); + } + + if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + j = eval('(' + this + ')'); + + return typeof filter === 'function' ? walk('', j) : j; + } + + throw new SyntaxError('parseJSON'); + }; + + + s.toJSONString = function () { + + if (/["\\\x00-\x1f]/.test(this)) { + return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) { + var c = m[a]; + if (c) { + return c; + } + c = a.charCodeAt(); + return '\\u00' + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }) + '"'; + } + return '"' + this + '"'; + }; + })(String.prototype); +} + +var tagInfoJSON = '[\n {\n \"tag\": "titillation",\n \"popularity\": 4294967296\n },\n {\n \"tag\": "foamless",\n \"popularity\": 1257718401\n },\n {\n \"tag\": "snarler",\n \"popularity\": 613166183\n },\n {\n \"tag\": "multangularness",\n \"popularity\": 368304452\n },\n {\n \"tag\": "Fesapo unventurous",\n \"popularity\": 248026512\n },\n {\n \"tag\": "esthesioblast",\n \"popularity\": 179556755\n },\n {\n \"tag\": "echeneidoid",\n \"popularity\": 136641578\n },\n {\n \"tag\": "embryoctony",\n \"popularity\": 107852576\n },\n {\n \"tag\": "undilatory",\n \"popularity\": 87537981\n },\n {\n \"tag\": "predisregard",\n \"popularity\": 72630939\n },\n {\n \"tag\": "allergenic",\n \"popularity\": 61345190\n },\n {\n \"tag\": "uncloudy",\n \"popularity\": 52580571\n },\n {\n \"tag\": "unforeseeably",\n \"popularity\": 45628109\n },\n {\n \"tag\": "sturniform",\n \"popularity\": 40013489\n },\n {\n \"tag\": "anesthetize",\n \"popularity\": 35409226\n },\n {\n \"tag\": "ametabolia",\n \"popularity\": 31583050\n },\n {\n \"tag\": "angiopathy",\n \"popularity\": 28366350\n },\n {\n \"tag\": "sultanaship",\n \"popularity\": 25634218\n },\n {\n \"tag\": "Frenchwise",\n \"popularity\": 23292461\n },\n {\n \"tag\": "cerviconasal",\n \"popularity\": 21268909\n },\n {\n \"tag\": "mercurialness",\n \"popularity\": 19507481\n },\n {\n \"tag\": "glutelin venditate",\n \"popularity\": 17964042\n },\n {\n \"tag\": "acred overblack",\n \"popularity\": 16603454\n },\n {\n \"tag\": "Atik",\n \"popularity\": 15397451\n },\n {\n \"tag\": "puncturer",\n \"popularity\": 14323077\n },\n {\n \"tag\": "pukatea",\n \"popularity\": 13361525\n },\n {\n \"tag\": "suberize",\n \"popularity\": 12497261\n },\n {\n \"tag\": "Godfrey",\n \"popularity\": 11717365\n },\n {\n \"tag\": "tetraptote",\n \"popularity\": 11011011\n },\n {\n \"tag\": "lucidness",\n \"popularity\": 10369074\n },\n {\n \"tag\": "tartness",\n \"popularity\": 9783815\n },\n {\n \"tag\": "axfetch",\n \"popularity\": 9248634\n },\n {\n \"tag\": "preacquittal",\n \"popularity\": 8757877\n },\n {\n \"tag\": "matris",\n \"popularity\": 8306671\n },\n {\n \"tag\": "hyphenate",\n \"popularity\": 7890801\n },\n {\n \"tag\": "semifabulous",\n \"popularity\": 7506606\n },\n {\n \"tag\": "oppressiveness",\n \"popularity\": 7150890\n },\n {\n \"tag\": "Protococcales",\n \"popularity\": 6820856\n },\n {\n \"tag\": "unpreventive",\n \"popularity\": 6514045\n },\n {\n \"tag\": "Cordia",\n \"popularity\": 6228289\n },\n {\n \"tag\": "Wakamba leaflike",\n \"popularity\": 5961668\n },\n {\n \"tag\": "dacryoma",\n \"popularity\": 5712480\n },\n {\n \"tag\": "inguinal",\n \"popularity\": 5479211\n },\n {\n \"tag\": "responseless",\n \"popularity\": 5260507\n },\n {\n \"tag\": "supplementarily",\n \"popularity\": 5055158\n },\n {\n \"tag\": "emu",\n \"popularity\": 4862079\n },\n {\n \"tag\": "countermeet",\n \"popularity\": 4680292\n },\n {\n \"tag\": "purrer",\n \"popularity\": 4508918\n },\n {\n \"tag\": "Corallinaceae",\n \"popularity\": 4347162\n },\n {\n \"tag\": "speculum",\n \"popularity\": 4194304\n },\n {\n \"tag\": "crimpness",\n \"popularity\": 4049690\n },\n {\n \"tag\": "antidetonant",\n \"popularity\": 3912727\n },\n {\n \"tag\": "topeewallah",\n \"popularity\": 3782875\n },\n {\n \"tag\": "fidalgo ballant",\n \"popularity\": 3659640\n },\n {\n \"tag\": "utriculose",\n \"popularity\": 3542572\n },\n {\n \"tag\": "testata",\n \"popularity\": 3431259\n },\n {\n \"tag\": "beltmaking",\n \"popularity\": 3325322\n },\n {\n \"tag\": "necrotype",\n \"popularity\": 3224413\n },\n {\n \"tag\": "ovistic",\n \"popularity\": 3128215\n },\n {\n \"tag\": "swindlership",\n \"popularity\": 3036431\n },\n {\n \"tag\": "augustal",\n \"popularity\": 2948792\n },\n {\n \"tag\": "Titoist",\n \"popularity\": 2865047\n },\n {\n \"tag\": "trisoctahedral",\n \"popularity\": 2784963\n },\n {\n \"tag\": "sequestrator",\n \"popularity\": 2708327\n },\n {\n \"tag\": "sideburns",\n \"popularity\": 2634939\n },\n {\n \"tag\": "paraphrasia",\n \"popularity\": 2564616\n },\n {\n \"tag\": "graminology unbay",\n \"popularity\": 2497185\n },\n {\n \"tag\": "acaridomatium emargination",\n \"popularity\": 2432487\n },\n {\n \"tag\": "roofward",\n \"popularity\": 2370373\n },\n {\n \"tag\": "lauder",\n \"popularity\": 2310705\n },\n {\n \"tag\": "subjunctive",\n \"popularity\": 2253354\n },\n {\n \"tag\": "subelongate",\n \"popularity\": 2198199\n },\n {\n \"tag\": "guacimo",\n \"popularity\": 2145128\n },\n {\n \"tag\": "cockade",\n \"popularity\": 2094033\n },\n {\n \"tag\": "misgauge",\n \"popularity\": 2044818\n },\n {\n \"tag\": "unexpensive",\n \"popularity\": 1997388\n },\n {\n \"tag\": "chebel",\n \"popularity\": 1951657\n },\n {\n \"tag\": "unpursuing",\n \"popularity\": 1907543\n },\n {\n \"tag\": "kilobar",\n \"popularity\": 1864969\n },\n {\n \"tag\": "obsecration",\n \"popularity\": 1823863\n },\n {\n \"tag\": "nacarine",\n \"popularity\": 1784157\n },\n {\n \"tag\": "spirituosity",\n \"popularity\": 1745787\n },\n {\n \"tag\": "movableness deity",\n \"popularity\": 1708692\n },\n {\n \"tag\": "exostracism",\n \"popularity\": 1672816\n },\n {\n \"tag\": "archipterygium",\n \"popularity\": 1638104\n },\n {\n \"tag\": "monostrophic",\n \"popularity\": 1604506\n },\n {\n \"tag\": "gynecide",\n \"popularity\": 1571974\n },\n {\n \"tag\": "gladden",\n \"popularity\": 1540462\n },\n {\n \"tag\": "throughbred",\n \"popularity\": 1509927\n },\n {\n \"tag\": "groper",\n \"popularity\": 1480329\n },\n {\n \"tag\": "Xenosaurus",\n \"popularity\": 1451628\n },\n {\n \"tag\": "photoetcher",\n \"popularity\": 1423788\n },\n {\n \"tag\": "glucosid",\n \"popularity\": 1396775\n },\n {\n \"tag\": "Galtonian",\n \"popularity\": 1370555\n },\n {\n \"tag\": "mesosporic",\n \"popularity\": 1345097\n },\n {\n \"tag\": "theody",\n \"popularity\": 1320370\n },\n {\n \"tag\": "zaffer",\n \"popularity\": 1296348\n },\n {\n \"tag\": "probiology",\n \"popularity\": 1273003\n },\n {\n \"tag\": "rhizomic",\n \"popularity\": 1250308\n },\n {\n \"tag\": "superphosphate",\n \"popularity\": 1228240\n },\n {\n \"tag\": "Hippolytan",\n \"popularity\": 1206776\n },\n {\n \"tag\": "garget",\n \"popularity\": 1185892\n },\n {\n \"tag\": "diploplacula",\n \"popularity\": 1165568\n },\n {\n \"tag\": "orohydrographical",\n \"popularity\": 1145785\n },\n {\n \"tag\": "enhypostatize",\n \"popularity\": 1126521\n },\n {\n \"tag\": "polisman",\n \"popularity\": 1107759\n },\n {\n \"tag\": "acetometer",\n \"popularity\": 1089482\n },\n {\n \"tag\": "unsnatched",\n \"popularity\": 1071672\n },\n {\n \"tag\": "yabber",\n \"popularity\": 1054313\n },\n {\n \"tag\": "demiwolf",\n \"popularity\": 1037390\n },\n {\n \"tag\": "chromascope",\n \"popularity\": 1020888\n },\n {\n \"tag\": "seamanship",\n \"popularity\": 1004794\n },\n {\n \"tag\": "nonfenestrated",\n \"popularity\": 989092\n },\n {\n \"tag\": "hydrophytism",\n \"popularity\": 973771\n },\n {\n \"tag\": "dotter",\n \"popularity\": 958819\n },\n {\n \"tag\": "thermoperiodism",\n \"popularity\": 944222\n },\n {\n \"tag\": "unlawyerlike",\n \"popularity\": 929970\n },\n {\n \"tag\": "enantiomeride citywards",\n \"popularity\": 916052\n },\n {\n \"tag\": "unmetallurgical",\n \"popularity\": 902456\n },\n {\n \"tag\": "prickled",\n \"popularity\": 889174\n },\n {\n \"tag\": "strangerwise manioc",\n \"popularity\": 876195\n },\n {\n \"tag\": "incisorial",\n \"popularity\": 863510\n },\n {\n \"tag\": "irrationalize",\n \"popularity\": 851110\n },\n {\n \"tag\": "nasology",\n \"popularity\": 838987\n },\n {\n \"tag\": "fatuism",\n \"popularity\": 827131\n },\n {\n \"tag\": "Huk",\n \"popularity\": 815535\n },\n {\n \"tag\": "properispomenon",\n \"popularity\": 804192\n },\n {\n \"tag\": "unpummelled",\n \"popularity\": 793094\n },\n {\n \"tag\": "technographically",\n \"popularity\": 782233\n },\n {\n \"tag\": "underfurnish",\n \"popularity\": 771603\n },\n {\n \"tag\": "sinter",\n \"popularity\": 761198\n },\n {\n \"tag\": "lateroanterior",\n \"popularity\": 751010\n },\n {\n \"tag\": "nonpersonification",\n \"popularity\": 741034\n },\n {\n \"tag\": "Sitophilus",\n \"popularity\": 731264\n },\n {\n \"tag\": "unstudded overexerted",\n \"popularity\": 721694\n },\n {\n \"tag\": "tracheation",\n \"popularity\": 712318\n },\n {\n \"tag\": "thirteenth begloze",\n \"popularity\": 703131\n },\n {\n \"tag\": "bespice",\n \"popularity\": 694129\n },\n {\n \"tag\": "doppia",\n \"popularity\": 685305\n },\n {\n \"tag\": "unadorned",\n \"popularity\": 676656\n },\n {\n \"tag\": "dovelet engraff",\n \"popularity\": 668176\n },\n {\n \"tag\": "diphyozooid",\n \"popularity\": 659862\n },\n {\n \"tag\": "mure",\n \"popularity\": 651708\n },\n {\n \"tag\": "Tripitaka",\n \"popularity\": 643710\n },\n {\n \"tag\": "Billjim",\n \"popularity\": 635865\n },\n {\n \"tag\": "pyramidical",\n \"popularity\": 628169\n },\n {\n \"tag\": "circumlocutionist",\n \"popularity\": 620617\n },\n {\n \"tag\": "slapstick",\n \"popularity\": 613207\n },\n {\n \"tag\": "preobedience",\n \"popularity\": 605934\n },\n {\n \"tag\": "unfriarlike",\n \"popularity\": 598795\n },\n {\n \"tag\": "microchromosome",\n \"popularity\": 591786\n },\n {\n \"tag\": "Orphicism",\n \"popularity\": 584905\n },\n {\n \"tag\": "peel",\n \"popularity\": 578149\n },\n {\n \"tag\": "obediential",\n \"popularity\": 571514\n },\n {\n \"tag\": "Peripatidea",\n \"popularity\": 564997\n },\n {\n \"tag\": "undoubtful",\n \"popularity\": 558596\n },\n {\n \"tag\": "lodgeable",\n \"popularity\": 552307\n },\n {\n \"tag\": "pustulated woodchat",\n \"popularity\": 546129\n },\n {\n \"tag\": "antepast",\n \"popularity\": 540057\n },\n {\n \"tag\": "sagittoid matrimoniously",\n \"popularity\": 534091\n },\n {\n \"tag\": "Albizzia",\n \"popularity\": 528228\n },\n {\n \"tag\": "Elateridae unnewness",\n \"popularity\": 522464\n },\n {\n \"tag\": "convertingness",\n \"popularity\": 516798\n },\n {\n \"tag\": "Pelew",\n \"popularity\": 511228\n },\n {\n \"tag\": "recapitulation",\n \"popularity\": 505751\n },\n {\n \"tag\": "shack",\n \"popularity\": 500365\n },\n {\n \"tag\": "unmellowed",\n \"popularity\": 495069\n },\n {\n \"tag\": "pavis capering",\n \"popularity\": 489859\n },\n {\n \"tag\": "fanfare",\n \"popularity\": 484735\n },\n {\n \"tag\": "sole",\n \"popularity\": 479695\n },\n {\n \"tag\": "subarcuate",\n \"popularity\": 474735\n },\n {\n \"tag\": "multivious",\n \"popularity\": 469856\n },\n {\n \"tag\": "squandermania",\n \"popularity\": 465054\n },\n {\n \"tag\": "scintle",\n \"popularity\": 460329\n },\n {\n \"tag\": "hash chirognomic",\n \"popularity\": 455679\n },\n {\n \"tag\": "linseed",\n \"popularity\": 451101\n },\n {\n \"tag\": "redoubtable",\n \"popularity\": 446596\n },\n {\n \"tag\": "poachy reimpact",\n \"popularity\": 442160\n },\n {\n \"tag\": "limestone",\n \"popularity\": 437792\n },\n {\n \"tag\": "serranid",\n \"popularity\": 433492\n },\n {\n \"tag\": "pohna",\n \"popularity\": 429258\n },\n {\n \"tag\": "warwolf",\n \"popularity\": 425088\n },\n {\n \"tag\": "ruthenous",\n \"popularity\": 420981\n },\n {\n \"tag\": "dover",\n \"popularity\": 416935\n },\n {\n \"tag\": "deuteroalbumose",\n \"popularity\": 412950\n },\n {\n \"tag\": "pseudoprophetic",\n \"popularity\": 409025\n },\n {\n \"tag\": "dissoluteness",\n \"popularity\": 405157\n },\n {\n \"tag\": "preinvention",\n \"popularity\": 401347\n },\n {\n \"tag\": "swagbellied",\n \"popularity\": 397592\n },\n {\n \"tag\": "Ophidia",\n \"popularity\": 393892\n },\n {\n \"tag\": "equanimity",\n \"popularity\": 390245\n },\n {\n \"tag\": "troutful",\n \"popularity\": 386651\n },\n {\n \"tag\": "uke",\n \"popularity\": 383108\n },\n {\n \"tag\": "preacquaint",\n \"popularity\": 379616\n },\n {\n \"tag\": "shoq",\n \"popularity\": 376174\n },\n {\n \"tag\": "yox",\n \"popularity\": 372780\n },\n {\n \"tag\": "unelemental",\n \"popularity\": 369434\n },\n {\n \"tag\": "Yavapai",\n \"popularity\": 366134\n },\n {\n \"tag\": "joulean",\n \"popularity\": 362880\n },\n {\n \"tag\": "dracontine",\n \"popularity\": 359672\n },\n {\n \"tag\": "hardmouth",\n \"popularity\": 356507\n },\n {\n \"tag\": "sylvanize",\n \"popularity\": 353386\n },\n {\n \"tag\": "intraparenchymatous meadowbur",\n \"popularity\": 350308\n },\n {\n \"tag\": "uncharily",\n \"popularity\": 347271\n },\n {\n \"tag\": "redtab flexibly",\n \"popularity\": 344275\n },\n {\n \"tag\": "centervelic",\n \"popularity\": 341319\n },\n {\n \"tag\": "unravellable",\n \"popularity\": 338403\n },\n {\n \"tag\": "infortunately",\n \"popularity\": 335526\n },\n {\n \"tag\": "cannel",\n \"popularity\": 332687\n },\n {\n \"tag\": "oxyblepsia",\n \"popularity\": 329885\n },\n {\n \"tag\": "Damon",\n \"popularity\": 327120\n },\n {\n \"tag\": "etherin",\n \"popularity\": 324391\n },\n {\n \"tag\": "luminal",\n \"popularity\": 321697\n },\n {\n \"tag\": "interrogatorily presbyte",\n \"popularity\": 319038\n },\n {\n \"tag\": "hemiclastic",\n \"popularity\": 316414\n },\n {\n \"tag\": "poh flush",\n \"popularity\": 313823\n },\n {\n \"tag\": "Psoroptes",\n \"popularity\": 311265\n },\n {\n \"tag\": "dispirit",\n \"popularity\": 308740\n },\n {\n \"tag\": "nashgab",\n \"popularity\": 306246\n },\n {\n \"tag\": "Aphidiinae",\n \"popularity\": 303784\n },\n {\n \"tag\": "rhapsody nonconstruction",\n \"popularity\": 301353\n },\n {\n \"tag\": "Osmond",\n \"popularity\": 298952\n },\n {\n \"tag\": "Leonis",\n \"popularity\": 296581\n },\n {\n \"tag\": "Lemnian",\n \"popularity\": 294239\n },\n {\n \"tag\": "acetonic gnathonic",\n \"popularity\": 291926\n },\n {\n \"tag\": "surculus",\n \"popularity\": 289641\n },\n {\n \"tag\": "diagonally",\n \"popularity\": 287384\n },\n {\n \"tag\": "counterpenalty",\n \"popularity\": 285154\n },\n {\n \"tag\": "Eugenie",\n \"popularity\": 282952\n },\n {\n \"tag\": "hornbook",\n \"popularity\": 280776\n },\n {\n \"tag\": "miscoin",\n \"popularity\": 278626\n },\n {\n \"tag\": "admi",\n \"popularity\": 276501\n },\n {\n \"tag\": "Tarmac",\n \"popularity\": 274402\n },\n {\n \"tag\": "inexplicable",\n \"popularity\": 272328\n },\n {\n \"tag\": "rascallion",\n \"popularity\": 270278\n },\n {\n \"tag\": "dusterman",\n \"popularity\": 268252\n },\n {\n \"tag\": "osteostomous unhoroscopic",\n \"popularity\": 266250\n },\n {\n \"tag\": "spinibulbar",\n \"popularity\": 264271\n },\n {\n \"tag\": "phototelegraphically",\n \"popularity\": 262315\n },\n {\n \"tag\": "Manihot",\n \"popularity\": 260381\n },\n {\n \"tag\": "neighborhood",\n \"popularity\": 258470\n },\n {\n \"tag\": "Vincetoxicum",\n \"popularity\": 256581\n },\n {\n \"tag\": "khirka",\n \"popularity\": 254713\n },\n {\n \"tag\": "conscriptive",\n \"popularity\": 252866\n },\n {\n \"tag\": "synechthran",\n \"popularity\": 251040\n },\n {\n \"tag\": "Guttiferales",\n \"popularity\": 249235\n },\n {\n \"tag\": "roomful",\n \"popularity\": 247450\n },\n {\n \"tag\": "germinal",\n \"popularity\": 245685\n },\n {\n \"tag\": "untraitorous",\n \"popularity\": 243939\n },\n {\n \"tag\": "nondissenting",\n \"popularity\": 242213\n },\n {\n \"tag\": "amotion",\n \"popularity\": 240506\n },\n {\n \"tag\": "badious",\n \"popularity\": 238817\n },\n {\n \"tag\": "sumpit",\n \"popularity\": 237147\n },\n {\n \"tag\": "ectozoic",\n \"popularity\": 235496\n },\n {\n \"tag\": "elvet",\n \"popularity\": 233862\n },\n {\n \"tag\": "underclerk",\n \"popularity\": 232246\n },\n {\n \"tag\": "reticency",\n \"popularity\": 230647\n },\n {\n \"tag\": "neutroclusion",\n \"popularity\": 229065\n },\n {\n \"tag\": "unbelieving",\n \"popularity\": 227500\n },\n {\n \"tag\": "histogenetic",\n \"popularity\": 225952\n },\n {\n \"tag\": "dermamyiasis",\n \"popularity\": 224421\n },\n {\n \"tag\": "telenergy",\n \"popularity\": 222905\n },\n {\n \"tag\": "axiomatic",\n \"popularity\": 221406\n },\n {\n \"tag\": "undominoed",\n \"popularity\": 219922\n },\n {\n \"tag\": "periosteoma",\n \"popularity\": 218454\n },\n {\n \"tag\": "justiciaryship",\n \"popularity\": 217001\n },\n {\n \"tag\": "autoluminescence",\n \"popularity\": 215563\n },\n {\n \"tag\": "osmous",\n \"popularity\": 214140\n },\n {\n \"tag\": "borgh",\n \"popularity\": 212731\n },\n {\n \"tag\": "bedebt",\n \"popularity\": 211337\n },\n {\n \"tag\": "considerableness adenoidism",\n \"popularity\": 209957\n },\n {\n \"tag\": "sailorizing",\n \"popularity\": 208592\n },\n {\n \"tag\": "Montauk",\n \"popularity\": 207240\n },\n {\n \"tag\": "Bridget",\n \"popularity\": 205901\n },\n {\n \"tag\": "Gekkota",\n \"popularity\": 204577\n },\n {\n \"tag\": "subcorymbose",\n \"popularity\": 203265\n },\n {\n \"tag\": "undersap",\n \"popularity\": 201967\n },\n {\n \"tag\": "poikilothermic",\n \"popularity\": 200681\n },\n {\n \"tag\": "enneatical",\n \"popularity\": 199409\n },\n {\n \"tag\": "martinetism",\n \"popularity\": 198148\n },\n {\n \"tag\": "sustanedly",\n \"popularity\": 196901\n },\n {\n \"tag\": "declaration",\n \"popularity\": 195665\n },\n {\n \"tag\": "myringoplasty",\n \"popularity\": 194442\n },\n {\n \"tag\": "Ginkgo",\n \"popularity\": 193230\n },\n {\n \"tag\": "unrecurrent",\n \"popularity\": 192031\n },\n {\n \"tag\": "proprecedent",\n \"popularity\": 190843\n },\n {\n \"tag\": "roadman",\n \"popularity\": 189666\n },\n {\n \"tag\": "elemin",\n \"popularity\": 188501\n },\n {\n \"tag\": "maggot",\n \"popularity\": 187347\n },\n {\n \"tag\": "alitrunk",\n \"popularity\": 186204\n },\n {\n \"tag\": "introspection",\n \"popularity\": 185071\n },\n {\n \"tag\": "batiker",\n \"popularity\": 183950\n },\n {\n \"tag\": "backhatch oversettle",\n \"popularity\": 182839\n },\n {\n \"tag\": "thresherman",\n \"popularity\": 181738\n },\n {\n \"tag\": "protemperance",\n \"popularity\": 180648\n },\n {\n \"tag\": "undern",\n \"popularity\": 179568\n },\n {\n \"tag\": "tweeg",\n \"popularity\": 178498\n },\n {\n \"tag\": "crosspath",\n \"popularity\": 177438\n },\n {\n \"tag\": "Tangaridae",\n \"popularity\": 176388\n },\n {\n \"tag\": "scrutation",\n \"popularity\": 175348\n },\n {\n \"tag\": "piecemaker",\n \"popularity\": 174317\n },\n {\n \"tag\": "paster",\n \"popularity\": 173296\n },\n {\n \"tag\": "unpretendingness",\n \"popularity\": 172284\n },\n {\n \"tag\": "inframundane",\n \"popularity\": 171281\n },\n {\n \"tag\": "kiblah",\n \"popularity\": 170287\n },\n {\n \"tag\": "playwrighting",\n \"popularity\": 169302\n },\n {\n \"tag\": "gonepoiesis snowslip",\n \"popularity\": 168326\n },\n {\n \"tag\": "hoodwise",\n \"popularity\": 167359\n },\n {\n \"tag\": "postseason",\n \"popularity\": 166401\n },\n {\n \"tag\": "equivocality",\n \"popularity\": 165451\n },\n {\n \"tag\": "Opiliaceae nuclease",\n \"popularity\": 164509\n },\n {\n \"tag\": "sextipara",\n \"popularity\": 163576\n },\n {\n \"tag\": "weeper",\n \"popularity\": 162651\n },\n {\n \"tag\": "frambesia",\n \"popularity\": 161735\n },\n {\n \"tag\": "answerable",\n \"popularity\": 160826\n },\n {\n \"tag\": "Trichosporum",\n \"popularity\": 159925\n },\n {\n \"tag\": "cajuputol",\n \"popularity\": 159033\n },\n {\n \"tag\": "pleomorphous",\n \"popularity\": 158148\n },\n {\n \"tag\": "aculeolate",\n \"popularity\": 157270\n },\n {\n \"tag\": "wherever",\n \"popularity\": 156400\n },\n {\n \"tag\": "collapse",\n \"popularity\": 155538\n },\n {\n \"tag\": "porky",\n \"popularity\": 154683\n },\n {\n \"tag\": "perule",\n \"popularity\": 153836\n },\n {\n \"tag\": "Nevada",\n \"popularity\": 152996\n },\n {\n \"tag\": "conalbumin",\n \"popularity\": 152162\n },\n {\n \"tag\": "tsunami",\n \"popularity\": 151336\n },\n {\n \"tag\": "Gulf",\n \"popularity\": 150517\n },\n {\n \"tag\": "hertz",\n \"popularity\": 149705\n },\n {\n \"tag\": "limmock",\n \"popularity\": 148900\n },\n {\n \"tag\": "Tartarize",\n \"popularity\": 148101\n },\n {\n \"tag\": "entosphenoid",\n \"popularity\": 147310\n },\n {\n \"tag\": "ibis",\n \"popularity\": 146524\n },\n {\n \"tag\": "unyeaned",\n \"popularity\": 145746\n },\n {\n \"tag\": "tritural",\n \"popularity\": 144973\n },\n {\n \"tag\": "hundredary",\n \"popularity\": 144207\n },\n {\n \"tag\": "stolonlike",\n \"popularity\": 143448\n },\n {\n \"tag\": "chorister",\n \"popularity\": 142694\n },\n {\n \"tag\": "mismove",\n \"popularity\": 141947\n },\n {\n \"tag\": "Andine",\n \"popularity\": 141206\n },\n {\n \"tag\": "Annette proneur escribe",\n \"popularity\": 140471\n },\n {\n \"tag\": "exoperidium",\n \"popularity\": 139742\n },\n {\n \"tag\": "disedge",\n \"popularity\": 139019\n },\n {\n \"tag\": "hypochloruria",\n \"popularity\": 138302\n },\n {\n \"tag\": "prepupa",\n \"popularity\": 137590\n },\n {\n \"tag\": "assent",\n \"popularity\": 136884\n },\n {\n \"tag\": "hydrazobenzene",\n \"popularity\": 136184\n },\n {\n \"tag\": "emballonurid",\n \"popularity\": 135489\n },\n {\n \"tag\": "roselle",\n \"popularity\": 134800\n },\n {\n \"tag\": "unifiedly",\n \"popularity\": 134117\n },\n {\n \"tag\": "clang",\n \"popularity\": 133439\n },\n {\n \"tag\": "acetolytic",\n \"popularity\": 132766\n },\n {\n \"tag\": "cladodont",\n \"popularity\": 132098\n },\n {\n \"tag\": "recoast",\n \"popularity\": 131436\n },\n {\n \"tag\": "celebrated tydie Eocarboniferous",\n \"popularity\": 130779\n },\n {\n \"tag\": "superconsciousness",\n \"popularity\": 130127\n },\n {\n \"tag\": "soberness",\n \"popularity\": 129480\n },\n {\n \"tag\": "panoramist",\n \"popularity\": 128838\n },\n {\n \"tag\": "Orbitolina",\n \"popularity\": 128201\n },\n {\n \"tag\": "overlewd",\n \"popularity\": 127569\n },\n {\n \"tag\": "demiquaver",\n \"popularity\": 126942\n },\n {\n \"tag\": "kamelaukion",\n \"popularity\": 126319\n },\n {\n \"tag\": "flancard",\n \"popularity\": 125702\n },\n {\n \"tag\": "tricuspid",\n \"popularity\": 125089\n },\n {\n \"tag\": "bepelt",\n \"popularity\": 124480\n },\n {\n \"tag\": "decuplet",\n \"popularity\": 123877\n },\n {\n \"tag\": "Rockies",\n \"popularity\": 123278\n },\n {\n \"tag\": "unforgeability",\n \"popularity\": 122683\n },\n {\n \"tag\": "mocha",\n \"popularity\": 122093\n },\n {\n \"tag\": "scrunge",\n \"popularity\": 121507\n },\n {\n \"tag\": "delighter",\n \"popularity\": 120926\n },\n {\n \"tag\": "willey Microtinae",\n \"popularity\": 120349\n },\n {\n \"tag\": "unhuntable",\n \"popularity\": 119777\n },\n {\n \"tag\": "historically",\n \"popularity\": 119208\n },\n {\n \"tag\": "vicegerentship",\n \"popularity\": 118644\n },\n {\n \"tag\": "hemangiosarcoma",\n \"popularity\": 118084\n },\n {\n \"tag\": "harpago",\n \"popularity\": 117528\n },\n {\n \"tag\": "unionoid",\n \"popularity\": 116976\n },\n {\n \"tag\": "wiseman",\n \"popularity\": 116429\n },\n {\n \"tag\": "diclinism",\n \"popularity\": 115885\n },\n {\n \"tag\": "Maud",\n \"popularity\": 115345\n },\n {\n \"tag\": "scaphocephalism",\n \"popularity\": 114809\n },\n {\n \"tag\": "obtenebration",\n \"popularity\": 114277\n },\n {\n \"tag\": "cymar predreadnought",\n \"popularity\": 113749\n },\n {\n \"tag\": "discommend",\n \"popularity\": 113225\n },\n {\n \"tag\": "crude",\n \"popularity\": 112704\n },\n {\n \"tag\": "upflash",\n \"popularity\": 112187\n },\n {\n \"tag\": "saltimbank",\n \"popularity\": 111674\n },\n {\n \"tag\": "posthysterical",\n \"popularity\": 111165\n },\n {\n \"tag\": "trample",\n \"popularity\": 110659\n },\n {\n \"tag\": "ungirthed",\n \"popularity\": 110157\n },\n {\n \"tag\": "unshakable",\n \"popularity\": 109658\n },\n {\n \"tag\": "hepatocystic",\n \"popularity\": 109163\n },\n {\n \"tag\": "psammophyte",\n \"popularity\": 108671\n },\n {\n \"tag\": "millionfold",\n \"popularity\": 108183\n },\n {\n \"tag\": "outtaste",\n \"popularity\": 107698\n },\n {\n \"tag\": "poppycockish",\n \"popularity\": 107217\n },\n {\n \"tag\": "viduine",\n \"popularity\": 106739\n },\n {\n \"tag\": "pleasureman",\n \"popularity\": 106264\n },\n {\n \"tag\": "cholesterolemia",\n \"popularity\": 105792\n },\n {\n \"tag\": "hostlerwife",\n \"popularity\": 105324\n },\n {\n \"tag\": "figure undergrass",\n \"popularity\": 104859\n },\n {\n \"tag\": "bedrape",\n \"popularity\": 104398\n },\n {\n \"tag\": "nuttishness",\n \"popularity\": 103939\n },\n {\n \"tag\": "fow",\n \"popularity\": 103484\n },\n {\n \"tag\": "rachianesthesia",\n \"popularity\": 103031\n },\n {\n \"tag\": "recruitable",\n \"popularity\": 102582\n },\n {\n \"tag\": "semianatomical Oenotheraceae",\n \"popularity\": 102136\n },\n {\n \"tag\": "extracapsular",\n \"popularity\": 101693\n },\n {\n \"tag\": "unsigneted",\n \"popularity\": 101253\n },\n {\n \"tag\": "fissural",\n \"popularity\": 100816\n },\n {\n \"tag\": "ayous",\n \"popularity\": 100381\n },\n {\n \"tag\": "crestfallenness odontograph",\n \"popularity\": 99950\n },\n {\n \"tag\": "monopodium",\n \"popularity\": 99522\n },\n {\n \"tag\": "germfree",\n \"popularity\": 99096\n },\n {\n \"tag\": "dauphin",\n \"popularity\": 98673\n },\n {\n \"tag\": "nonagesimal",\n \"popularity\": 98254\n },\n {\n \"tag\": "waterchat",\n \"popularity\": 97836\n },\n {\n \"tag\": "Entelodon",\n \"popularity\": 97422\n },\n {\n \"tag\": "semischolastic",\n \"popularity\": 97010\n },\n {\n \"tag\": "somata",\n \"popularity\": 96602\n },\n {\n \"tag\": "expositorily",\n \"popularity\": 96195\n },\n {\n \"tag\": "bass",\n \"popularity\": 95792\n },\n {\n \"tag\": "calorimetry",\n \"popularity\": 95391\n },\n {\n \"tag\": "entireness",\n \"popularity\": 94993\n },\n {\n \"tag\": "ratline soppiness",\n \"popularity\": 94597\n },\n {\n \"tag\": "shor",\n \"popularity\": 94204\n },\n {\n \"tag\": "coprecipitation",\n \"popularity\": 93813\n },\n {\n \"tag\": "unblushingly",\n \"popularity\": 93425\n },\n {\n \"tag\": "macarize",\n \"popularity\": 93040\n },\n {\n \"tag\": "scruplesomeness",\n \"popularity\": 92657\n },\n {\n \"tag\": "offsaddle",\n \"popularity\": 92276\n },\n {\n \"tag\": "hypertragical",\n \"popularity\": 91898\n },\n {\n \"tag\": "uncassock loined",\n \"popularity\": 91522\n },\n {\n \"tag\": "interlobate",\n \"popularity\": 91149\n },\n {\n \"tag\": "releasor orrisroot stoloniferously",\n \"popularity\": 90778\n },\n {\n \"tag\": "elementoid",\n \"popularity\": 90410\n },\n {\n \"tag\": "Lentilla",\n \"popularity\": 90043\n },\n {\n \"tag\": "distressing",\n \"popularity\": 89679\n },\n {\n \"tag\": "hydrodrome",\n \"popularity\": 89318\n },\n {\n \"tag\": "Jeannette",\n \"popularity\": 88958\n },\n {\n \"tag\": "Kuli",\n \"popularity\": 88601\n },\n {\n \"tag\": "taxinomist",\n \"popularity\": 88246\n },\n {\n \"tag\": "southwestwardly",\n \"popularity\": 87894\n },\n {\n \"tag\": "polyparia",\n \"popularity\": 87543\n },\n {\n \"tag\": "exmeridian",\n \"popularity\": 87195\n },\n {\n \"tag\": "splenius regimentaled",\n \"popularity\": 86849\n },\n {\n \"tag\": "Sphaeropsidaceae",\n \"popularity\": 86505\n },\n {\n \"tag\": "unbegun",\n \"popularity\": 86163\n },\n {\n \"tag\": "something",\n \"popularity\": 85823\n },\n {\n \"tag\": "contaminable nonexpulsion",\n \"popularity\": 85486\n },\n {\n \"tag\": "douser",\n \"popularity\": 85150\n },\n {\n \"tag\": "prostrike",\n \"popularity\": 84817\n },\n {\n \"tag\": "worky",\n \"popularity\": 84485\n },\n {\n \"tag\": "folliful",\n \"popularity\": 84156\n },\n {\n \"tag\": "prioracy",\n \"popularity\": 83828\n },\n {\n \"tag\": "undermentioned",\n \"popularity\": 83503\n },\n {\n \"tag\": "Judaica",\n \"popularity\": 83179\n },\n {\n \"tag\": "multifarious",\n \"popularity\": 82858\n },\n {\n \"tag\": "poogye",\n \"popularity\": 82538\n },\n {\n \"tag\": "Sparganium",\n \"popularity\": 82221\n },\n {\n \"tag\": "thurrock",\n \"popularity\": 81905\n },\n {\n \"tag\": "outblush",\n \"popularity\": 81591\n },\n {\n \"tag\": "Strophanthus supraordination",\n \"popularity\": 81279\n },\n {\n \"tag\": "gingerroot",\n \"popularity\": 80969\n },\n {\n \"tag\": "unconscient",\n \"popularity\": 80661\n },\n {\n \"tag\": "unconstitutionally",\n \"popularity\": 80354\n },\n {\n \"tag\": "plaguily",\n \"popularity\": 80050\n },\n {\n \"tag\": "waterily equatorwards",\n \"popularity\": 79747\n },\n {\n \"tag\": "nondeposition",\n \"popularity\": 79446\n },\n {\n \"tag\": "dronishly",\n \"popularity\": 79147\n },\n {\n \"tag\": "gateado",\n \"popularity\": 78849\n },\n {\n \"tag\": "dislink",\n \"popularity\": 78553\n },\n {\n \"tag\": "Joceline",\n \"popularity\": 78259\n },\n {\n \"tag\": "amphiboliferous",\n \"popularity\": 77967\n },\n {\n \"tag\": "bushrope",\n \"popularity\": 77676\n },\n {\n \"tag\": "plumicorn sulphosalicylic",\n \"popularity\": 77387\n },\n {\n \"tag\": "nonefficiency",\n \"popularity\": 77100\n },\n {\n \"tag\": "hieroscopy",\n \"popularity\": 76815\n },\n {\n \"tag\": "causativeness",\n \"popularity\": 76531\n },\n {\n \"tag\": "swird paleoeremology",\n \"popularity\": 76249\n },\n {\n \"tag\": "camphoric",\n \"popularity\": 75968\n },\n {\n \"tag\": "retaining",\n \"popularity\": 75689\n },\n {\n \"tag\": "thyreoprotein",\n \"popularity\": 75411\n },\n {\n \"tag\": "carbona",\n \"popularity\": 75136\n },\n {\n \"tag\": "protectively",\n \"popularity\": 74861\n },\n {\n \"tag\": "mosasaur",\n \"popularity\": 74589\n },\n {\n \"tag\": "reciprocator",\n \"popularity\": 74317\n },\n {\n \"tag\": "detentive",\n \"popularity\": 74048\n },\n {\n \"tag\": "supravital",\n \"popularity\": 73780\n },\n {\n \"tag\": "Vespertilionidae",\n \"popularity\": 73513\n },\n {\n \"tag\": "parka",\n \"popularity\": 73248\n },\n {\n \"tag\": "pickaway",\n \"popularity\": 72984\n },\n {\n \"tag\": "oleaceous",\n \"popularity\": 72722\n },\n {\n \"tag\": "anticogitative",\n \"popularity\": 72462\n },\n {\n \"tag\": "woe",\n \"popularity\": 72203\n },\n {\n \"tag\": "skeuomorph",\n \"popularity\": 71945\n },\n {\n \"tag\": "helpmeet",\n \"popularity\": 71689\n },\n {\n \"tag\": "Hexactinellida brickmaking",\n \"popularity\": 71434\n },\n {\n \"tag\": "resink",\n \"popularity\": 71180\n },\n {\n \"tag\": "diluter",\n \"popularity\": 70928\n },\n {\n \"tag\": "micromicron",\n \"popularity\": 70677\n },\n {\n \"tag\": "parentage",\n \"popularity\": 70428\n },\n {\n \"tag\": "galactorrhoea",\n \"popularity\": 70180\n },\n {\n \"tag\": "gey",\n \"popularity\": 69934\n },\n {\n \"tag\": "gesticulatory",\n \"popularity\": 69689\n },\n {\n \"tag\": "wergil",\n \"popularity\": 69445\n },\n {\n \"tag\": "Lecanora",\n \"popularity\": 69202\n },\n {\n \"tag\": "malanders karst",\n \"popularity\": 68961\n },\n {\n \"tag\": "vibetoite",\n \"popularity\": 68721\n },\n {\n \"tag\": "unrequitedness",\n \"popularity\": 68483\n },\n {\n \"tag\": "outwash",\n \"popularity\": 68245\n },\n {\n \"tag\": "unsacred",\n \"popularity\": 68009\n },\n {\n \"tag\": "unabetted dividend",\n \"popularity\": 67775\n },\n {\n \"tag\": "untraveling",\n \"popularity\": 67541\n },\n {\n \"tag\": "thermobattery",\n \"popularity\": 67309\n },\n {\n \"tag\": "polypragmist",\n \"popularity\": 67078\n },\n {\n \"tag\": "irrefutableness",\n \"popularity\": 66848\n },\n {\n \"tag\": "remiges",\n \"popularity\": 66620\n },\n {\n \"tag\": "implode",\n \"popularity\": 66393\n },\n {\n \"tag\": "superfluousness",\n \"popularity\": 66166\n },\n {\n \"tag\": "croakily unalleviated",\n \"popularity\": 65942\n },\n {\n \"tag\": "edicule",\n \"popularity\": 65718\n },\n {\n \"tag\": "entophytous",\n \"popularity\": 65495\n },\n {\n \"tag\": "benefactorship Toryish",\n \"popularity\": 65274\n },\n {\n \"tag\": "pseudoamateurish",\n \"popularity\": 65054\n },\n {\n \"tag\": "flueless Iguanodontoidea snipnose",\n \"popularity\": 64835\n },\n {\n \"tag\": "zealotical Zamicrus interpole",\n \"popularity\": 64617\n },\n {\n \"tag\": "whereabout",\n \"popularity\": 64401\n },\n {\n \"tag\": "benzazide",\n \"popularity\": 64185\n },\n {\n \"tag\": "pokeweed",\n \"popularity\": 63971\n },\n {\n \"tag\": "calamitoid",\n \"popularity\": 63757\n },\n {\n \"tag\": "sporozoal",\n \"popularity\": 63545\n },\n {\n \"tag\": "physcioid Welshwoman",\n \"popularity\": 63334\n },\n {\n \"tag\": "wanting",\n \"popularity\": 63124\n },\n {\n \"tag\": "unencumbering",\n \"popularity\": 62915\n },\n {\n \"tag\": "Tupi",\n \"popularity\": 62707\n },\n {\n \"tag\": "potbank",\n \"popularity\": 62501\n },\n {\n \"tag\": "bulked",\n \"popularity\": 62295\n },\n {\n \"tag\": "uparise",\n \"popularity\": 62090\n },\n {\n \"tag\": "Sudra",\n \"popularity\": 61887\n },\n {\n \"tag\": "hyperscrupulosity",\n \"popularity\": 61684\n },\n {\n \"tag\": "subterraneously unmaid",\n \"popularity\": 61483\n },\n {\n \"tag\": "poisonousness",\n \"popularity\": 61282\n },\n {\n \"tag\": "phare",\n \"popularity\": 61083\n },\n {\n \"tag\": "dicynodont",\n \"popularity\": 60884\n },\n {\n \"tag\": "chewer",\n \"popularity\": 60687\n },\n {\n \"tag\": "uliginous",\n \"popularity\": 60490\n },\n {\n \"tag\": "tinman",\n \"popularity\": 60295\n },\n {\n \"tag\": "coconut",\n \"popularity\": 60100\n },\n {\n \"tag\": "phryganeoid",\n \"popularity\": 59907\n },\n {\n \"tag\": "bismillah",\n \"popularity\": 59714\n },\n {\n \"tag\": "tautomeric",\n \"popularity\": 59523\n },\n {\n \"tag\": "jerquer",\n \"popularity\": 59332\n },\n {\n \"tag\": "Dryopithecinae",\n \"popularity\": 59143\n },\n {\n \"tag\": "ghizite",\n \"popularity\": 58954\n },\n {\n \"tag\": "unliveable",\n \"popularity\": 58766\n },\n {\n \"tag\": "craftsmaster",\n \"popularity\": 58579\n },\n {\n \"tag\": "semiscenic",\n \"popularity\": 58394\n },\n {\n \"tag\": "danaid",\n \"popularity\": 58209\n },\n {\n \"tag\": "flawful",\n \"popularity\": 58025\n },\n {\n \"tag\": "risibleness",\n \"popularity\": 57841\n },\n {\n \"tag\": "Muscovite",\n \"popularity\": 57659\n },\n {\n \"tag\": "snaringly",\n \"popularity\": 57478\n },\n {\n \"tag\": "brilliantwise",\n \"popularity\": 57297\n },\n {\n \"tag\": "plebeity",\n \"popularity\": 57118\n },\n {\n \"tag\": "historicalness",\n \"popularity\": 56939\n },\n {\n \"tag\": "piecemeal",\n \"popularity\": 56761\n },\n {\n \"tag\": "maxillipedary",\n \"popularity\": 56584\n },\n {\n \"tag\": "Hypenantron",\n \"popularity\": 56408\n },\n {\n \"tag\": "quaintness avigate",\n \"popularity\": 56233\n },\n {\n \"tag\": "ave",\n \"popularity\": 56059\n },\n {\n \"tag\": "mediaevally",\n \"popularity\": 55885\n },\n {\n \"tag\": "brucite",\n \"popularity\": 55712\n },\n {\n \"tag\": "Schwendenerian",\n \"popularity\": 55541\n },\n {\n \"tag\": "julole",\n \"popularity\": 55370\n },\n {\n \"tag\": "palaeolith",\n \"popularity\": 55199\n },\n {\n \"tag\": "cotyledonary",\n \"popularity\": 55030\n },\n {\n \"tag\": "rond",\n \"popularity\": 54861\n },\n {\n \"tag\": "boomster tassoo",\n \"popularity\": 54694\n },\n {\n \"tag\": "cattishly",\n \"popularity\": 54527\n },\n {\n \"tag\": "tonguefence",\n \"popularity\": 54360\n },\n {\n \"tag\": "hexastylar triskele",\n \"popularity\": 54195\n },\n {\n \"tag\": "ariot",\n \"popularity\": 54030\n },\n {\n \"tag\": "intarsist",\n \"popularity\": 53867\n },\n {\n \"tag\": "Oscines",\n \"popularity\": 53704\n },\n {\n \"tag\": "Spaniolize",\n \"popularity\": 53541\n },\n {\n \"tag\": "smellfungus",\n \"popularity\": 53380\n },\n {\n \"tag\": "redisplay",\n \"popularity\": 53219\n },\n {\n \"tag\": "phosphene",\n \"popularity\": 53059\n },\n {\n \"tag\": "phycomycete",\n \"popularity\": 52900\n },\n {\n \"tag\": "prophetic",\n \"popularity\": 52741\n },\n {\n \"tag\": "overtrustful",\n \"popularity\": 52584\n },\n {\n \"tag\": "pinitol",\n \"popularity\": 52427\n },\n {\n \"tag\": "asthmatic",\n \"popularity\": 52270\n },\n {\n \"tag\": "convulsive",\n \"popularity\": 52115\n },\n {\n \"tag\": "draughtswoman",\n \"popularity\": 51960\n },\n {\n \"tag\": "unetymologizable",\n \"popularity\": 51806\n },\n {\n \"tag\": "centrarchoid",\n \"popularity\": 51652\n },\n {\n \"tag\": "mesioincisal",\n \"popularity\": 51500\n },\n {\n \"tag\": "transbaikal",\n \"popularity\": 51348\n },\n {\n \"tag\": "silveriness",\n \"popularity\": 51196\n },\n {\n \"tag\": "costotomy",\n \"popularity\": 51046\n },\n {\n \"tag\": "caracore",\n \"popularity\": 50896\n },\n {\n \"tag\": "depotentiation",\n \"popularity\": 50747\n },\n {\n \"tag\": "glossoepiglottidean",\n \"popularity\": 50598\n },\n {\n \"tag\": "upswell",\n \"popularity\": 50450\n },\n {\n \"tag\": "flecnodal",\n \"popularity\": 50303\n },\n {\n \"tag\": "coventrate",\n \"popularity\": 50157\n },\n {\n \"tag\": "duchesse",\n \"popularity\": 50011\n },\n {\n \"tag\": "excisemanship trophied",\n \"popularity\": 49866\n },\n {\n \"tag\": "cytinaceous",\n \"popularity\": 49721\n },\n {\n \"tag\": "assuringly",\n \"popularity\": 49577\n },\n {\n \"tag\": "unconducted upliftitis",\n \"popularity\": 49434\n },\n {\n \"tag\": "rachicentesis",\n \"popularity\": 49292\n },\n {\n \"tag\": "antiangular",\n \"popularity\": 49150\n },\n {\n \"tag\": "advisal",\n \"popularity\": 49008\n },\n {\n \"tag\": "birdcatcher",\n \"popularity\": 48868\n },\n {\n \"tag\": "secularistic",\n \"popularity\": 48728\n },\n {\n \"tag\": "grandeeism superinformal",\n \"popularity\": 48588\n },\n {\n \"tag\": "unapprehension",\n \"popularity\": 48449\n },\n {\n \"tag\": "excipulum",\n \"popularity\": 48311\n },\n {\n \"tag\": "decimole",\n \"popularity\": 48174\n },\n {\n \"tag\": "semidrachm",\n \"popularity\": 48037\n },\n {\n \"tag\": "uvulotome",\n \"popularity\": 47901\n },\n {\n \"tag\": "Lemaneaceae",\n \"popularity\": 47765\n },\n {\n \"tag\": "corrade",\n \"popularity\": 47630\n },\n {\n \"tag\": "Kuroshio",\n \"popularity\": 47495\n },\n {\n \"tag\": "Araliophyllum",\n \"popularity\": 47361\n },\n {\n \"tag\": "victoriousness cardiosphygmograph",\n \"popularity\": 47228\n },\n {\n \"tag\": "reinvent",\n \"popularity\": 47095\n },\n {\n \"tag\": "Macrotolagus",\n \"popularity\": 46963\n },\n {\n \"tag\": "strenuousness",\n \"popularity\": 46831\n },\n {\n \"tag\": "deviability",\n \"popularity\": 46700\n },\n {\n \"tag\": "phyllospondylous",\n \"popularity\": 46570\n },\n {\n \"tag\": "bisect rudderhole",\n \"popularity\": 46440\n },\n {\n \"tag\": "crownwork",\n \"popularity\": 46311\n },\n {\n \"tag\": "Ascalabota",\n \"popularity\": 46182\n },\n {\n \"tag\": "prostatomyomectomy",\n \"popularity\": 46054\n },\n {\n \"tag\": "neurosyphilis",\n \"popularity\": 45926\n },\n {\n \"tag\": "tabloid scraplet",\n \"popularity\": 45799\n },\n {\n \"tag\": "nonmedullated servility",\n \"popularity\": 45673\n },\n {\n \"tag\": "melopoeic practicalization",\n \"popularity\": 45547\n },\n {\n \"tag\": "nonrhythmic",\n \"popularity\": 45421\n },\n {\n \"tag\": "deplorer",\n \"popularity\": 45296\n },\n {\n \"tag\": "Ophion",\n \"popularity\": 45172\n },\n {\n \"tag\": "subprioress",\n \"popularity\": 45048\n },\n {\n \"tag\": "semiregular",\n \"popularity\": 44925\n },\n {\n \"tag\": "praelection",\n \"popularity\": 44802\n },\n {\n \"tag\": "discinct",\n \"popularity\": 44680\n },\n {\n \"tag\": "preplace",\n \"popularity\": 44558\n },\n {\n \"tag\": "paternoster",\n \"popularity\": 44437\n },\n {\n \"tag\": "suboccipital",\n \"popularity\": 44316\n },\n {\n \"tag\": "Teutophil",\n \"popularity\": 44196\n },\n {\n \"tag\": "tracheole",\n \"popularity\": 44076\n },\n {\n \"tag\": "subsmile",\n \"popularity\": 43957\n },\n {\n \"tag\": "nonapostatizing",\n \"popularity\": 43839\n },\n {\n \"tag\": "cleidotomy",\n \"popularity\": 43720\n },\n {\n \"tag\": "hingle",\n \"popularity\": 43603\n },\n {\n \"tag\": "jocoque",\n \"popularity\": 43486\n },\n {\n \"tag\": "trundler notidanian",\n \"popularity\": 43369\n },\n {\n \"tag\": "strangling misdaub",\n \"popularity\": 43253\n },\n {\n \"tag\": "noncancellable",\n \"popularity\": 43137\n },\n {\n \"tag\": "lavabo",\n \"popularity\": 43022\n },\n {\n \"tag\": "lanterloo",\n \"popularity\": 42907\n },\n {\n \"tag\": "uncitizenly",\n \"popularity\": 42793\n },\n {\n \"tag\": "autoturning",\n \"popularity\": 42679\n },\n {\n \"tag\": "Haganah",\n \"popularity\": 42566\n },\n {\n \"tag\": "Glecoma",\n \"popularity\": 42453\n },\n {\n \"tag\": "membered",\n \"popularity\": 42341\n },\n {\n \"tag\": "consuetudinal",\n \"popularity\": 42229\n },\n {\n \"tag\": "gatehouse",\n \"popularity\": 42117\n },\n {\n \"tag\": "tetherball",\n \"popularity\": 42006\n },\n {\n \"tag\": "counterrevolutionist numismatical",\n \"popularity\": 41896\n },\n {\n \"tag\": "pagehood plateiasmus",\n \"popularity\": 41786\n },\n {\n \"tag\": "pelterer",\n \"popularity\": 41676\n },\n {\n \"tag\": "splenemphraxis",\n \"popularity\": 41567\n },\n {\n \"tag\": "Crypturidae",\n \"popularity\": 41458\n },\n {\n \"tag\": "caboodle",\n \"popularity\": 41350\n },\n {\n \"tag\": "Filaria",\n \"popularity\": 41242\n },\n {\n \"tag\": "noninvincibility",\n \"popularity\": 41135\n },\n {\n \"tag\": "preadvertisement",\n \"popularity\": 41028\n },\n {\n \"tag\": "bathrobe",\n \"popularity\": 40921\n },\n {\n \"tag\": "nitrifier",\n \"popularity\": 40815\n },\n {\n \"tag\": "furthermore",\n \"popularity\": 40709\n },\n {\n \"tag\": "recrate",\n \"popularity\": 40604\n },\n {\n \"tag\": "inexist",\n \"popularity\": 40499\n },\n {\n \"tag\": "Mocoan",\n \"popularity\": 40395\n },\n {\n \"tag\": "forint",\n \"popularity\": 40291\n },\n {\n \"tag\": "cardiomyoliposis",\n \"popularity\": 40187\n },\n {\n \"tag\": "channeling",\n \"popularity\": 40084\n },\n {\n \"tag\": "quebrachine",\n \"popularity\": 39981\n },\n {\n \"tag\": "magistery",\n \"popularity\": 39879\n },\n {\n \"tag\": "koko",\n \"popularity\": 39777\n },\n {\n \"tag\": "nobilify",\n \"popularity\": 39676\n },\n {\n \"tag\": "articulate taprooted",\n \"popularity\": 39575\n },\n {\n \"tag\": "cardiotonic Nicaragua",\n \"popularity\": 39474\n },\n {\n \"tag\": "assertiveness",\n \"popularity\": 39374\n },\n {\n \"tag\": "springtail",\n \"popularity\": 39274\n },\n {\n \"tag\": "spontoon",\n \"popularity\": 39174\n },\n {\n \"tag\": "plesiobiosis",\n \"popularity\": 39075\n },\n {\n \"tag\": "rooinek",\n \"popularity\": 38976\n },\n {\n \"tag\": "hairif falsehood",\n \"popularity\": 38878\n },\n {\n \"tag\": "synodally",\n \"popularity\": 38780\n },\n {\n \"tag\": "biodynamics",\n \"popularity\": 38683\n },\n {\n \"tag\": "trickling",\n \"popularity\": 38585\n },\n {\n \"tag\": "oxfly daystar",\n \"popularity\": 38489\n },\n {\n \"tag\": "epicycloidal",\n \"popularity\": 38392\n },\n {\n \"tag\": "shorthand",\n \"popularity\": 38296\n },\n {\n \"tag\": "herpolhode",\n \"popularity\": 38201\n },\n {\n \"tag\": "polysynthesism",\n \"popularity\": 38105\n },\n {\n \"tag\": "cany",\n \"popularity\": 38010\n },\n {\n \"tag\": "sideage",\n \"popularity\": 37916\n },\n {\n \"tag\": "strainableness",\n \"popularity\": 37822\n },\n {\n \"tag\": "superformidable",\n \"popularity\": 37728\n },\n {\n \"tag\": "slendang",\n \"popularity\": 37634\n },\n {\n \"tag\": "impropriation",\n \"popularity\": 37541\n },\n {\n \"tag\": "ficklehearted",\n \"popularity\": 37449\n },\n {\n \"tag\": "wintrify",\n \"popularity\": 37356\n },\n {\n \"tag\": "geomorphogenist",\n \"popularity\": 37264\n },\n {\n \"tag\": "smuggleable",\n \"popularity\": 37173\n },\n {\n \"tag\": "delapsion",\n \"popularity\": 37081\n },\n {\n \"tag\": "projective",\n \"popularity\": 36990\n },\n {\n \"tag\": "unglue exfoliation",\n \"popularity\": 36900\n },\n {\n \"tag\": "Acerae",\n \"popularity\": 36810\n },\n {\n \"tag\": "unstaged",\n \"popularity\": 36720\n },\n {\n \"tag\": "ranal",\n \"popularity\": 36630\n },\n {\n \"tag\": "worrier",\n \"popularity\": 36541\n },\n {\n \"tag\": "unhid",\n \"popularity\": 36452\n },\n {\n \"tag\": "adequation",\n \"popularity\": 36363\n },\n {\n \"tag\": "strongylid Sokotri",\n \"popularity\": 36275\n },\n {\n \"tag\": "fumingly",\n \"popularity\": 36187\n },\n {\n \"tag\": "gynosporangium phaenogenetic",\n \"popularity\": 36100\n },\n {\n \"tag\": "uniunguiculate",\n \"popularity\": 36012\n },\n {\n \"tag\": "prudelike",\n \"popularity\": 35926\n },\n {\n \"tag\": "seminomata",\n \"popularity\": 35839\n },\n {\n \"tag\": "trinklet",\n \"popularity\": 35753\n },\n {\n \"tag\": "risorial",\n \"popularity\": 35667\n },\n {\n \"tag\": "pericardiocentesis",\n \"popularity\": 35581\n },\n {\n \"tag\": "filmist",\n \"popularity\": 35496\n },\n {\n \"tag\": "Nana",\n \"popularity\": 35411\n },\n {\n \"tag\": "cynipoid",\n \"popularity\": 35326\n },\n {\n \"tag\": "cteniform",\n \"popularity\": 35242\n },\n {\n \"tag\": "semiflex",\n \"popularity\": 35158\n },\n {\n \"tag\": "solstitially",\n \"popularity\": 35074\n },\n {\n \"tag\": "Algarsife",\n \"popularity\": 34991\n },\n {\n \"tag\": "noncriminal",\n \"popularity\": 34908\n },\n {\n \"tag\": "compassion",\n \"popularity\": 34825\n },\n {\n \"tag\": "Buddhic",\n \"popularity\": 34743\n },\n {\n \"tag\": "vellicative dactylically hotfoot",\n \"popularity\": 34661\n },\n {\n \"tag\": "chicory",\n \"popularity\": 34579\n },\n {\n \"tag\": "transperitoneally",\n \"popularity\": 34497\n },\n {\n \"tag\": "pennae",\n \"popularity\": 34416\n },\n {\n \"tag\": "Flamandize",\n \"popularity\": 34335\n },\n {\n \"tag\": "underviewer",\n \"popularity\": 34254\n },\n {\n \"tag\": "assoil",\n \"popularity\": 34174\n },\n {\n \"tag\": "saccharobacillus",\n \"popularity\": 34094\n },\n {\n \"tag\": "biacetylene",\n \"popularity\": 34014\n },\n {\n \"tag\": "mouchardism",\n \"popularity\": 33935\n },\n {\n \"tag\": "anisomeric",\n \"popularity\": 33856\n },\n {\n \"tag\": "digestive",\n \"popularity\": 33777\n },\n {\n \"tag\": "darlingly",\n \"popularity\": 33698\n },\n {\n \"tag\": "liman",\n \"popularity\": 33620\n },\n {\n \"tag\": "soldanrie",\n \"popularity\": 33542\n },\n {\n \"tag\": "sully",\n \"popularity\": 33464\n },\n {\n \"tag\": "brightsmith",\n \"popularity\": 33387\n },\n {\n \"tag\": "inwrap antiliturgist ureterocervical",\n \"popularity\": 33309\n },\n {\n \"tag\": "discommodity",\n \"popularity\": 33232\n },\n {\n \"tag\": "typical aggrandizer",\n \"popularity\": 33156\n },\n {\n \"tag\": "xenogeny",\n \"popularity\": 33079\n },\n {\n \"tag\": "uncountrified",\n \"popularity\": 33003\n },\n {\n \"tag\": "Podarge",\n \"popularity\": 32928\n },\n {\n \"tag\": "uninterviewed",\n \"popularity\": 32852\n },\n {\n \"tag\": "underprior",\n \"popularity\": 32777\n },\n {\n \"tag\": "leiomyomatous",\n \"popularity\": 32702\n },\n {\n \"tag\": "postdysenteric",\n \"popularity\": 32627\n },\n {\n \"tag\": "Fusicladium",\n \"popularity\": 32553\n },\n {\n \"tag\": "Dulcinea",\n \"popularity\": 32478\n },\n {\n \"tag\": "interspersion",\n \"popularity\": 32404\n },\n {\n \"tag\": "preobligate",\n \"popularity\": 32331\n },\n {\n \"tag\": "subaggregate",\n \"popularity\": 32257\n },\n {\n \"tag\": "grammarianism",\n \"popularity\": 32184\n },\n {\n \"tag\": "palikar",\n \"popularity\": 32111\n },\n {\n \"tag\": "facileness",\n \"popularity\": 32039\n },\n {\n \"tag\": "deuterofibrinose",\n \"popularity\": 31966\n },\n {\n \"tag\": "pseudesthesia",\n \"popularity\": 31894\n },\n {\n \"tag\": "sedimentary",\n \"popularity\": 31822\n },\n {\n \"tag\": "typewrite",\n \"popularity\": 31751\n },\n {\n \"tag\": "immemorable",\n \"popularity\": 31679\n },\n {\n \"tag\": "Myrtus",\n \"popularity\": 31608\n },\n {\n \"tag\": "hauchecornite",\n \"popularity\": 31537\n },\n {\n \"tag\": "galleylike",\n \"popularity\": 31467\n },\n {\n \"tag\": "thimber",\n \"popularity\": 31396\n },\n {\n \"tag\": "Hegelianism",\n \"popularity\": 31326\n },\n {\n \"tag\": "strig",\n \"popularity\": 31256\n },\n {\n \"tag\": "skyre",\n \"popularity\": 31187\n },\n {\n \"tag\": "eupepticism",\n \"popularity\": 31117\n },\n {\n \"tag\": "eponymism",\n \"popularity\": 31048\n },\n {\n \"tag\": "flunkeyhood",\n \"popularity\": 30979\n },\n {\n \"tag\": "Abama",\n \"popularity\": 30911\n },\n {\n \"tag\": "adiadochokinesis",\n \"popularity\": 30842\n },\n {\n \"tag\": "spendthrifty",\n \"popularity\": 30774\n },\n {\n \"tag\": "chalcedony",\n \"popularity\": 30706\n },\n {\n \"tag\": "authorism",\n \"popularity\": 30638\n },\n {\n \"tag\": "nasturtium",\n \"popularity\": 30571\n },\n {\n \"tag\": "Acanthocereus",\n \"popularity\": 30504\n },\n {\n \"tag\": "uncollapsible",\n \"popularity\": 30437\n },\n {\n \"tag\": "excursionist",\n \"popularity\": 30370\n },\n {\n \"tag\": "fogbow",\n \"popularity\": 30303\n },\n {\n \"tag\": "overlie",\n \"popularity\": 30237\n },\n {\n \"tag\": "velours",\n \"popularity\": 30171\n },\n {\n \"tag\": "zoodendria madrigal stagbush",\n \"popularity\": 30105\n },\n {\n \"tag\": "imi",\n \"popularity\": 30039\n },\n {\n \"tag\": "cojudge",\n \"popularity\": 29974\n },\n {\n \"tag\": "depurate argal",\n \"popularity\": 29909\n },\n {\n \"tag\": "unrecognition",\n \"popularity\": 29844\n },\n {\n \"tag\": "paunchful",\n \"popularity\": 29779\n },\n {\n \"tag\": "invalued",\n \"popularity\": 29714\n },\n {\n \"tag\": "probang",\n \"popularity\": 29650\n },\n {\n \"tag\": "chetvert",\n \"popularity\": 29586\n },\n {\n \"tag\": "enactable",\n \"popularity\": 29522\n },\n {\n \"tag\": "detoxicate adhibit",\n \"popularity\": 29458\n },\n {\n \"tag\": "kullaite",\n \"popularity\": 29395\n },\n {\n \"tag\": "undazzling",\n \"popularity\": 29332\n },\n {\n \"tag\": "excalation",\n \"popularity\": 29269\n },\n {\n \"tag\": "sievings",\n \"popularity\": 29206\n },\n {\n \"tag\": "disenthral",\n \"popularity\": 29143\n },\n {\n \"tag\": "disinterestedly",\n \"popularity\": 29081\n },\n {\n \"tag\": "stanner",\n \"popularity\": 29018\n },\n {\n \"tag\": "recapitulative",\n \"popularity\": 28956\n },\n {\n \"tag\": "objectivist",\n \"popularity\": 28895\n },\n {\n \"tag\": "hypermetropia",\n \"popularity\": 28833\n },\n {\n \"tag\": "incumbency",\n \"popularity\": 28772\n },\n {\n \"tag\": "protegee",\n \"popularity\": 28711\n },\n {\n \"tag\": "zealotic",\n \"popularity\": 28650\n },\n {\n \"tag\": "predebit",\n \"popularity\": 28589\n },\n {\n \"tag\": "cupolar",\n \"popularity\": 28528\n },\n {\n \"tag\": "unattributed",\n \"popularity\": 28468\n },\n {\n \"tag\": "louisine",\n \"popularity\": 28408\n },\n {\n \"tag\": "illustrate",\n \"popularity\": 28348\n },\n {\n \"tag\": "inofficiousness",\n \"popularity\": 28288\n },\n {\n \"tag\": "Americawards",\n \"popularity\": 28228\n },\n {\n \"tag\": "foreflap",\n \"popularity\": 28169\n },\n {\n \"tag\": "eruditeness",\n \"popularity\": 28110\n },\n {\n \"tag\": "copiopsia",\n \"popularity\": 28051\n },\n {\n \"tag\": "sporuliferous",\n \"popularity\": 27992\n },\n {\n \"tag\": "muttering",\n \"popularity\": 27934\n },\n {\n \"tag\": "prepsychology adrip",\n \"popularity\": 27875\n },\n {\n \"tag\": "unfriendly",\n \"popularity\": 27817\n },\n {\n \"tag\": "sulphanilic",\n \"popularity\": 27759\n },\n {\n \"tag\": "Coelococcus",\n \"popularity\": 27701\n },\n {\n \"tag\": "undoubtfulness",\n \"popularity\": 27643\n },\n {\n \"tag\": "flaringly",\n \"popularity\": 27586\n },\n {\n \"tag\": "unordain",\n \"popularity\": 27529\n },\n {\n \"tag\": "fratchety",\n \"popularity\": 27472\n },\n {\n \"tag\": "decadentism dolefully",\n \"popularity\": 27415\n },\n {\n \"tag\": "synthronus",\n \"popularity\": 27358\n },\n {\n \"tag\": "maiid",\n \"popularity\": 27301\n },\n {\n \"tag\": "rhinobyon",\n \"popularity\": 27245\n },\n {\n \"tag\": "Didynamia",\n \"popularity\": 27189\n },\n {\n \"tag\": "millionairedom",\n \"popularity\": 27133\n },\n {\n \"tag\": "mulierine",\n \"popularity\": 27077\n },\n {\n \"tag\": "Mayo",\n \"popularity\": 27021\n },\n {\n \"tag\": "perceivedness",\n \"popularity\": 26966\n },\n {\n \"tag\": "unadoration",\n \"popularity\": 26911\n },\n {\n \"tag\": "regraft",\n \"popularity\": 26856\n },\n {\n \"tag\": "witch",\n \"popularity\": 26801\n },\n {\n \"tag\": "ungrow",\n \"popularity\": 26746\n },\n {\n \"tag\": "glossopharyngeus",\n \"popularity\": 26691\n },\n {\n \"tag\": "unstirrable",\n \"popularity\": 26637\n },\n {\n \"tag\": "synodsman",\n \"popularity\": 26583\n },\n {\n \"tag\": "placentalian",\n \"popularity\": 26529\n },\n {\n \"tag\": "corpulently",\n \"popularity\": 26475\n },\n {\n \"tag\": "photochromoscope",\n \"popularity\": 26421\n },\n {\n \"tag\": "indusiate retinasphaltum chokestrap",\n \"popularity\": 26368\n },\n {\n \"tag\": "murdrum",\n \"popularity\": 26314\n },\n {\n \"tag\": "belatedness",\n \"popularity\": 26261\n },\n {\n \"tag\": "Cochin",\n \"popularity\": 26208\n },\n {\n \"tag\": "Leonist",\n \"popularity\": 26155\n },\n {\n \"tag\": "keeker confined",\n \"popularity\": 26102\n },\n {\n \"tag\": "unintellectual",\n \"popularity\": 26050\n },\n {\n \"tag\": "nymphaline bait",\n \"popularity\": 25997\n },\n {\n \"tag\": "sarcosporidiosis",\n \"popularity\": 25945\n },\n {\n \"tag\": "catawamptiously",\n \"popularity\": 25893\n },\n {\n \"tag\": "outshame",\n \"popularity\": 25841\n },\n {\n \"tag\": "animalism",\n \"popularity\": 25790\n },\n {\n \"tag\": "epithalamial",\n \"popularity\": 25738\n },\n {\n \"tag\": "ganner",\n \"popularity\": 25687\n },\n {\n \"tag\": "desilicify",\n \"popularity\": 25635\n },\n {\n \"tag\": "dandyism",\n \"popularity\": 25584\n },\n {\n \"tag\": "hyleg",\n \"popularity\": 25533\n },\n {\n \"tag\": "photophysical",\n \"popularity\": 25483\n },\n {\n \"tag\": "underload",\n \"popularity\": 25432\n },\n {\n \"tag\": "unintrusive",\n \"popularity\": 25382\n },\n {\n \"tag\": "succinamic",\n \"popularity\": 25331\n },\n {\n \"tag\": "matchy",\n \"popularity\": 25281\n },\n {\n \"tag\": "concordal",\n \"popularity\": 25231\n },\n {\n \"tag\": "exteriority",\n \"popularity\": 25181\n },\n {\n \"tag\": "sterculiad",\n \"popularity\": 25132\n },\n {\n \"tag\": "sulfoxylic",\n \"popularity\": 25082\n },\n {\n \"tag\": "oversubscription",\n \"popularity\": 25033\n },\n {\n \"tag\": "chiasmic",\n \"popularity\": 24984\n },\n {\n \"tag\": "pseudoparthenogenesis",\n \"popularity\": 24935\n },\n {\n \"tag\": "indorse",\n \"popularity\": 24886\n },\n {\n \"tag\": "Krishnaite",\n \"popularity\": 24837\n },\n {\n \"tag\": "calcinize",\n \"popularity\": 24788\n },\n {\n \"tag\": "rhodium",\n \"popularity\": 24740\n },\n {\n \"tag\": "tragopan",\n \"popularity\": 24692\n },\n {\n \"tag\": "overwhelmingly",\n \"popularity\": 24643\n },\n {\n \"tag\": "procidence accorporate",\n \"popularity\": 24595\n },\n {\n \"tag\": "polemize speelless",\n \"popularity\": 24548\n },\n {\n \"tag\": "radiocarpal goran",\n \"popularity\": 24500\n },\n {\n \"tag\": "counteroffer Pelodytes",\n \"popularity\": 24452\n },\n {\n \"tag\": "lionhearted",\n \"popularity\": 24405\n },\n {\n \"tag\": "paramastoid",\n \"popularity\": 24358\n },\n {\n \"tag\": "murine",\n \"popularity\": 24310\n },\n {\n \"tag\": "woodbined",\n \"popularity\": 24263\n },\n {\n \"tag\": "packthread",\n \"popularity\": 24217\n },\n {\n \"tag\": "citreous",\n \"popularity\": 24170\n },\n {\n \"tag\": "unfallaciously",\n \"popularity\": 24123\n },\n {\n \"tag\": "tentwork reincarnadine",\n \"popularity\": 24077\n },\n {\n \"tag\": "verminousness",\n \"popularity\": 24030\n },\n {\n \"tag\": "sillometer",\n \"popularity\": 23984\n },\n {\n \"tag\": "jointy",\n \"popularity\": 23938\n },\n {\n \"tag\": "streptolysin",\n \"popularity\": 23892\n },\n {\n \"tag\": "Florentinism",\n \"popularity\": 23847\n },\n {\n \"tag\": "monosomatous",\n \"popularity\": 23801\n },\n {\n \"tag\": "capsulociliary",\n \"popularity\": 23756\n },\n {\n \"tag\": "organum",\n \"popularity\": 23710\n },\n {\n \"tag\": "overtly",\n \"popularity\": 23665\n },\n {\n \"tag\": "ophthalmoscopical",\n \"popularity\": 23620\n },\n {\n \"tag\": "supposititiously",\n \"popularity\": 23575\n },\n {\n \"tag\": "radiochemistry",\n \"popularity\": 23530\n },\n {\n \"tag\": "flaxtail",\n \"popularity\": 23486\n },\n {\n \"tag\": "pretympanic",\n \"popularity\": 23441\n },\n {\n \"tag\": "auscultation",\n \"popularity\": 23397\n },\n {\n \"tag\": "hairdresser",\n \"popularity\": 23352\n },\n {\n \"tag\": "chaffless",\n \"popularity\": 23308\n },\n {\n \"tag\": "polioencephalitis",\n \"popularity\": 23264\n },\n {\n \"tag\": "axolotl",\n \"popularity\": 23220\n },\n {\n \"tag\": "smous",\n \"popularity\": 23177\n },\n {\n \"tag\": "morgen disenamour toothed",\n \"popularity\": 23133\n },\n {\n \"tag\": "chaiseless",\n \"popularity\": 23089\n },\n {\n \"tag\": "frugally",\n \"popularity\": 23046\n },\n {\n \"tag\": "combustive antievolutionist cinenegative",\n \"popularity\": 23003\n },\n {\n \"tag\": "malacolite",\n \"popularity\": 22960\n },\n {\n \"tag\": "borne",\n \"popularity\": 22917\n },\n {\n \"tag\": "mercaptole",\n \"popularity\": 22874\n },\n {\n \"tag\": "judicatory",\n \"popularity\": 22831\n },\n {\n \"tag\": "noctivagation",\n \"popularity\": 22789\n },\n {\n \"tag\": "synthete",\n \"popularity\": 22746\n },\n {\n \"tag\": "tomboyism",\n \"popularity\": 22704\n },\n {\n \"tag\": "serranoid",\n \"popularity\": 22661\n },\n {\n \"tag\": "impostorism",\n \"popularity\": 22619\n },\n {\n \"tag\": "flagellosis Talitha",\n \"popularity\": 22577\n },\n {\n \"tag\": "pseudoviscous",\n \"popularity\": 22535\n },\n {\n \"tag\": "Galleriidae",\n \"popularity\": 22494\n },\n {\n \"tag\": "undulation didelph Comintern",\n \"popularity\": 22452\n },\n {\n \"tag\": "triangulopyramidal",\n \"popularity\": 22411\n },\n {\n \"tag\": "middlings",\n \"popularity\": 22369\n },\n {\n \"tag\": "piperazin",\n \"popularity\": 22328\n },\n {\n \"tag\": "endostitis",\n \"popularity\": 22287\n },\n {\n \"tag\": "swordlike",\n \"popularity\": 22246\n },\n {\n \"tag\": "forthwith",\n \"popularity\": 22205\n },\n {\n \"tag\": "menaceful",\n \"popularity\": 22164\n },\n {\n \"tag\": "explantation defective",\n \"popularity\": 22123\n },\n {\n \"tag\": "arrear",\n \"popularity\": 22083\n },\n {\n \"tag\": "engraft",\n \"popularity\": 22042\n },\n {\n \"tag\": "revolunteer",\n \"popularity\": 22002\n },\n {\n \"tag\": "foliaceous",\n \"popularity\": 21962\n },\n {\n \"tag\": "pseudograph",\n \"popularity\": 21922\n },\n {\n \"tag\": "maenaite",\n \"popularity\": 21882\n },\n {\n \"tag\": "interfinger",\n \"popularity\": 21842\n },\n {\n \"tag\": "macroscopically",\n \"popularity\": 21802\n },\n {\n \"tag\": "bluewood",\n \"popularity\": 21762\n },\n {\n \"tag\": "chikara",\n \"popularity\": 21723\n },\n {\n \"tag\": "reprehension diazeuxis nickelous",\n \"popularity\": 21683\n },\n {\n \"tag\": "vacuation",\n \"popularity\": 21644\n },\n {\n \"tag\": "Sartish",\n \"popularity\": 21605\n },\n {\n \"tag\": "pseudogyny",\n \"popularity\": 21566\n },\n {\n \"tag\": "friedcake",\n \"popularity\": 21527\n },\n {\n \"tag\": "thraw",\n \"popularity\": 21488\n },\n {\n \"tag\": "bifid",\n \"popularity\": 21449\n },\n {\n \"tag\": "truthlessly",\n \"popularity\": 21411\n },\n {\n \"tag\": "lungy",\n \"popularity\": 21372\n },\n {\n \"tag\": "fluoborite",\n \"popularity\": 21334\n },\n {\n \"tag\": "anthropolithic",\n \"popularity\": 21295\n },\n {\n \"tag\": "coachee straw",\n \"popularity\": 21257\n },\n {\n \"tag\": "dehorner Grecize",\n \"popularity\": 21219\n },\n {\n \"tag\": "spondylopyosis",\n \"popularity\": 21181\n },\n {\n \"tag\": "institutionary",\n \"popularity\": 21143\n },\n {\n \"tag\": "agentry",\n \"popularity\": 21105\n },\n {\n \"tag\": "musing bietle",\n \"popularity\": 21068\n },\n {\n \"tag\": "cormophyte",\n \"popularity\": 21030\n },\n {\n \"tag\": "semielliptic",\n \"popularity\": 20993\n },\n {\n \"tag\": "ependytes",\n \"popularity\": 20955\n },\n {\n \"tag\": "coachmaster",\n \"popularity\": 20918\n },\n {\n \"tag\": "overexuberant",\n \"popularity\": 20881\n },\n {\n \"tag\": "selectable",\n \"popularity\": 20844\n },\n {\n \"tag\": "saclike",\n \"popularity\": 20807\n },\n {\n \"tag\": "mullion",\n \"popularity\": 20770\n },\n {\n \"tag\": "pantheonize prevalency",\n \"popularity\": 20733\n },\n {\n \"tag\": "trophosperm",\n \"popularity\": 20697\n },\n {\n \"tag\": "paraphrasist",\n \"popularity\": 20660\n },\n {\n \"tag\": "undercarry",\n \"popularity\": 20624\n },\n {\n \"tag\": "thallogenic",\n \"popularity\": 20587\n },\n {\n \"tag\": "bulgy forbid",\n \"popularity\": 20551\n },\n {\n \"tag\": "proliquor gratulatory",\n \"popularity\": 20515\n },\n {\n \"tag\": "booker",\n \"popularity\": 20479\n },\n {\n \"tag\": "wizen",\n \"popularity\": 20443\n },\n {\n \"tag\": "synchondrosially",\n \"popularity\": 20407\n },\n {\n \"tag\": "herbless",\n \"popularity\": 20371\n },\n {\n \"tag\": "arfvedsonite",\n \"popularity\": 20336\n },\n {\n \"tag\": "Neuroptera",\n \"popularity\": 20300\n },\n {\n \"tag\": "fingerstone",\n \"popularity\": 20265\n },\n {\n \"tag\": "Odontoglossae",\n \"popularity\": 20229\n },\n {\n \"tag\": "transmigrator",\n \"popularity\": 20194\n },\n {\n \"tag\": "Dehaites",\n \"popularity\": 20159\n },\n {\n \"tag\": "Molinist",\n \"popularity\": 20124\n },\n {\n \"tag\": "novelistic",\n \"popularity\": 20089\n },\n {\n \"tag\": "astelic",\n \"popularity\": 20054\n },\n {\n \"tag\": "pyelometry",\n \"popularity\": 20019\n },\n {\n \"tag\": "pigmentation",\n \"popularity\": 19984\n },\n {\n \"tag\": "epinaos",\n \"popularity\": 19950\n },\n {\n \"tag\": "outdare",\n \"popularity\": 19915\n },\n {\n \"tag\": "Funje philaristocracy",\n \"popularity\": 19881\n },\n {\n \"tag\": "keddah",\n \"popularity\": 19846\n },\n {\n \"tag\": "axoidean",\n \"popularity\": 19812\n },\n {\n \"tag\": "ovule",\n \"popularity\": 19778\n },\n {\n \"tag\": "solidify",\n \"popularity\": 19744\n },\n {\n \"tag\": "noncelestial",\n \"popularity\": 19710\n },\n {\n \"tag\": "overmultiplication",\n \"popularity\": 19676\n },\n {\n \"tag\": "hexatetrahedron",\n \"popularity\": 19642\n },\n {\n \"tag\": "pliciform",\n \"popularity\": 19609\n },\n {\n \"tag\": "zimbalon",\n \"popularity\": 19575\n },\n {\n \"tag\": "annexational",\n \"popularity\": 19542\n },\n {\n \"tag\": "eurhodol",\n \"popularity\": 19508\n },\n {\n \"tag\": "yark",\n \"popularity\": 19475\n },\n {\n \"tag\": "illegality nitroalizarin",\n \"popularity\": 19442\n },\n {\n \"tag\": "quadratum",\n \"popularity\": 19409\n },\n {\n \"tag\": "saccharine",\n \"popularity\": 19376\n },\n {\n \"tag\": "unemploy",\n \"popularity\": 19343\n },\n {\n \"tag\": "uniclinal unipotent",\n \"popularity\": 19310\n },\n {\n \"tag\": "turbo",\n \"popularity\": 19277\n },\n {\n \"tag\": "sybarism",\n \"popularity\": 19244\n },\n {\n \"tag\": "motacilline",\n \"popularity\": 19212\n },\n {\n \"tag\": "weaselly",\n \"popularity\": 19179\n },\n {\n \"tag\": "plastid",\n \"popularity\": 19147\n },\n {\n \"tag\": "wasting",\n \"popularity\": 19114\n },\n {\n \"tag\": "begrime fluting",\n \"popularity\": 19082\n },\n {\n \"tag\": "Nephilinae",\n \"popularity\": 19050\n },\n {\n \"tag\": "disregardance",\n \"popularity\": 19018\n },\n {\n \"tag\": "Shakerlike",\n \"popularity\": 18986\n },\n {\n \"tag\": "uniped",\n \"popularity\": 18954\n },\n {\n \"tag\": "knap",\n \"popularity\": 18922\n },\n {\n \"tag\": "electivism undergardener",\n \"popularity\": 18890\n },\n {\n \"tag\": "hulverheaded",\n \"popularity\": 18858\n },\n {\n \"tag\": "unruptured",\n \"popularity\": 18827\n },\n {\n \"tag\": "solemnize credently",\n \"popularity\": 18795\n },\n {\n \"tag\": "pentastomoid possessingly",\n \"popularity\": 18764\n },\n {\n \"tag\": "octose",\n \"popularity\": 18733\n },\n {\n \"tag\": "psithurism indefensibility",\n \"popularity\": 18701\n },\n {\n \"tag\": "torrentuous cyanometer subcrenate",\n \"popularity\": 18670\n },\n {\n \"tag\": "photoplaywright tapaculo",\n \"popularity\": 18639\n },\n {\n \"tag\": "univalence",\n \"popularity\": 18608\n },\n {\n \"tag\": "Porthetria",\n \"popularity\": 18577\n },\n {\n \"tag\": "funambulo",\n \"popularity\": 18546\n },\n {\n \"tag\": "pedion",\n \"popularity\": 18515\n },\n {\n \"tag\": "horticulturally",\n \"popularity\": 18485\n },\n {\n \"tag\": "marennin",\n \"popularity\": 18454\n },\n {\n \"tag\": "horselaugh",\n \"popularity\": 18423\n },\n {\n \"tag\": "semiexecutive",\n \"popularity\": 18393\n },\n {\n \"tag\": "Monopteridae",\n \"popularity\": 18363\n },\n {\n \"tag\": "commonable",\n \"popularity\": 18332\n },\n {\n \"tag\": "dreariment",\n \"popularity\": 18302\n },\n {\n \"tag\": "disbud",\n \"popularity\": 18272\n },\n {\n \"tag\": "monocled",\n \"popularity\": 18242\n },\n {\n \"tag\": "hurlbarrow",\n \"popularity\": 18212\n },\n {\n \"tag\": "opiateproof",\n \"popularity\": 18182\n },\n {\n \"tag\": "Fahrenheit",\n \"popularity\": 18152\n },\n {\n \"tag\": "writhed",\n \"popularity\": 18122\n },\n {\n \"tag\": "Volstead",\n \"popularity\": 18093\n },\n {\n \"tag\": "yesternight",\n \"popularity\": 18063\n },\n {\n \"tag\": "readmittance",\n \"popularity\": 18033\n },\n {\n \"tag\": "reiterable",\n \"popularity\": 18004\n },\n {\n \"tag\": "triquetral",\n \"popularity\": 17975\n },\n {\n \"tag\": "guillotinement",\n \"popularity\": 17945\n },\n {\n \"tag\": "repermission",\n \"popularity\": 17916\n },\n {\n \"tag\": "assishly",\n \"popularity\": 17887\n },\n {\n \"tag\": "daidle",\n \"popularity\": 17858\n },\n {\n \"tag\": "prismatoid",\n \"popularity\": 17829\n },\n {\n \"tag\": "irreptitious",\n \"popularity\": 17800\n },\n {\n \"tag\": "sourdeline",\n \"popularity\": 17771\n },\n {\n \"tag\": "Austrian",\n \"popularity\": 17742\n },\n {\n \"tag\": "psychorrhagic",\n \"popularity\": 17713\n },\n {\n \"tag\": "Monumbo",\n \"popularity\": 17685\n },\n {\n \"tag\": "cloiochoanitic",\n \"popularity\": 17656\n },\n {\n \"tag\": "hant",\n \"popularity\": 17628\n },\n {\n \"tag\": "roily pulldown",\n \"popularity\": 17599\n },\n {\n \"tag\": "recongratulation",\n \"popularity\": 17571\n },\n {\n \"tag\": "Peking",\n \"popularity\": 17543\n },\n {\n \"tag\": "erdvark",\n \"popularity\": 17514\n },\n {\n \"tag\": "antimnemonic",\n \"popularity\": 17486\n },\n {\n \"tag\": "noncapillarity",\n \"popularity\": 17458\n },\n {\n \"tag\": "irrepressive",\n \"popularity\": 17430\n },\n {\n \"tag\": "Petromyzontes",\n \"popularity\": 17402\n },\n {\n \"tag\": "piscatorially",\n \"popularity\": 17374\n },\n {\n \"tag\": "cholesterosis",\n \"popularity\": 17346\n },\n {\n \"tag\": "denunciate",\n \"popularity\": 17319\n },\n {\n \"tag\": "unmetalled",\n \"popularity\": 17291\n },\n {\n \"tag\": "Tigris enruin",\n \"popularity\": 17263\n },\n {\n \"tag\": "anaspalin",\n \"popularity\": 17236\n },\n {\n \"tag\": "monodromy",\n \"popularity\": 17208\n },\n {\n \"tag\": "Canichanan",\n \"popularity\": 17181\n },\n {\n \"tag\": "mesolabe",\n \"popularity\": 17154\n },\n {\n \"tag\": "trichothallic overcunningness",\n \"popularity\": 17127\n },\n {\n \"tag\": "spinsterishly",\n \"popularity\": 17099\n },\n {\n \"tag\": "sensilla",\n \"popularity\": 17072\n },\n {\n \"tag\": "wifelkin",\n \"popularity\": 17045\n },\n {\n \"tag\": "suppositionless",\n \"popularity\": 17018\n },\n {\n \"tag\": "irksomeness",\n \"popularity\": 16991\n },\n {\n \"tag\": "sanbenito",\n \"popularity\": 16964\n },\n {\n \"tag\": "nonstatement",\n \"popularity\": 16938\n },\n {\n \"tag\": "phenoloid",\n \"popularity\": 16911\n },\n {\n \"tag\": "Steinberger",\n \"popularity\": 16884\n },\n {\n \"tag\": "replicated boom",\n \"popularity\": 16858\n },\n {\n \"tag\": "sciomachiology",\n \"popularity\": 16831\n },\n {\n \"tag\": "starwise",\n \"popularity\": 16805\n },\n {\n \"tag\": "prerich",\n \"popularity\": 16778\n },\n {\n \"tag\": "unspawned",\n \"popularity\": 16752\n },\n {\n \"tag\": "unindentable",\n \"popularity\": 16726\n },\n {\n \"tag\": "stromatic",\n \"popularity\": 16700\n },\n {\n \"tag\": "fetishize",\n \"popularity\": 16673\n },\n {\n \"tag\": "dihydroxy",\n \"popularity\": 16647\n },\n {\n \"tag\": "precaudal",\n \"popularity\": 16621\n },\n {\n \"tag\": "Madagascar",\n \"popularity\": 16595\n },\n {\n \"tag\": "repinement",\n \"popularity\": 16570\n },\n {\n \"tag\": "noncathedral wenzel",\n \"popularity\": 16544\n },\n {\n \"tag\": "corollike",\n \"popularity\": 16518\n },\n {\n \"tag\": "pubes unamortization",\n \"popularity\": 16492\n },\n {\n \"tag\": "brickcroft",\n \"popularity\": 16467\n },\n {\n \"tag\": "intertrabecular",\n \"popularity\": 16441\n },\n {\n \"tag\": "formulaic",\n \"popularity\": 16416\n },\n {\n \"tag\": "arienzo",\n \"popularity\": 16390\n },\n {\n \"tag\": "Mazzinian",\n \"popularity\": 16365\n },\n {\n \"tag\": "wallowishly",\n \"popularity\": 16339\n },\n {\n \"tag\": "sysselman",\n \"popularity\": 16314\n },\n {\n \"tag\": "seligmannite",\n \"popularity\": 16289\n },\n {\n \"tag\": "harlequinery",\n \"popularity\": 16264\n },\n {\n \"tag\": "zucchetto",\n \"popularity\": 16239\n },\n {\n \"tag\": "malonyl",\n \"popularity\": 16214\n },\n {\n \"tag\": "patwari",\n \"popularity\": 16189\n },\n {\n \"tag\": "neoholmia venturesomeness",\n \"popularity\": 16164\n },\n {\n \"tag\": "Dehwar",\n \"popularity\": 16139\n },\n {\n \"tag\": "fetiferous",\n \"popularity\": 16114\n },\n {\n \"tag\": "chromatophore",\n \"popularity\": 16090\n },\n {\n \"tag\": "reregistration",\n \"popularity\": 16065\n },\n {\n \"tag\": "alienor",\n \"popularity\": 16040\n },\n {\n \"tag\": "Hexagynia",\n \"popularity\": 16016\n },\n {\n \"tag\": "cerebrotonia",\n \"popularity\": 15991\n },\n {\n \"tag\": "deedbox",\n \"popularity\": 15967\n },\n {\n \"tag\": "staab",\n \"popularity\": 15943\n },\n {\n \"tag\": "uratemia",\n \"popularity\": 15918\n },\n {\n \"tag\": "flaunt",\n \"popularity\": 15894\n },\n {\n \"tag\": "bogy",\n \"popularity\": 15870\n },\n {\n \"tag\": "subcartilaginous",\n \"popularity\": 15846\n },\n {\n \"tag\": "protonephridial",\n \"popularity\": 15822\n },\n {\n \"tag\": "Boswellia",\n \"popularity\": 15798\n },\n {\n \"tag\": "relaxant untiaraed protoepiphyte",\n \"popularity\": 15774\n },\n {\n \"tag\": "nesslerization",\n \"popularity\": 15750\n },\n {\n \"tag\": "precession",\n \"popularity\": 15726\n },\n {\n \"tag\": "peat",\n \"popularity\": 15702\n },\n {\n \"tag\": "unbit",\n \"popularity\": 15678\n },\n {\n \"tag\": "snailish",\n \"popularity\": 15655\n },\n {\n \"tag\": "porismatical",\n \"popularity\": 15631\n },\n {\n \"tag\": "hooflike",\n \"popularity\": 15608\n },\n {\n \"tag\": "resuppose phene cranic",\n \"popularity\": 15584\n },\n {\n \"tag\": "peptonization kipskin",\n \"popularity\": 15561\n },\n {\n \"tag\": "birdstone",\n \"popularity\": 15537\n },\n {\n \"tag\": "empty inferoanterior",\n \"popularity\": 15514\n },\n {\n \"tag\": "androtauric",\n \"popularity\": 15491\n },\n {\n \"tag\": "triamide",\n \"popularity\": 15467\n },\n {\n \"tag\": "showmanry",\n \"popularity\": 15444\n },\n {\n \"tag\": "doing",\n \"popularity\": 15421\n },\n {\n \"tag\": "bouchaleen",\n \"popularity\": 15398\n },\n {\n \"tag\": "precollude",\n \"popularity\": 15375\n },\n {\n \"tag\": "finger",\n \"popularity\": 15352\n },\n {\n \"tag\": "limnetic intermessenger",\n \"popularity\": 15329\n },\n {\n \"tag\": "uncharitable picrotoxic",\n \"popularity\": 15306\n },\n {\n \"tag\": "nationalizer Phasmidae",\n \"popularity\": 15283\n },\n {\n \"tag\": "laughingstock",\n \"popularity\": 15261\n },\n {\n \"tag\": "nondeferential",\n \"popularity\": 15238\n },\n {\n \"tag\": "uproariously",\n \"popularity\": 15215\n },\n {\n \"tag\": "manzanilla",\n \"popularity\": 15193\n },\n {\n \"tag\": "khahoon",\n \"popularity\": 15170\n },\n {\n \"tag\": "olericulturally longshanks",\n \"popularity\": 15148\n },\n {\n \"tag\": "enthusiastically methionic",\n \"popularity\": 15125\n },\n {\n \"tag\": "pobs",\n \"popularity\": 15103\n },\n {\n \"tag\": "tricarpellate",\n \"popularity\": 15081\n },\n {\n \"tag\": "souterrain",\n \"popularity\": 15058\n },\n {\n \"tag\": "tethelin",\n \"popularity\": 15036\n },\n {\n \"tag\": "tartle",\n \"popularity\": 15014\n },\n {\n \"tag\": "tidelike",\n \"popularity\": 14992\n },\n {\n \"tag\": "cosmoramic",\n \"popularity\": 14970\n },\n {\n \"tag\": "pretardiness",\n \"popularity\": 14948\n },\n {\n \"tag\": "insoul",\n \"popularity\": 14926\n },\n {\n \"tag\": "anthroxan",\n \"popularity\": 14904\n },\n {\n \"tag\": "jilter",\n \"popularity\": 14882\n },\n {\n \"tag\": "pectinibranchian trematode",\n \"popularity\": 14860\n },\n {\n \"tag\": "Renaissancist",\n \"popularity\": 14838\n },\n {\n \"tag\": "imaginant",\n \"popularity\": 14817\n },\n {\n \"tag\": "supercensure",\n \"popularity\": 14795\n },\n {\n \"tag\": "festilogy",\n \"popularity\": 14773\n },\n {\n \"tag\": "regression",\n \"popularity\": 14752\n },\n {\n \"tag\": "mesobregmate languorously",\n \"popularity\": 14730\n },\n {\n \"tag\": "unsupernaturalized",\n \"popularity\": 14709\n },\n {\n \"tag\": "boobyish",\n \"popularity\": 14687\n },\n {\n \"tag\": "scopolamine",\n \"popularity\": 14666\n },\n {\n \"tag\": "reamputation unchristianly",\n \"popularity\": 14645\n },\n {\n \"tag\": "cuneatic",\n \"popularity\": 14623\n },\n {\n \"tag\": "heathberry",\n \"popularity\": 14602\n },\n {\n \"tag\": "hate",\n \"popularity\": 14581\n },\n {\n \"tag\": "redeemableness",\n \"popularity\": 14560\n },\n {\n \"tag\": "damasse",\n \"popularity\": 14539\n },\n {\n \"tag\": "thrillsome",\n \"popularity\": 14518\n },\n {\n \"tag\": "disseverment",\n \"popularity\": 14497\n },\n {\n \"tag\": "underbishopric Ostyak",\n \"popularity\": 14476\n },\n {\n \"tag\": "Exoascales",\n \"popularity\": 14455\n },\n {\n \"tag\": "soiled",\n \"popularity\": 14434\n },\n {\n \"tag\": "Cain",\n \"popularity\": 14413\n },\n {\n \"tag\": "mismanageable arenae",\n \"popularity\": 14392\n },\n {\n \"tag\": "manducate unhinderably",\n \"popularity\": 14372\n },\n {\n \"tag\": "peregrin",\n \"popularity\": 14351\n },\n {\n \"tag\": "musicianly",\n \"popularity\": 14330\n },\n {\n \"tag\": "aln",\n \"popularity\": 14310\n },\n {\n \"tag\": "intercentrum",\n \"popularity\": 14289\n },\n {\n \"tag\": "roothold",\n \"popularity\": 14269\n },\n {\n \"tag\": "jane aneurism",\n \"popularity\": 14248\n },\n {\n \"tag\": "insinuatively forefeel phytolatrous",\n \"popularity\": 14228\n },\n {\n \"tag\": "kanchil",\n \"popularity\": 14208\n },\n {\n \"tag\": "Austrophile",\n \"popularity\": 14187\n },\n {\n \"tag\": "unterrorized",\n \"popularity\": 14167\n },\n {\n \"tag\": "admeasure",\n \"popularity\": 14147\n },\n {\n \"tag\": "electrodissolution",\n \"popularity\": 14127\n },\n {\n \"tag\": "unweddedly",\n \"popularity\": 14107\n },\n {\n \"tag\": "unannoying",\n \"popularity\": 14087\n },\n {\n \"tag\": "uningenuous",\n \"popularity\": 14067\n },\n {\n \"tag\": "omnibenevolent",\n \"popularity\": 14047\n },\n {\n \"tag\": "commissure",\n \"popularity\": 14027\n },\n {\n \"tag\": "tellureted",\n \"popularity\": 14007\n },\n {\n \"tag\": "suffragan",\n \"popularity\": 13987\n },\n {\n \"tag\": "sphaeriaceous",\n \"popularity\": 13967\n },\n {\n \"tag\": "unfearing",\n \"popularity\": 13947\n },\n {\n \"tag\": "stentoriousness precounsellor",\n \"popularity\": 13928\n },\n {\n \"tag\": "haemaspectroscope",\n \"popularity\": 13908\n },\n {\n \"tag\": "teras",\n \"popularity\": 13888\n },\n {\n \"tag\": "pulicine",\n \"popularity\": 13869\n },\n {\n \"tag\": "colicystopyelitis",\n \"popularity\": 13849\n },\n {\n \"tag\": "Physalia",\n \"popularity\": 13830\n },\n {\n \"tag\": "Saxicolidae",\n \"popularity\": 13810\n },\n {\n \"tag\": "peritonital",\n \"popularity\": 13791\n },\n {\n \"tag\": "dysphotic",\n \"popularity\": 13771\n },\n {\n \"tag\": "unabandoned",\n \"popularity\": 13752\n },\n {\n \"tag\": "rashful",\n \"popularity\": 13733\n },\n {\n \"tag\": "goodyness Manobo",\n \"popularity\": 13714\n },\n {\n \"tag\": "glaring",\n \"popularity\": 13694\n },\n {\n \"tag\": "horrorful",\n \"popularity\": 13675\n },\n {\n \"tag\": "intercepting",\n \"popularity\": 13656\n },\n {\n \"tag\": "semifine",\n \"popularity\": 13637\n },\n {\n \"tag\": "Gaypoo",\n \"popularity\": 13618\n },\n {\n \"tag\": "Metrosideros",\n \"popularity\": 13599\n },\n {\n \"tag\": "thoracicolumbar",\n \"popularity\": 13580\n },\n {\n \"tag\": "unserried",\n \"popularity\": 13561\n },\n {\n \"tag\": "keeperess cauterization",\n \"popularity\": 13542\n },\n {\n \"tag\": "administrant",\n \"popularity\": 13523\n },\n {\n \"tag\": "unpropitiatedness",\n \"popularity\": 13505\n },\n {\n \"tag\": "pensileness",\n \"popularity\": 13486\n },\n {\n \"tag\": "quinaldic unreceivable",\n \"popularity\": 13467\n },\n {\n \"tag\": "Carnaria",\n \"popularity\": 13448\n },\n {\n \"tag\": "azothionium wurrus",\n \"popularity\": 13430\n },\n {\n \"tag\": "mistresshood",\n \"popularity\": 13411\n },\n {\n \"tag\": "Savara",\n \"popularity\": 13393\n },\n {\n \"tag\": "dasyurine",\n \"popularity\": 13374\n },\n {\n \"tag\": "superideal",\n \"popularity\": 13356\n },\n {\n \"tag\": "Parisianize",\n \"popularity\": 13337\n },\n {\n \"tag\": "underearth",\n \"popularity\": 13319\n },\n {\n \"tag\": "athrogenic",\n \"popularity\": 13301\n },\n {\n \"tag\": "communicate",\n \"popularity\": 13282\n },\n {\n \"tag\": "denervation enworthed",\n \"popularity\": 13264\n },\n {\n \"tag\": "subbromide",\n \"popularity\": 13246\n },\n {\n \"tag\": "stenocoriasis",\n \"popularity\": 13228\n },\n {\n \"tag\": "facetiousness",\n \"popularity\": 13209\n },\n {\n \"tag\": "twaddling",\n \"popularity\": 13191\n },\n {\n \"tag\": "tetartoconid",\n \"popularity\": 13173\n },\n {\n \"tag\": "audiophile",\n \"popularity\": 13155\n },\n {\n \"tag\": "fustigate",\n \"popularity\": 13137\n },\n {\n \"tag\": "Sorbian cacophonia",\n \"popularity\": 13119\n },\n {\n \"tag\": "fondish",\n \"popularity\": 13101\n },\n {\n \"tag\": "endomastoiditis",\n \"popularity\": 13084\n },\n {\n \"tag\": "sniptious",\n \"popularity\": 13066\n },\n {\n \"tag\": "glochidiate",\n \"popularity\": 13048\n },\n {\n \"tag\": "polycarboxylic",\n \"popularity\": 13030\n },\n {\n \"tag\": "stamp",\n \"popularity\": 13012\n },\n {\n \"tag\": "tritonymph endotoxoid",\n \"popularity\": 12995\n },\n {\n \"tag\": "wolfskin",\n \"popularity\": 12977\n },\n {\n \"tag\": "oncosimeter",\n \"popularity\": 12959\n },\n {\n \"tag\": "outward",\n \"popularity\": 12942\n },\n {\n \"tag\": "circumscribed",\n \"popularity\": 12924\n },\n {\n \"tag\": "autohemolytic",\n \"popularity\": 12907\n },\n {\n \"tag\": "isorhamnose",\n \"popularity\": 12889\n },\n {\n \"tag\": "monarchomachic",\n \"popularity\": 12872\n },\n {\n \"tag\": "phaenomenon",\n \"popularity\": 12855\n },\n {\n \"tag\": "angiopressure",\n \"popularity\": 12837\n },\n {\n \"tag\": "similarize",\n \"popularity\": 12820\n },\n {\n \"tag\": "unseeable",\n \"popularity\": 12803\n },\n {\n \"tag\": "Toryize",\n \"popularity\": 12785\n },\n {\n \"tag\": "fruitling",\n \"popularity\": 12768\n },\n {\n \"tag\": "axle",\n \"popularity\": 12751\n },\n {\n \"tag\": "priestal cocked",\n \"popularity\": 12734\n },\n {\n \"tag\": "serotoxin",\n \"popularity\": 12717\n },\n {\n \"tag\": "unmovably",\n \"popularity\": 12700\n },\n {\n \"tag\": "darbha",\n \"popularity\": 12683\n },\n {\n \"tag\": "Mongolize",\n \"popularity\": 12666\n },\n {\n \"tag\": "clusteringly",\n \"popularity\": 12649\n },\n {\n \"tag\": "tendence",\n \"popularity\": 12632\n },\n {\n \"tag\": "foziness",\n \"popularity\": 12615\n },\n {\n \"tag\": "brickkiln lithify",\n \"popularity\": 12598\n },\n {\n \"tag\": "unpriest",\n \"popularity\": 12581\n },\n {\n \"tag\": "convincer",\n \"popularity\": 12564\n },\n {\n \"tag\": "mornlike",\n \"popularity\": 12548\n },\n {\n \"tag\": "overaddiction ostentatiousness",\n \"popularity\": 12531\n },\n {\n \"tag\": "diffusively moccasin pendom",\n \"popularity\": 12514\n },\n {\n \"tag\": "boose",\n \"popularity\": 12498\n },\n {\n \"tag\": "myonosus",\n \"popularity\": 12481\n },\n {\n \"tag\": "handsome",\n \"popularity\": 12464\n },\n {\n \"tag\": "paroxysmic",\n \"popularity\": 12448\n },\n {\n \"tag\": "Ulidian",\n \"popularity\": 12431\n },\n {\n \"tag\": "heartache",\n \"popularity\": 12415\n },\n {\n \"tag\": "torporize",\n \"popularity\": 12398\n },\n {\n \"tag\": "hippish",\n \"popularity\": 12382\n },\n {\n \"tag\": "stigmal militation",\n \"popularity\": 12366\n },\n {\n \"tag\": "matmaker",\n \"popularity\": 12349\n },\n {\n \"tag\": "marantaceous bivoluminous",\n \"popularity\": 12333\n },\n {\n \"tag\": "Uraniidae",\n \"popularity\": 12317\n },\n {\n \"tag\": "risper",\n \"popularity\": 12301\n },\n {\n \"tag\": "tintinnabulation",\n \"popularity\": 12284\n },\n {\n \"tag\": "tributorian",\n \"popularity\": 12268\n },\n {\n \"tag\": "ashamedly",\n \"popularity\": 12252\n },\n {\n \"tag\": "Macrourus",\n \"popularity\": 12236\n },\n {\n \"tag\": "Chora",\n \"popularity\": 12220\n },\n {\n \"tag\": "caul",\n \"popularity\": 12204\n },\n {\n \"tag\": "exsector",\n \"popularity\": 12188\n },\n {\n \"tag\": "acutish",\n \"popularity\": 12172\n },\n {\n \"tag\": "amphichrome",\n \"popularity\": 12156\n },\n {\n \"tag\": "guarder",\n \"popularity\": 12140\n },\n {\n \"tag\": "sculpturally",\n \"popularity\": 12124\n },\n {\n \"tag\": "benightmare",\n \"popularity\": 12108\n },\n {\n \"tag\": "chucky",\n \"popularity\": 12093\n },\n {\n \"tag\": "Venetian",\n \"popularity\": 12077\n },\n {\n \"tag\": "autotheater",\n \"popularity\": 12061\n },\n {\n \"tag\": "planarioid",\n \"popularity\": 12045\n },\n {\n \"tag\": "handkerchiefful",\n \"popularity\": 12030\n },\n {\n \"tag\": "fuliginousness potentize",\n \"popularity\": 12014\n },\n {\n \"tag\": "pantheum",\n \"popularity\": 11998\n },\n {\n \"tag\": "heavyweight",\n \"popularity\": 11983\n },\n {\n \"tag\": "unbrick",\n \"popularity\": 11967\n },\n {\n \"tag\": "duomachy",\n \"popularity\": 11952\n },\n {\n \"tag\": "polyphyodont",\n \"popularity\": 11936\n },\n {\n \"tag\": "hibernacle",\n \"popularity\": 11921\n },\n {\n \"tag\": "undistend",\n \"popularity\": 11905\n },\n {\n \"tag\": "hystericky",\n \"popularity\": 11890\n },\n {\n \"tag\": "paleolimnology",\n \"popularity\": 11875\n },\n {\n \"tag\": "cedarware",\n \"popularity\": 11859\n },\n {\n \"tag\": "overwrested",\n \"popularity\": 11844\n },\n {\n \"tag\": "Syriacism",\n \"popularity\": 11829\n },\n {\n \"tag\": "pretan",\n \"popularity\": 11813\n },\n {\n \"tag\": "formant",\n \"popularity\": 11798\n },\n {\n \"tag\": "pharmacopoeist Fedia",\n \"popularity\": 11783\n },\n {\n \"tag\": "exorcist eerisome",\n \"popularity\": 11768\n },\n {\n \"tag\": "separation",\n \"popularity\": 11753\n },\n {\n \"tag\": "infancy",\n \"popularity\": 11738\n },\n {\n \"tag\": "ecrasite",\n \"popularity\": 11723\n },\n {\n \"tag\": "propolize",\n \"popularity\": 11708\n },\n {\n \"tag\": "uncram phyllin",\n \"popularity\": 11693\n },\n {\n \"tag\": "thymopathy",\n \"popularity\": 11678\n },\n {\n \"tag\": "omniscient",\n \"popularity\": 11663\n },\n {\n \"tag\": "coussinet hazer",\n \"popularity\": 11648\n },\n {\n \"tag\": "contributiveness",\n \"popularity\": 11633\n },\n {\n \"tag\": "septifluous",\n \"popularity\": 11618\n },\n {\n \"tag\": "halfness",\n \"popularity\": 11603\n },\n {\n \"tag\": "tocher",\n \"popularity\": 11589\n },\n {\n \"tag\": "monotonist",\n \"popularity\": 11574\n },\n {\n \"tag\": "headchair",\n \"popularity\": 11559\n },\n {\n \"tag\": "everywhence",\n \"popularity\": 11544\n },\n {\n \"tag\": "gerate",\n \"popularity\": 11530\n },\n {\n \"tag\": "unrepellent",\n \"popularity\": 11515\n },\n {\n \"tag\": "inidoneous",\n \"popularity\": 11500\n },\n {\n \"tag\": "Rifi",\n \"popularity\": 11486\n },\n {\n \"tag\": "unstop",\n \"popularity\": 11471\n },\n {\n \"tag\": "conformer",\n \"popularity\": 11457\n },\n {\n \"tag\": "vivisectionally",\n \"popularity\": 11442\n },\n {\n \"tag\": "nonfinishing",\n \"popularity\": 11428\n },\n {\n \"tag\": "tyranness",\n \"popularity\": 11413\n },\n {\n \"tag\": "shepherdage havoc",\n \"popularity\": 11399\n },\n {\n \"tag\": "coronale",\n \"popularity\": 11385\n },\n {\n \"tag\": "airmarker",\n \"popularity\": 11370\n },\n {\n \"tag\": "subpanel",\n \"popularity\": 11356\n },\n {\n \"tag\": "conciliation",\n \"popularity\": 11342\n },\n {\n \"tag\": "supergun",\n \"popularity\": 11327\n },\n {\n \"tag\": "photoheliography",\n \"popularity\": 11313\n },\n {\n \"tag\": "cacosmia",\n \"popularity\": 11299\n },\n {\n \"tag\": "caressant",\n \"popularity\": 11285\n },\n {\n \"tag\": "swivet",\n \"popularity\": 11270\n },\n {\n \"tag\": "coddler",\n \"popularity\": 11256\n },\n {\n \"tag\": "rakehellish",\n \"popularity\": 11242\n },\n {\n \"tag\": "recohabitation",\n \"popularity\": 11228\n },\n {\n \"tag\": "postillator",\n \"popularity\": 11214\n },\n {\n \"tag\": "receipt",\n \"popularity\": 11200\n },\n {\n \"tag\": "nonconformistical",\n \"popularity\": 11186\n },\n {\n \"tag\": "unglorified",\n \"popularity\": 11172\n },\n {\n \"tag\": "unordinariness",\n \"popularity\": 11158\n },\n {\n \"tag\": "tetrahydroxy",\n \"popularity\": 11144\n },\n {\n \"tag\": "haploperistomic corporeity",\n \"popularity\": 11130\n },\n {\n \"tag\": "varical",\n \"popularity\": 11117\n },\n {\n \"tag\": "pilferment",\n \"popularity\": 11103\n },\n {\n \"tag\": "reverentially playcraft",\n \"popularity\": 11089\n },\n {\n \"tag\": "unretentive",\n \"popularity\": 11075\n },\n {\n \"tag\": "readiness",\n \"popularity\": 11061\n },\n {\n \"tag\": "thermomagnetism",\n \"popularity\": 11048\n },\n {\n \"tag\": "spotless",\n \"popularity\": 11034\n },\n {\n \"tag\": "semishrubby",\n \"popularity\": 11020\n },\n {\n \"tag\": "metrotomy",\n \"popularity\": 11007\n },\n {\n \"tag\": "hocker",\n \"popularity\": 10993\n },\n {\n \"tag\": "anecdotal",\n \"popularity\": 10979\n },\n {\n \"tag\": "tetrabelodont",\n \"popularity\": 10966\n },\n {\n \"tag\": "Ramillied",\n \"popularity\": 10952\n },\n {\n \"tag\": "sympatheticism",\n \"popularity\": 10939\n },\n {\n \"tag\": "kiskatom",\n \"popularity\": 10925\n },\n {\n \"tag\": "concyclically",\n \"popularity\": 10912\n },\n {\n \"tag\": "tunicless",\n \"popularity\": 10899\n },\n {\n \"tag\": "formalistic",\n \"popularity\": 10885\n },\n {\n \"tag\": "thermacogenesis",\n \"popularity\": 10872\n },\n {\n \"tag\": "multimotored",\n \"popularity\": 10858\n },\n {\n \"tag\": "inversive",\n \"popularity\": 10845\n },\n {\n \"tag\": "Jatki",\n \"popularity\": 10832\n },\n {\n \"tag\": "highest",\n \"popularity\": 10818\n },\n {\n \"tag\": "rubidic",\n \"popularity\": 10805\n },\n {\n \"tag\": "acranial",\n \"popularity\": 10792\n },\n {\n \"tag\": "pulvinulus",\n \"popularity\": 10779\n },\n {\n \"tag\": "nattiness",\n \"popularity\": 10766\n },\n {\n \"tag\": "antisimoniacal",\n \"popularity\": 10752\n },\n {\n \"tag\": "tetanize",\n \"popularity\": 10739\n },\n {\n \"tag\": "spectrophobia",\n \"popularity\": 10726\n },\n {\n \"tag\": "monopolitical",\n \"popularity\": 10713\n },\n {\n \"tag\": "teallite",\n \"popularity\": 10700\n },\n {\n \"tag\": "alicyclic interpellator",\n \"popularity\": 10687\n },\n {\n \"tag\": "nonsynthesized",\n \"popularity\": 10674\n },\n {\n \"tag\": "wheelwrighting",\n \"popularity\": 10661\n },\n {\n \"tag\": "pelliculate",\n \"popularity\": 10648\n },\n {\n \"tag\": "Euphyllopoda",\n \"popularity\": 10635\n },\n {\n \"tag\": "graver",\n \"popularity\": 10622\n },\n {\n \"tag\": "automorph",\n \"popularity\": 10609\n },\n {\n \"tag\": "underhanded",\n \"popularity\": 10597\n },\n {\n \"tag\": "causal",\n \"popularity\": 10584\n },\n {\n \"tag\": "odoom",\n \"popularity\": 10571\n },\n {\n \"tag\": "apodictical",\n \"popularity\": 10558\n },\n {\n \"tag\": "foundery",\n \"popularity\": 10545\n },\n {\n \"tag\": "unneighbored",\n \"popularity\": 10533\n },\n {\n \"tag\": "woolshearing",\n \"popularity\": 10520\n },\n {\n \"tag\": "boschveld",\n \"popularity\": 10507\n },\n {\n \"tag\": "unhardened lipopod",\n \"popularity\": 10495\n },\n {\n \"tag\": "unenriching",\n \"popularity\": 10482\n },\n {\n \"tag\": "spak",\n \"popularity\": 10469\n },\n {\n \"tag\": "yogasana",\n \"popularity\": 10457\n },\n {\n \"tag\": "depoetize",\n \"popularity\": 10444\n },\n {\n \"tag\": "parousiamania",\n \"popularity\": 10432\n },\n {\n \"tag\": "longlegs",\n \"popularity\": 10419\n },\n {\n \"tag\": "gelatinizability",\n \"popularity\": 10407\n },\n {\n \"tag\": "edeology",\n \"popularity\": 10394\n },\n {\n \"tag\": "sodwork",\n \"popularity\": 10382\n },\n {\n \"tag\": "somnambule",\n \"popularity\": 10369\n },\n {\n \"tag\": "antiquing",\n \"popularity\": 10357\n },\n {\n \"tag\": "intaker",\n \"popularity\": 10344\n },\n {\n \"tag\": "Gerberia",\n \"popularity\": 10332\n },\n {\n \"tag\": "preadmit",\n \"popularity\": 10320\n },\n {\n \"tag\": "bullhorn",\n \"popularity\": 10307\n },\n {\n \"tag\": "sororal",\n \"popularity\": 10295\n },\n {\n \"tag\": "phaeophyceous",\n \"popularity\": 10283\n },\n {\n \"tag\": "omphalopsychite",\n \"popularity\": 10271\n },\n {\n \"tag\": "substantious",\n \"popularity\": 10258\n },\n {\n \"tag\": "undemonstratively",\n \"popularity\": 10246\n },\n {\n \"tag\": "corallike blackit",\n \"popularity\": 10234\n },\n {\n \"tag\": "amoebous",\n \"popularity\": 10222\n },\n {\n \"tag\": "Polypodium",\n \"popularity\": 10210\n },\n {\n \"tag\": "blodite",\n \"popularity\": 10198\n },\n {\n \"tag\": "hordarian",\n \"popularity\": 10186\n },\n {\n \"tag\": "nonmoral",\n \"popularity\": 10174\n },\n {\n \"tag\": "dredgeful",\n \"popularity\": 10162\n },\n {\n \"tag\": "nourishingly",\n \"popularity\": 10150\n },\n {\n \"tag\": "seamy",\n \"popularity\": 10138\n },\n {\n \"tag\": "vara",\n \"popularity\": 10126\n },\n {\n \"tag\": "incorruptibleness",\n \"popularity\": 10114\n },\n {\n \"tag\": "manipulator",\n \"popularity\": 10102\n },\n {\n \"tag\": "chromodiascope uncountably",\n \"popularity\": 10090\n },\n {\n \"tag\": "typhemia",\n \"popularity\": 10078\n },\n {\n \"tag\": "Smalcaldic",\n \"popularity\": 10066\n },\n {\n \"tag\": "precontrive",\n \"popularity\": 10054\n },\n {\n \"tag\": "sowarry",\n \"popularity\": 10042\n },\n {\n \"tag\": "monopodic",\n \"popularity\": 10031\n },\n {\n \"tag\": "recodify",\n \"popularity\": 10019\n },\n {\n \"tag\": "phosphowolframic rimple",\n \"popularity\": 10007\n },\n {\n \"tag\": "triconch",\n \"popularity\": 9995\n },\n {\n \"tag\": "pycnodontoid",\n \"popularity\": 9984\n },\n {\n \"tag\": "bradyspermatism",\n \"popularity\": 9972\n },\n {\n \"tag\": "extensionist",\n \"popularity\": 9960\n },\n {\n \"tag\": "characterize",\n \"popularity\": 9949\n },\n {\n \"tag\": "anatreptic proteolytic",\n \"popularity\": 9937\n },\n {\n \"tag\": "waterboard",\n \"popularity\": 9925\n },\n {\n \"tag\": "allopathically",\n \"popularity\": 9914\n },\n {\n \"tag\": "arithmetician",\n \"popularity\": 9902\n },\n {\n \"tag\": "subsist",\n \"popularity\": 9891\n },\n {\n \"tag\": "Islamitish",\n \"popularity\": 9879\n },\n {\n \"tag\": "biddy",\n \"popularity\": 9868\n },\n {\n \"tag\": "reverberation",\n \"popularity\": 9856\n },\n {\n \"tag\": "Zaporogue",\n \"popularity\": 9845\n },\n {\n \"tag\": "soapberry",\n \"popularity\": 9833\n },\n {\n \"tag\": "physiognomics",\n \"popularity\": 9822\n },\n {\n \"tag\": "hospitalization",\n \"popularity\": 9810\n },\n {\n \"tag\": "dissembler",\n \"popularity\": 9799\n },\n {\n \"tag\": "festinate",\n \"popularity\": 9788\n },\n {\n \"tag\": "angiectopia",\n \"popularity\": 9776\n },\n {\n \"tag\": "Pulicidae",\n \"popularity\": 9765\n },\n {\n \"tag\": "beslimer",\n \"popularity\": 9754\n },\n {\n \"tag\": "nontreaty",\n \"popularity\": 9743\n },\n {\n \"tag\": "unhaggled",\n \"popularity\": 9731\n },\n {\n \"tag\": "catfall",\n \"popularity\": 9720\n },\n {\n \"tag\": "stola",\n \"popularity\": 9709\n },\n {\n \"tag\": "pataco",\n \"popularity\": 9698\n },\n {\n \"tag\": "ontologistic",\n \"popularity\": 9686\n },\n {\n \"tag\": "aerosphere",\n \"popularity\": 9675\n },\n {\n \"tag\": "deobstruent",\n \"popularity\": 9664\n },\n {\n \"tag\": "threepence",\n \"popularity\": 9653\n },\n {\n \"tag\": "cyprinoid",\n \"popularity\": 9642\n },\n {\n \"tag\": "overbank",\n \"popularity\": 9631\n },\n {\n \"tag\": "prostyle",\n \"popularity\": 9620\n },\n {\n \"tag\": "photoactivation",\n \"popularity\": 9609\n },\n {\n \"tag\": "homothetic",\n \"popularity\": 9598\n },\n {\n \"tag\": "roguedom",\n \"popularity\": 9587\n },\n {\n \"tag\": "underschool",\n \"popularity\": 9576\n },\n {\n \"tag\": "tractility",\n \"popularity\": 9565\n },\n {\n \"tag\": "gardenin",\n \"popularity\": 9554\n },\n {\n \"tag\": "Micromastictora",\n \"popularity\": 9543\n },\n {\n \"tag\": "gossypine",\n \"popularity\": 9532\n },\n {\n \"tag\": "amylodyspepsia",\n \"popularity\": 9521\n },\n {\n \"tag\": "Luciana",\n \"popularity\": 9510\n },\n {\n \"tag\": "meetly nonfisherman",\n \"popularity\": 9500\n },\n {\n \"tag\": "backhanded",\n \"popularity\": 9489\n },\n {\n \"tag\": "decrustation",\n \"popularity\": 9478\n },\n {\n \"tag\": "pinrail",\n \"popularity\": 9467\n },\n {\n \"tag\": "Mahori",\n \"popularity\": 9456\n },\n {\n \"tag\": "unsizable",\n \"popularity\": 9446\n },\n {\n \"tag\": "disawa",\n \"popularity\": 9435\n },\n {\n \"tag\": "launderability inconsidered",\n \"popularity\": 9424\n },\n {\n \"tag\": "unclassical",\n \"popularity\": 9414\n },\n {\n \"tag\": "inobtrusiveness",\n \"popularity\": 9403\n },\n {\n \"tag\": "sialogenous",\n \"popularity\": 9392\n },\n {\n \"tag\": "sulphonamide",\n \"popularity\": 9382\n },\n {\n \"tag\": "diluvion",\n \"popularity\": 9371\n },\n {\n \"tag\": "deuteranope",\n \"popularity\": 9361\n },\n {\n \"tag\": "addition",\n \"popularity\": 9350\n },\n {\n \"tag\": "bockeret",\n \"popularity\": 9339\n },\n {\n \"tag\": "unidentified",\n \"popularity\": 9329\n },\n {\n \"tag\": "caryatic",\n \"popularity\": 9318\n },\n {\n \"tag\": "misattribution",\n \"popularity\": 9308\n },\n {\n \"tag\": "outray",\n \"popularity\": 9297\n },\n {\n \"tag\": "areometrical",\n \"popularity\": 9287\n },\n {\n \"tag\": "antilogism",\n \"popularity\": 9277\n },\n {\n \"tag\": "inadjustable",\n \"popularity\": 9266\n },\n {\n \"tag\": "byssus",\n \"popularity\": 9256\n },\n {\n \"tag\": "trun",\n \"popularity\": 9245\n },\n {\n \"tag\": "thereology",\n \"popularity\": 9235\n },\n {\n \"tag\": "extort",\n \"popularity\": 9225\n },\n {\n \"tag\": "bumpkin",\n \"popularity\": 9214\n },\n {\n \"tag\": "sulphobenzide",\n \"popularity\": 9204\n },\n {\n \"tag\": "hydrogeology",\n \"popularity\": 9194\n },\n {\n \"tag\": "nidulariaceous",\n \"popularity\": 9183\n },\n {\n \"tag\": "propodiale",\n \"popularity\": 9173\n },\n {\n \"tag\": "fierily",\n \"popularity\": 9163\n },\n {\n \"tag\": "aerotonometry",\n \"popularity\": 9153\n },\n {\n \"tag\": "pelobatid oversuperstitious",\n \"popularity\": 9142\n },\n {\n \"tag\": "restringent",\n \"popularity\": 9132\n },\n {\n \"tag\": "tetrapodic",\n \"popularity\": 9122\n },\n {\n \"tag\": "heroicness Vendidad",\n \"popularity\": 9112\n },\n {\n \"tag\": "Sphingurus",\n \"popularity\": 9102\n },\n {\n \"tag\": "sclerote",\n \"popularity\": 9092\n },\n {\n \"tag\": "unkeyed",\n \"popularity\": 9082\n },\n {\n \"tag\": "superparliamentary",\n \"popularity\": 9072\n },\n {\n \"tag\": "hetericism",\n \"popularity\": 9061\n },\n {\n \"tag\": "hucklebone",\n \"popularity\": 9051\n },\n {\n \"tag\": "yojan",\n \"popularity\": 9041\n },\n {\n \"tag\": "bossed",\n \"popularity\": 9031\n },\n {\n \"tag\": "spiderwork",\n \"popularity\": 9021\n },\n {\n \"tag\": "millfeed dullery",\n \"popularity\": 9011\n },\n {\n \"tag\": "adnoun",\n \"popularity\": 9001\n },\n {\n \"tag\": "mesometric",\n \"popularity\": 8992\n },\n {\n \"tag\": "doublehandedness",\n \"popularity\": 8982\n },\n {\n \"tag\": "suppurant",\n \"popularity\": 8972\n },\n {\n \"tag\": "Berlinize",\n \"popularity\": 8962\n },\n {\n \"tag\": "sontag",\n \"popularity\": 8952\n },\n {\n \"tag\": "biplane",\n \"popularity\": 8942\n },\n {\n \"tag\": "insula",\n \"popularity\": 8932\n },\n {\n \"tag\": "unbrand",\n \"popularity\": 8922\n },\n {\n \"tag\": "Basilosaurus",\n \"popularity\": 8913\n },\n {\n \"tag\": "prenomination",\n \"popularity\": 8903\n },\n {\n \"tag\": "untextual",\n \"popularity\": 8893\n },\n {\n \"tag\": "coleslaw",\n \"popularity\": 8883\n },\n {\n \"tag\": "langsyne",\n \"popularity\": 8874\n },\n {\n \"tag\": "impede",\n \"popularity\": 8864\n },\n {\n \"tag\": "irrigator",\n \"popularity\": 8854\n },\n {\n \"tag\": "deflocculation",\n \"popularity\": 8844\n },\n {\n \"tag\": "narghile",\n \"popularity\": 8835\n },\n {\n \"tag\": "unguardedly ebenaceous",\n \"popularity\": 8825\n },\n {\n \"tag\": "conversantly subocular",\n \"popularity\": 8815\n },\n {\n \"tag\": "hydroponic",\n \"popularity\": 8806\n },\n {\n \"tag\": "anthropopsychism",\n \"popularity\": 8796\n },\n {\n \"tag\": "panoptic",\n \"popularity\": 8787\n },\n {\n \"tag\": "insufferable",\n \"popularity\": 8777\n },\n {\n \"tag\": "salema",\n \"popularity\": 8768\n },\n {\n \"tag\": "Myriapoda",\n \"popularity\": 8758\n },\n {\n \"tag\": "regarrison",\n \"popularity\": 8748\n },\n {\n \"tag\": "overlearned",\n \"popularity\": 8739\n },\n {\n \"tag\": "ultraroyalist conventical bureaucratical",\n \"popularity\": 8729\n },\n {\n \"tag\": "epicaridan",\n \"popularity\": 8720\n },\n {\n \"tag\": "poetastress",\n \"popularity\": 8711\n },\n {\n \"tag\": "monophthalmus",\n \"popularity\": 8701\n },\n {\n \"tag\": "simnel",\n \"popularity\": 8692\n },\n {\n \"tag\": "compotor",\n \"popularity\": 8682\n },\n {\n \"tag\": "hydrolase",\n \"popularity\": 8673\n },\n {\n \"tag\": "attemptless",\n \"popularity\": 8663\n },\n {\n \"tag\": "visceroptosis",\n \"popularity\": 8654\n },\n {\n \"tag\": "unpreparedly",\n \"popularity\": 8645\n },\n {\n \"tag\": "mastage",\n \"popularity\": 8635\n },\n {\n \"tag\": "preinfluence",\n \"popularity\": 8626\n },\n {\n \"tag\": "Siwan",\n \"popularity\": 8617\n },\n {\n \"tag\": "ceratotheca belvedere",\n \"popularity\": 8607\n },\n {\n \"tag\": "disenablement",\n \"popularity\": 8598\n },\n {\n \"tag\": "nine",\n \"popularity\": 8589\n },\n {\n \"tag\": "spellingdown abridgment",\n \"popularity\": 8580\n },\n {\n \"tag\": "twilightless",\n \"popularity\": 8571\n },\n {\n \"tag\": "overflow",\n \"popularity\": 8561\n },\n {\n \"tag\": "mismeasurement",\n \"popularity\": 8552\n },\n {\n \"tag\": "nawabship",\n \"popularity\": 8543\n },\n {\n \"tag\": "Phrynosoma",\n \"popularity\": 8534\n },\n {\n \"tag\": "unanticipatingly",\n \"popularity\": 8525\n },\n {\n \"tag\": "blankite",\n \"popularity\": 8516\n },\n {\n \"tag\": "role",\n \"popularity\": 8506\n },\n {\n \"tag\": "peperine edelweiss",\n \"popularity\": 8497\n },\n {\n \"tag\": "unhysterical",\n \"popularity\": 8488\n },\n {\n \"tag\": "attentiveness",\n \"popularity\": 8479\n },\n {\n \"tag\": "scintillant",\n \"popularity\": 8470\n },\n {\n \"tag\": "stenostomatous",\n \"popularity\": 8461\n },\n {\n \"tag\": "pectinite",\n \"popularity\": 8452\n },\n {\n \"tag\": "herring",\n \"popularity\": 8443\n },\n {\n \"tag\": "interroom",\n \"popularity\": 8434\n },\n {\n \"tag\": "laccol",\n \"popularity\": 8425\n },\n {\n \"tag\": "unpartably kylite",\n \"popularity\": 8416\n },\n {\n \"tag\": "spirivalve",\n \"popularity\": 8407\n },\n {\n \"tag\": "hoosegow",\n \"popularity\": 8398\n },\n {\n \"tag\": "doat",\n \"popularity\": 8389\n },\n {\n \"tag\": "amphibian",\n \"popularity\": 8380\n },\n {\n \"tag\": "exposit",\n \"popularity\": 8371\n },\n {\n \"tag\": "canopy",\n \"popularity\": 8363\n },\n {\n \"tag\": "houndlike",\n \"popularity\": 8354\n },\n {\n \"tag\": "spikebill",\n \"popularity\": 8345\n },\n {\n \"tag\": "wiseacre pyrotechnic",\n \"popularity\": 8336\n },\n {\n \"tag\": "confessingly woodman",\n \"popularity\": 8327\n },\n {\n \"tag\": "overside",\n \"popularity\": 8318\n },\n {\n \"tag\": "oftwhiles",\n \"popularity\": 8310\n },\n {\n \"tag\": "Musophagidae",\n \"popularity\": 8301\n },\n {\n \"tag\": "slumberer",\n \"popularity\": 8292\n },\n {\n \"tag\": "leiotrichy",\n \"popularity\": 8283\n },\n {\n \"tag\": "Mantispidae",\n \"popularity\": 8275\n },\n {\n \"tag\": "perceptually",\n \"popularity\": 8266\n },\n {\n \"tag\": "biller",\n \"popularity\": 8257\n },\n {\n \"tag\": "eudaemonical",\n \"popularity\": 8249\n },\n {\n \"tag\": "underfiend",\n \"popularity\": 8240\n },\n {\n \"tag\": "impartible",\n \"popularity\": 8231\n },\n {\n \"tag\": "saxicavous",\n \"popularity\": 8223\n },\n {\n \"tag\": "yapster",\n \"popularity\": 8214\n },\n {\n \"tag\": "aliseptal",\n \"popularity\": 8205\n },\n {\n \"tag\": "omniparient",\n \"popularity\": 8197\n },\n {\n \"tag\": "nishiki",\n \"popularity\": 8188\n },\n {\n \"tag\": "yuzluk",\n \"popularity\": 8180\n },\n {\n \"tag\": "solderer",\n \"popularity\": 8171\n },\n {\n \"tag\": "Pinna",\n \"popularity\": 8162\n },\n {\n \"tag\": "reinterfere",\n \"popularity\": 8154\n },\n {\n \"tag\": "superepic",\n \"popularity\": 8145\n },\n {\n \"tag\": "ronquil",\n \"popularity\": 8137\n },\n {\n \"tag\": "bratstvo",\n \"popularity\": 8128\n },\n {\n \"tag\": "Thea",\n \"popularity\": 8120\n },\n {\n \"tag\": "hermaphroditical",\n \"popularity\": 8111\n },\n {\n \"tag\": "enlief",\n \"popularity\": 8103\n },\n {\n \"tag\": "Jesuate",\n \"popularity\": 8095\n },\n {\n \"tag\": "gaysome",\n \"popularity\": 8086\n },\n {\n \"tag\": "iliohypogastric",\n \"popularity\": 8078\n },\n {\n \"tag\": "regardance",\n \"popularity\": 8069\n },\n {\n \"tag\": "cumulately",\n \"popularity\": 8061\n },\n {\n \"tag\": "haustorial nucleolocentrosome",\n \"popularity\": 8053\n },\n {\n \"tag\": "cosmocrat",\n \"popularity\": 8044\n },\n {\n \"tag\": "onyxitis",\n \"popularity\": 8036\n },\n {\n \"tag\": "Cabinda",\n \"popularity\": 8028\n },\n {\n \"tag\": "coresort",\n \"popularity\": 8019\n },\n {\n \"tag\": "drusy preformant",\n \"popularity\": 8011\n },\n {\n \"tag\": "piningly",\n \"popularity\": 8003\n },\n {\n \"tag\": "bootlessly",\n \"popularity\": 7994\n },\n {\n \"tag\": "talari",\n \"popularity\": 7986\n },\n {\n \"tag\": "amidoacetal",\n \"popularity\": 7978\n },\n {\n \"tag\": "pschent",\n \"popularity\": 7970\n },\n {\n \"tag\": "consumptional scarer titivate",\n \"popularity\": 7962\n },\n {\n \"tag\": "Anserinae",\n \"popularity\": 7953\n },\n {\n \"tag\": "flaunter",\n \"popularity\": 7945\n },\n {\n \"tag\": "reindeer",\n \"popularity\": 7937\n },\n {\n \"tag\": "disparage",\n \"popularity\": 7929\n },\n {\n \"tag\": "superheat",\n \"popularity\": 7921\n },\n {\n \"tag\": "Chromatium",\n \"popularity\": 7912\n },\n {\n \"tag\": "Tina",\n \"popularity\": 7904\n },\n {\n \"tag\": "rededicatory",\n \"popularity\": 7896\n },\n {\n \"tag\": "nontransient",\n \"popularity\": 7888\n },\n {\n \"tag\": "Phocaean brinkless",\n \"popularity\": 7880\n },\n {\n \"tag\": "ventriculose",\n \"popularity\": 7872\n },\n {\n \"tag\": "upplough",\n \"popularity\": 7864\n },\n {\n \"tag\": "succorless",\n \"popularity\": 7856\n },\n {\n \"tag\": "hayrake",\n \"popularity\": 7848\n },\n {\n \"tag\": "merriness amorphia",\n \"popularity\": 7840\n },\n {\n \"tag\": "merycism",\n \"popularity\": 7832\n },\n {\n \"tag\": "checkrow",\n \"popularity\": 7824\n },\n {\n \"tag\": "scry",\n \"popularity\": 7816\n },\n {\n \"tag\": "obvolve",\n \"popularity\": 7808\n },\n {\n \"tag\": "orchard",\n \"popularity\": 7800\n },\n {\n \"tag\": "isomerize",\n \"popularity\": 7792\n },\n {\n \"tag\": "competitrix",\n \"popularity\": 7784\n },\n {\n \"tag\": "unbannered",\n \"popularity\": 7776\n },\n {\n \"tag\": "undoctrined",\n \"popularity\": 7768\n },\n {\n \"tag\": "theologian",\n \"popularity\": 7760\n },\n {\n \"tag\": "nebby",\n \"popularity\": 7752\n },\n {\n \"tag\": "Cardiazol",\n \"popularity\": 7745\n },\n {\n \"tag\": "phagedenic",\n \"popularity\": 7737\n },\n {\n \"tag\": "nostalgic",\n \"popularity\": 7729\n },\n {\n \"tag\": "orthodoxy",\n \"popularity\": 7721\n },\n {\n \"tag\": "oversanguine",\n \"popularity\": 7713\n },\n {\n \"tag\": "lish",\n \"popularity\": 7705\n },\n {\n \"tag\": "ketogenic",\n \"popularity\": 7698\n },\n {\n \"tag\": "syndicalize",\n \"popularity\": 7690\n },\n {\n \"tag\": "leeftail",\n \"popularity\": 7682\n },\n {\n \"tag\": "bulbomedullary",\n \"popularity\": 7674\n },\n {\n \"tag\": "reletter",\n \"popularity\": 7667\n },\n {\n \"tag\": "bitterly",\n \"popularity\": 7659\n },\n {\n \"tag\": "participatory",\n \"popularity\": 7651\n },\n {\n \"tag\": "baldberry",\n \"popularity\": 7643\n },\n {\n \"tag\": "prowaterpower",\n \"popularity\": 7636\n },\n {\n \"tag\": "lexicographical",\n \"popularity\": 7628\n },\n {\n \"tag\": "Anisodactyli",\n \"popularity\": 7620\n },\n {\n \"tag\": "amphipodous",\n \"popularity\": 7613\n },\n {\n \"tag\": "triglandular",\n \"popularity\": 7605\n },\n {\n \"tag\": "xanthopsin",\n \"popularity\": 7597\n },\n {\n \"tag\": "indefinitude",\n \"popularity\": 7590\n },\n {\n \"tag\": "bookworm",\n \"popularity\": 7582\n },\n {\n \"tag\": "suffocative",\n \"popularity\": 7574\n },\n {\n \"tag\": "uncongested tyrant",\n \"popularity\": 7567\n },\n {\n \"tag\": "alow harmoniously Pamir",\n \"popularity\": 7559\n },\n {\n \"tag\": "monander",\n \"popularity\": 7552\n },\n {\n \"tag\": "bagatelle",\n \"popularity\": 7544\n },\n {\n \"tag\": "membranology",\n \"popularity\": 7537\n },\n {\n \"tag\": "parturifacient",\n \"popularity\": 7529\n },\n {\n \"tag\": "excitovascular",\n \"popularity\": 7522\n },\n {\n \"tag\": "homopolar",\n \"popularity\": 7514\n },\n {\n \"tag\": "phobiac",\n \"popularity\": 7507\n },\n {\n \"tag\": "clype",\n \"popularity\": 7499\n },\n {\n \"tag\": "unsubversive",\n \"popularity\": 7492\n },\n {\n \"tag\": "bostrychoidal scorpionwort",\n \"popularity\": 7484\n },\n {\n \"tag\": "biliteralism",\n \"popularity\": 7477\n },\n {\n \"tag\": "dentatocostate",\n \"popularity\": 7469\n },\n {\n \"tag\": "Pici",\n \"popularity\": 7462\n },\n {\n \"tag\": "sideritic",\n \"popularity\": 7454\n },\n {\n \"tag\": "syntaxis",\n \"popularity\": 7447\n },\n {\n \"tag\": "ingest",\n \"popularity\": 7440\n },\n {\n \"tag\": "rigmarolish",\n \"popularity\": 7432\n },\n {\n \"tag\": "ocreaceous",\n \"popularity\": 7425\n },\n {\n \"tag\": "hyperbrachyskelic",\n \"popularity\": 7418\n },\n {\n \"tag\": "basophobia",\n \"popularity\": 7410\n },\n {\n \"tag\": "substantialness",\n \"popularity\": 7403\n },\n {\n \"tag\": "agglutinoid",\n \"popularity\": 7396\n },\n {\n \"tag\": "longleaf",\n \"popularity\": 7388\n },\n {\n \"tag\": "electroengraving",\n \"popularity\": 7381\n },\n {\n \"tag\": "laparoenterotomy",\n \"popularity\": 7374\n },\n {\n \"tag\": "oxalylurea",\n \"popularity\": 7366\n },\n {\n \"tag\": "unattaintedly",\n \"popularity\": 7359\n },\n {\n \"tag\": "pennystone",\n \"popularity\": 7352\n },\n {\n \"tag\": "Plumbaginaceae",\n \"popularity\": 7345\n },\n {\n \"tag\": "horntip",\n \"popularity\": 7337\n },\n {\n \"tag\": "begrudge",\n \"popularity\": 7330\n },\n {\n \"tag\": "bechignoned",\n \"popularity\": 7323\n },\n {\n \"tag\": "hologonidium",\n \"popularity\": 7316\n },\n {\n \"tag\": "Pulian",\n \"popularity\": 7309\n },\n {\n \"tag\": "gratulation",\n \"popularity\": 7301\n },\n {\n \"tag\": "Sebright",\n \"popularity\": 7294\n },\n {\n \"tag\": "coinstantaneous emotionally",\n \"popularity\": 7287\n },\n {\n \"tag\": "thoracostracan",\n \"popularity\": 7280\n },\n {\n \"tag\": "saurodont",\n \"popularity\": 7273\n },\n {\n \"tag\": "coseat",\n \"popularity\": 7266\n },\n {\n \"tag\": "irascibility",\n \"popularity\": 7259\n },\n {\n \"tag\": "occlude",\n \"popularity\": 7251\n },\n {\n \"tag\": "metallurgist",\n \"popularity\": 7244\n },\n {\n \"tag\": "extraviolet",\n \"popularity\": 7237\n },\n {\n \"tag\": "clinic",\n \"popularity\": 7230\n },\n {\n \"tag\": "skater",\n \"popularity\": 7223\n },\n {\n \"tag\": "linguistic",\n \"popularity\": 7216\n },\n {\n \"tag\": "attacheship",\n \"popularity\": 7209\n },\n {\n \"tag\": "Rachianectes",\n \"popularity\": 7202\n },\n {\n \"tag\": "foliolose",\n \"popularity\": 7195\n },\n {\n \"tag\": "claudetite",\n \"popularity\": 7188\n },\n {\n \"tag\": "aphidian scratching",\n \"popularity\": 7181\n },\n {\n \"tag\": "Carida",\n \"popularity\": 7174\n },\n {\n \"tag\": "tiepin polymicroscope",\n \"popularity\": 7167\n },\n {\n \"tag\": "telpherage",\n \"popularity\": 7160\n },\n {\n \"tag\": "meek",\n \"popularity\": 7153\n },\n {\n \"tag\": "swiftness",\n \"popularity\": 7146\n },\n {\n \"tag\": "gentes",\n \"popularity\": 7139\n },\n {\n \"tag\": "uncommemorated",\n \"popularity\": 7132\n },\n {\n \"tag\": "Lazarus",\n \"popularity\": 7125\n },\n {\n \"tag\": "redivive",\n \"popularity\": 7119\n },\n {\n \"tag\": "nonfebrile",\n \"popularity\": 7112\n },\n {\n \"tag\": "nymphet",\n \"popularity\": 7105\n },\n {\n \"tag\": "areologically",\n \"popularity\": 7098\n },\n {\n \"tag\": "undonkey",\n \"popularity\": 7091\n },\n {\n \"tag\": "projecting",\n \"popularity\": 7084\n },\n {\n \"tag\": "pinnigrade",\n \"popularity\": 7077\n },\n {\n \"tag\": "butylation",\n \"popularity\": 7071\n },\n {\n \"tag\": "philologistic lenticle",\n \"popularity\": 7064\n },\n {\n \"tag\": "nooky",\n \"popularity\": 7057\n },\n {\n \"tag\": "incestuousness",\n \"popularity\": 7050\n },\n {\n \"tag\": "palingenetically",\n \"popularity\": 7043\n },\n {\n \"tag\": "mitochondria",\n \"popularity\": 7037\n },\n {\n \"tag\": "truthify",\n \"popularity\": 7030\n },\n {\n \"tag\": "titanyl",\n \"popularity\": 7023\n },\n {\n \"tag\": "bestride",\n \"popularity\": 7016\n },\n {\n \"tag\": "chende",\n \"popularity\": 7010\n },\n {\n \"tag\": "Chaucerian monophote",\n \"popularity\": 7003\n },\n {\n \"tag\": "cutback",\n \"popularity\": 6996\n },\n {\n \"tag\": "unpatiently",\n \"popularity\": 6989\n },\n {\n \"tag\": "subvitreous",\n \"popularity\": 6983\n },\n {\n \"tag\": "organizable",\n \"popularity\": 6976\n },\n {\n \"tag\": "anniverse uncomprehensible",\n \"popularity\": 6969\n },\n {\n \"tag\": "hyalescence",\n \"popularity\": 6963\n },\n {\n \"tag\": "amniochorial",\n \"popularity\": 6956\n },\n {\n \"tag\": "Corybantian",\n \"popularity\": 6949\n },\n {\n \"tag\": "genocide Scaphitidae",\n \"popularity\": 6943\n },\n {\n \"tag\": "accordionist",\n \"popularity\": 6936\n },\n {\n \"tag\": "becheck",\n \"popularity\": 6930\n },\n {\n \"tag\": "overproduce",\n \"popularity\": 6923\n },\n {\n \"tag\": "unmaniac frijolillo",\n \"popularity\": 6916\n },\n {\n \"tag\": "multisulcated",\n \"popularity\": 6910\n },\n {\n \"tag\": "wennebergite",\n \"popularity\": 6903\n },\n {\n \"tag\": "tautousious mowth",\n \"popularity\": 6897\n },\n {\n \"tag\": "marigold",\n \"popularity\": 6890\n },\n {\n \"tag\": "affray",\n \"popularity\": 6884\n },\n {\n \"tag\": "nonidolatrous",\n \"popularity\": 6877\n },\n {\n \"tag\": "aphrasia",\n \"popularity\": 6871\n },\n {\n \"tag\": "muddlingly",\n \"popularity\": 6864\n },\n {\n \"tag\": "clear",\n \"popularity\": 6858\n },\n {\n \"tag\": "Clitoria",\n \"popularity\": 6851\n },\n {\n \"tag\": "apportionment underwaist",\n \"popularity\": 6845\n },\n {\n \"tag\": "kodakist",\n \"popularity\": 6838\n },\n {\n \"tag\": "Momotidae",\n \"popularity\": 6832\n },\n {\n \"tag\": "cryptovalency",\n \"popularity\": 6825\n },\n {\n \"tag\": "floe",\n \"popularity\": 6819\n },\n {\n \"tag\": "aphagia",\n \"popularity\": 6812\n },\n {\n \"tag\": "brontograph",\n \"popularity\": 6806\n },\n {\n \"tag\": "tubulous",\n \"popularity\": 6799\n },\n {\n \"tag\": "unhorse",\n \"popularity\": 6793\n },\n {\n \"tag\": "chlordane",\n \"popularity\": 6787\n },\n {\n \"tag\": "colloquy brochan",\n \"popularity\": 6780\n },\n {\n \"tag\": "sloosh",\n \"popularity\": 6774\n },\n {\n \"tag\": "battered",\n \"popularity\": 6767\n },\n {\n \"tag\": "monocularity pluriguttulate",\n \"popularity\": 6761\n },\n {\n \"tag\": "chiastoneury",\n \"popularity\": 6755\n },\n {\n \"tag\": "Sanguinaria",\n \"popularity\": 6748\n },\n {\n \"tag\": "confessionary",\n \"popularity\": 6742\n },\n {\n \"tag\": "enzymic",\n \"popularity\": 6736\n },\n {\n \"tag\": "cord",\n \"popularity\": 6729\n },\n {\n \"tag\": "oviducal",\n \"popularity\": 6723\n },\n {\n \"tag\": "crozzle outsea",\n \"popularity\": 6717\n },\n {\n \"tag\": "balladical",\n \"popularity\": 6710\n },\n {\n \"tag\": "uncollectibleness",\n \"popularity\": 6704\n },\n {\n \"tag\": "predorsal",\n \"popularity\": 6698\n },\n {\n \"tag\": "reauthenticate",\n \"popularity\": 6692\n },\n {\n \"tag\": "ravissant",\n \"popularity\": 6685\n },\n {\n \"tag\": "advantageousness",\n \"popularity\": 6679\n },\n {\n \"tag\": "rung",\n \"popularity\": 6673\n },\n {\n \"tag\": "duncedom",\n \"popularity\": 6667\n },\n {\n \"tag\": "hematolite",\n \"popularity\": 6660\n },\n {\n \"tag\": "thisness",\n \"popularity\": 6654\n },\n {\n \"tag\": "mapau",\n \"popularity\": 6648\n },\n {\n \"tag\": "Hecatic",\n \"popularity\": 6642\n },\n {\n \"tag\": "meningoencephalocele",\n \"popularity\": 6636\n },\n {\n \"tag\": "confection sorra",\n \"popularity\": 6630\n },\n {\n \"tag\": "unsedate",\n \"popularity\": 6623\n },\n {\n \"tag\": "meningocerebritis",\n \"popularity\": 6617\n },\n {\n \"tag\": "biopsychological",\n \"popularity\": 6611\n },\n {\n \"tag\": "clavicithern",\n \"popularity\": 6605\n },\n {\n \"tag\": "resun",\n \"popularity\": 6599\n },\n {\n \"tag\": "bayamo",\n \"popularity\": 6593\n },\n {\n \"tag\": "seeableness",\n \"popularity\": 6587\n },\n {\n \"tag\": "hypsidolichocephalism",\n \"popularity\": 6581\n },\n {\n \"tag\": "salivous",\n \"popularity\": 6574\n },\n {\n \"tag\": "neumatize",\n \"popularity\": 6568\n },\n {\n \"tag\": "stree",\n \"popularity\": 6562\n },\n {\n \"tag\": "markshot",\n \"popularity\": 6556\n },\n {\n \"tag\": "phraseologically",\n \"popularity\": 6550\n },\n {\n \"tag\": "yealing",\n \"popularity\": 6544\n },\n {\n \"tag\": "puggy",\n \"popularity\": 6538\n },\n {\n \"tag\": "sexadecimal",\n \"popularity\": 6532\n },\n {\n \"tag\": "unofficerlike",\n \"popularity\": 6526\n },\n {\n \"tag\": "curiosa",\n \"popularity\": 6520\n },\n {\n \"tag\": "pedomotor",\n \"popularity\": 6514\n },\n {\n \"tag\": "astrally",\n \"popularity\": 6508\n },\n {\n \"tag\": "prosomatic",\n \"popularity\": 6502\n },\n {\n \"tag\": "bulletheaded",\n \"popularity\": 6496\n },\n {\n \"tag\": "fortuned",\n \"popularity\": 6490\n },\n {\n \"tag\": "pixy",\n \"popularity\": 6484\n },\n {\n \"tag\": "protectrix",\n \"popularity\": 6478\n },\n {\n \"tag\": "arthritical",\n \"popularity\": 6472\n },\n {\n \"tag\": "coction",\n \"popularity\": 6466\n },\n {\n \"tag\": "Anthropos",\n \"popularity\": 6460\n },\n {\n \"tag\": "runer",\n \"popularity\": 6454\n },\n {\n \"tag\": "prenotify",\n \"popularity\": 6449\n },\n {\n \"tag\": "microspheric gastroparalysis",\n \"popularity\": 6443\n },\n {\n \"tag\": "Jovicentrical",\n \"popularity\": 6437\n },\n {\n \"tag\": "ceratopsid",\n \"popularity\": 6431\n },\n {\n \"tag\": "Theodoric",\n \"popularity\": 6425\n },\n {\n \"tag\": "Pactolus",\n \"popularity\": 6419\n },\n {\n \"tag\": "spawning",\n \"popularity\": 6413\n },\n {\n \"tag\": "nonconfidential",\n \"popularity\": 6407\n },\n {\n \"tag\": "halotrichite infumate",\n \"popularity\": 6402\n },\n {\n \"tag\": "undiscriminatingly",\n \"popularity\": 6396\n },\n {\n \"tag\": "unexasperated",\n \"popularity\": 6390\n },\n {\n \"tag\": "isoeugenol",\n \"popularity\": 6384\n },\n {\n \"tag\": "pressboard",\n \"popularity\": 6378\n },\n {\n \"tag\": "unshrew",\n \"popularity\": 6372\n },\n {\n \"tag\": "huffingly",\n \"popularity\": 6367\n },\n {\n \"tag\": "wagaun",\n \"popularity\": 6361\n },\n {\n \"tag\": "squirt Philistine",\n \"popularity\": 6355\n },\n {\n \"tag\": "kryptic",\n \"popularity\": 6349\n },\n {\n \"tag\": "paraform",\n \"popularity\": 6344\n },\n {\n \"tag\": "preverify",\n \"popularity\": 6338\n },\n {\n \"tag\": "dalar",\n \"popularity\": 6332\n },\n {\n \"tag\": "interdictor appraisingly",\n \"popularity\": 6326\n },\n {\n \"tag\": "chipped",\n \"popularity\": 6321\n },\n {\n \"tag\": "Pteropoda",\n \"popularity\": 6315\n },\n {\n \"tag\": "Bohairic",\n \"popularity\": 6309\n },\n {\n \"tag\": "felting",\n \"popularity\": 6303\n },\n {\n \"tag\": "compurgatorial",\n \"popularity\": 6298\n },\n {\n \"tag\": "unclead",\n \"popularity\": 6292\n },\n {\n \"tag\": "stockish",\n \"popularity\": 6286\n },\n {\n \"tag\": "mulligatawny",\n \"popularity\": 6281\n },\n {\n \"tag\": "Monotheletism",\n \"popularity\": 6275\n },\n {\n \"tag\": "lutanist",\n \"popularity\": 6269\n },\n {\n \"tag\": "gluttonize",\n \"popularity\": 6264\n },\n {\n \"tag\": "hackneyed",\n \"popularity\": 6258\n },\n {\n \"tag\": "yield",\n \"popularity\": 6253\n },\n {\n \"tag\": "sulphonamido",\n \"popularity\": 6247\n },\n {\n \"tag\": "granulative",\n \"popularity\": 6241\n },\n {\n \"tag\": "swingy",\n \"popularity\": 6236\n },\n {\n \"tag\": "Desmidiales",\n \"popularity\": 6230\n },\n {\n \"tag\": "tootlish",\n \"popularity\": 6224\n },\n {\n \"tag\": "unsatisfiedly",\n \"popularity\": 6219\n },\n {\n \"tag\": "burucha",\n \"popularity\": 6213\n },\n {\n \"tag\": "premeditatingly",\n \"popularity\": 6208\n },\n {\n \"tag\": "cowrie",\n \"popularity\": 6202\n },\n {\n \"tag\": "pleurolysis",\n \"popularity\": 6197\n },\n {\n \"tag\": "nationalist",\n \"popularity\": 6191\n },\n {\n \"tag\": "Pholadacea",\n \"popularity\": 6186\n },\n {\n \"tag\": "anakrousis",\n \"popularity\": 6180\n },\n {\n \"tag\": "proctorial",\n \"popularity\": 6175\n },\n {\n \"tag\": "cavillation",\n \"popularity\": 6169\n },\n {\n \"tag\": "cervicobregmatic",\n \"popularity\": 6163\n },\n {\n \"tag\": "interspecific",\n \"popularity\": 6158\n },\n {\n \"tag\": "Teutonity",\n \"popularity\": 6152\n },\n {\n \"tag\": "snakeholing",\n \"popularity\": 6147\n },\n {\n \"tag\": "balcony",\n \"popularity\": 6142\n },\n {\n \"tag\": "latchless",\n \"popularity\": 6136\n },\n {\n \"tag\": "Mithraea",\n \"popularity\": 6131\n },\n {\n \"tag\": "pseudepigraph",\n \"popularity\": 6125\n },\n {\n \"tag\": "flosser",\n \"popularity\": 6120\n },\n {\n \"tag\": "kotyle",\n \"popularity\": 6114\n },\n {\n \"tag\": "outdo",\n \"popularity\": 6109\n },\n {\n \"tag\": "interclerical",\n \"popularity\": 6103\n },\n {\n \"tag\": "aurar",\n \"popularity\": 6098\n },\n {\n \"tag\": "apophyseal",\n \"popularity\": 6093\n },\n {\n \"tag\": "Miro",\n \"popularity\": 6087\n },\n {\n \"tag\": "Priscillian",\n \"popularity\": 6082\n },\n {\n \"tag\": "alluvia",\n \"popularity\": 6076\n },\n {\n \"tag\": "exordize",\n \"popularity\": 6071\n },\n {\n \"tag\": "breakage",\n \"popularity\": 6066\n },\n {\n \"tag\": "unclosable",\n \"popularity\": 6060\n },\n {\n \"tag\": "monocondylous",\n \"popularity\": 6055\n },\n {\n \"tag\": "dyarchy",\n \"popularity\": 6050\n },\n {\n \"tag\": "subchelate",\n \"popularity\": 6044\n },\n {\n \"tag\": "hearsay",\n \"popularity\": 6039\n },\n {\n \"tag\": "prestigiously",\n \"popularity\": 6034\n },\n {\n \"tag\": "unimuscular",\n \"popularity\": 6028\n },\n {\n \"tag\": "lingwort",\n \"popularity\": 6023\n },\n {\n \"tag\": "jealous",\n \"popularity\": 6018\n },\n {\n \"tag\": "artilleryman",\n \"popularity\": 6012\n },\n {\n \"tag\": "phantasmagorially",\n \"popularity\": 6007\n },\n {\n \"tag\": "stagnum",\n \"popularity\": 6002\n },\n {\n \"tag\": "organotropism shatteringly",\n \"popularity\": 5997\n },\n {\n \"tag\": "Mytilus Hebraist",\n \"popularity\": 5991\n },\n {\n \"tag\": "returf",\n \"popularity\": 5986\n },\n {\n \"tag\": "townfolk",\n \"popularity\": 5981\n },\n {\n \"tag\": "propitiative",\n \"popularity\": 5976\n },\n {\n \"tag\": "Anita unsullied",\n \"popularity\": 5970\n },\n {\n \"tag\": "bandoleered",\n \"popularity\": 5965\n },\n {\n \"tag\": "cubby",\n \"popularity\": 5960\n },\n {\n \"tag\": "Hexanchus",\n \"popularity\": 5955\n },\n {\n \"tag\": "circuminsular",\n \"popularity\": 5949\n },\n {\n \"tag\": "chamberletted eumycete",\n \"popularity\": 5944\n },\n {\n \"tag\": "secure",\n \"popularity\": 5939\n },\n {\n \"tag\": "Edwardean",\n \"popularity\": 5934\n },\n {\n \"tag\": "strenth",\n \"popularity\": 5929\n },\n {\n \"tag\": "exhaustless",\n \"popularity\": 5923\n },\n {\n \"tag\": "electioneerer",\n \"popularity\": 5918\n },\n {\n \"tag\": "estoile",\n \"popularity\": 5913\n },\n {\n \"tag\": "redden",\n \"popularity\": 5908\n },\n {\n \"tag\": "solicitee",\n \"popularity\": 5903\n },\n {\n \"tag\": "nonpatented",\n \"popularity\": 5898\n },\n {\n \"tag\": "lemming",\n \"popularity\": 5893\n },\n {\n \"tag\": "marled subalate",\n \"popularity\": 5887\n },\n {\n \"tag\": "premial horizonward",\n \"popularity\": 5882\n },\n {\n \"tag\": "nonrefueling",\n \"popularity\": 5877\n },\n {\n \"tag\": "rupturewort",\n \"popularity\": 5872\n },\n {\n \"tag\": "unfed",\n \"popularity\": 5867\n },\n {\n \"tag\": "empanelment",\n \"popularity\": 5862\n },\n {\n \"tag\": "isoosmosis",\n \"popularity\": 5857\n },\n {\n \"tag\": "jipijapa",\n \"popularity\": 5852\n },\n {\n \"tag\": "Fiji",\n \"popularity\": 5847\n },\n {\n \"tag\": "interferant",\n \"popularity\": 5842\n },\n {\n \"tag\": "reconstitution",\n \"popularity\": 5837\n },\n {\n \"tag\": "dockyardman",\n \"popularity\": 5832\n },\n {\n \"tag\": "dolichopodous",\n \"popularity\": 5826\n },\n {\n \"tag\": "whiteworm",\n \"popularity\": 5821\n },\n {\n \"tag\": "atheistically",\n \"popularity\": 5816\n },\n {\n \"tag\": "nonconcern",\n \"popularity\": 5811\n },\n {\n \"tag\": "scarabaeidoid",\n \"popularity\": 5806\n },\n {\n \"tag\": "triumviri",\n \"popularity\": 5801\n },\n {\n \"tag\": "rakit",\n \"popularity\": 5796\n },\n {\n \"tag\": "leecheater",\n \"popularity\": 5791\n },\n {\n \"tag\": "Arthrostraca",\n \"popularity\": 5786\n },\n {\n \"tag\": "upknit",\n \"popularity\": 5781\n },\n {\n \"tag\": "tymbalon",\n \"popularity\": 5776\n },\n {\n \"tag\": "inventurous",\n \"popularity\": 5771\n },\n {\n \"tag\": "perradiate",\n \"popularity\": 5766\n },\n {\n \"tag\": "seer",\n \"popularity\": 5762\n },\n {\n \"tag\": "Auricularia",\n \"popularity\": 5757\n },\n {\n \"tag\": "wettish exclusivity",\n \"popularity\": 5752\n },\n {\n \"tag\": "arteriosympathectomy",\n \"popularity\": 5747\n },\n {\n \"tag\": "tunlike",\n \"popularity\": 5742\n },\n {\n \"tag\": "cephalocercal",\n \"popularity\": 5737\n },\n {\n \"tag\": "meaninglessness",\n \"popularity\": 5732\n },\n {\n \"tag\": "fountful",\n \"popularity\": 5727\n },\n {\n \"tag\": "appraisement",\n \"popularity\": 5722\n },\n {\n \"tag\": "geniculated",\n \"popularity\": 5717\n },\n {\n \"tag\": "rotator",\n \"popularity\": 5712\n },\n {\n \"tag\": "foremarch biography",\n \"popularity\": 5707\n },\n {\n \"tag\": "arid",\n \"popularity\": 5703\n },\n {\n \"tag\": "inapprehensible",\n \"popularity\": 5698\n },\n {\n \"tag\": "chlorosulphonic",\n \"popularity\": 5693\n },\n {\n \"tag\": "braguette",\n \"popularity\": 5688\n },\n {\n \"tag\": "panophthalmitis",\n \"popularity\": 5683\n },\n {\n \"tag\": "pro objurgatorily",\n \"popularity\": 5678\n },\n {\n \"tag\": "zooplasty",\n \"popularity\": 5673\n },\n {\n \"tag\": "Terebratulidae",\n \"popularity\": 5669\n },\n {\n \"tag\": "Mahran",\n \"popularity\": 5664\n },\n {\n \"tag\": "anthologize merocele",\n \"popularity\": 5659\n },\n {\n \"tag\": "firecracker chiropractic",\n \"popularity\": 5654\n },\n {\n \"tag\": "tenorist",\n \"popularity\": 5649\n },\n {\n \"tag\": "amphitene",\n \"popularity\": 5645\n },\n {\n \"tag\": "silverbush toadstone",\n \"popularity\": 5640\n },\n {\n \"tag\": "entozoological",\n \"popularity\": 5635\n },\n {\n \"tag\": "trustlessness",\n \"popularity\": 5630\n },\n {\n \"tag\": "reassay",\n \"popularity\": 5625\n },\n {\n \"tag\": "chrysalides",\n \"popularity\": 5621\n },\n {\n \"tag\": "truncation",\n \"popularity\": 5616\n },\n {\n \"tag\": "unwavered mausoleal",\n \"popularity\": 5611\n },\n {\n \"tag\": "unserrated",\n \"popularity\": 5606\n },\n {\n \"tag\": "frampler",\n \"popularity\": 5602\n },\n {\n \"tag\": "celestial",\n \"popularity\": 5597\n },\n {\n \"tag\": "depreter",\n \"popularity\": 5592\n },\n {\n \"tag\": "retaliate",\n \"popularity\": 5588\n },\n {\n \"tag\": "decempunctate",\n \"popularity\": 5583\n },\n {\n \"tag\": "submitter",\n \"popularity\": 5578\n },\n {\n \"tag\": "phenothiazine",\n \"popularity\": 5573\n },\n {\n \"tag\": "hobbledehoyish",\n \"popularity\": 5569\n },\n {\n \"tag\": "erraticness",\n \"popularity\": 5564\n },\n {\n \"tag\": "ovariodysneuria",\n \"popularity\": 5559\n },\n {\n \"tag\": "puja",\n \"popularity\": 5555\n },\n {\n \"tag\": "cesspool",\n \"popularity\": 5550\n },\n {\n \"tag\": "sonation",\n \"popularity\": 5545\n },\n {\n \"tag\": "moggan",\n \"popularity\": 5541\n },\n {\n \"tag\": "overjutting",\n \"popularity\": 5536\n },\n {\n \"tag\": "cohobate",\n \"popularity\": 5531\n },\n {\n \"tag\": "Distoma",\n \"popularity\": 5527\n },\n {\n \"tag\": "Plectognathi",\n \"popularity\": 5522\n },\n {\n \"tag\": "dumple caliphate",\n \"popularity\": 5517\n },\n {\n \"tag\": "shiko",\n \"popularity\": 5513\n },\n {\n \"tag\": "downness",\n \"popularity\": 5508\n },\n {\n \"tag\": "whippletree",\n \"popularity\": 5504\n },\n {\n \"tag\": "nymphaeum",\n \"popularity\": 5499\n },\n {\n \"tag\": "there trest",\n \"popularity\": 5494\n },\n {\n \"tag\": "psychrometer",\n \"popularity\": 5490\n },\n {\n \"tag\": "pyelograph",\n \"popularity\": 5485\n },\n {\n \"tag\": "unsalvable",\n \"popularity\": 5481\n },\n {\n \"tag\": "bescreen",\n \"popularity\": 5476\n },\n {\n \"tag\": "cushy",\n \"popularity\": 5471\n },\n {\n \"tag\": "plicatolobate",\n \"popularity\": 5467\n },\n {\n \"tag\": "lakie",\n \"popularity\": 5462\n },\n {\n \"tag\": "anthropodeoxycholic",\n \"popularity\": 5458\n },\n {\n \"tag\": "resatisfaction",\n \"popularity\": 5453\n },\n {\n \"tag\": "unravelment unaccidental",\n \"popularity\": 5449\n },\n {\n \"tag\": "telewriter monogeneous",\n \"popularity\": 5444\n },\n {\n \"tag\": "unsabred",\n \"popularity\": 5440\n },\n {\n \"tag\": "startlingly",\n \"popularity\": 5435\n },\n {\n \"tag\": "Aralia",\n \"popularity\": 5431\n },\n {\n \"tag\": "alamonti",\n \"popularity\": 5426\n },\n {\n \"tag\": "Franklinization",\n \"popularity\": 5422\n },\n {\n \"tag\": "parliament",\n \"popularity\": 5417\n },\n {\n \"tag\": "schoolkeeper",\n \"popularity\": 5413\n },\n {\n \"tag\": "nonsociety",\n \"popularity\": 5408\n },\n {\n \"tag\": "parenthetic",\n \"popularity\": 5404\n },\n {\n \"tag\": "stog",\n \"popularity\": 5399\n },\n {\n \"tag\": "Pristipomidae",\n \"popularity\": 5395\n },\n {\n \"tag\": "exocarp",\n \"popularity\": 5390\n },\n {\n \"tag\": "monaxonial",\n \"popularity\": 5386\n },\n {\n \"tag\": "tramroad",\n \"popularity\": 5381\n },\n {\n \"tag\": "hookah",\n \"popularity\": 5377\n },\n {\n \"tag\": "saccharonic",\n \"popularity\": 5372\n },\n {\n \"tag\": "perimetrium",\n \"popularity\": 5368\n },\n {\n \"tag\": "libelluloid",\n \"popularity\": 5364\n },\n {\n \"tag\": "overrunningly",\n \"popularity\": 5359\n },\n {\n \"tag\": "untwister",\n \"popularity\": 5355\n },\n {\n \"tag\": "ninnyhammer",\n \"popularity\": 5350\n },\n {\n \"tag\": "metranate",\n \"popularity\": 5346\n },\n {\n \"tag\": "sarcoblast",\n \"popularity\": 5341\n },\n {\n \"tag\": "porkish",\n \"popularity\": 5337\n },\n {\n \"tag\": "chauvinistic",\n \"popularity\": 5333\n },\n {\n \"tag\": "sexagesimal",\n \"popularity\": 5328\n },\n {\n \"tag\": "hematogenic",\n \"popularity\": 5324\n },\n {\n \"tag\": "selfpreservatory",\n \"popularity\": 5320\n },\n {\n \"tag\": "myelauxe",\n \"popularity\": 5315\n },\n {\n \"tag\": "triply",\n \"popularity\": 5311\n },\n {\n \"tag\": "metaphysicous",\n \"popularity\": 5306\n },\n {\n \"tag\": "vitrinoid",\n \"popularity\": 5302\n },\n {\n \"tag\": "glabellae",\n \"popularity\": 5298\n },\n {\n \"tag\": "moonlighter",\n \"popularity\": 5293\n },\n {\n \"tag\": "monotheistically epexegetical",\n \"popularity\": 5289\n },\n {\n \"tag\": "pseudolateral",\n \"popularity\": 5285\n },\n {\n \"tag\": "heptamethylene",\n \"popularity\": 5280\n },\n {\n \"tag\": "salvadora",\n \"popularity\": 5276\n },\n {\n \"tag\": "unjovial diphenylthiourea",\n \"popularity\": 5272\n },\n {\n \"tag\": "thievishness",\n \"popularity\": 5268\n },\n {\n \"tag\": "unridable",\n \"popularity\": 5263\n },\n {\n \"tag\": "underhandedly",\n \"popularity\": 5259\n },\n {\n \"tag\": "fungiform",\n \"popularity\": 5255\n },\n {\n \"tag\": "scruffle",\n \"popularity\": 5250\n },\n {\n \"tag\": "preindisposition",\n \"popularity\": 5246\n },\n {\n \"tag\": "Amadis",\n \"popularity\": 5242\n },\n {\n \"tag\": "Culex",\n \"popularity\": 5238\n },\n {\n \"tag\": "churning",\n \"popularity\": 5233\n },\n {\n \"tag\": "imperite",\n \"popularity\": 5229\n },\n {\n \"tag\": "levorotation",\n \"popularity\": 5225\n },\n {\n \"tag\": "barbate",\n \"popularity\": 5221\n },\n {\n \"tag\": "knotwort",\n \"popularity\": 5216\n },\n {\n \"tag\": "gypsiferous",\n \"popularity\": 5212\n },\n {\n \"tag\": "tourmalinic",\n \"popularity\": 5208\n },\n {\n \"tag\": "helleboric",\n \"popularity\": 5204\n },\n {\n \"tag\": "pneumograph",\n \"popularity\": 5199\n },\n {\n \"tag\": "Peltigeraceae",\n \"popularity\": 5195\n },\n {\n \"tag\": "busine",\n \"popularity\": 5191\n },\n {\n \"tag\": "Ailuridae",\n \"popularity\": 5187\n },\n {\n \"tag\": "azotate",\n \"popularity\": 5183\n },\n {\n \"tag\": "unlikable",\n \"popularity\": 5178\n },\n {\n \"tag\": "sloyd",\n \"popularity\": 5174\n },\n {\n \"tag\": "biblioclasm",\n \"popularity\": 5170\n },\n {\n \"tag\": "Seres",\n \"popularity\": 5166\n },\n {\n \"tag\": "unaccurateness",\n \"popularity\": 5162\n },\n {\n \"tag\": "scrollwise",\n \"popularity\": 5157\n },\n {\n \"tag\": "flandowser",\n \"popularity\": 5153\n },\n {\n \"tag\": "unblackened",\n \"popularity\": 5149\n },\n {\n \"tag\": "schistosternia",\n \"popularity\": 5145\n },\n {\n \"tag\": "fuse",\n \"popularity\": 5141\n },\n {\n \"tag\": "narthecal",\n \"popularity\": 5137\n },\n {\n \"tag\": "Cueva",\n \"popularity\": 5133\n },\n {\n \"tag\": "appositeness",\n \"popularity\": 5128\n },\n {\n \"tag\": "proindustrial",\n \"popularity\": 5124\n },\n {\n \"tag\": "dermatorrhoea",\n \"popularity\": 5120\n },\n {\n \"tag\": "oxyurous tendential",\n \"popularity\": 5116\n },\n {\n \"tag\": "isopurpurin",\n \"popularity\": 5112\n },\n {\n \"tag\": "impose",\n \"popularity\": 5108\n },\n {\n \"tag\": "wordsmanship",\n \"popularity\": 5104\n },\n {\n \"tag\": "saturator",\n \"popularity\": 5100\n },\n {\n \"tag\": "Nordicity",\n \"popularity\": 5096\n },\n {\n \"tag\": "interaccuse",\n \"popularity\": 5092\n },\n {\n \"tag\": "acridinic",\n \"popularity\": 5087\n },\n {\n \"tag\": "scholion",\n \"popularity\": 5083\n },\n {\n \"tag\": "pseudoaconitine",\n \"popularity\": 5079\n },\n {\n \"tag\": "doctorial",\n \"popularity\": 5075\n },\n {\n \"tag\": "Etchimin",\n \"popularity\": 5071\n },\n {\n \"tag\": "oliviform",\n \"popularity\": 5067\n },\n {\n \"tag\": "Pele",\n \"popularity\": 5063\n },\n {\n \"tag\": "Chiromantis Progymnasium",\n \"popularity\": 5059\n },\n {\n \"tag\": "toxosis",\n \"popularity\": 5055\n },\n {\n \"tag\": "spadilla",\n \"popularity\": 5051\n },\n {\n \"tag\": "Actinopterygii",\n \"popularity\": 5047\n },\n {\n \"tag\": "untiring",\n \"popularity\": 5043\n },\n {\n \"tag\": "butyral",\n \"popularity\": 5039\n },\n {\n \"tag\": "Gymnoderinae",\n \"popularity\": 5035\n },\n {\n \"tag\": "testudo",\n \"popularity\": 5031\n },\n {\n \"tag\": "frigorify",\n \"popularity\": 5027\n },\n {\n \"tag\": "aliency",\n \"popularity\": 5023\n },\n {\n \"tag\": "jargon",\n \"popularity\": 5019\n },\n {\n \"tag\": "counterservice",\n \"popularity\": 5015\n },\n {\n \"tag\": "isostrychnine",\n \"popularity\": 5011\n },\n {\n \"tag\": "tellership",\n \"popularity\": 5007\n },\n {\n \"tag\": "miscegenetic",\n \"popularity\": 5003\n },\n {\n \"tag\": "sorcer",\n \"popularity\": 4999\n },\n {\n \"tag\": "tilewright",\n \"popularity\": 4995\n },\n {\n \"tag\": "cyanoplastid",\n \"popularity\": 4991\n },\n {\n \"tag\": "fluxionally",\n \"popularity\": 4987\n },\n {\n \"tag\": "proudhearted",\n \"popularity\": 4983\n },\n {\n \"tag\": "blithely",\n \"popularity\": 4979\n },\n {\n \"tag\": "jestproof",\n \"popularity\": 4975\n },\n {\n \"tag\": "jestwise",\n \"popularity\": 4971\n },\n {\n \"tag\": "nonassimilable",\n \"popularity\": 4967\n },\n {\n \"tag\": "compurgation",\n \"popularity\": 4964\n },\n {\n \"tag\": "unhate",\n \"popularity\": 4960\n },\n {\n \"tag\": "haplodonty",\n \"popularity\": 4956\n },\n {\n \"tag\": "cardholder",\n \"popularity\": 4952\n },\n {\n \"tag\": "rainlight megohmmeter overstout",\n \"popularity\": 4948\n },\n {\n \"tag\": "itchless",\n \"popularity\": 4944\n },\n {\n \"tag\": "begiggle",\n \"popularity\": 4940\n },\n {\n \"tag\": "chromatosphere",\n \"popularity\": 4936\n },\n {\n \"tag\": "typicality",\n \"popularity\": 4932\n },\n {\n \"tag\": "overgrown",\n \"popularity\": 4928\n },\n {\n \"tag\": "envolume",\n \"popularity\": 4925\n },\n {\n \"tag\": "pachycholia",\n \"popularity\": 4921\n },\n {\n \"tag\": "passageable",\n \"popularity\": 4917\n },\n {\n \"tag\": "pathopoiesis",\n \"popularity\": 4913\n },\n {\n \"tag\": "overbreak",\n \"popularity\": 4909\n },\n {\n \"tag\": "satyric",\n \"popularity\": 4905\n },\n {\n \"tag\": "unaudited",\n \"popularity\": 4901\n },\n {\n \"tag\": "whimble",\n \"popularity\": 4898\n },\n {\n \"tag\": "pressureless",\n \"popularity\": 4894\n },\n {\n \"tag\": "Selene",\n \"popularity\": 4890\n },\n {\n \"tag\": "slithery",\n \"popularity\": 4886\n },\n {\n \"tag\": "nondisfigurement",\n \"popularity\": 4882\n },\n {\n \"tag\": "overdelicious",\n \"popularity\": 4878\n },\n {\n \"tag\": "Perca",\n \"popularity\": 4875\n },\n {\n \"tag\": "Palladium",\n \"popularity\": 4871\n },\n {\n \"tag\": "insagacity",\n \"popularity\": 4867\n },\n {\n \"tag\": "peristoma",\n \"popularity\": 4863\n },\n {\n \"tag\": "uncreativeness",\n \"popularity\": 4859\n },\n {\n \"tag\": "incomparability surfboarding",\n \"popularity\": 4856\n },\n {\n \"tag\": "bacillar",\n \"popularity\": 4852\n },\n {\n \"tag\": "ulcerative",\n \"popularity\": 4848\n },\n {\n \"tag\": "stychomythia",\n \"popularity\": 4844\n },\n {\n \"tag\": "sesma somatics nonentry",\n \"popularity\": 4840\n },\n {\n \"tag\": "unsepulchred",\n \"popularity\": 4837\n },\n {\n \"tag\": "cephalanthium",\n \"popularity\": 4833\n },\n {\n \"tag\": "Asiaticization",\n \"popularity\": 4829\n },\n {\n \"tag\": "killeen",\n \"popularity\": 4825\n },\n {\n \"tag\": "Pseudococcus",\n \"popularity\": 4822\n },\n {\n \"tag\": "untractable",\n \"popularity\": 4818\n },\n {\n \"tag\": "apolegamic",\n \"popularity\": 4814\n },\n {\n \"tag\": "hyperpnea",\n \"popularity\": 4810\n },\n {\n \"tag\": "martyrolatry",\n \"popularity\": 4807\n },\n {\n \"tag\": "Sarmatic",\n \"popularity\": 4803\n },\n {\n \"tag\": "nonsurface",\n \"popularity\": 4799\n },\n {\n \"tag\": "adjoined",\n \"popularity\": 4796\n },\n {\n \"tag\": "vasiform",\n \"popularity\": 4792\n },\n {\n \"tag\": "tastelessness",\n \"popularity\": 4788\n },\n {\n \"tag\": "rumbo",\n \"popularity\": 4784\n },\n {\n \"tag\": "subdititious",\n \"popularity\": 4781\n },\n {\n \"tag\": "reparticipation",\n \"popularity\": 4777\n },\n {\n \"tag\": "Yorkshireism",\n \"popularity\": 4773\n },\n {\n \"tag\": "outcrow",\n \"popularity\": 4770\n },\n {\n \"tag\": "casserole",\n \"popularity\": 4766\n },\n {\n \"tag\": "semideltaic",\n \"popularity\": 4762\n },\n {\n \"tag\": "freemason",\n \"popularity\": 4759\n },\n {\n \"tag\": "catkin",\n \"popularity\": 4755\n },\n {\n \"tag\": "conscient",\n \"popularity\": 4751\n },\n {\n \"tag\": "reliably",\n \"popularity\": 4748\n },\n {\n \"tag\": "Telembi",\n \"popularity\": 4744\n },\n {\n \"tag\": "hide",\n \"popularity\": 4740\n },\n {\n \"tag\": "social",\n \"popularity\": 4737\n },\n {\n \"tag\": "ichneutic",\n \"popularity\": 4733\n },\n {\n \"tag\": "polypotome blouse pentagrammatic",\n \"popularity\": 4729\n },\n {\n \"tag\": "airdrome pesthole",\n \"popularity\": 4726\n },\n {\n \"tag\": "unportended",\n \"popularity\": 4722\n },\n {\n \"tag\": "sheerly",\n \"popularity\": 4719\n },\n {\n \"tag\": "acardiac",\n \"popularity\": 4715\n },\n {\n \"tag\": "fetor",\n \"popularity\": 4711\n },\n {\n \"tag\": "storax",\n \"popularity\": 4708\n },\n {\n \"tag\": "syndactylic",\n \"popularity\": 4704\n },\n {\n \"tag\": "otiatrics",\n \"popularity\": 4700\n },\n {\n \"tag\": "range",\n \"popularity\": 4697\n },\n {\n \"tag\": "branchway",\n \"popularity\": 4693\n },\n {\n \"tag\": "beatific",\n \"popularity\": 4690\n },\n {\n \"tag\": "Rugosa",\n \"popularity\": 4686\n },\n {\n \"tag\": "rafty",\n \"popularity\": 4682\n },\n {\n \"tag\": "gapy",\n \"popularity\": 4679\n },\n {\n \"tag\": "heterocercal",\n \"popularity\": 4675\n },\n {\n \"tag\": "actinopterygious",\n \"popularity\": 4672\n },\n {\n \"tag\": "glauconite",\n \"popularity\": 4668\n },\n {\n \"tag\": "limbless priest",\n \"popularity\": 4665\n },\n {\n \"tag\": "chrysene",\n \"popularity\": 4661\n },\n {\n \"tag\": "isentropic",\n \"popularity\": 4658\n },\n {\n \"tag\": "lairdess",\n \"popularity\": 4654\n },\n {\n \"tag\": "butterhead choliambic",\n \"popularity\": 4650\n },\n {\n \"tag\": "hexaseme",\n \"popularity\": 4647\n },\n {\n \"tag\": "treeify",\n \"popularity\": 4643\n },\n {\n \"tag\": "coronetted fructify",\n \"popularity\": 4640\n },\n {\n \"tag\": "admiralty",\n \"popularity\": 4636\n },\n {\n \"tag\": "Flosculariidae",\n \"popularity\": 4633\n },\n {\n \"tag\": "limaceous",\n \"popularity\": 4629\n },\n {\n \"tag\": "subterconscious",\n \"popularity\": 4626\n },\n {\n \"tag\": "stayless",\n \"popularity\": 4622\n },\n {\n \"tag\": "psha",\n \"popularity\": 4619\n },\n {\n \"tag\": "Mediterraneanize",\n \"popularity\": 4615\n },\n {\n \"tag\": "impenetrably",\n \"popularity\": 4612\n },\n {\n \"tag\": "Myrmeleonidae",\n \"popularity\": 4608\n },\n {\n \"tag\": "germander",\n \"popularity\": 4605\n },\n {\n \"tag\": "Buri",\n \"popularity\": 4601\n },\n {\n \"tag\": "papyrotamia",\n \"popularity\": 4598\n },\n {\n \"tag\": "Toxylon",\n \"popularity\": 4594\n },\n {\n \"tag\": "batatilla",\n \"popularity\": 4591\n },\n {\n \"tag\": "fabella assumer",\n \"popularity\": 4587\n },\n {\n \"tag\": "macromethod",\n \"popularity\": 4584\n },\n {\n \"tag\": "Blechnum",\n \"popularity\": 4580\n },\n {\n \"tag\": "pantography",\n \"popularity\": 4577\n },\n {\n \"tag\": "seminovel",\n \"popularity\": 4574\n },\n {\n \"tag\": "disembarrassment",\n \"popularity\": 4570\n },\n {\n \"tag\": "bushmaking",\n \"popularity\": 4567\n },\n {\n \"tag\": "neurosis",\n \"popularity\": 4563\n },\n {\n \"tag\": "Animalia",\n \"popularity\": 4560\n },\n {\n \"tag\": "Bernice",\n \"popularity\": 4556\n },\n {\n \"tag\": "wisen",\n \"popularity\": 4553\n },\n {\n \"tag\": "subhymenium",\n \"popularity\": 4549\n },\n {\n \"tag\": "esophagomycosis",\n \"popularity\": 4546\n },\n {\n \"tag\": "wireworks",\n \"popularity\": 4543\n },\n {\n \"tag\": "Sabellidae",\n \"popularity\": 4539\n },\n {\n \"tag\": "fustianish",\n \"popularity\": 4536\n },\n {\n \"tag\": "professively",\n \"popularity\": 4532\n },\n {\n \"tag\": "overcorruptly",\n \"popularity\": 4529\n },\n {\n \"tag\": "overcreep",\n \"popularity\": 4526\n },\n {\n \"tag\": "Castilloa",\n \"popularity\": 4522\n },\n {\n \"tag\": "forelady Georgie",\n \"popularity\": 4519\n },\n {\n \"tag\": "outsider",\n \"popularity\": 4515\n },\n {\n \"tag\": "Enukki",\n \"popularity\": 4512\n },\n {\n \"tag\": "gypsy",\n \"popularity\": 4509\n },\n {\n \"tag\": "Passamaquoddy",\n \"popularity\": 4505\n },\n {\n \"tag\": "reposit",\n \"popularity\": 4502\n },\n {\n \"tag\": "overtenderness",\n \"popularity\": 4499\n },\n {\n \"tag\": "keratome",\n \"popularity\": 4495\n },\n {\n \"tag\": "interclavicular hypermonosyllable Susanna",\n \"popularity\": 4492\n },\n {\n \"tag\": "mispropose",\n \"popularity\": 4489\n },\n {\n \"tag\": "Membranipora",\n \"popularity\": 4485\n },\n {\n \"tag\": "lampad",\n \"popularity\": 4482\n },\n {\n \"tag\": "header",\n \"popularity\": 4479\n },\n {\n \"tag\": "triseriate",\n \"popularity\": 4475\n },\n {\n \"tag\": "distrainment",\n \"popularity\": 4472\n },\n {\n \"tag\": "staphyloplastic",\n \"popularity\": 4469\n },\n {\n \"tag\": "outscour",\n \"popularity\": 4465\n },\n {\n \"tag\": "tallowmaking",\n \"popularity\": 4462\n },\n {\n \"tag\": "plugger",\n \"popularity\": 4459\n },\n {\n \"tag\": "fashionize",\n \"popularity\": 4455\n },\n {\n \"tag\": "puzzle",\n \"popularity\": 4452\n },\n {\n \"tag\": "imbrue",\n \"popularity\": 4449\n },\n {\n \"tag\": "osteoblast",\n \"popularity\": 4445\n },\n {\n \"tag\": "Hydrocores",\n \"popularity\": 4442\n },\n {\n \"tag\": "Lutra",\n \"popularity\": 4439\n },\n {\n \"tag\": "upridge scarfy",\n \"popularity\": 4435\n },\n {\n \"tag\": "ancon taffle",\n \"popularity\": 4432\n },\n {\n \"tag\": "impest",\n \"popularity\": 4429\n },\n {\n \"tag\": "uncollatedness",\n \"popularity\": 4426\n },\n {\n \"tag\": "hypersensitize",\n \"popularity\": 4422\n },\n {\n \"tag\": "autographically",\n \"popularity\": 4419\n },\n {\n \"tag\": "louther",\n \"popularity\": 4416\n },\n {\n \"tag\": "Ollie",\n \"popularity\": 4413\n },\n {\n \"tag\": "recompensate",\n \"popularity\": 4409\n },\n {\n \"tag\": "Shan",\n \"popularity\": 4406\n },\n {\n \"tag\": "brachycnemic",\n \"popularity\": 4403\n },\n {\n \"tag\": "Carinatae",\n \"popularity\": 4399\n },\n {\n \"tag\": "geotherm",\n \"popularity\": 4396\n },\n {\n \"tag\": "sawback",\n \"popularity\": 4393\n },\n {\n \"tag\": "Novatianist",\n \"popularity\": 4390\n },\n {\n \"tag\": "reapproach",\n \"popularity\": 4387\n },\n {\n \"tag\": "myelopoietic",\n \"popularity\": 4383\n },\n {\n \"tag\": "cyanin",\n \"popularity\": 4380\n },\n {\n \"tag\": "unsmutted",\n \"popularity\": 4377\n },\n {\n \"tag\": "nonpapist",\n \"popularity\": 4374\n },\n {\n \"tag\": "transbaikalian",\n \"popularity\": 4370\n },\n {\n \"tag\": "connately",\n \"popularity\": 4367\n },\n {\n \"tag\": "tenderize iterance",\n \"popularity\": 4364\n },\n {\n \"tag\": "hydrostatical",\n \"popularity\": 4361\n },\n {\n \"tag\": "unflag",\n \"popularity\": 4358\n },\n {\n \"tag\": "translate",\n \"popularity\": 4354\n },\n {\n \"tag\": "Scorzonera",\n \"popularity\": 4351\n },\n {\n \"tag\": "uncomforted",\n \"popularity\": 4348\n },\n {\n \"tag\": "risser varied",\n \"popularity\": 4345\n },\n {\n \"tag\": "plumbate",\n \"popularity\": 4342\n },\n {\n \"tag\": "Usneaceae",\n \"popularity\": 4338\n },\n {\n \"tag\": "fohat",\n \"popularity\": 4335\n },\n {\n \"tag\": "slagging",\n \"popularity\": 4332\n },\n {\n \"tag\": "superserious",\n \"popularity\": 4329\n },\n {\n \"tag\": "theocracy",\n \"popularity\": 4326\n },\n {\n \"tag\": "valonia",\n \"popularity\": 4323\n },\n {\n \"tag\": "Sapindales",\n \"popularity\": 4319\n },\n {\n \"tag\": "palaeozoologist",\n \"popularity\": 4316\n },\n {\n \"tag\": "yalb",\n \"popularity\": 4313\n },\n {\n \"tag\": "unviewed",\n \"popularity\": 4310\n },\n {\n \"tag\": "polyarteritis",\n \"popularity\": 4307\n },\n {\n \"tag\": "vectorial",\n \"popularity\": 4304\n },\n {\n \"tag\": "skimpingly",\n \"popularity\": 4301\n },\n {\n \"tag\": "athort",\n \"popularity\": 4297\n },\n {\n \"tag\": "tribofluorescence",\n \"popularity\": 4294\n },\n {\n \"tag\": "benzonitrol",\n \"popularity\": 4291\n },\n {\n \"tag\": "swiller subobtuse subjacency",\n \"popularity\": 4288\n },\n {\n \"tag\": "uncompassed",\n \"popularity\": 4285\n },\n {\n \"tag\": "cacochymia",\n \"popularity\": 4282\n },\n {\n \"tag\": "commensalist butadiene",\n \"popularity\": 4279\n },\n {\n \"tag\": "culpable",\n \"popularity\": 4276\n },\n {\n \"tag\": "contributive",\n \"popularity\": 4273\n },\n {\n \"tag\": "attemperately",\n \"popularity\": 4269\n },\n {\n \"tag\": "spelt",\n \"popularity\": 4266\n },\n {\n \"tag\": "exoneration",\n \"popularity\": 4263\n },\n {\n \"tag\": "antivivisectionist",\n \"popularity\": 4260\n },\n {\n \"tag\": "granitification",\n \"popularity\": 4257\n },\n {\n \"tag\": "palladize",\n \"popularity\": 4254\n },\n {\n \"tag\": "marksmanship",\n \"popularity\": 4251\n },\n {\n \"tag\": "bullydom",\n \"popularity\": 4248\n },\n {\n \"tag\": "spirality",\n \"popularity\": 4245\n },\n {\n \"tag\": "caliginous",\n \"popularity\": 4242\n },\n {\n \"tag\": "reportedly",\n \"popularity\": 4239\n },\n {\n \"tag\": "polyad",\n \"popularity\": 4236\n },\n {\n \"tag\": "arthroempyesis",\n \"popularity\": 4233\n },\n {\n \"tag\": "semibay facultatively",\n \"popularity\": 4229\n },\n {\n \"tag\": "metastatically",\n \"popularity\": 4226\n },\n {\n \"tag\": "prophetically",\n \"popularity\": 4223\n },\n {\n \"tag\": "Linguatula elapid",\n \"popularity\": 4220\n },\n {\n \"tag\": "pyknatom",\n \"popularity\": 4217\n },\n {\n \"tag\": "centimeter",\n \"popularity\": 4214\n },\n {\n \"tag\": "mensurate",\n \"popularity\": 4211\n },\n {\n \"tag\": "migraine",\n \"popularity\": 4208\n },\n {\n \"tag\": "pentagamist",\n \"popularity\": 4205\n },\n {\n \"tag\": "querken",\n \"popularity\": 4202\n },\n {\n \"tag\": "ambulance",\n \"popularity\": 4199\n },\n {\n \"tag\": "Stokavian",\n \"popularity\": 4196\n },\n {\n \"tag\": "malvasian",\n \"popularity\": 4193\n },\n {\n \"tag\": "uncouthsome",\n \"popularity\": 4190\n },\n {\n \"tag\": "readable",\n \"popularity\": 4187\n },\n {\n \"tag\": "enlodge",\n \"popularity\": 4184\n },\n {\n \"tag\": "plasterwise Appendiculariidae perspectograph",\n \"popularity\": 4181\n },\n {\n \"tag\": "inkweed",\n \"popularity\": 4178\n },\n {\n \"tag\": "streep",\n \"popularity\": 4175\n },\n {\n \"tag\": "diadelphian cultured",\n \"popularity\": 4172\n },\n {\n \"tag\": "hymenopterous",\n \"popularity\": 4169\n },\n {\n \"tag\": "unexorableness",\n \"popularity\": 4166\n },\n {\n \"tag\": "cascaron",\n \"popularity\": 4163\n },\n {\n \"tag\": "undaintiness",\n \"popularity\": 4160\n },\n {\n \"tag\": "Curtana",\n \"popularity\": 4157\n },\n {\n \"tag\": "scurvied",\n \"popularity\": 4154\n },\n {\n \"tag\": "molluscoidal",\n \"popularity\": 4151\n },\n {\n \"tag\": "yurt",\n \"popularity\": 4148\n },\n {\n \"tag\": "deciduitis",\n \"popularity\": 4145\n },\n {\n \"tag\": "creephole",\n \"popularity\": 4142\n },\n {\n \"tag\": "quatrefeuille",\n \"popularity\": 4139\n },\n {\n \"tag\": "bicapitate adenomatome",\n \"popularity\": 4136\n },\n {\n \"tag\": "damassin",\n \"popularity\": 4134\n },\n {\n \"tag\": "planching",\n \"popularity\": 4131\n },\n {\n \"tag\": "dashedly inferential",\n \"popularity\": 4128\n },\n {\n \"tag\": "lobe",\n \"popularity\": 4125\n },\n {\n \"tag\": "Hyrachyus",\n \"popularity\": 4122\n },\n {\n \"tag\": "knab",\n \"popularity\": 4119\n },\n {\n \"tag\": "discohexaster",\n \"popularity\": 4116\n },\n {\n \"tag\": "malign",\n \"popularity\": 4113\n },\n {\n \"tag\": "pedagoguism",\n \"popularity\": 4110\n },\n {\n \"tag\": "shrubbery",\n \"popularity\": 4107\n },\n {\n \"tag\": "undershrub",\n \"popularity\": 4104\n },\n {\n \"tag\": "bureaucrat",\n \"popularity\": 4101\n },\n {\n \"tag\": "pantaleon",\n \"popularity\": 4098\n },\n {\n \"tag\": "mesoventral",\n \"popularity\": 4096\n }]'; + +var log2 = Math.log(2); +var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); + +function makeTagCloud(tagInfo) +{ + var output = '
'; + + tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; }); + + for (var i = 0; i < tagInfo.length; i++) { + var tag = tagInfo[i].tag; + + var validates = true; + for (var j = 0; j < tag.length; j++) { + var ch = tag.charCodeAt(j); + if (ch < 0x20 || ch >= 0x7f) { + validates = false; + break; + } + } + + if (!validates) + continue; + + var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); + var popularity = tagInfo[i].popularity; + var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; + output += ' ' + tag + ' \n'; + } + + output += '
'; + output.replace(" ", " "); + + return output; +} + +var tagcloud = makeTagCloud(tagInfo); +tagInfo = null; + +// The result string embeds floating-point numbers, which can vary a bit on different platforms, +// so we truncate them a bit before comparing. +var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) +assertEq(tagcloud_norm.length, 295906) diff --git a/js/src/tests/js1_8_1/jit/jstests.list b/js/src/tests/js1_8_1/jit/jstests.list new file mode 100644 index 00000000000..d21cf7d0743 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/jstests.list @@ -0,0 +1,24 @@ +url-prefix ../../jsreftest.html?test=js1_8_1/jit/ +script math-jit-tests.js +skip script regress-451673.js # bogus perf test (bug 540512) +skip script regress-451974-01.js # bogus perf test (bug 540512) +skip script regress-451974-02.js # bogus perf test (bug 540512) +skip script regress-452498-01.js # bogus perf test (bug 540512) +script regress-458838.js +script regress-462459-01.js +script regress-462459-02.js +script regress-462459-03.js +script regress-462459-04.js +script regress-462459-05.js +script regress-462459-06.js +script regress-462459-07.js +script regress-462459-08.js +script regress-462459-09.js +script regress-462459-10.js +script regress-462459-11.js +script regress-462459-12.js +skip script regress-469927.js # bogus perf test (bug 540512) +skip script regress-470739.js # bogus perf test (bug 540512) +script regress-471635.js +script regress-489682.js +script testDeepBailFromNonNative.js diff --git a/js/src/tests/js1_8_1/jit/regress-451673.js b/js/src/tests/js1_8_1/jit/regress-451673.js new file mode 100644 index 00000000000..5c7202fe039 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451673.js @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451673; +var summary = 'TM: Tracing prime number generation'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function doTest(enablejit) + { + if (enablejit) + jit(true); + else + jit(false); + + var n = 1000000; + var start = new Date(); + var i=0; + var j=0; + var numprimes=0; + var limit=0; + numprimes = 1; // 2 is prime + var mceil = Math.floor; + var msqrt = Math.sqrt; + var isPrime = 1; + + for (i = 3; i<= n; i+=2) + { + isPrime=1; + limit = mceil(msqrt(i)+1) + 1; + + for (j = 3; j < limit; j+=2) + { + if (i % j == 0) + { + isPrime = 0; + break; + } + } + + if (isPrime) + { + numprimes ++; + } + } + + var end = new Date(); + + var timetaken = end - start; + timetaken = timetaken / 1000; + + if (enablejit) + jit(false); + + print((enablejit ? ' JIT' : 'Non-JIT') + ": Number of primes up to: " + n + " is " + numprimes + ", counted in " + timetaken + " secs."); + + return timetaken; + } + + var timenonjit = doTest(false); + var timejit = doTest(true); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-451974-01.js b/js/src/tests/js1_8_1/jit/regress-451974-01.js new file mode 100644 index 00000000000..59fc1415da3 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451974-01.js @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451974; +var summary = 'TM: loops with anon functions should not be slower with jit enabled'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var chars = '0123456789abcdef'; +var size = 10000; +var mult = 1000; +var densearray = []; +var lsize = size; + +while (lsize--) +{ + densearray.push(chars); +} + +function loop() +{ + var start = new Date(); + + for (var a = 0; a < mult; a++) + { + var f = (function(x){}); + for (var i = 0, len = densearray.length; i < len; i++) + { + f(densearray[i]); + } + } + + var stop = new Date(); + return stop - start; +} + +jit(false); +var timenonjit = loop(); +jit(true); +var timejit = loop(); +jit(false); + +print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + +expect = true; +actual = timejit < timenonjit/2; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-451974-02.js b/js/src/tests/js1_8_1/jit/regress-451974-02.js new file mode 100644 index 00000000000..f0de29d49bf --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451974-02.js @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451974; +var summary = 'TM: loops with anon functions should not be slower with jit enabled'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + var chars = '0123456789abcdef'; + var size = 10000; + var mult = 1000; + var densearray = []; + var lsize = size; + + while (lsize--) + { + densearray.push(chars); + } + + function loop() + { + var start = new Date(); + + for (var a = 0; a < mult; a++) + { + var f = (function(x){}); + for (var i = 0, len = densearray.length; i < len; i++) + { + f(densearray[i]); + } + } + + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = loop(); + jit(true); + var timejit = loop(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit/2; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-452498-01.js b/js/src/tests/js1_8_1/jit/regress-452498-01.js new file mode 100644 index 00000000000..c857e2087af --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-452498-01.js @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 452498; +var summary = 'TM: upvar2: jit heavyweight functions'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function complex(aReal, aImag) { + this.r = aReal; + this.i = aImag; + this.square = function() { + return new complex(this.r * this.r - this.i * this.i, + 2 * this.r * this.i); + } + this.dist = function() { + return Math.sqrt(this.r * this.r + this.i * this.i); + } + this.add = function(aComplex) { + return new complex(this.r + aComplex.r, this.i + aComplex.i); + } +} + +function mandelbrotValueOO (aC, aIterMax) { + let Z = new complex(0.0, 0.0); + for (var iter = 0; iter < aIterMax; iter++) { + Z = Z.square().add(aC); + if (Z.r * Z.r + Z.i * Z.i > 256) { break; } + } + return iter; +} + +function f(trace) { + jit(trace); + var start = Date.now(); + const width = 60; + const height = 60; + const max_iters = 50; + var output = []; + for (let img_x = 0; img_x < width; img_x++) { + for (let img_y = 0; img_y < height; img_y++) { + let C = new complex(-2 + (img_x / width) * 3, + -1.5 + (img_y / height) * 3); + var res = mandelbrotValueOO(C, max_iters); + if (output.length > 0 && output[output.length -1][0] == res) { + output[output.length-1][1]++; + } else { + output.push([res, 1]); + } + } + } + jit(false); + const reference = "[[2, 6], [3, 17], [4, 6], [5, 1], [50, 1], [5, 1], [4, 6], [3, 17], [2, 10], [3, 17], [4, 6], [5, 1], [6, 1], [50, 1], [6, 1], [5, 1], [4, 6], [3, 17], [2, 8], [3, 17], [4, 6], [5, 2], [6, 1], [50, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 6], [3, 17], [4, 6], [5, 2], [6, 1], [7, 1], [50, 1], [7, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 4], [3, 17], [4, 7], [5, 2], [6, 1], [8, 1], [50, 1], [8, 1], [6, 1], [5, 2], [4, 7], [3, 17], [2, 2], [3, 17], [4, 7], [5, 3], [6, 1], [9, 1], [50, 1], [9, 1], [6, 1], [5, 3], [4, 7], [3, 17], [2, 1], [3, 16], [4, 7], [5, 3], [6, 2], [8, 1], [50, 1], [8, 1], [6, 2], [5, 3], [4, 7], [3, 32], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 31], [4, 7], [5, 3], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 30], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 28], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [10, 1], [50, 1], [10, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 26], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [11, 1], [50, 1], [11, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 25], [4, 6], [5, 3], [6, 3], [7, 1], [8, 1], [18, 1], [13, 1], [15, 1], [50, 1], [15, 1], [13, 1], [18, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 6], [3, 24], [4, 7], [5, 2], [6, 2], [7, 3], [8, 1], [10, 1], [14, 1], [50, 3], [14, 1], [10, 1], [8, 1], [7, 3], [6, 2], [5, 2], [4, 7], [3, 23], [4, 6], [5, 3], [7, 1], [8, 1], [9, 1], [8, 2], [10, 1], [11, 1], [15, 1], [50, 3], [15, 1], [11, 1], [10, 1], [8, 2], [9, 1], [8, 1], [7, 1], [5, 3], [4, 6], [3, 22], [4, 7], [5, 2], [6, 1], [7, 1], [14, 1], [16, 1], [11, 1], [10, 1], [12, 1], [20, 1], [23, 1], [46, 1], [50, 1], [46, 1], [23, 1], [20, 1], [12, 1], [10, 1], [11, 1], [16, 1], [14, 1], [7, 1], [6, 1], [5, 2], [4, 7], [3, 20], [4, 7], [5, 3], [6, 1], [7, 1], [8, 1], [10, 1], [17, 1], [16, 1], [20, 1], [50, 7], [20, 1], [16, 1], [17, 1], [10, 1], [8, 1], [7, 1], [6, 1], [5, 3], [4, 7], [3, 19], [4, 7], [5, 3], [6, 2], [7, 1], [10, 1], [21, 1], [50, 11], [21, 1], [10, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 18], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [9, 1], [13, 1], [25, 1], [50, 9], [25, 1], [13, 1], [9, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 17], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [14, 2], [50, 11], [14, 2], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 16], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [11, 1], [36, 1], [50, 11], [36, 1], [11, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 15], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [14, 1], [50, 11], [14, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 14], [4, 7], [5, 4], [6, 3], [7, 1], [8, 1], [9, 1], [12, 1], [26, 1], [50, 9], [26, 1], [12, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 4], [4, 7], [3, 13], [4, 7], [5, 4], [6, 2], [7, 2], [8, 1], [9, 1], [10, 1], [15, 1], [50, 9], [15, 1], [10, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 4], [4, 7], [3, 12], [4, 7], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [10, 1], [12, 1], [16, 1], [50, 7], [16, 1], [12, 1], [10, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 7], [3, 11], [4, 6], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [11, 1], [12, 1], [14, 1], [17, 1], [23, 1], [34, 1], [50, 3], [34, 1], [23, 1], [17, 1], [14, 1], [12, 1], [11, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 6], [3, 10], [4, 7], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [22, 1], [12, 1], [50, 1], [25, 1], [50, 11], [25, 1], [50, 1], [12, 1], [22, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 7], [3, 9], [4, 6], [5, 4], [6, 1], [7, 1], [8, 2], [9, 1], [14, 1], [50, 1], [21, 1], [50, 15], [21, 1], [50, 1], [14, 1], [9, 1], [8, 2], [7, 1], [6, 1], [5, 4], [4, 6], [3, 8], [4, 7], [5, 3], [6, 2], [9, 1], [14, 1], [13, 1], [11, 1], [13, 1], [26, 1], [50, 17], [26, 1], [13, 1], [11, 1], [13, 1], [14, 1], [9, 1], [6, 2], [5, 3], [4, 7], [3, 7], [4, 6], [5, 4], [6, 1], [7, 1], [9, 1], [49, 1], [43, 1], [50, 23], [43, 1], [49, 1], [9, 1], [7, 1], [6, 1], [5, 4], [4, 6], [3, 7], [4, 5], [5, 4], [6, 2], [7, 1], [9, 1], [13, 1], [50, 25], [13, 1], [9, 1], [7, 1], [6, 2], [5, 4], [4, 5], [3, 6], [4, 6], [5, 3], [6, 2], [7, 2], [9, 1], [11, 1], [17, 1], [50, 23], [17, 1], [11, 1], [9, 1], [7, 2], [6, 2], [5, 3], [4, 6], [3, 5], [4, 5], [5, 3], [6, 3], [7, 1], [8, 1], [9, 1], [50, 1], [26, 1], [50, 23], [26, 1], [50, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 5], [4, 4], [5, 3], [6, 3], [7, 1], [8, 2], [10, 1], [21, 1], [50, 25], [21, 1], [10, 1], [8, 2], [7, 1], [6, 3], [5, 3], [4, 4], [3, 5], [4, 4], [5, 2], [6, 3], [7, 1], [12, 1], [9, 1], [10, 1], [11, 1], [50, 27], [11, 1], [10, 1], [9, 1], [12, 1], [7, 1], [6, 3], [5, 2], [4, 4], [3, 5], [4, 3], [5, 2], [6, 2], [7, 2], [9, 1], [42, 1], [15, 1], [23, 1], [14, 1], [50, 27], [14, 1], [23, 1], [15, 1], [42, 1], [9, 1], [7, 2], [6, 2], [5, 2], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [20, 1], [9, 1], [8, 1], [9, 1], [10, 1], [16, 1], [50, 33], [16, 1], [10, 1], [9, 1], [8, 1], [9, 1], [20, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [9, 1], [13, 1], [12, 1], [11, 1], [38, 1], [25, 1], [50, 33], [25, 1], [38, 1], [11, 1], [12, 1], [13, 1], [9, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 2], [6, 1], [7, 1], [10, 1], [24, 1], [25, 1], [50, 35], [25, 1], [24, 1], [10, 1], [7, 1], [6, 1], [5, 2], [4, 3], [3, 5], [4, 4], [5, 1], [6, 1], [7, 1], [11, 2], [13, 1], [19, 1], [50, 33], [19, 1], [13, 1], [11, 2], [7, 1], [6, 1], [5, 1], [4, 4], [3, 5], [4, 4], [5, 2], [6, 1], [50, 1], [8, 2], [17, 1], [19, 1], [35, 1], [14, 1], [24, 1], [50, 25], [24, 1], [14, 1], [35, 1], [19, 1], [17, 1], [8, 2], [50, 1], [6, 1], [5, 2], [4, 4], [3, 5], [4, 5], [5, 2], [6, 2], [7, 1], [8, 1], [9, 2], [11, 1], [38, 1], [50, 25], [38, 1], [11, 1], [9, 2], [8, 1], [7, 1], [6, 2], [5, 2], [4, 5], [3, 6], [4, 4], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [15, 1], [50, 25], [15, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 4], [3, 7], [4, 5], [5, 3], [6, 3], [7, 1], [9, 1], [42, 1], [21, 1], [50, 23], [21, 1], [42, 1], [9, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 8], [4, 5], [5, 3], [6, 2], [7, 1], [8, 1], [9, 1], [13, 1], [50, 23], [13, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 5], [3, 9], [4, 6], [5, 3], [6, 2], [7, 1], [9, 1], [14, 1], [50, 23], [14, 1], [9, 1], [7, 1], [6, 2], [5, 3], [4, 6], [3, 10], [4, 6], [5, 3], [6, 1], [7, 1], [9, 1], [16, 1], [50, 2], [35, 1], [50, 8], [13, 1], [50, 8], [35, 1], [50, 2], [16, 1], [9, 1], [7, 1], [6, 1], [5, 3], [4, 6], [3, 12], [4, 6], [5, 2], [6, 1], [19, 1], [16, 1], [17, 1], [25, 1], [21, 1], [13, 1], [18, 1], [50, 6], [11, 1], [9, 1], [11, 1], [50, 6], [18, 1], [13, 1], [21, 1], [25, 1], [17, 1], [16, 1], [19, 1], [6, 1], [5, 2], [4, 6], [3, 14], [4, 5], [5, 3], [6, 1], [8, 1], [16, 1], [10, 1], [8, 2], [11, 1], [50, 1], [16, 1], [15, 1], [32, 1], [29, 1], [9, 1], [8, 1], [7, 1], [8, 1], [9, 1], [29, 1], [32, 1], [15, 1], [16, 1], [50, 1], [11, 1], [8, 2], [10, 1], [16, 1], [8, 1], [6, 1], [5, 3], [4, 5], [3, 15], [4, 6], [5, 3], [6, 4], [7, 1], [20, 1], [19, 1], [9, 3], [7, 3], [6, 1], [7, 3], [9, 3], [19, 1], [20, 1], [7, 1], [6, 4], [5, 3], [4, 6], [3, 16], [4, 7], [5, 4], [6, 3], [7, 1], [6, 13], [7, 1], [6, 3], [5, 4], [4, 7], [3, 18], [4, 7], [5, 27], [4, 7], [3, 20], [4, 9], [5, 21], [4, 9], [3, 23], [4, 12], [5, 11], [4, 12], [3, 26], [4, 33], [3, 29], [4, 29], [3, 33], [4, 25], [3, 38], [4, 19], [3, 20], [2, 1], [3, 26], [4, 7], [3, 26], [2, 2], [3, 57], [2, 1]]"; + reportCompare(reference, output.toSource(), summary + ': correctness jit=' + trace); + return (Date.now() - start); +} + + +var timenonjit = f(false); +var timejit = f(true); + +expect = true; +actual = timejit < timenonjit; + +print('time nonjit: ' + timenonjit + ', time jit: ' + timejit); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-458838.js b/js/src/tests/js1_8_1/jit/regress-458838.js new file mode 100644 index 00000000000..0cc6991eb78 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-458838.js @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarksy + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 458838; +var summary = 'TM: do not fall off trace when nested function accesses var of outer function'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + jit(true); + + function f() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); + } + + expect = 10; + actual = f(); + + var recorderStarted; + var recorderAborted; + var traceCompleted; + var skip = true; + + if (this.tracemonkey && !this.tracemonkey.profiler) + { + recorderStarted = this.tracemonkey.recorderStarted; + recorderAborted = this.tracemonkey.recorderAborted; + traceCompleted = this.tracemonkey.traceCompleted; + skip = false; + } + + jit(false); + + reportCompare(expect, actual, summary + ': return value 10'); + + if (!skip) + { + expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; + actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; + reportCompare(expect, actual, summary + ': trace'); + } + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-462459-01.js b/js/src/tests/js1_8_1/jit/regress-462459-01.js new file mode 100644 index 00000000000..7cfe2a90ba4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-01.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array()'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-02.js b/js/src/tests/js1_8_1/jit/regress-462459-02.js new file mode 100644 index 00000000000..14cc20198c4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-02.js @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-03.js b/js/src/tests/js1_8_1/jit/regress-462459-03.js new file mode 100644 index 00000000000..a1d3db47083 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-03.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1, 2)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1, 2); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-04.js b/js/src/tests/js1_8_1/jit/regress-462459-04.js new file mode 100644 index 00000000000..3bfe7278b1e --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-04.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1, 2, 3)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1, 2, 3); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-05.js b/js/src/tests/js1_8_1/jit/regress-462459-05.js new file mode 100644 index 00000000000..5513b078e44 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-05.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array()'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-06.js b/js/src/tests/js1_8_1/jit/regress-462459-06.js new file mode 100644 index 00000000000..aab4093ab5a --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-06.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-07.js b/js/src/tests/js1_8_1/jit/regress-462459-07.js new file mode 100644 index 00000000000..0a9632a723d --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-07.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1, 2)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1, 2); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-08.js b/js/src/tests/js1_8_1/jit/regress-462459-08.js new file mode 100644 index 00000000000..2c57b27fde4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-08.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1, 2, 3)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1, 2, 3); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-09.js b/js/src/tests/js1_8_1/jit/regress-462459-09.js new file mode 100644 index 00000000000..221fc19c429 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-09.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace []'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + []; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-10.js b/js/src/tests/js1_8_1/jit/regress-462459-10.js new file mode 100644 index 00000000000..4917d5cf31b --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-10.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-11.js b/js/src/tests/js1_8_1/jit/regress-462459-11.js new file mode 100644 index 00000000000..2f7cb1c5945 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-11.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1, 2]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1, 2]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-12.js b/js/src/tests/js1_8_1/jit/regress-462459-12.js new file mode 100644 index 00000000000..524a7e4ae4c --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-12.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1, 2, 3]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1, 2, 3]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-469927.js b/js/src/tests/js1_8_1/jit/regress-469927.js new file mode 100644 index 00000000000..17b893674b1 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-469927.js @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469927; +var summary = 'TM: jit should not slow down short loop with let'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function letitbe() { + var start = new Date(); + for (let i = 0; i < 500000; ++i) { + for (let j = 0; j < 4; ++j) { } + } + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = letitbe(); + jit(true); + var timejit = letitbe(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-470739.js b/js/src/tests/js1_8_1/jit/regress-470739.js new file mode 100644 index 00000000000..b6b0e64e0f2 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-470739.js @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470739; +var summary = 'TM: never abort on =='; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function loop() + { + var i; + var start = new Date(); + + for(i=0;i<500000;++i) { var r = (void 0) == null; } + + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = loop(); + jit(true); + var timejit = loop(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-471635.js b/js/src/tests/js1_8_1/jit/regress-471635.js new file mode 100644 index 00000000000..76078649204 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-471635.js @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarksy + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 471635; +var summary = 'TM: trace js shell print()'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + jit(true); + + (function(){ + for (var i = 1; i < 20; ++i) { + print("#"); + } + })(); + + var recorderStarted; + var recorderAborted; + var traceCompleted; + var skip = true; + + if (this.tracemonkey && !this.tracemonkey.profiler) + { + recorderStarted = this.tracemonkey.recorderStarted; + recorderAborted = this.tracemonkey.recorderAborted; + traceCompleted = this.tracemonkey.traceCompleted; + skip = false; + } + + jit(false); + + if (!skip) + { + expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; + actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; + } + else + { + expect = actual = 'Test skipped due to lack of tracemonkey jitstats object.'; + } + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-489682.js b/js/src/tests/js1_8_1/jit/regress-489682.js new file mode 100644 index 00000000000..b8b73ec1ca7 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-489682.js @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 489682; +var summary = 'TM: wrong number with nested type-unstable loops'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +var v = 0; + +for each (var a in [0, {}, {}, {}]) { + print(v); + v = v >>> 0; + for each (var b in [{}, {}, new String(''), 42, new String(''), {}, 42]) + { + } + } +print(v); + +jit(false); + +expect = '0'; +actual = v + ''; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/shell.js b/js/src/tests/js1_8_1/jit/shell.js new file mode 100644 index 00000000000..63f283b96f8 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/shell.js @@ -0,0 +1,4 @@ +// The loop count at which we trace +const RECORDLOOP = this.tracemonkey ? tracemonkey.HOTLOOP : 8; +// The loop count at which we run the trace +const RUNLOOP = RECORDLOOP + 1; diff --git a/toolkit/crashreporter/tools/upload_symbols.sh b/toolkit/crashreporter/tools/upload_symbols.sh index d620fbf08ee..e3d6ebc35b9 100755 --- a/toolkit/crashreporter/tools/upload_symbols.sh +++ b/toolkit/crashreporter/tools/upload_symbols.sh @@ -44,9 +44,6 @@ # And will use the following optional environment variables if set: # SYMBOL_SERVER_SSH_KEY : path to a ssh private key to use # SYMBOL_SERVER_PORT : port to use for ssh -# POST_SYMBOL_UPLOAD_CMD: a commandline to run on the remote host after -# uploading. The full path of the symbol index -# file will be appended to the commandline. # set -e @@ -66,11 +63,4 @@ ssh -2 ${SYMBOL_SERVER_PORT:+-p $SYMBOL_SERVER_PORT} \ cd ${SYMBOL_SERVER_PATH}; unzip -o '$archive'; rm -v '$archive';" -if test -n "$POST_SYMBOL_UPLOAD_CMD"; then - echo "${POST_SYMBOL_UPLOAD_CMD} \"${SYMBOL_SERVER_PATH}/${SYMBOL_INDEX_NAME}\"" - ssh -2 ${SYMBOL_SERVER_PORT:+-p $SYMBOL_SERVER_PORT} \ - ${SYMBOL_SERVER_SSH_KEY:+-i "$SYMBOL_SERVER_SSH_KEY"} \ - -l ${SYMBOL_SERVER_USER} ${SYMBOL_SERVER_HOST} \ - "${POST_SYMBOL_UPLOAD_CMD} \"${SYMBOL_SERVER_PATH}/${SYMBOL_INDEX_NAME}\"" -fi echo "Symbol transfer completed" From 55244a7a5c071496f0fdea2695c33049cbc4cd07 Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Tue, 2 Nov 2010 14:09:08 +0100 Subject: [PATCH 160/263] bug 596087, update shipped-locales for beta7, adding gd and mk. a=blocker --- browser/locales/shipped-locales | 2 ++ 1 file changed, 2 insertions(+) diff --git a/browser/locales/shipped-locales b/browser/locales/shipped-locales index cbb6fc07b37..abb558f2e0b 100644 --- a/browser/locales/shipped-locales +++ b/browser/locales/shipped-locales @@ -21,6 +21,7 @@ fi fr fy-NL ga-IE +gd he hu hy-AM @@ -34,6 +35,7 @@ ku lg lt lv +mk nb-NO nl nn-NO From 3c1c65baa3e96ce23b01a35e0ddad0d0779b3abb Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Tue, 2 Nov 2010 15:28:19 +0100 Subject: [PATCH 161/263] bug 596087, update shipped-locales for beta7, adding eu. a=blocker --- browser/locales/shipped-locales | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/locales/shipped-locales b/browser/locales/shipped-locales index abb558f2e0b..50eab37b089 100644 --- a/browser/locales/shipped-locales +++ b/browser/locales/shipped-locales @@ -17,6 +17,7 @@ eo es-AR es-ES et +eu fi fr fy-NL From 6492961a2f5a3a31922ef123f2d018f6da5b5c45 Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Tue, 2 Nov 2010 10:46:19 -0700 Subject: [PATCH 162/263] Followup for review comment in bug 608545. a=b7+ --- netwerk/cookie/nsCookieService.cpp | 21 +++++++++++---------- netwerk/cookie/nsCookieService.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index 88e3ccf45e7..2312f05c5f5 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -1324,6 +1324,15 @@ nsCookieService::NotifyChanged(nsISupports *aSubject, mObserverService->NotifyObservers(aSubject, "cookie-changed", aData); } +void +nsCookieService::NotifyPurged(nsICookie2* aCookie) +{ + nsCOMPtr removedList = + do_CreateInstance(NS_ARRAY_CONTRACTID); + removedList->AppendElement(aCookie, PR_FALSE); + NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get()); +} + /****************************************************************************** * nsCookieService: * pref observer impl @@ -2336,11 +2345,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain, RemoveCookieFromList(matchIter); COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "stale cookie was purged"); - - nsCOMPtr removedList = - do_CreateInstance(NS_ARRAY_CONTRACTID); - removedList->AppendElement(oldCookie, PR_FALSE); - NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get()); + NotifyPurged(oldCookie); // We've done all we need to wrt removing and notifying the stale cookie. // From here on out, we pretend pretend it didn't exist, so that we @@ -2389,11 +2394,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain, // remove the oldest cookie from the domain RemoveCookieFromList(iter); COOKIE_LOGEVICTED(oldCookie, "Too many cookies for this domain"); - - nsCOMPtr removedList = - do_CreateInstance(NS_ARRAY_CONTRACTID); - removedList->AppendElement(oldCookie, PR_FALSE); - NotifyChanged(removedList, NS_LITERAL_STRING("batch-deleted").get()); + NotifyPurged(oldCookie); } else if (mDBState->cookieCount >= ADD_TEN_PERCENT(mMaxNumberOfCookies)) { PRInt64 maxAge = aCurrentTimeInUsec - mDBState->cookieOldestTime; diff --git a/netwerk/cookie/nsCookieService.h b/netwerk/cookie/nsCookieService.h index 46f722c9eee..8b848399ec6 100644 --- a/netwerk/cookie/nsCookieService.h +++ b/netwerk/cookie/nsCookieService.h @@ -251,6 +251,7 @@ class nsCookieService : public nsICookieService static void FindStaleCookie(nsCookieEntry *aEntry, PRInt64 aCurrentTime, nsListIter &aIter); void NotifyRejected(nsIURI *aHostURI); void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData); + void NotifyPurged(nsICookie2* aCookie); protected: // cached members. From 7e460ee2c74de9f0f6ffb6278b32699feebf6d13 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 2 Nov 2010 10:56:17 -0700 Subject: [PATCH 163/263] Backed out changeset 4a6259d13882 (bug 608810, a=blocking). --- .../tests/jaeger/testDenseCallElem.js | 89 ------------------ .../jit-test/tests/jaeger/testPropCallElem.js | 93 ------------------- .../tests/jaeger/testPropCallElem2.js | 20 ---- js/src/methodjit/Compiler.cpp | 18 ++-- js/src/methodjit/Compiler.h | 4 +- js/src/methodjit/FastOps.cpp | 63 +++---------- js/src/methodjit/PolyIC.cpp | 82 +--------------- js/src/methodjit/PolyIC.h | 1 - 8 files changed, 26 insertions(+), 344 deletions(-) delete mode 100644 js/src/jit-test/tests/jaeger/testDenseCallElem.js delete mode 100644 js/src/jit-test/tests/jaeger/testPropCallElem.js delete mode 100644 js/src/jit-test/tests/jaeger/testPropCallElem2.js 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 eadb77f55b9..00000000000 --- 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 fd067bbf7a5..00000000000 --- 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 328193ae4b2..00000000000 --- 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 66d4cd004f8..0a895bbc838 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1189,7 +1189,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) @@ -1766,7 +1766,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) @@ -4488,13 +4492,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 6307aa8513d..3bf27b46e14 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -351,7 +351,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(); @@ -417,8 +416,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); void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused); void 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 f9abaea567a..2f9dc0c77b5 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1360,39 +1360,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; } @@ -1420,14 +1411,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. @@ -1473,14 +1456,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 { @@ -1495,23 +1470,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 0c051bdad2d..df2b29e24e5 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 31341e53c9d..dad2448aedd 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 */ From d45729224ea147832a37970b5697329c9b41fb52 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 21 Oct 2010 10:39:51 -0700 Subject: [PATCH 164/263] Bug 594909 - Intermittent failure in browser/base/content/test/tabview/browser_tabview_launch.js | Tab View is visible r=dietrich, a=test --HG-- extra : rebase_source : ea0c0fc840f6679501b608958e75a4583889cce3 --- .../test/tabview/browser_tabview_launch.js | 27 +- js/src/jit-test/README | 74 --- js/src/jit-test/lib/prolog.js | 48 -- js/src/jit-test/tests/arguments/args6.js | 22 - js/src/jit-test/tests/arguments/args8.js | 14 - js/src/jit-test/tests/arguments/argsx-4.js | 23 - js/src/jit-test/tests/basic/arith.js | 11 - js/src/jit-test/tests/basic/bug520498.js | 9 - js/src/jit-test/tests/basic/bug522136.js | 10 - js/src/jit-test/tests/basic/bug528644.js | 16 - js/src/jit-test/tests/basic/bug578041.js | 3 - js/src/jit-test/tests/basic/bug584565.js | 10 - .../tests/basic/delete-named-names.js | 17 - .../jit-test/tests/basic/jitstatsArchFlags.js | 14 - js/src/jit-test/tests/basic/parseIntTests.js | 23 - .../tests/basic/strictParseIntOctal.js | 16 - .../testAssignmentThatIgnoresSetterRetval.js | 10 - js/src/jit-test/tests/basic/testBug458838.js | 19 - js/src/jit-test/tests/basic/testBug504520.js | 11 - .../tests/basic/testBug504520Harder.js | 33 -- js/src/jit-test/tests/basic/testBug552248.js | 36 -- js/src/jit-test/tests/basic/testBug579602.js | 21 - js/src/jit-test/tests/basic/testBug579646.js | 22 - js/src/jit-test/tests/basic/testBug584650.js | 9 - js/src/jit-test/tests/basic/testBug597736.js | 32 -- .../basic/testEliminatedGuardWithinAnchor.js | 12 - .../tests/basic/testHoleInDenseArray.js | 18 - .../jit-test/tests/basic/testIntOverflow.js | 15 - .../tests/basic/testMethodInitSafety.js | 14 - .../tests/basic/testNativeArgsRooting.js | 14 - .../tests/basic/testNestedDeepBail.js | 20 - .../tests/basic/testNestedExitStackOuter.js | 29 -- .../jit-test/tests/basic/testNewArrayCount.js | 12 - .../tests/basic/testNewArrayCount2.js | 8 - .../tests/basic/testProxyConstructors.js | 9 - .../jit-test/tests/basic/testRebranding2.js | 21 - .../basic/testReconstructImacroPCStack.js | 28 -- js/src/jit-test/tests/basic/testRegExpTest.js | 10 - .../basic/testScriptGetter_JSOP_CALLPROP.js | 11 - js/src/jit-test/tests/basic/testShiftLeft.js | 38 -- .../tests/basic/testShiftRightArithmetic.js | 44 -- .../tests/basic/testSideExitInConstructor.js | 39 -- .../tests/basic/testSlowNativeBail.js | 10 - .../tests/basic/testStackQuotaExhausted.js | 29 -- js/src/jit-test/tests/closures/bug540136.js | 17 - js/src/jit-test/tests/closures/bug540242.js | 17 - js/src/jit-test/tests/closures/bug540243.js | 10 - js/src/jit-test/tests/closures/bug541239.js | 16 - js/src/jit-test/tests/closures/lambda.js | 27 -- .../tests/closures/setname-inner-heavy.js | 18 - js/src/jit-test/tests/jaeger/bug554580-5.js | 20 - js/src/jit-test/tests/jaeger/bug555155.js | 12 - js/src/jit-test/tests/jaeger/bug555543.js | 8 - js/src/jit-test/tests/jaeger/bug556525.js | 5 - .../tests/jaeger/bug563000/eif-trap-newvar.js | 9 - .../jaeger/bug563000/eif-trap-typechange.js | 10 - .../tests/jaeger/bug563000/eif-trap.js | 10 - .../tests/jaeger/bug563000/simple-trap-1.js | 9 - .../tests/jaeger/bug563000/simple-trap-2.js | 10 - .../tests/jaeger/bug563000/simple-untrap.js | 11 - .../jaeger/bug563000/trap-force-return-1.js | 7 - .../jaeger/bug563000/trap-force-return-2.js | 7 - .../jaeger/bug563000/trap-own-callsite.js | 15 - .../jaeger/bug563000/trap-parent-from-trap.js | 21 - .../tests/jaeger/bug563000/trap-parent.js | 16 - .../jaeger/bug563000/trap-self-as-parent.js | 18 - .../jaeger/bug563000/trap-self-from-trap.js | 23 - .../tests/jaeger/bug563000/trap-self.js | 11 - .../jaeger/bug563000/untrap-own-trapsite.js | 15 - .../tests/jaeger/bug563000/untrap-self.js | 13 - js/src/jit-test/tests/jaeger/bug573433.js | 7 - js/src/jit-test/tests/jaeger/bug580884.js | 8 - js/src/jit-test/tests/jaeger/bug582286.js | 3 - js/src/jit-test/tests/jaeger/bug583158.js | 9 - js/src/jit-test/tests/jaeger/bug585341.js | 6 - js/src/jit-test/tests/jaeger/bug588338.js | 14 - js/src/jit-test/tests/jaeger/bug588363-2.js | 7 - .../jit-test/tests/jaeger/crash-on-compare.js | 1 - js/src/jit-test/tests/jaeger/fused-eq-ifeq.js | 6 - js/src/jit-test/tests/pic/bug558099.js | 60 --- .../sunspider/check-date-format-xparb.js | 422 ------------------ .../sunspider/check-math-partial-sums.js | 41 -- .../tests/sunspider/check-string-tagcloud.js | 270 ----------- js/src/tests/js1_8_1/jit/jstests.list | 24 - js/src/tests/js1_8_1/jit/regress-451673.js | 115 ----- js/src/tests/js1_8_1/jit/regress-451974-01.js | 86 ---- js/src/tests/js1_8_1/jit/regress-451974-02.js | 97 ---- js/src/tests/js1_8_1/jit/regress-452498-01.js | 105 ----- js/src/tests/js1_8_1/jit/regress-458838.js | 97 ---- js/src/tests/js1_8_1/jit/regress-462459-01.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-02.js | 106 ----- js/src/tests/js1_8_1/jit/regress-462459-03.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-04.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-05.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-06.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-07.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-08.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-09.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-10.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-11.js | 107 ----- js/src/tests/js1_8_1/jit/regress-462459-12.js | 107 ----- js/src/tests/js1_8_1/jit/regress-469927.js | 78 ---- js/src/tests/js1_8_1/jit/regress-470739.js | 80 ---- js/src/tests/js1_8_1/jit/regress-471635.js | 90 ---- js/src/tests/js1_8_1/jit/regress-489682.js | 65 --- js/src/tests/js1_8_1/jit/shell.js | 4 - 106 files changed, 21 insertions(+), 4223 deletions(-) delete mode 100644 js/src/jit-test/README delete mode 100644 js/src/jit-test/lib/prolog.js delete mode 100644 js/src/jit-test/tests/arguments/args6.js delete mode 100644 js/src/jit-test/tests/arguments/args8.js delete mode 100644 js/src/jit-test/tests/arguments/argsx-4.js delete mode 100644 js/src/jit-test/tests/basic/arith.js delete mode 100644 js/src/jit-test/tests/basic/bug520498.js delete mode 100644 js/src/jit-test/tests/basic/bug522136.js delete mode 100644 js/src/jit-test/tests/basic/bug528644.js delete mode 100644 js/src/jit-test/tests/basic/bug578041.js delete mode 100644 js/src/jit-test/tests/basic/bug584565.js delete mode 100644 js/src/jit-test/tests/basic/delete-named-names.js delete mode 100644 js/src/jit-test/tests/basic/jitstatsArchFlags.js delete mode 100644 js/src/jit-test/tests/basic/parseIntTests.js delete mode 100644 js/src/jit-test/tests/basic/strictParseIntOctal.js delete mode 100644 js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js delete mode 100644 js/src/jit-test/tests/basic/testBug458838.js delete mode 100644 js/src/jit-test/tests/basic/testBug504520.js delete mode 100644 js/src/jit-test/tests/basic/testBug504520Harder.js delete mode 100644 js/src/jit-test/tests/basic/testBug552248.js delete mode 100644 js/src/jit-test/tests/basic/testBug579602.js delete mode 100644 js/src/jit-test/tests/basic/testBug579646.js delete mode 100644 js/src/jit-test/tests/basic/testBug584650.js delete mode 100644 js/src/jit-test/tests/basic/testBug597736.js delete mode 100644 js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js delete mode 100644 js/src/jit-test/tests/basic/testHoleInDenseArray.js delete mode 100644 js/src/jit-test/tests/basic/testIntOverflow.js delete mode 100644 js/src/jit-test/tests/basic/testMethodInitSafety.js delete mode 100644 js/src/jit-test/tests/basic/testNativeArgsRooting.js delete mode 100644 js/src/jit-test/tests/basic/testNestedDeepBail.js delete mode 100644 js/src/jit-test/tests/basic/testNestedExitStackOuter.js delete mode 100644 js/src/jit-test/tests/basic/testNewArrayCount.js delete mode 100644 js/src/jit-test/tests/basic/testNewArrayCount2.js delete mode 100644 js/src/jit-test/tests/basic/testProxyConstructors.js delete mode 100644 js/src/jit-test/tests/basic/testRebranding2.js delete mode 100644 js/src/jit-test/tests/basic/testReconstructImacroPCStack.js delete mode 100644 js/src/jit-test/tests/basic/testRegExpTest.js delete mode 100644 js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js delete mode 100644 js/src/jit-test/tests/basic/testShiftLeft.js delete mode 100644 js/src/jit-test/tests/basic/testShiftRightArithmetic.js delete mode 100644 js/src/jit-test/tests/basic/testSideExitInConstructor.js delete mode 100644 js/src/jit-test/tests/basic/testSlowNativeBail.js delete mode 100644 js/src/jit-test/tests/basic/testStackQuotaExhausted.js delete mode 100644 js/src/jit-test/tests/closures/bug540136.js delete mode 100644 js/src/jit-test/tests/closures/bug540242.js delete mode 100644 js/src/jit-test/tests/closures/bug540243.js delete mode 100644 js/src/jit-test/tests/closures/bug541239.js delete mode 100644 js/src/jit-test/tests/closures/lambda.js delete mode 100644 js/src/jit-test/tests/closures/setname-inner-heavy.js delete mode 100644 js/src/jit-test/tests/jaeger/bug554580-5.js delete mode 100644 js/src/jit-test/tests/jaeger/bug555155.js delete mode 100644 js/src/jit-test/tests/jaeger/bug555543.js delete mode 100644 js/src/jit-test/tests/jaeger/bug556525.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js delete mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-self.js delete mode 100644 js/src/jit-test/tests/jaeger/bug573433.js delete mode 100644 js/src/jit-test/tests/jaeger/bug580884.js delete mode 100644 js/src/jit-test/tests/jaeger/bug582286.js delete mode 100644 js/src/jit-test/tests/jaeger/bug583158.js delete mode 100644 js/src/jit-test/tests/jaeger/bug585341.js delete mode 100644 js/src/jit-test/tests/jaeger/bug588338.js delete mode 100644 js/src/jit-test/tests/jaeger/bug588363-2.js delete mode 100644 js/src/jit-test/tests/jaeger/crash-on-compare.js delete mode 100644 js/src/jit-test/tests/jaeger/fused-eq-ifeq.js delete mode 100644 js/src/jit-test/tests/pic/bug558099.js delete mode 100644 js/src/jit-test/tests/sunspider/check-date-format-xparb.js delete mode 100644 js/src/jit-test/tests/sunspider/check-math-partial-sums.js delete mode 100644 js/src/jit-test/tests/sunspider/check-string-tagcloud.js delete mode 100644 js/src/tests/js1_8_1/jit/jstests.list delete mode 100644 js/src/tests/js1_8_1/jit/regress-451673.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-451974-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-451974-02.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-452498-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-458838.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-01.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-02.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-03.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-04.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-05.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-06.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-07.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-08.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-09.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-10.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-11.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-462459-12.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-469927.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-470739.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-471635.js delete mode 100644 js/src/tests/js1_8_1/jit/regress-489682.js delete mode 100644 js/src/tests/js1_8_1/jit/shell.js diff --git a/browser/base/content/test/tabview/browser_tabview_launch.js b/browser/base/content/test/tabview/browser_tabview_launch.js index 661ecf3be38..c8673e9f1e6 100644 --- a/browser/base/content/test/tabview/browser_tabview_launch.js +++ b/browser/base/content/test/tabview/browser_tabview_launch.js @@ -55,13 +55,28 @@ function test() { function onTabViewLoadedAndShown() { window.removeEventListener("tabviewshown", onTabViewLoadedAndShown, false); - ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); - tabViewShownCount++; + // Evidently sometimes isVisible (which is based on the selectedIndex of the + // tabview deck) isn't updated immediately when called from button.doCommand, + // so we add a little timeout here to get outside of the doCommand call. + // If the initial timeout isn't enough, we keep waiting in case it's taking + // longer than expected. + // See bug 594909. + let deck = document.getElementById("tab-view-deck"); + function waitForSwitch() { + if (deck.selectedIndex == 1) { + ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); + tabViewShownCount++; + + // kick off the series + window.addEventListener("tabviewshown", onTabViewShown, false); + window.addEventListener("tabviewhidden", onTabViewHidden, false); + TabView.toggle(); + } else { + setTimeout(waitForSwitch, 10); + } + } - // kick off the series - window.addEventListener("tabviewshown", onTabViewShown, false); - window.addEventListener("tabviewhidden", onTabViewHidden, false); - TabView.toggle(); + setTimeout(waitForSwitch, 1); } // ---------- diff --git a/js/src/jit-test/README b/js/src/jit-test/README deleted file mode 100644 index ddde38dc962..00000000000 --- a/js/src/jit-test/README +++ /dev/null @@ -1,74 +0,0 @@ -JS Trace Test Suite - -* PURPOSE - -This is a test suite for testing TraceMonkey. All tests are run in the JS shell -with tracing enabled (-j). - -* REQUIREMENTS - -Python 2.5. This is already a standard requirement for building our tree. - -* RUNNING THE TESTS - -Basic usage: - - python jit_test.py - -The progress bar shows [#tests passed, #tests failed, #tests run] at the left. -If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted -at any time with Ctrl+C and partial results will be printed. - -To run only the basic tests, not including the slow tests: - - python jit_test.py basic - -For more options: - - python jit_test.py -h - -* CREATING NEW TESTS - -Simply create a JS file under the 'tests/' directory. Most tests should go in -'tests/basic/'. - -All tests are run with 'lib/prolog.js' included first on the command line. The -command line also creates a global variable 'libdir' that is set to the path -of the 'lib' directory. To include a file 'foo.js' from the lib directory in a -test case: - - load(libdir + 'foo.js') - -* TEST METALINES - -The first line of a test case can contain a special comment controlling how the -test is run. For example: - - // |jit-test| allow-oom; - -The general format in EBNF is: - - metaline ::= cookie { item ";" } - cookie ::= "|jit-test|" - item ::= flag | attribute - - flag ::= "slow" | "allow-oom" - - attribute ::= name ":" value - name ::= "TMFLAGS" | "error" - value ::= - -The metaline may appear anywhere in the first line of the file: this allows it -to be placed inside any kind of comment. - -The meaning of the items: - - slow Test runs slowly. Do not run if the --no-slow option is given. - allow-oom If the test runs out of memory, it counts as passing. - valgrind Run test under valgrind. - - error The test should be considered to pass iff it throws the - given JS exception. - TMFLAGS Set the environment variable TMFLAGS to the given value. - -* END diff --git a/js/src/jit-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js deleted file mode 100644 index 5d577b39bda..00000000000 --- a/js/src/jit-test/lib/prolog.js +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -const HAVE_TM = 'tracemonkey' in this; - -const HOTLOOP = HAVE_TM ? tracemonkey.HOTLOOP : 8; -const RECORDLOOP = HOTLOOP; -const RUNLOOP = HOTLOOP + 1; - -var checkStats; -if (HAVE_TM) { - checkStats = function(stats) - { - // Temporarily disabled while we work on heuristics. - return; - function jit(on) - { - if (on && !options().match(/tracejit/)) - { - options('tracejit'); - } - else if (!on && options().match(/tracejit/)) - { - options('tracejit'); - } - } - - jit(false); - for (var name in stats) { - var expected = stats[name]; - var actual = tracemonkey[name]; - if (expected != actual) { - print('Trace stats check failed: got ' + actual + ', expected ' + expected + ' for ' + name); - } - } - jit(true); - }; -} else { - checkStats = function() {}; -} - -var appendToActual = function(s) { - actual += s + ','; -} - -if (!("gczeal" in this)) { - gczeal = function() { } -} - diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js deleted file mode 100644 index a2fc60d36a8..00000000000 --- a/js/src/jit-test/tests/arguments/args6.js +++ /dev/null @@ -1,22 +0,0 @@ -actual = ''; -expected = '6,'; - -// tracing length - -var g = 0; - -function h(args) { - g = args.length; -} - -function f() { - h(arguments); -} - -for (var i = 0; i < 5; ++i) { - f(10, 20, 30, 40, 50, 60); -} -appendToActual(g); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js deleted file mode 100644 index 57938d9e231..00000000000 --- a/js/src/jit-test/tests/arguments/args8.js +++ /dev/null @@ -1,14 +0,0 @@ -actual = ''; -expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],'; - -function h() { - return arguments; -} - -for (var i = 0; i < 5; ++i) { - var p = h(i, i*2); - appendToActual(p); -} - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js deleted file mode 100644 index b52b14853cf..00000000000 --- a/js/src/jit-test/tests/arguments/argsx-4.js +++ /dev/null @@ -1,23 +0,0 @@ -actual = ''; -expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,'; - -function f() { - g(arguments); -} - -function g(a, b, c) { - h(arguments); - a = 1; - b = 2; - c = 3; - h(arguments); -} - -function h(a, b, c) { - appendToActual(a + ' ' + b + ' ' + c); -} - -f(4, 5, 6); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/basic/arith.js b/js/src/jit-test/tests/basic/arith.js deleted file mode 100644 index b7f551dccd0..00000000000 --- a/js/src/jit-test/tests/basic/arith.js +++ /dev/null @@ -1,11 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis - -function arith() -{ - var accum = 0; - for (var i = 0; i < 100; i++) { - accum += (i * 2) - 1; - } - return accum; -} -assertEq(arith(), 9800); diff --git a/js/src/jit-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js deleted file mode 100644 index 55324f6f30d..00000000000 --- a/js/src/jit-test/tests/basic/bug520498.js +++ /dev/null @@ -1,9 +0,0 @@ -var Q = 0; -try { - (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) -} catch (e) { -} - -if (Q == 100000) - assertEq(Q, "fail"); - diff --git a/js/src/jit-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js deleted file mode 100644 index 9267c99ccfa..00000000000 --- a/js/src/jit-test/tests/basic/bug522136.js +++ /dev/null @@ -1,10 +0,0 @@ -var Q = 0; -try { - (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) -} catch (e) { -} - -// Exact behavior of recursion check depends on which JIT we use. -var ok = (Q == 3000 || Q == 3001); -assertEq(ok, true); - diff --git a/js/src/jit-test/tests/basic/bug528644.js b/js/src/jit-test/tests/basic/bug528644.js deleted file mode 100644 index 260e0d99590..00000000000 --- a/js/src/jit-test/tests/basic/bug528644.js +++ /dev/null @@ -1,16 +0,0 @@ -// Don't crash - -function g(foo) { - for (a in foo) { - } -} - -var makegen = eval("\n\ - (function(b) {\n\ - var h = \n\ - eval(\"new function() { yield print(b) }\" ); \n\ - return h\n\ - })\n\ -"); - -g(makegen()); diff --git a/js/src/jit-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js deleted file mode 100644 index 7a81feb1800..00000000000 --- a/js/src/jit-test/tests/basic/bug578041.js +++ /dev/null @@ -1,3 +0,0 @@ -__defineGetter__('x', Float32Array); -with(this) - x; diff --git a/js/src/jit-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js deleted file mode 100644 index ad7d4b47577..00000000000 --- a/js/src/jit-test/tests/basic/bug584565.js +++ /dev/null @@ -1,10 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ -// Contributor: Luke Wagner - -var x, f; -for (var i = 0; i < 100; i++) { - f = function() {}; - f.foo; - x = f.length; -} diff --git a/js/src/jit-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js deleted file mode 100644 index 1e0ac407321..00000000000 --- a/js/src/jit-test/tests/basic/delete-named-names.js +++ /dev/null @@ -1,17 +0,0 @@ -var a = ['p', 'q', 'r', 's', 't']; -var o = {p:1, q:2, r:3, s:4, t:5}; -for (var i in o) { - delete o.p; - delete o.q; - delete o.r; - delete o.s; - delete o.t; -} -for each (var i in a) - assertEq(o.hasOwnProperty(i), false); - -checkStats({ - recorderAborted:0, - traceCompleted:1, - sideExitIntoInterpreter:1 -}); diff --git a/js/src/jit-test/tests/basic/jitstatsArchFlags.js b/js/src/jit-test/tests/basic/jitstatsArchFlags.js deleted file mode 100644 index a4ec0c4ee4b..00000000000 --- a/js/src/jit-test/tests/basic/jitstatsArchFlags.js +++ /dev/null @@ -1,14 +0,0 @@ -// Make sure the arch flags are valid on startup, even if nothing has -// been traced yet. We don't know what arch the user is building on, -// but presumably we want at least 1 flag to be set on all supported -// platforms. - -if (HAVE_TM) { - assertEq(jitstats.archIsIA32 || - jitstats.archIs64BIT || - jitstats.archIsARM || - jitstats.archIsSPARC || - jitstats.archIsPPC || - jitstats.archIsAMD64, - 1); - } diff --git a/js/src/jit-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js deleted file mode 100644 index c8ecb366556..00000000000 --- a/js/src/jit-test/tests/basic/parseIntTests.js +++ /dev/null @@ -1,23 +0,0 @@ -function parseIntHelper(n) { - var a; - for (var i = 0; i < 5; i++) - a = parseInt(n); - return a; -} -function doParseIntTests() { - var inputs = [0, -0, .1, -.1, .7, -.7, 1.3, -1.3]; - var outputs = new Array(8); - //avoid jit, unrolled - outputs[0] = outputs[1] = outputs[2] = outputs[4] = 0; - outputs[3] = outputs[5] = -0; - outputs[6] = 1; - outputs[7] = -1; - for (var i = 0; i < 8; i++) { - var testfn = new Function('return parseIntHelper(' + uneval(inputs[i]) + ');'); - assertEq(testfn(), outputs[i]); - } -} -doParseIntTests(); - -assertEq(parseInt("08"), 0); -assertEq(parseInt("09"), 0); diff --git a/js/src/jit-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js deleted file mode 100644 index 536d2d7dd0c..00000000000 --- a/js/src/jit-test/tests/basic/strictParseIntOctal.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -assertEq(parseInt("08"), 0); -assertEq(parseInt("09"), 0); -assertEq(parseInt("014"), 12); -assertEq(parseInt("0xA"), 10); -assertEq(parseInt("00123"), 83); - -for (var i = 0; i < 5; i++) -{ - assertEq(parseInt("08"), 0); - assertEq(parseInt("09"), 0); - assertEq(parseInt("014"), 12); - assertEq(parseInt("0xA"), 10); - assertEq(parseInt("00123"), 83); -} diff --git a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js deleted file mode 100644 index 1c59113482d..00000000000 --- a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js +++ /dev/null @@ -1,10 +0,0 @@ -var o = { - set x(v) { - return 42; - } -}; - -for (var i = 0; i < 10; ++i) { - var z = o.x = "choose me"; - assertEq(z, "choose me"); -} diff --git a/js/src/jit-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js deleted file mode 100644 index cd1e05cf77b..00000000000 --- a/js/src/jit-test/tests/basic/testBug458838.js +++ /dev/null @@ -1,19 +0,0 @@ -var escape; -function testBug458838() { - var a = 1; - function g() { - var b = 0 - for (var i = 0; i < 10; ++i) { - b += a; - } - return b; - } - - return g(); -} -assertEq(testBug458838(), 10); -checkStats({ - recorderStarted: 1, - recorderAborted: 0, - traceCompleted: 1 -}); diff --git a/js/src/jit-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js deleted file mode 100644 index 73e2e3013fb..00000000000 --- a/js/src/jit-test/tests/basic/testBug504520.js +++ /dev/null @@ -1,11 +0,0 @@ -function testBug504520() { - // A bug involving comparisons. - var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 0]; - assertEq(arr.length > RUNLOOP, true); - - var s = ''; - for (var i = 0; i < arr.length; i++) - arr[i] >= 1/0 ? null : (s += i); - assertEq(s, '9'); -} -testBug504520(); diff --git a/js/src/jit-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js deleted file mode 100644 index 0a63ebf4075..00000000000 --- a/js/src/jit-test/tests/basic/testBug504520Harder.js +++ /dev/null @@ -1,33 +0,0 @@ -function testBug504520Harder() { - // test 1024 similar cases - var vals = [1/0, -1/0, 0, 0/0]; - var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; - for each (var x in vals) { - for each (var y in vals) { - for each (var op in ops) { - for each (var z in vals) { - // Assume eval is correct. This depends on the global - // Infinity property not having been reassigned. - var xz = eval(x + op + z); - var yz = eval(y + op + z); - - var arr = [x, x, x, x, x, x, x, x, x, y]; - assertEq(arr.length > RUNLOOP, true); - var expected = [xz, xz, xz, xz, xz, xz, xz, xz, xz, yz]; - - // ?: looks superfluous but that's what we're testing here - var fun = eval( - '(function (arr, results) {\n' + - ' for (let i = 0; i < arr.length; i++)\n' + - ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + - '});\n'); - var actual = []; - fun(arr, actual); - print(x, y, op, z); - assertEq("" + actual, "" + expected); - } - } - } - } -} -testBug504520Harder(); diff --git a/js/src/jit-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js deleted file mode 100644 index 28782b665bb..00000000000 --- a/js/src/jit-test/tests/basic/testBug552248.js +++ /dev/null @@ -1,36 +0,0 @@ -setDebug(true); -var a = new Array(); - -function i(save) { - var x = 9; - evalInFrame(0, "a.push(x)", save); - evalInFrame(1, "a.push(z)", save); - evalInFrame(2, "a.push(z)", save); - evalInFrame(3, "a.push(y)", save); - evalInFrame(4, "a.push(x)", save); -} - -function h() { - var z = 5; - evalInFrame(0, "a.push(z)"); - evalInFrame(1, "a.push(y)"); - evalInFrame(2, "a.push(x)"); - evalInFrame(0, "i(false)"); - evalInFrame(0, "a.push(z)", true); - evalInFrame(1, "a.push(y)", true); - evalInFrame(2, "a.push(x)", true); - evalInFrame(0, "i(true)", true); -} - -function g() { - var y = 4; - h(); -} - -function f() { - var x = 3; - g(); -} - -f(); -assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+''); diff --git a/js/src/jit-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js deleted file mode 100644 index 5871c24d46e..00000000000 --- a/js/src/jit-test/tests/basic/testBug579602.js +++ /dev/null @@ -1,21 +0,0 @@ -// don't panic - -f = function() { - x = yield -} -rv = f() -for (a in rv) (function() {}) -x = Proxy.create((function() { - return { - defineProperty: gc - } -})(), x) -with({ - d: (({ - x: Object.defineProperty(x, "", ({ - set: Array.e - })) - })) -}) {} - -// don't crash diff --git a/js/src/jit-test/tests/basic/testBug579646.js b/js/src/jit-test/tests/basic/testBug579646.js deleted file mode 100644 index d034410f9cc..00000000000 --- a/js/src/jit-test/tests/basic/testBug579646.js +++ /dev/null @@ -1,22 +0,0 @@ -if (typeof gczeal != "function") - gczeal = function() {} - -for (a = 0; a < 9; a++) - for (b = 0; b < 1; b++) - for (c = 0; c < 2; c++) - gczeal(); - -for each(e in [NaN]) - for (d = 0; d < 1; d++) - z = 0; - -for (w in [0, 0]) - {} - -x = 0; - -for (e = 0; e < 3; e++) - for (f = 0; f < 4; f++) - x = -x - -// don't crash diff --git a/js/src/jit-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js deleted file mode 100644 index b6c9d8ab7fd..00000000000 --- a/js/src/jit-test/tests/basic/testBug584650.js +++ /dev/null @@ -1,9 +0,0 @@ -if (typeof gczeal != "function") - gczeal = function() {} - -// don't crash -x = (evalcx('lazy')) -x.watch("", function () {}) -gczeal(1) -for (w in x) {} - diff --git a/js/src/jit-test/tests/basic/testBug597736.js b/js/src/jit-test/tests/basic/testBug597736.js deleted file mode 100644 index ded33842776..00000000000 --- a/js/src/jit-test/tests/basic/testBug597736.js +++ /dev/null @@ -1,32 +0,0 @@ -function leak_test() { - // Create a reference loop function->script->traceFragment->object->function - // that GC must be able to break. To embedd object into the fragment the - // code use prototype chain of depth 2 which caches obj.__proto__.__proto__ - // into the fragment. - - // To make sure that we have no references to the function f after this - // function returns due via the conservative scan of the native stack we - // loop here multiple times overwriting the stack and registers with new garabge. - for (var j = 0; j != 8; ++j) { - var f = Function("a", "var s = 0; for (var i = 0; i != 100; ++i) s += a.b; return s;"); - var c = {b: 1, f: f, leakDetection: makeFinalizeObserver()}; - f({ __proto__: { __proto__: c}}); - f = c = a = null; - gc(); - } -} - -function test() -{ - if (typeof finalizeCount != "function") - return; - - var base = finalizeCount(); - leak_test(); - gc(); - gc(); - var n = finalizeCount(); - assertEq(base + 4 < finalizeCount(), true, "Some finalizations must happen"); -} - -test(); diff --git a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js deleted file mode 100644 index cc80e779c37..00000000000 --- a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js +++ /dev/null @@ -1,12 +0,0 @@ -function testEliminatedGuardWithinAnchor() { - for (let i = 0; i < 5; ++i) { i / (i * i); } - return "ok"; -} - -assertEq(testEliminatedGuardWithinAnchor(), "ok"); - -if (HAVE_TM) { - checkStats({ - sideExitIntoInterpreter: (jitstats.archIsARM ? 1 : 3) - }); -} diff --git a/js/src/jit-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js deleted file mode 100644 index ba7a2c01e16..00000000000 --- a/js/src/jit-test/tests/basic/testHoleInDenseArray.js +++ /dev/null @@ -1,18 +0,0 @@ -var s; - -function f(i) { - if (i > 4) /* side exit when arr[i] changes from bool to undefined (via a hole) */ - assertEq(s, undefined); - else - assertEq(s, false); - return 1; -} - -/* trailing 'true' ensures array has capacity >= 10 */ -var arr = [ false, false, false, false, false, , , , , , true ]; - -for (var i = 0; i < 10; ++i) { - (s = arr[i]) + f(i); -} - -checkStats({ traceTriggered: 2, sideExitIntoInterpreter: 2 }) diff --git a/js/src/jit-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js deleted file mode 100644 index 712ef0c6529..00000000000 --- a/js/src/jit-test/tests/basic/testIntOverflow.js +++ /dev/null @@ -1,15 +0,0 @@ -function testIntOverflow() { - // int32_max - 7 - var ival = 2147483647 - 7; - for (var i = 0; i < 30; i++) { - ival += 30; - } - return (ival < 2147483647); -} -assertEq(testIntOverflow(), false); -checkStats({ - recorderStarted: 1, - recorderAborted: 0, - traceCompleted: 1, - traceTriggered: 1, -}); diff --git a/js/src/jit-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js deleted file mode 100644 index ebd6309bdf9..00000000000 --- a/js/src/jit-test/tests/basic/testMethodInitSafety.js +++ /dev/null @@ -1,14 +0,0 @@ -function testMethodInitSafety() { - function f() { return 'fail'; } - function g() { return 'ok'; } - - var s; - var arr = [f, f, f, f, g]; - //assertEq(arr.length > RUNLOOP, true); - for (var i = 0; i < arr.length; i++) { - var x = {m: arr[i]}; - s = x.m(); - } - return s; -} -assertEq(testMethodInitSafety(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js deleted file mode 100644 index 1ce8259f2d4..00000000000 --- a/js/src/jit-test/tests/basic/testNativeArgsRooting.js +++ /dev/null @@ -1,14 +0,0 @@ -if ('gczeal' in this) -(function () { - (eval("\ - (function () {\ - for (var y = 0; y < 16; ++y) {\ - if (y % 3 == 2) {\ - gczeal(1);\ - } else {\ - print(0 / 0);\ - }\ - }\ - });\ - "))() -})(); diff --git a/js/src/jit-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js deleted file mode 100644 index 8e59b04cdaa..00000000000 --- a/js/src/jit-test/tests/basic/testNestedDeepBail.js +++ /dev/null @@ -1,20 +0,0 @@ -var _quit; -function testNestedDeepBail() -{ - _quit = false; - function loop() { - for (var i = 0; i < 4; i++) - ; - } - loop(); - - function f() { - loop(); - _quit = true; - } - - var stk = [[1], [], [], [], []]; - while (!_quit) - stk.pop().forEach(f); -} -testNestedDeepBail(); diff --git a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js deleted file mode 100644 index 88b795e7cbc..00000000000 --- a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js +++ /dev/null @@ -1,29 +0,0 @@ -// Test stack reconstruction after a nested exit -function testNestedExitStackInner(j, counter) { - ++counter; - var b = 0; - for (var i = 1; i <= RUNLOOP; i++) { - ++b; - var a; - // Make sure that once everything has been traced we suddenly switch to - // a different control flow the first time we run the outermost tree, - // triggering a side exit. - if (j < RUNLOOP) - a = 1; - else - a = 0; - ++b; - b += a; - } - return counter + b; -} -function testNestedExitStackOuter() { - var counter = 0; - for (var j = 1; j <= RUNLOOP; ++j) { - for (var k = 1; k <= RUNLOOP; ++k) { - counter = testNestedExitStackInner(j, counter); - } - } - return counter; -} -//assertEq(testNestedExitStackOuter(), 81); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js deleted file mode 100644 index cb7e6d9843c..00000000000 --- a/js/src/jit-test/tests/basic/testNewArrayCount.js +++ /dev/null @@ -1,12 +0,0 @@ -function testNewArrayCount() -{ - function count(a) { var n = 0; for (var p in a) n++; return n; } - var a = []; - for (var i = 0; i < 5; i++) - a = [0]; - assertEq(count(a), 1); - for (var i = 0; i < 5; i++) - a = [0, , 2]; - assertEq(count(a), 2); -} -testNewArrayCount(); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js deleted file mode 100644 index 6318e4c25f3..00000000000 --- a/js/src/jit-test/tests/basic/testNewArrayCount2.js +++ /dev/null @@ -1,8 +0,0 @@ -function testNewArrayCount2() { - function count(a) { var n = 0; for (var p in a) n++; return n; } - var x = 0; - for (var i = 0; i < 10; ++i) - x = count(new Array(1,2,3)); - return x; -} -assertEq(testNewArrayCount2(), 3); diff --git a/js/src/jit-test/tests/basic/testProxyConstructors.js b/js/src/jit-test/tests/basic/testProxyConstructors.js deleted file mode 100644 index e716b361ef0..00000000000 --- a/js/src/jit-test/tests/basic/testProxyConstructors.js +++ /dev/null @@ -1,9 +0,0 @@ -// proxies can return primitives -assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined); - -x = Proxy.createFunction((function () {}), Uint16Array, wrap) -new(wrap(x)) - -// proxies can return the callee -var x = Proxy.createFunction({}, function (q) { return q; }); -new x(x); diff --git a/js/src/jit-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js deleted file mode 100644 index 2bf26eeaff5..00000000000 --- a/js/src/jit-test/tests/basic/testRebranding2.js +++ /dev/null @@ -1,21 +0,0 @@ -delete q; -delete g; -delete h; -delete a; -delete f; - -function testRebranding2() { - // Same as testRebranding, but the object to be rebranded isn't the global. - var x = "FAIL"; - function g(){} - function h(){ x = "ok"; } - var obj = {m: g}; - var arr = [g, g, g, g, h]; - //assertEq(arr.length > RUNLOOP, true); - for (var i = 0; i < 5; i++) { - obj.m = arr[i]; - obj.m(); - } - return x; -} -assertEq(testRebranding2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js deleted file mode 100644 index 2dc51508d4f..00000000000 --- a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js +++ /dev/null @@ -1,28 +0,0 @@ -x = Proxy.create((function () { - return { - get: function () {} - } -}()), Object.e) - -var hit = false; - -try { - Function("\ - for(var a = 0; a < 2; ++a) {\ - if (a == 0) {}\ - else {\ - x > x\ - }\ - }\ - ")() -} catch (e) { - hit = true; - - var str = String(e); - var match = (str == "TypeError: x is not a function" || - str == "TypeError: can't convert x to number"); - - assertEq(match, true); -} - -assertEq(hit, true); diff --git a/js/src/jit-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js deleted file mode 100644 index 78917ba9be3..00000000000 --- a/js/src/jit-test/tests/basic/testRegExpTest.js +++ /dev/null @@ -1,10 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -function testRegExpTest() { - var r = /abc/; - var flag = false; - for (var i = 0; i < 10; ++i) - flag = r.test("abc"); - return flag; -} -assertEq(testRegExpTest(), true); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js deleted file mode 100644 index 14574b146bf..00000000000 --- a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js +++ /dev/null @@ -1,11 +0,0 @@ -var a = {_val: 'q', - get p() { return f; }}; - -function f() { return this._val; } - -var g = ''; -for (var i = 0; i < 9; i++) - g += a.p(); -assertEq(g, 'qqqqqqqqq'); - -checkStats({recorderStarted: 1, recorderAborted: 0, traceCompleted: 1, traceTriggered: 1}); diff --git a/js/src/jit-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js deleted file mode 100644 index 4a7f5d98289..00000000000 --- a/js/src/jit-test/tests/basic/testShiftLeft.js +++ /dev/null @@ -1,38 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -/* Test the proper operation of the left shift operator. This is especially - * important on ARM as an explicit mask is required at the native instruction - * level. */ - -load(libdir + 'range.js'); - -function testShiftLeft() -{ - var r = []; - var i = 0; - var j = 0; - - var shifts = [0,1,7,8,15,16,23,24,31]; - - /* Samples from the simple shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << shifts[i]; - - /* Samples outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 32); - - /* Samples far outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 224); - for (i = 0; i < shifts.length; i++) - r[j++] = 1 << (shifts[i] + 256); - - return r.join(","); -} - -assertEq(testShiftLeft(), - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ - "1,2,128,256,32768,65536,8388608,16777216,-2147483648"); diff --git a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js deleted file mode 100644 index 7268dc0bad3..00000000000 --- a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Test the proper operation of the arithmetic right shift operator. This is - * especially important on ARM as an explicit mask is required at the native - * instruction level. */ - -load(libdir + 'range.js'); - -/* Test different combinations of literals/variables. */ -var s = 4; -var t = 100; -assertEq(42 >> s, 2); -assertEq(s >> 1, 2); -assertEq(23 >> 3, 2); -assertEq(t >> s, 6); - - -function testShiftRightArithmetic() -{ - var r = []; - var i = 0; - var j = 0; - - var shifts = [0,1,7,8,15,16,23,24,31]; - - /* Samples from the simple shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> shifts[i]; - - /* Samples outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 32); - - /* Samples far outside the normal shift range. */ - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 224); - for (i = 0; i < shifts.length; i++) - r[j++] = -2147483648 >> (shifts[i] + 256); - - return r.join(","); -} -assertEq(testShiftRightArithmetic(), - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ - "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"); diff --git a/js/src/jit-test/tests/basic/testSideExitInConstructor.js b/js/src/jit-test/tests/basic/testSideExitInConstructor.js deleted file mode 100644 index d46543ef7bd..00000000000 --- a/js/src/jit-test/tests/basic/testSideExitInConstructor.js +++ /dev/null @@ -1,39 +0,0 @@ -// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind - -function testSideExitInConstructor() { - var FCKConfig = {}; - FCKConfig.CoreStyles = - { - 'Bold': { }, - 'Italic': { }, - 'FontFace': { }, - 'Size' : - { - Overrides: [ ] - }, - - 'Color' : - { - Element: '', - Styles: { }, - Overrides: [ ] - }, - 'BackColor': { - Element : '', - Styles : { 'background-color' : '' } - }, - - }; - var FCKStyle = function(A) { - A.Element; - }; - - var pass = true; - for (var s in FCKConfig.CoreStyles) { - var x = new FCKStyle(FCKConfig.CoreStyles[s]); - if (!x) - pass = false; - } - return pass; -} -assertEq(testSideExitInConstructor(), true); diff --git a/js/src/jit-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js deleted file mode 100644 index f7a1443a71a..00000000000 --- a/js/src/jit-test/tests/basic/testSlowNativeBail.js +++ /dev/null @@ -1,10 +0,0 @@ -function testSlowNativeBail() { - var a = ['0', '1', '2', '3', '+']; - try { - for (var i = 0; i < a.length; i++) - new RegExp(a[i]); - } catch (exc) { - assertEq(""+exc, "SyntaxError: invalid quantifier"); - } -} -testSlowNativeBail(); diff --git a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js deleted file mode 100644 index f65957a74b7..00000000000 --- a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js +++ /dev/null @@ -1,29 +0,0 @@ -const numFatArgs = Math.pow(2,19) - 1024; - -function fun(x) { - if (x <= 0) - return 0; - return fun(x-1); -} - -function fatStack() { - return fun(10000); -} - -function assertRightFailure(e) { - assertEq(e.toString() == "InternalError: script stack space quota is exhausted" || - e.toString() == "InternalError: too much recursion", - true); -} - -exception = false; -try { - fatStack.apply(null, new Array(numFatArgs)); -} catch (e) { - assertRightFailure(e); - exception = true; -} -assertEq(exception, true); - -// No more trace recursion w/ JM -checkStats({traceCompleted:0}); diff --git a/js/src/jit-test/tests/closures/bug540136.js b/js/src/jit-test/tests/closures/bug540136.js deleted file mode 100644 index 54b57713a7f..00000000000 --- a/js/src/jit-test/tests/closures/bug540136.js +++ /dev/null @@ -1,17 +0,0 @@ -// |jit-test| error: TypeError - -(eval("\ - (function () {\ - for (var[x] = function(){} in \ - (function m(a) {\ - if (a < 1) {\ - x;\ - return\ - }\ - return m(a - 1) + m(a - 2)\ - })(7)\ - (eval(\"\"))\ - )\ - ([])\ - })\ -"))() diff --git a/js/src/jit-test/tests/closures/bug540242.js b/js/src/jit-test/tests/closures/bug540242.js deleted file mode 100644 index 56c1a5a3143..00000000000 --- a/js/src/jit-test/tests/closures/bug540242.js +++ /dev/null @@ -1,17 +0,0 @@ -for (j = 0; j < 1; j++) { - var f = eval("\ - (function() {\ - for (var a = 0; a < 8; ++a) {\ - if (a % 3 == 2) {\ - eval(\"\ - for(b in[0,0,0,0]) {\ - print()\ - }\ - \")\ - }\ - gc()\ - }\ - })\ - "); - f() -} diff --git a/js/src/jit-test/tests/closures/bug540243.js b/js/src/jit-test/tests/closures/bug540243.js deleted file mode 100644 index 07faa26b6e7..00000000000 --- a/js/src/jit-test/tests/closures/bug540243.js +++ /dev/null @@ -1,10 +0,0 @@ -for (a in (eval("\ - (function() {\ - return function() {\ - yield ((function() {\ - return d\ - })())\ - } ();\ - var d = []\ - })\ -"))()); diff --git a/js/src/jit-test/tests/closures/bug541239.js b/js/src/jit-test/tests/closures/bug541239.js deleted file mode 100644 index 32e3af1565b..00000000000 --- a/js/src/jit-test/tests/closures/bug541239.js +++ /dev/null @@ -1,16 +0,0 @@ -function m() { - var d = 73; - - return (eval("\n\ - (function() {\n\ - return function() {\n\ - yield ((function() {\n\ - print(d);\n\ - return d\n\ - })())\n\ - } ();\n\ - })\n\ - "))(); -} - -m().next(); diff --git a/js/src/jit-test/tests/closures/lambda.js b/js/src/jit-test/tests/closures/lambda.js deleted file mode 100644 index fd7cbd16ed7..00000000000 --- a/js/src/jit-test/tests/closures/lambda.js +++ /dev/null @@ -1,27 +0,0 @@ -function f() { - var k = 0; - - var g = function() { - return ++k; - } - - return g; -} - -function h() { - for (var i = 0; i < 10; ++i) { - var vf = f(); - assertEq(vf(), 1); - assertEq(vf(), 2); - for (var j = 0; j < 10; ++j) { - assertEq(vf(), j + 3); - } - } -} - -h(); - -checkStats({ - recorderAborted: 8, // Inner tree is trying to grow -}); - diff --git a/js/src/jit-test/tests/closures/setname-inner-heavy.js b/js/src/jit-test/tests/closures/setname-inner-heavy.js deleted file mode 100644 index 9c1919dc2f3..00000000000 --- a/js/src/jit-test/tests/closures/setname-inner-heavy.js +++ /dev/null @@ -1,18 +0,0 @@ -actual = ''; -expected = 'undefined,'; - -function f() { - (eval("\ - (function () {\ - for (var z = 0; z < 2; ++z) {\ - x = ''\ - }\ - })\ - "))(); -} -__defineSetter__("x", eval) -f() -appendToActual(x); - - -assertEq(actual, expected) diff --git a/js/src/jit-test/tests/jaeger/bug554580-5.js b/js/src/jit-test/tests/jaeger/bug554580-5.js deleted file mode 100644 index 1d3ee522b07..00000000000 --- a/js/src/jit-test/tests/jaeger/bug554580-5.js +++ /dev/null @@ -1,20 +0,0 @@ -(function() { - (function g(m, n) { - if (m = n) { - return eval("x=this") - } - g(m, 1)[[]] - })() -})() -Function("\ - for (let b in [0]) {\ - for (var k = 0; k < 6; ++k) {\ - if (k == 1) {\ - print(x)\ - }\ - }\ - }\ -")() - -/* Don't crash/assert. */ - diff --git a/js/src/jit-test/tests/jaeger/bug555155.js b/js/src/jit-test/tests/jaeger/bug555155.js deleted file mode 100644 index db7b57aa1bc..00000000000 --- a/js/src/jit-test/tests/jaeger/bug555155.js +++ /dev/null @@ -1,12 +0,0 @@ -// |jit-test| error: undefined -(function() { - throw (function f(a, b) { - if (a.h == b) { - return eval("((function(){return 1})())!=this") - } - f(b) - })([], 0) -})() - -/* Don't assert/crash. */ - diff --git a/js/src/jit-test/tests/jaeger/bug555543.js b/js/src/jit-test/tests/jaeger/bug555543.js deleted file mode 100644 index b641c1b5832..00000000000 --- a/js/src/jit-test/tests/jaeger/bug555543.js +++ /dev/null @@ -1,8 +0,0 @@ -(function() { - for each(let z in [new String(''), new String('q'), new String('')]) { - if (uneval() < z) (function(){}) - } -})() - -/* Don't assert/crash. */ - diff --git a/js/src/jit-test/tests/jaeger/bug556525.js b/js/src/jit-test/tests/jaeger/bug556525.js deleted file mode 100644 index 0b59f3274b0..00000000000 --- a/js/src/jit-test/tests/jaeger/bug556525.js +++ /dev/null @@ -1,5 +0,0 @@ -for each(x in [new Number]) - x.__proto__ = [] -++x[x] - -// don't assert diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js deleted file mode 100644 index 2cde4fde8a9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js +++ /dev/null @@ -1,9 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - return x; -} -trap(caller, 7, "var x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js deleted file mode 100644 index 11f2ff0a659..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - var x = ({ dana : "zuul" }); - return x; -} -trap(caller, 23, "x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js deleted file mode 100644 index 9eeb76d07eb..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); - -function nop(){} -function caller(obj) { - assertJit(); - var x = "failure"; - return x; -} -trap(caller, 14, "x = 'success'; nop()"); -assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js deleted file mode 100644 index 266db65090d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js +++ /dev/null @@ -1,9 +0,0 @@ -setDebug(true); -var x = "failure"; -function main() { x = "success"; } - -/* The JSOP_STOP in a. */ -trap(main, 8, ""); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js deleted file mode 100644 index db7e4b82b2a..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js +++ /dev/null @@ -1,10 +0,0 @@ -setDebug(true); -var x = "notset"; -function main() { x = "failure"; } -function success() { x = "success"; } - -/* The JSOP_STOP in a. */ -trap(main, 7, "success()"); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js deleted file mode 100644 index 2f89f58bc3d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js +++ /dev/null @@ -1,11 +0,0 @@ -setDebug(true); -var x = "notset"; -function main() { x = "success"; } -function failure() { x = "failure"; } - -/* The JSOP_STOP in a. */ -trap(main, 8, "failure()"); -untrap(main, 8); -main(); - -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js deleted file mode 100644 index 1d19aeebeb1..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js +++ /dev/null @@ -1,7 +0,0 @@ -setDebug(true); -function main() { - return "failure"; -} -/* JSOP_RETURN in main. */ -trap(main, 3, "'success'"); -assertEq(main(), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js deleted file mode 100644 index b2b516826a9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js +++ /dev/null @@ -1,7 +0,0 @@ -setDebug(true); -function main() { - return 1; -} -/* JSOP_RETURN in main. */ -trap(main, 1, "0"); -assertEq(main(), 0); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js deleted file mode 100644 index 18378b7808f..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js +++ /dev/null @@ -1,15 +0,0 @@ -setDebug(true); -x = "notset"; -function myparent(nested) { - if (nested) { - /* myparent call in myparent. */ - trap(myparent, 39, "failure()"); - } else { - x = "success"; - myparent(true); - } -} -function failure() { x = "failure"; } - -myparent(false); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js deleted file mode 100644 index d6ded288128..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js +++ /dev/null @@ -1,21 +0,0 @@ -setDebug(true); -x = "notset"; - -function child() { - x = "failure1"; - /* JSOP_STOP in parent. */ - trap(parent, 10, "success()"); -} - -function parent() { - x = "failure2"; -} -/* First op in parent. */ -trap(parent, 0, "child()"); - -function success() { - x = "success"; -} - -parent(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js deleted file mode 100644 index 2209f946af9..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js +++ /dev/null @@ -1,16 +0,0 @@ -setDebug(true); -x = "notset"; -function child() { - /* JSOP_STOP in parent. */ - trap(parent, 17, "success()"); -} -function parent() { - child(); - x = "failure"; -} -function success() { - x = "success"; -} - -parent() -assertEq(x, "success"); diff --git 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 deleted file mode 100644 index 65d3e73135e..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js +++ /dev/null @@ -1,18 +0,0 @@ -setDebug(true); -x = "notset"; - -function myparent(nested) { - if (nested) { - /* noop call in myparent */ - trap(myparent, 50, "success()"); - } else { - myparent(true); - x = "failure"; - noop(); - } -} -function noop() { } -function success() { x = "success"; } - -myparent(); -assertEq(x, "success"); diff --git 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 deleted file mode 100644 index 8a9caaaafda..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js +++ /dev/null @@ -1,23 +0,0 @@ -setDebug(true); -x = "notset"; - -function doNothing() { } - -function myparent(nested) { - if (nested) { - /* JSOP_CALL to doNothing in myparent with nested = true. */ - trap(myparent, 24, "success()"); - doNothing(); - } else { - doNothing(); - } -} -/* JSOP_CALL to doNothing in myparent with nested = false. */ -trap(myparent, 35, "myparent(true)"); - -function success() { - x = "success"; -} - -myparent(false); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js deleted file mode 100644 index 9b94fd1c8cc..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js +++ /dev/null @@ -1,11 +0,0 @@ -setDebug(true); -x = "notset"; -function main() { - /* The JSOP_STOP in a. */ - trap(main, 25, "success()"); - x = "failure"; -} -function success() { x = "success"; } - -main(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js deleted file mode 100644 index e4dd9d7dc97..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js +++ /dev/null @@ -1,15 +0,0 @@ -setDebug(true); -x = "notset"; -function child() { - /* JSOP_STOP in parent */ - untrap(parent, 10); - x = "success"; -} -function parent() { - x = "failure"; -} -/* JSOP_STOP in parent */ -trap(parent, 10, "child()"); - -parent(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js deleted file mode 100644 index 4c18db52e8e..00000000000 --- a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js +++ /dev/null @@ -1,13 +0,0 @@ -setDebug(true); -x = "notset"; -function main() { - /* JSOP_STOP in main. */ - untrap(main, 23); - x = "success"; -} -function failure() { x = "failure"; } - -/* JSOP_STOP in main. */ -trap(main, 23, "failure()"); -main(); -assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug573433.js b/js/src/jit-test/tests/jaeger/bug573433.js deleted file mode 100644 index aa39022bb74..00000000000 --- a/js/src/jit-test/tests/jaeger/bug573433.js +++ /dev/null @@ -1,7 +0,0 @@ -// |jit-test| error: TypeError -function f() { - eval("(function() \n{\nfor(x in[])\n{}\n})"); - ("")() -} -f() - diff --git a/js/src/jit-test/tests/jaeger/bug580884.js b/js/src/jit-test/tests/jaeger/bug580884.js deleted file mode 100644 index b7a26f70566..00000000000 --- a/js/src/jit-test/tests/jaeger/bug580884.js +++ /dev/null @@ -1,8 +0,0 @@ -// |jit-test| error: ReferenceError -for (let a in [0]) -a = e -for (let a in [0]) -(function () { - a -}) - diff --git a/js/src/jit-test/tests/jaeger/bug582286.js b/js/src/jit-test/tests/jaeger/bug582286.js deleted file mode 100644 index 094366a3c79..00000000000 --- a/js/src/jit-test/tests/jaeger/bug582286.js +++ /dev/null @@ -1,3 +0,0 @@ -evalcx("function s(){}",evalcx('lazy')) - - diff --git a/js/src/jit-test/tests/jaeger/bug583158.js b/js/src/jit-test/tests/jaeger/bug583158.js deleted file mode 100644 index 6d8c124487d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug583158.js +++ /dev/null @@ -1,9 +0,0 @@ -// |jit-test| error: ReferenceError -function g() { - var rv = (function() { - this << 1 - })() - if (a) (function() {}) -} -g() - diff --git a/js/src/jit-test/tests/jaeger/bug585341.js b/js/src/jit-test/tests/jaeger/bug585341.js deleted file mode 100644 index fb96b92c3c3..00000000000 --- a/js/src/jit-test/tests/jaeger/bug585341.js +++ /dev/null @@ -1,6 +0,0 @@ -__defineGetter__("x", Float64Array) -Function("\ - with(this) {\ - eval(\"x\")\ - }\ -")() diff --git a/js/src/jit-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js deleted file mode 100644 index 65c30952077..00000000000 --- a/js/src/jit-test/tests/jaeger/bug588338.js +++ /dev/null @@ -1,14 +0,0 @@ -// |jit-test| error: is not a function -function f() { (e) -} (x = Proxy.createFunction((function(x) { - return { - get: function(r, b) { - return x[b] - } - } -})(/x/), wrap)) -for (z = 0; z < 100; x.unwatch(), z++) -for (e in [0]) { - gczeal(2) -} ( )("") - diff --git a/js/src/jit-test/tests/jaeger/bug588363-2.js b/js/src/jit-test/tests/jaeger/bug588363-2.js deleted file mode 100644 index 5550be3ea8d..00000000000 --- a/js/src/jit-test/tests/jaeger/bug588363-2.js +++ /dev/null @@ -1,7 +0,0 @@ -with(evalcx('')) { - delete eval; - eval("x", this.__defineGetter__("x", Function)); -} - -/* Don't assert or crash. */ - diff --git a/js/src/jit-test/tests/jaeger/crash-on-compare.js b/js/src/jit-test/tests/jaeger/crash-on-compare.js deleted file mode 100644 index 5abd7aa045e..00000000000 --- a/js/src/jit-test/tests/jaeger/crash-on-compare.js +++ /dev/null @@ -1 +0,0 @@ -assertEq(Infinity >= Infinity ? true : false, true); diff --git a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js deleted file mode 100644 index b5d2bf2f61b..00000000000 --- a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js +++ /dev/null @@ -1,6 +0,0 @@ -function ack(m,n){ - if (m==0) { return n+1; } - if (n==0) { return ack(m-1,1); } - return ack(m-1, ack(m,n-1) ); -} -assertEq(ack(3, 3), 61); diff --git a/js/src/jit-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js deleted file mode 100644 index 5d8c68fa590..00000000000 --- a/js/src/jit-test/tests/pic/bug558099.js +++ /dev/null @@ -1,60 +0,0 @@ -(function()[function() function() function() function() function() function() {}]); -foo = [{ - text: "(function(){if(d){(1)}})", - s: function() {}, - test: function() { - try { - f - } catch(e) {} - } -}, -{ - text: "(function(){t})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){if(0){}})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){if(1){}(2)})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){g})", - b: function() {}, - test: function() {} -}, -{ - text: "(function(){})", - s: function() {}, - test: function() {} -}, -{ - text: "(function(){1})", - s: function() {}, - test: function() {} -}]; (function() { - for (i = 0; i < foo.length; ++i) { - a = foo[i] - text = a.text - eval(text.replace(/@/, "")); - if (a.test()) {} - } -} ()); -s = [function() function() function() function() function() function() {}] -[function() function() function() function() {}]; -(function() { [function() function() {}] }); -(function() {}); -(eval("\ - (function(){\ - for each(d in[\ - 0,0,0,0,0,0,0,0,0,0,0,0,0,null,NaN,1,Boolean(false),Boolean(false)\ - ]){\ - [].filter(new Function,gczeal(2))\ - }\ - })\ -"))(); diff --git a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js deleted file mode 100644 index 41f44fed50c..00000000000 --- a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2004 Baron Schwartz - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, version 2.1. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - */ - -Date.parseFunctions = {count:0}; -Date.parseRegexes = []; -Date.formatFunctions = {count:0}; - -Date.prototype.dateFormat = function(format) { - if (Date.formatFunctions[format] == null) { - Date.createNewFormat(format); - } - var func = Date.formatFunctions[format]; - return this[func](); -} - -Date.createNewFormat = function(format) { - var funcName = "format" + Date.formatFunctions.count++; - Date.formatFunctions[format] = funcName; - var code = "Date.prototype." + funcName + " = function(){return "; - var special = false; - var ch = ''; - for (var i = 0; i < format.length; ++i) { - ch = format.charAt(i); - if (!special && ch == "\\") { - special = true; - } - else if (special) { - special = false; - code += "'" + String.escape(ch) + "' + "; - } - else { - code += Date.getFormatCode(ch); - } - } - eval(code.substring(0, code.length - 3) + ";}"); -} - -Date.getFormatCode = function(character) { - switch (character) { - case "d": - return "String.leftPad(this.getDate(), 2, '0') + "; - case "D": - return "Date.dayNames[this.getDay()].substring(0, 3) + "; - case "j": - return "this.getDate() + "; - case "l": - return "Date.dayNames[this.getDay()] + "; - case "S": - return "this.getSuffix() + "; - case "w": - return "this.getDay() + "; - case "z": - return "this.getDayOfYear() + "; - case "W": - return "this.getWeekOfYear() + "; - case "F": - return "Date.monthNames[this.getMonth()] + "; - case "m": - return "String.leftPad(this.getMonth() + 1, 2, '0') + "; - case "M": - return "Date.monthNames[this.getMonth()].substring(0, 3) + "; - case "n": - return "(this.getMonth() + 1) + "; - case "t": - return "this.getDaysInMonth() + "; - case "L": - return "(this.isLeapYear() ? 1 : 0) + "; - case "Y": - return "this.getFullYear() + "; - case "y": - return "('' + this.getFullYear()).substring(2, 4) + "; - case "a": - return "(this.getHours() < 12 ? 'am' : 'pm') + "; - case "A": - return "(this.getHours() < 12 ? 'AM' : 'PM') + "; - case "g": - return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; - case "G": - return "this.getHours() + "; - case "h": - return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; - case "H": - return "String.leftPad(this.getHours(), 2, '0') + "; - case "i": - return "String.leftPad(this.getMinutes(), 2, '0') + "; - case "s": - return "String.leftPad(this.getSeconds(), 2, '0') + "; - case "O": - return "this.getGMTOffset() + "; - case "T": - return "this.getTimezone() + "; - case "Z": - return "(this.getTimezoneOffset() * -60) + "; - default: - return "'" + String.escape(character) + "' + "; - } -} - -Date.parseDate = function(input, format) { - if (Date.parseFunctions[format] == null) { - Date.createParser(format); - } - var func = Date.parseFunctions[format]; - return Date[func](input); -} - -Date.createParser = function(format) { - var funcName = "parse" + Date.parseFunctions.count++; - var regexNum = Date.parseRegexes.length; - var currentGroup = 1; - Date.parseFunctions[format] = funcName; - - var code = "Date." + funcName + " = function(input){\n" - + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" - + "var d = new Date();\n" - + "y = d.getFullYear();\n" - + "m = d.getMonth();\n" - + "d = d.getDate();\n" - + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" - + "if (results && results.length > 0) {" - var regex = ""; - - var special = false; - var ch = ''; - for (var i = 0; i < format.length; ++i) { - ch = format.charAt(i); - if (!special && ch == "\\") { - special = true; - } - else if (special) { - special = false; - regex += String.escape(ch); - } - else { - obj = Date.formatCodeToRegex(ch, currentGroup); - currentGroup += obj.g; - regex += obj.s; - if (obj.g && obj.c) { - code += obj.c; - } - } - } - - code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" - + "{return new Date(y, m, d, h, i, s);}\n" - + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" - + "{return new Date(y, m, d, h, i);}\n" - + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" - + "{return new Date(y, m, d, h);}\n" - + "else if (y > 0 && m >= 0 && d > 0)\n" - + "{return new Date(y, m, d);}\n" - + "else if (y > 0 && m >= 0)\n" - + "{return new Date(y, m);}\n" - + "else if (y > 0)\n" - + "{return new Date(y);}\n" - + "}return null;}"; - - Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); - eval(code); -} - -Date.formatCodeToRegex = function(character, currentGroup) { - switch (character) { - case "D": - return {g:0, - c:null, - s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; - case "j": - case "d": - return {g:1, - c:"d = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{1,2})"}; - case "l": - return {g:0, - c:null, - s:"(?:" + Date.dayNames.join("|") + ")"}; - case "S": - return {g:0, - c:null, - s:"(?:st|nd|rd|th)"}; - case "w": - return {g:0, - c:null, - s:"\\d"}; - case "z": - return {g:0, - c:null, - s:"(?:\\d{1,3})"}; - case "W": - return {g:0, - c:null, - s:"(?:\\d{2})"}; - case "F": - return {g:1, - c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", - s:"(" + Date.monthNames.join("|") + ")"}; - case "M": - return {g:1, - c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", - s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; - case "n": - case "m": - return {g:1, - c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", - s:"(\\d{1,2})"}; - case "t": - return {g:0, - c:null, - s:"\\d{1,2}"}; - case "L": - return {g:0, - c:null, - s:"(?:1|0)"}; - case "Y": - return {g:1, - c:"y = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{4})"}; - case "y": - return {g:1, - c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" - + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", - s:"(\\d{1,2})"}; - case "a": - return {g:1, - c:"if (results[" + currentGroup + "] == 'am') {\n" - + "if (h == 12) { h = 0; }\n" - + "} else { if (h < 12) { h += 12; }}", - s:"(am|pm)"}; - case "A": - return {g:1, - c:"if (results[" + currentGroup + "] == 'AM') {\n" - + "if (h == 12) { h = 0; }\n" - + "} else { if (h < 12) { h += 12; }}", - s:"(AM|PM)"}; - case "g": - case "G": - case "h": - case "H": - return {g:1, - c:"h = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{1,2})"}; - case "i": - return {g:1, - c:"i = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{2})"}; - case "s": - return {g:1, - c:"s = parseInt(results[" + currentGroup + "], 10);\n", - s:"(\\d{2})"}; - case "O": - return {g:0, - c:null, - s:"[+-]\\d{4}"}; - case "T": - return {g:0, - c:null, - s:"[A-Z]{3}"}; - case "Z": - return {g:0, - c:null, - s:"[+-]\\d{1,5}"}; - default: - return {g:0, - c:null, - s:String.escape(character)}; - } -} - -Date.prototype.getTimezone = function() { - return this.toString().replace( - /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( - /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); -} - -Date.prototype.getGMTOffset = function() { - return (this.getTimezoneOffset() > 0 ? "-" : "+") - + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") - + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); -} - -Date.prototype.getDayOfYear = function() { - var num = 0; - Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; - for (var i = 0; i < this.getMonth(); ++i) { - num += Date.daysInMonth[i]; - } - return num + this.getDate() - 1; -} - -Date.prototype.getWeekOfYear = function() { - // Skip to Thursday of this week - var now = this.getDayOfYear() + (4 - this.getDay()); - // Find the first Thursday of the year - var jan1 = new Date(this.getFullYear(), 0, 1); - var then = (7 - jan1.getDay() + 4); - document.write(then); - return String.leftPad(((now - then) / 7) + 1, 2, "0"); -} - -Date.prototype.isLeapYear = function() { - var year = this.getFullYear(); - return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); -} - -Date.prototype.getFirstDayOfMonth = function() { - var day = (this.getDay() - (this.getDate() - 1)) % 7; - return (day < 0) ? (day + 7) : day; -} - -Date.prototype.getLastDayOfMonth = function() { - var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; - return (day < 0) ? (day + 7) : day; -} - -Date.prototype.getDaysInMonth = function() { - Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; - return Date.daysInMonth[this.getMonth()]; -} - -Date.prototype.getSuffix = function() { - switch (this.getDate()) { - case 1: - case 21: - case 31: - return "st"; - case 2: - case 22: - return "nd"; - case 3: - case 23: - return "rd"; - default: - return "th"; - } -} - -String.escape = function(string) { - return string.replace(/('|\\)/g, "\\$1"); -} - -String.leftPad = function (val, size, ch) { - var result = new String(val); - if (ch == null) { - ch = " "; - } - while (result.length < size) { - result = ch + result; - } - return result; -} - -Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; -Date.monthNames = - ["January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December"]; -Date.dayNames = - ["Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday"]; -Date.y2kYear = 50; -Date.monthNumbers = { - Jan:0, - Feb:1, - Mar:2, - Apr:3, - May:4, - Jun:5, - Jul:6, - Aug:7, - Sep:8, - Oct:9, - Nov:10, - Dec:11}; -Date.patterns = { - ISO8601LongPattern:"Y-m-d H:i:s", - ISO8601ShortPattern:"Y-m-d", - ShortDatePattern: "n/j/Y", - LongDatePattern: "l, F d, Y", - FullDateTimePattern: "l, F d, Y g:i:s A", - MonthDayPattern: "F d", - ShortTimePattern: "g:i A", - LongTimePattern: "g:i:s A", - SortableDateTimePattern: "Y-m-d\\TH:i:s", - UniversalSortableDateTimePattern: "Y-m-d H:i:sO", - YearMonthPattern: "F, Y"}; - -var date = new Date("1/1/2007 1:11:11"); - -var ret; -for (i = 0; i < 4000; ++i) { - var shortFormat = date.dateFormat("Y-m-d"); - var longFormat = date.dateFormat("l, F d, Y g:i:s A"); - ret = shortFormat + longFormat; - date.setTime(date.getTime() + 84266956); -} - -// No exact match because the output depends on the locale's time zone. See bug 524490. -assertEq(/^2017-09-05Tuesday, September 05, 2017 [0-9:]* AM$/.exec(ret) != null, true); diff --git a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js deleted file mode 100644 index a9082702ccf..00000000000 --- a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js +++ /dev/null @@ -1,41 +0,0 @@ -// The Computer Language Shootout -// http://shootout.alioth.debian.org/ -// contributed by Isaac Gouy - -function partial(n){ - var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; - var twothirds = 2.0/3.0; - var alt = -1.0; - var k2 = k3 = sk = ck = 0.0; - - for (var k = 1; k <= n; k++){ - k2 = k*k; - k3 = k2*k; - sk = Math.sin(k); - ck = Math.cos(k); - alt = -alt; - - a1 += Math.pow(twothirds,k-1); - a2 += Math.pow(k,-0.5); - a3 += 1.0/(k*(k+1.0)); - a4 += 1.0/(k3 * sk*sk); - a5 += 1.0/(k3 * ck*ck); - a6 += 1.0/k; - a7 += 1.0/k2; - a8 += alt/k; - a9 += alt/(2*k -1); - } - - return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ]; -} - -var actual = []; -for (var i = 1024; i <= 16384; i *= 2) - Array.prototype.push.apply(actual, partial(i)); - -var eps = 1e-12; -var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998]; - -assertEq(actual.length, expect.length); -for (var i = 0; i < expect.length; ++i) - assertEq(Math.abs(actual[i] - expect[i]) < eps, true); diff --git a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js deleted file mode 100644 index f446e46ed5c..00000000000 --- a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js +++ /dev/null @@ -1,270 +0,0 @@ - -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Portions from: - json.js - 2007-10-10 - - Public Domain -*/ - -// This test parses a JSON string giving tag names and popularity, and -// generates html markup for a "tagcloud" view. - -if (!Object.prototype.toJSONString) { - - Array.prototype.toJSONString = function (w) { - var a = [], // The array holding the partial texts. - i, // Loop counter. - l = this.length, - v; // The value to be stringified. - - for (i = 0; i < l; i += 1) { - v = this[i]; - switch (typeof v) { - case 'object': - - if (v && typeof v.toJSONString === 'function') { - a.push(v.toJSONString(w)); - } else { - a.push('null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(v.toJSONString()); - break; - default: - a.push('null'); - } - } - - return '[' + a.join(',') + ']'; - }; - - - Boolean.prototype.toJSONString = function () { - return String(this); - }; - - - Date.prototype.toJSONString = function () { - - function f(n) { - - return n < 10 ? '0' + n : n; - } - - return '"' + this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z"'; - }; - - - Number.prototype.toJSONString = function () { - - return isFinite(this) ? String(this) : 'null'; - }; - - - Object.prototype.toJSONString = function (w) { - var a = [], // The array holding the partial texts. - k, // The current key. - i, // The loop counter. - v; // The current value. - - if (w) { - for (i = 0; i < w.length; i += 1) { - k = w[i]; - if (typeof k === 'string') { - v = this[k]; - switch (typeof v) { - case 'object': - - if (v) { - if (typeof v.toJSONString === 'function') { - a.push(k.toJSONString() + ':' + - v.toJSONString(w)); - } - } else { - a.push(k.toJSONString() + ':null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(k.toJSONString() + ':' + v.toJSONString()); - - } - } - } - } else { - - for (k in this) { - if (typeof k === 'string' && - Object.prototype.hasOwnProperty.apply(this, [k])) { - v = this[k]; - switch (typeof v) { - case 'object': - - if (v) { - if (typeof v.toJSONString === 'function') { - a.push(k.toJSONString() + ':' + - v.toJSONString()); - } - } else { - a.push(k.toJSONString() + ':null'); - } - break; - - case 'string': - case 'number': - case 'boolean': - a.push(k.toJSONString() + ':' + v.toJSONString()); - - } - } - } - } - - return '{' + a.join(',') + '}'; - }; - - - (function (s) { - - var m = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }; - - - s.parseJSON = function (filter) { - var j; - - function walk(k, v) { - var i, n; - if (v && typeof v === 'object') { - for (i in v) { - if (Object.prototype.hasOwnProperty.apply(v, [i])) { - n = walk(i, v[i]); - if (n !== undefined) { - v[i] = n; - } - } - } - } - return filter(k, v); - } - - if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@'). - replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). - replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - - j = eval('(' + this + ')'); - - return typeof filter === 'function' ? walk('', j) : j; - } - - throw new SyntaxError('parseJSON'); - }; - - - s.toJSONString = function () { - - if (/["\\\x00-\x1f]/.test(this)) { - return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) { - var c = m[a]; - if (c) { - return c; - } - c = a.charCodeAt(); - return '\\u00' + Math.floor(c / 16).toString(16) + - (c % 16).toString(16); - }) + '"'; - } - return '"' + this + '"'; - }; - })(String.prototype); -} - -var tagInfoJSON = '[\n {\n \"tag\": "titillation",\n \"popularity\": 4294967296\n },\n {\n \"tag\": "foamless",\n \"popularity\": 1257718401\n },\n {\n \"tag\": "snarler",\n \"popularity\": 613166183\n },\n {\n \"tag\": "multangularness",\n \"popularity\": 368304452\n },\n {\n \"tag\": "Fesapo unventurous",\n \"popularity\": 248026512\n },\n {\n \"tag\": "esthesioblast",\n \"popularity\": 179556755\n },\n {\n \"tag\": "echeneidoid",\n \"popularity\": 136641578\n },\n {\n \"tag\": "embryoctony",\n \"popularity\": 107852576\n },\n {\n \"tag\": "undilatory",\n \"popularity\": 87537981\n },\n {\n \"tag\": "predisregard",\n \"popularity\": 72630939\n },\n {\n \"tag\": "allergenic",\n \"popularity\": 61345190\n },\n {\n \"tag\": "uncloudy",\n \"popularity\": 52580571\n },\n {\n \"tag\": "unforeseeably",\n \"popularity\": 45628109\n },\n {\n \"tag\": "sturniform",\n \"popularity\": 40013489\n },\n {\n \"tag\": "anesthetize",\n \"popularity\": 35409226\n },\n {\n \"tag\": "ametabolia",\n \"popularity\": 31583050\n },\n {\n \"tag\": "angiopathy",\n \"popularity\": 28366350\n },\n {\n \"tag\": "sultanaship",\n \"popularity\": 25634218\n },\n {\n \"tag\": "Frenchwise",\n \"popularity\": 23292461\n },\n {\n \"tag\": "cerviconasal",\n \"popularity\": 21268909\n },\n {\n \"tag\": "mercurialness",\n \"popularity\": 19507481\n },\n {\n \"tag\": "glutelin venditate",\n \"popularity\": 17964042\n },\n {\n \"tag\": "acred overblack",\n \"popularity\": 16603454\n },\n {\n \"tag\": "Atik",\n \"popularity\": 15397451\n },\n {\n \"tag\": "puncturer",\n \"popularity\": 14323077\n },\n {\n \"tag\": "pukatea",\n \"popularity\": 13361525\n },\n {\n \"tag\": "suberize",\n \"popularity\": 12497261\n },\n {\n \"tag\": "Godfrey",\n \"popularity\": 11717365\n },\n {\n \"tag\": "tetraptote",\n \"popularity\": 11011011\n },\n {\n \"tag\": "lucidness",\n \"popularity\": 10369074\n },\n {\n \"tag\": "tartness",\n \"popularity\": 9783815\n },\n {\n \"tag\": "axfetch",\n \"popularity\": 9248634\n },\n {\n \"tag\": "preacquittal",\n \"popularity\": 8757877\n },\n {\n \"tag\": "matris",\n \"popularity\": 8306671\n },\n {\n \"tag\": "hyphenate",\n \"popularity\": 7890801\n },\n {\n \"tag\": "semifabulous",\n \"popularity\": 7506606\n },\n {\n \"tag\": "oppressiveness",\n \"popularity\": 7150890\n },\n {\n \"tag\": "Protococcales",\n \"popularity\": 6820856\n },\n {\n \"tag\": "unpreventive",\n \"popularity\": 6514045\n },\n {\n \"tag\": "Cordia",\n \"popularity\": 6228289\n },\n {\n \"tag\": "Wakamba leaflike",\n \"popularity\": 5961668\n },\n {\n \"tag\": "dacryoma",\n \"popularity\": 5712480\n },\n {\n \"tag\": "inguinal",\n \"popularity\": 5479211\n },\n {\n \"tag\": "responseless",\n \"popularity\": 5260507\n },\n {\n \"tag\": "supplementarily",\n \"popularity\": 5055158\n },\n {\n \"tag\": "emu",\n \"popularity\": 4862079\n },\n {\n \"tag\": "countermeet",\n \"popularity\": 4680292\n },\n {\n \"tag\": "purrer",\n \"popularity\": 4508918\n },\n {\n \"tag\": "Corallinaceae",\n \"popularity\": 4347162\n },\n {\n \"tag\": "speculum",\n \"popularity\": 4194304\n },\n {\n \"tag\": "crimpness",\n \"popularity\": 4049690\n },\n {\n \"tag\": "antidetonant",\n \"popularity\": 3912727\n },\n {\n \"tag\": "topeewallah",\n \"popularity\": 3782875\n },\n {\n \"tag\": "fidalgo ballant",\n \"popularity\": 3659640\n },\n {\n \"tag\": "utriculose",\n \"popularity\": 3542572\n },\n {\n \"tag\": "testata",\n \"popularity\": 3431259\n },\n {\n \"tag\": "beltmaking",\n \"popularity\": 3325322\n },\n {\n \"tag\": "necrotype",\n \"popularity\": 3224413\n },\n {\n \"tag\": "ovistic",\n \"popularity\": 3128215\n },\n {\n \"tag\": "swindlership",\n \"popularity\": 3036431\n },\n {\n \"tag\": "augustal",\n \"popularity\": 2948792\n },\n {\n \"tag\": "Titoist",\n \"popularity\": 2865047\n },\n {\n \"tag\": "trisoctahedral",\n \"popularity\": 2784963\n },\n {\n \"tag\": "sequestrator",\n \"popularity\": 2708327\n },\n {\n \"tag\": "sideburns",\n \"popularity\": 2634939\n },\n {\n \"tag\": "paraphrasia",\n \"popularity\": 2564616\n },\n {\n \"tag\": "graminology unbay",\n \"popularity\": 2497185\n },\n {\n \"tag\": "acaridomatium emargination",\n \"popularity\": 2432487\n },\n {\n \"tag\": "roofward",\n \"popularity\": 2370373\n },\n {\n \"tag\": "lauder",\n \"popularity\": 2310705\n },\n {\n \"tag\": "subjunctive",\n \"popularity\": 2253354\n },\n {\n \"tag\": "subelongate",\n \"popularity\": 2198199\n },\n {\n \"tag\": "guacimo",\n \"popularity\": 2145128\n },\n {\n \"tag\": "cockade",\n \"popularity\": 2094033\n },\n {\n \"tag\": "misgauge",\n \"popularity\": 2044818\n },\n {\n \"tag\": "unexpensive",\n \"popularity\": 1997388\n },\n {\n \"tag\": "chebel",\n \"popularity\": 1951657\n },\n {\n \"tag\": "unpursuing",\n \"popularity\": 1907543\n },\n {\n \"tag\": "kilobar",\n \"popularity\": 1864969\n },\n {\n \"tag\": "obsecration",\n \"popularity\": 1823863\n },\n {\n \"tag\": "nacarine",\n \"popularity\": 1784157\n },\n {\n \"tag\": "spirituosity",\n \"popularity\": 1745787\n },\n {\n \"tag\": "movableness deity",\n \"popularity\": 1708692\n },\n {\n \"tag\": "exostracism",\n \"popularity\": 1672816\n },\n {\n \"tag\": "archipterygium",\n \"popularity\": 1638104\n },\n {\n \"tag\": "monostrophic",\n \"popularity\": 1604506\n },\n {\n \"tag\": "gynecide",\n \"popularity\": 1571974\n },\n {\n \"tag\": "gladden",\n \"popularity\": 1540462\n },\n {\n \"tag\": "throughbred",\n \"popularity\": 1509927\n },\n {\n \"tag\": "groper",\n \"popularity\": 1480329\n },\n {\n \"tag\": "Xenosaurus",\n \"popularity\": 1451628\n },\n {\n \"tag\": "photoetcher",\n \"popularity\": 1423788\n },\n {\n \"tag\": "glucosid",\n \"popularity\": 1396775\n },\n {\n \"tag\": "Galtonian",\n \"popularity\": 1370555\n },\n {\n \"tag\": "mesosporic",\n \"popularity\": 1345097\n },\n {\n \"tag\": "theody",\n \"popularity\": 1320370\n },\n {\n \"tag\": "zaffer",\n \"popularity\": 1296348\n },\n {\n \"tag\": "probiology",\n \"popularity\": 1273003\n },\n {\n \"tag\": "rhizomic",\n \"popularity\": 1250308\n },\n {\n \"tag\": "superphosphate",\n \"popularity\": 1228240\n },\n {\n \"tag\": "Hippolytan",\n \"popularity\": 1206776\n },\n {\n \"tag\": "garget",\n \"popularity\": 1185892\n },\n {\n \"tag\": "diploplacula",\n \"popularity\": 1165568\n },\n {\n \"tag\": "orohydrographical",\n \"popularity\": 1145785\n },\n {\n \"tag\": "enhypostatize",\n \"popularity\": 1126521\n },\n {\n \"tag\": "polisman",\n \"popularity\": 1107759\n },\n {\n \"tag\": "acetometer",\n \"popularity\": 1089482\n },\n {\n \"tag\": "unsnatched",\n \"popularity\": 1071672\n },\n {\n \"tag\": "yabber",\n \"popularity\": 1054313\n },\n {\n \"tag\": "demiwolf",\n \"popularity\": 1037390\n },\n {\n \"tag\": "chromascope",\n \"popularity\": 1020888\n },\n {\n \"tag\": "seamanship",\n \"popularity\": 1004794\n },\n {\n \"tag\": "nonfenestrated",\n \"popularity\": 989092\n },\n {\n \"tag\": "hydrophytism",\n \"popularity\": 973771\n },\n {\n \"tag\": "dotter",\n \"popularity\": 958819\n },\n {\n \"tag\": "thermoperiodism",\n \"popularity\": 944222\n },\n {\n \"tag\": "unlawyerlike",\n \"popularity\": 929970\n },\n {\n \"tag\": "enantiomeride citywards",\n \"popularity\": 916052\n },\n {\n \"tag\": "unmetallurgical",\n \"popularity\": 902456\n },\n {\n \"tag\": "prickled",\n \"popularity\": 889174\n },\n {\n \"tag\": "strangerwise manioc",\n \"popularity\": 876195\n },\n {\n \"tag\": "incisorial",\n \"popularity\": 863510\n },\n {\n \"tag\": "irrationalize",\n \"popularity\": 851110\n },\n {\n \"tag\": "nasology",\n \"popularity\": 838987\n },\n {\n \"tag\": "fatuism",\n \"popularity\": 827131\n },\n {\n \"tag\": "Huk",\n \"popularity\": 815535\n },\n {\n \"tag\": "properispomenon",\n \"popularity\": 804192\n },\n {\n \"tag\": "unpummelled",\n \"popularity\": 793094\n },\n {\n \"tag\": "technographically",\n \"popularity\": 782233\n },\n {\n \"tag\": "underfurnish",\n \"popularity\": 771603\n },\n {\n \"tag\": "sinter",\n \"popularity\": 761198\n },\n {\n \"tag\": "lateroanterior",\n \"popularity\": 751010\n },\n {\n \"tag\": "nonpersonification",\n \"popularity\": 741034\n },\n {\n \"tag\": "Sitophilus",\n \"popularity\": 731264\n },\n {\n \"tag\": "unstudded overexerted",\n \"popularity\": 721694\n },\n {\n \"tag\": "tracheation",\n \"popularity\": 712318\n },\n {\n \"tag\": "thirteenth begloze",\n \"popularity\": 703131\n },\n {\n \"tag\": "bespice",\n \"popularity\": 694129\n },\n {\n \"tag\": "doppia",\n \"popularity\": 685305\n },\n {\n \"tag\": "unadorned",\n \"popularity\": 676656\n },\n {\n \"tag\": "dovelet engraff",\n \"popularity\": 668176\n },\n {\n \"tag\": "diphyozooid",\n \"popularity\": 659862\n },\n {\n \"tag\": "mure",\n \"popularity\": 651708\n },\n {\n \"tag\": "Tripitaka",\n \"popularity\": 643710\n },\n {\n \"tag\": "Billjim",\n \"popularity\": 635865\n },\n {\n \"tag\": "pyramidical",\n \"popularity\": 628169\n },\n {\n \"tag\": "circumlocutionist",\n \"popularity\": 620617\n },\n {\n \"tag\": "slapstick",\n \"popularity\": 613207\n },\n {\n \"tag\": "preobedience",\n \"popularity\": 605934\n },\n {\n \"tag\": "unfriarlike",\n \"popularity\": 598795\n },\n {\n \"tag\": "microchromosome",\n \"popularity\": 591786\n },\n {\n \"tag\": "Orphicism",\n \"popularity\": 584905\n },\n {\n \"tag\": "peel",\n \"popularity\": 578149\n },\n {\n \"tag\": "obediential",\n \"popularity\": 571514\n },\n {\n \"tag\": "Peripatidea",\n \"popularity\": 564997\n },\n {\n \"tag\": "undoubtful",\n \"popularity\": 558596\n },\n {\n \"tag\": "lodgeable",\n \"popularity\": 552307\n },\n {\n \"tag\": "pustulated woodchat",\n \"popularity\": 546129\n },\n {\n \"tag\": "antepast",\n \"popularity\": 540057\n },\n {\n \"tag\": "sagittoid matrimoniously",\n \"popularity\": 534091\n },\n {\n \"tag\": "Albizzia",\n \"popularity\": 528228\n },\n {\n \"tag\": "Elateridae unnewness",\n \"popularity\": 522464\n },\n {\n \"tag\": "convertingness",\n \"popularity\": 516798\n },\n {\n \"tag\": "Pelew",\n \"popularity\": 511228\n },\n {\n \"tag\": "recapitulation",\n \"popularity\": 505751\n },\n {\n \"tag\": "shack",\n \"popularity\": 500365\n },\n {\n \"tag\": "unmellowed",\n \"popularity\": 495069\n },\n {\n \"tag\": "pavis capering",\n \"popularity\": 489859\n },\n {\n \"tag\": "fanfare",\n \"popularity\": 484735\n },\n {\n \"tag\": "sole",\n \"popularity\": 479695\n },\n {\n \"tag\": "subarcuate",\n \"popularity\": 474735\n },\n {\n \"tag\": "multivious",\n \"popularity\": 469856\n },\n {\n \"tag\": "squandermania",\n \"popularity\": 465054\n },\n {\n \"tag\": "scintle",\n \"popularity\": 460329\n },\n {\n \"tag\": "hash chirognomic",\n \"popularity\": 455679\n },\n {\n \"tag\": "linseed",\n \"popularity\": 451101\n },\n {\n \"tag\": "redoubtable",\n \"popularity\": 446596\n },\n {\n \"tag\": "poachy reimpact",\n \"popularity\": 442160\n },\n {\n \"tag\": "limestone",\n \"popularity\": 437792\n },\n {\n \"tag\": "serranid",\n \"popularity\": 433492\n },\n {\n \"tag\": "pohna",\n \"popularity\": 429258\n },\n {\n \"tag\": "warwolf",\n \"popularity\": 425088\n },\n {\n \"tag\": "ruthenous",\n \"popularity\": 420981\n },\n {\n \"tag\": "dover",\n \"popularity\": 416935\n },\n {\n \"tag\": "deuteroalbumose",\n \"popularity\": 412950\n },\n {\n \"tag\": "pseudoprophetic",\n \"popularity\": 409025\n },\n {\n \"tag\": "dissoluteness",\n \"popularity\": 405157\n },\n {\n \"tag\": "preinvention",\n \"popularity\": 401347\n },\n {\n \"tag\": "swagbellied",\n \"popularity\": 397592\n },\n {\n \"tag\": "Ophidia",\n \"popularity\": 393892\n },\n {\n \"tag\": "equanimity",\n \"popularity\": 390245\n },\n {\n \"tag\": "troutful",\n \"popularity\": 386651\n },\n {\n \"tag\": "uke",\n \"popularity\": 383108\n },\n {\n \"tag\": "preacquaint",\n \"popularity\": 379616\n },\n {\n \"tag\": "shoq",\n \"popularity\": 376174\n },\n {\n \"tag\": "yox",\n \"popularity\": 372780\n },\n {\n \"tag\": "unelemental",\n \"popularity\": 369434\n },\n {\n \"tag\": "Yavapai",\n \"popularity\": 366134\n },\n {\n \"tag\": "joulean",\n \"popularity\": 362880\n },\n {\n \"tag\": "dracontine",\n \"popularity\": 359672\n },\n {\n \"tag\": "hardmouth",\n \"popularity\": 356507\n },\n {\n \"tag\": "sylvanize",\n \"popularity\": 353386\n },\n {\n \"tag\": "intraparenchymatous meadowbur",\n \"popularity\": 350308\n },\n {\n \"tag\": "uncharily",\n \"popularity\": 347271\n },\n {\n \"tag\": "redtab flexibly",\n \"popularity\": 344275\n },\n {\n \"tag\": "centervelic",\n \"popularity\": 341319\n },\n {\n \"tag\": "unravellable",\n \"popularity\": 338403\n },\n {\n \"tag\": "infortunately",\n \"popularity\": 335526\n },\n {\n \"tag\": "cannel",\n \"popularity\": 332687\n },\n {\n \"tag\": "oxyblepsia",\n \"popularity\": 329885\n },\n {\n \"tag\": "Damon",\n \"popularity\": 327120\n },\n {\n \"tag\": "etherin",\n \"popularity\": 324391\n },\n {\n \"tag\": "luminal",\n \"popularity\": 321697\n },\n {\n \"tag\": "interrogatorily presbyte",\n \"popularity\": 319038\n },\n {\n \"tag\": "hemiclastic",\n \"popularity\": 316414\n },\n {\n \"tag\": "poh flush",\n \"popularity\": 313823\n },\n {\n \"tag\": "Psoroptes",\n \"popularity\": 311265\n },\n {\n \"tag\": "dispirit",\n \"popularity\": 308740\n },\n {\n \"tag\": "nashgab",\n \"popularity\": 306246\n },\n {\n \"tag\": "Aphidiinae",\n \"popularity\": 303784\n },\n {\n \"tag\": "rhapsody nonconstruction",\n \"popularity\": 301353\n },\n {\n \"tag\": "Osmond",\n \"popularity\": 298952\n },\n {\n \"tag\": "Leonis",\n \"popularity\": 296581\n },\n {\n \"tag\": "Lemnian",\n \"popularity\": 294239\n },\n {\n \"tag\": "acetonic gnathonic",\n \"popularity\": 291926\n },\n {\n \"tag\": "surculus",\n \"popularity\": 289641\n },\n {\n \"tag\": "diagonally",\n \"popularity\": 287384\n },\n {\n \"tag\": "counterpenalty",\n \"popularity\": 285154\n },\n {\n \"tag\": "Eugenie",\n \"popularity\": 282952\n },\n {\n \"tag\": "hornbook",\n \"popularity\": 280776\n },\n {\n \"tag\": "miscoin",\n \"popularity\": 278626\n },\n {\n \"tag\": "admi",\n \"popularity\": 276501\n },\n {\n \"tag\": "Tarmac",\n \"popularity\": 274402\n },\n {\n \"tag\": "inexplicable",\n \"popularity\": 272328\n },\n {\n \"tag\": "rascallion",\n \"popularity\": 270278\n },\n {\n \"tag\": "dusterman",\n \"popularity\": 268252\n },\n {\n \"tag\": "osteostomous unhoroscopic",\n \"popularity\": 266250\n },\n {\n \"tag\": "spinibulbar",\n \"popularity\": 264271\n },\n {\n \"tag\": "phototelegraphically",\n \"popularity\": 262315\n },\n {\n \"tag\": "Manihot",\n \"popularity\": 260381\n },\n {\n \"tag\": "neighborhood",\n \"popularity\": 258470\n },\n {\n \"tag\": "Vincetoxicum",\n \"popularity\": 256581\n },\n {\n \"tag\": "khirka",\n \"popularity\": 254713\n },\n {\n \"tag\": "conscriptive",\n \"popularity\": 252866\n },\n {\n \"tag\": "synechthran",\n \"popularity\": 251040\n },\n {\n \"tag\": "Guttiferales",\n \"popularity\": 249235\n },\n {\n \"tag\": "roomful",\n \"popularity\": 247450\n },\n {\n \"tag\": "germinal",\n \"popularity\": 245685\n },\n {\n \"tag\": "untraitorous",\n \"popularity\": 243939\n },\n {\n \"tag\": "nondissenting",\n \"popularity\": 242213\n },\n {\n \"tag\": "amotion",\n \"popularity\": 240506\n },\n {\n \"tag\": "badious",\n \"popularity\": 238817\n },\n {\n \"tag\": "sumpit",\n \"popularity\": 237147\n },\n {\n \"tag\": "ectozoic",\n \"popularity\": 235496\n },\n {\n \"tag\": "elvet",\n \"popularity\": 233862\n },\n {\n \"tag\": "underclerk",\n \"popularity\": 232246\n },\n {\n \"tag\": "reticency",\n \"popularity\": 230647\n },\n {\n \"tag\": "neutroclusion",\n \"popularity\": 229065\n },\n {\n \"tag\": "unbelieving",\n \"popularity\": 227500\n },\n {\n \"tag\": "histogenetic",\n \"popularity\": 225952\n },\n {\n \"tag\": "dermamyiasis",\n \"popularity\": 224421\n },\n {\n \"tag\": "telenergy",\n \"popularity\": 222905\n },\n {\n \"tag\": "axiomatic",\n \"popularity\": 221406\n },\n {\n \"tag\": "undominoed",\n \"popularity\": 219922\n },\n {\n \"tag\": "periosteoma",\n \"popularity\": 218454\n },\n {\n \"tag\": "justiciaryship",\n \"popularity\": 217001\n },\n {\n \"tag\": "autoluminescence",\n \"popularity\": 215563\n },\n {\n \"tag\": "osmous",\n \"popularity\": 214140\n },\n {\n \"tag\": "borgh",\n \"popularity\": 212731\n },\n {\n \"tag\": "bedebt",\n \"popularity\": 211337\n },\n {\n \"tag\": "considerableness adenoidism",\n \"popularity\": 209957\n },\n {\n \"tag\": "sailorizing",\n \"popularity\": 208592\n },\n {\n \"tag\": "Montauk",\n \"popularity\": 207240\n },\n {\n \"tag\": "Bridget",\n \"popularity\": 205901\n },\n {\n \"tag\": "Gekkota",\n \"popularity\": 204577\n },\n {\n \"tag\": "subcorymbose",\n \"popularity\": 203265\n },\n {\n \"tag\": "undersap",\n \"popularity\": 201967\n },\n {\n \"tag\": "poikilothermic",\n \"popularity\": 200681\n },\n {\n \"tag\": "enneatical",\n \"popularity\": 199409\n },\n {\n \"tag\": "martinetism",\n \"popularity\": 198148\n },\n {\n \"tag\": "sustanedly",\n \"popularity\": 196901\n },\n {\n \"tag\": "declaration",\n \"popularity\": 195665\n },\n {\n \"tag\": "myringoplasty",\n \"popularity\": 194442\n },\n {\n \"tag\": "Ginkgo",\n \"popularity\": 193230\n },\n {\n \"tag\": "unrecurrent",\n \"popularity\": 192031\n },\n {\n \"tag\": "proprecedent",\n \"popularity\": 190843\n },\n {\n \"tag\": "roadman",\n \"popularity\": 189666\n },\n {\n \"tag\": "elemin",\n \"popularity\": 188501\n },\n {\n \"tag\": "maggot",\n \"popularity\": 187347\n },\n {\n \"tag\": "alitrunk",\n \"popularity\": 186204\n },\n {\n \"tag\": "introspection",\n \"popularity\": 185071\n },\n {\n \"tag\": "batiker",\n \"popularity\": 183950\n },\n {\n \"tag\": "backhatch oversettle",\n \"popularity\": 182839\n },\n {\n \"tag\": "thresherman",\n \"popularity\": 181738\n },\n {\n \"tag\": "protemperance",\n \"popularity\": 180648\n },\n {\n \"tag\": "undern",\n \"popularity\": 179568\n },\n {\n \"tag\": "tweeg",\n \"popularity\": 178498\n },\n {\n \"tag\": "crosspath",\n \"popularity\": 177438\n },\n {\n \"tag\": "Tangaridae",\n \"popularity\": 176388\n },\n {\n \"tag\": "scrutation",\n \"popularity\": 175348\n },\n {\n \"tag\": "piecemaker",\n \"popularity\": 174317\n },\n {\n \"tag\": "paster",\n \"popularity\": 173296\n },\n {\n \"tag\": "unpretendingness",\n \"popularity\": 172284\n },\n {\n \"tag\": "inframundane",\n \"popularity\": 171281\n },\n {\n \"tag\": "kiblah",\n \"popularity\": 170287\n },\n {\n \"tag\": "playwrighting",\n \"popularity\": 169302\n },\n {\n \"tag\": "gonepoiesis snowslip",\n \"popularity\": 168326\n },\n {\n \"tag\": "hoodwise",\n \"popularity\": 167359\n },\n {\n \"tag\": "postseason",\n \"popularity\": 166401\n },\n {\n \"tag\": "equivocality",\n \"popularity\": 165451\n },\n {\n \"tag\": "Opiliaceae nuclease",\n \"popularity\": 164509\n },\n {\n \"tag\": "sextipara",\n \"popularity\": 163576\n },\n {\n \"tag\": "weeper",\n \"popularity\": 162651\n },\n {\n \"tag\": "frambesia",\n \"popularity\": 161735\n },\n {\n \"tag\": "answerable",\n \"popularity\": 160826\n },\n {\n \"tag\": "Trichosporum",\n \"popularity\": 159925\n },\n {\n \"tag\": "cajuputol",\n \"popularity\": 159033\n },\n {\n \"tag\": "pleomorphous",\n \"popularity\": 158148\n },\n {\n \"tag\": "aculeolate",\n \"popularity\": 157270\n },\n {\n \"tag\": "wherever",\n \"popularity\": 156400\n },\n {\n \"tag\": "collapse",\n \"popularity\": 155538\n },\n {\n \"tag\": "porky",\n \"popularity\": 154683\n },\n {\n \"tag\": "perule",\n \"popularity\": 153836\n },\n {\n \"tag\": "Nevada",\n \"popularity\": 152996\n },\n {\n \"tag\": "conalbumin",\n \"popularity\": 152162\n },\n {\n \"tag\": "tsunami",\n \"popularity\": 151336\n },\n {\n \"tag\": "Gulf",\n \"popularity\": 150517\n },\n {\n \"tag\": "hertz",\n \"popularity\": 149705\n },\n {\n \"tag\": "limmock",\n \"popularity\": 148900\n },\n {\n \"tag\": "Tartarize",\n \"popularity\": 148101\n },\n {\n \"tag\": "entosphenoid",\n \"popularity\": 147310\n },\n {\n \"tag\": "ibis",\n \"popularity\": 146524\n },\n {\n \"tag\": "unyeaned",\n \"popularity\": 145746\n },\n {\n \"tag\": "tritural",\n \"popularity\": 144973\n },\n {\n \"tag\": "hundredary",\n \"popularity\": 144207\n },\n {\n \"tag\": "stolonlike",\n \"popularity\": 143448\n },\n {\n \"tag\": "chorister",\n \"popularity\": 142694\n },\n {\n \"tag\": "mismove",\n \"popularity\": 141947\n },\n {\n \"tag\": "Andine",\n \"popularity\": 141206\n },\n {\n \"tag\": "Annette proneur escribe",\n \"popularity\": 140471\n },\n {\n \"tag\": "exoperidium",\n \"popularity\": 139742\n },\n {\n \"tag\": "disedge",\n \"popularity\": 139019\n },\n {\n \"tag\": "hypochloruria",\n \"popularity\": 138302\n },\n {\n \"tag\": "prepupa",\n \"popularity\": 137590\n },\n {\n \"tag\": "assent",\n \"popularity\": 136884\n },\n {\n \"tag\": "hydrazobenzene",\n \"popularity\": 136184\n },\n {\n \"tag\": "emballonurid",\n \"popularity\": 135489\n },\n {\n \"tag\": "roselle",\n \"popularity\": 134800\n },\n {\n \"tag\": "unifiedly",\n \"popularity\": 134117\n },\n {\n \"tag\": "clang",\n \"popularity\": 133439\n },\n {\n \"tag\": "acetolytic",\n \"popularity\": 132766\n },\n {\n \"tag\": "cladodont",\n \"popularity\": 132098\n },\n {\n \"tag\": "recoast",\n \"popularity\": 131436\n },\n {\n \"tag\": "celebrated tydie Eocarboniferous",\n \"popularity\": 130779\n },\n {\n \"tag\": "superconsciousness",\n \"popularity\": 130127\n },\n {\n \"tag\": "soberness",\n \"popularity\": 129480\n },\n {\n \"tag\": "panoramist",\n \"popularity\": 128838\n },\n {\n \"tag\": "Orbitolina",\n \"popularity\": 128201\n },\n {\n \"tag\": "overlewd",\n \"popularity\": 127569\n },\n {\n \"tag\": "demiquaver",\n \"popularity\": 126942\n },\n {\n \"tag\": "kamelaukion",\n \"popularity\": 126319\n },\n {\n \"tag\": "flancard",\n \"popularity\": 125702\n },\n {\n \"tag\": "tricuspid",\n \"popularity\": 125089\n },\n {\n \"tag\": "bepelt",\n \"popularity\": 124480\n },\n {\n \"tag\": "decuplet",\n \"popularity\": 123877\n },\n {\n \"tag\": "Rockies",\n \"popularity\": 123278\n },\n {\n \"tag\": "unforgeability",\n \"popularity\": 122683\n },\n {\n \"tag\": "mocha",\n \"popularity\": 122093\n },\n {\n \"tag\": "scrunge",\n \"popularity\": 121507\n },\n {\n \"tag\": "delighter",\n \"popularity\": 120926\n },\n {\n \"tag\": "willey Microtinae",\n \"popularity\": 120349\n },\n {\n \"tag\": "unhuntable",\n \"popularity\": 119777\n },\n {\n \"tag\": "historically",\n \"popularity\": 119208\n },\n {\n \"tag\": "vicegerentship",\n \"popularity\": 118644\n },\n {\n \"tag\": "hemangiosarcoma",\n \"popularity\": 118084\n },\n {\n \"tag\": "harpago",\n \"popularity\": 117528\n },\n {\n \"tag\": "unionoid",\n \"popularity\": 116976\n },\n {\n \"tag\": "wiseman",\n \"popularity\": 116429\n },\n {\n \"tag\": "diclinism",\n \"popularity\": 115885\n },\n {\n \"tag\": "Maud",\n \"popularity\": 115345\n },\n {\n \"tag\": "scaphocephalism",\n \"popularity\": 114809\n },\n {\n \"tag\": "obtenebration",\n \"popularity\": 114277\n },\n {\n \"tag\": "cymar predreadnought",\n \"popularity\": 113749\n },\n {\n \"tag\": "discommend",\n \"popularity\": 113225\n },\n {\n \"tag\": "crude",\n \"popularity\": 112704\n },\n {\n \"tag\": "upflash",\n \"popularity\": 112187\n },\n {\n \"tag\": "saltimbank",\n \"popularity\": 111674\n },\n {\n \"tag\": "posthysterical",\n \"popularity\": 111165\n },\n {\n \"tag\": "trample",\n \"popularity\": 110659\n },\n {\n \"tag\": "ungirthed",\n \"popularity\": 110157\n },\n {\n \"tag\": "unshakable",\n \"popularity\": 109658\n },\n {\n \"tag\": "hepatocystic",\n \"popularity\": 109163\n },\n {\n \"tag\": "psammophyte",\n \"popularity\": 108671\n },\n {\n \"tag\": "millionfold",\n \"popularity\": 108183\n },\n {\n \"tag\": "outtaste",\n \"popularity\": 107698\n },\n {\n \"tag\": "poppycockish",\n \"popularity\": 107217\n },\n {\n \"tag\": "viduine",\n \"popularity\": 106739\n },\n {\n \"tag\": "pleasureman",\n \"popularity\": 106264\n },\n {\n \"tag\": "cholesterolemia",\n \"popularity\": 105792\n },\n {\n \"tag\": "hostlerwife",\n \"popularity\": 105324\n },\n {\n \"tag\": "figure undergrass",\n \"popularity\": 104859\n },\n {\n \"tag\": "bedrape",\n \"popularity\": 104398\n },\n {\n \"tag\": "nuttishness",\n \"popularity\": 103939\n },\n {\n \"tag\": "fow",\n \"popularity\": 103484\n },\n {\n \"tag\": "rachianesthesia",\n \"popularity\": 103031\n },\n {\n \"tag\": "recruitable",\n \"popularity\": 102582\n },\n {\n \"tag\": "semianatomical Oenotheraceae",\n \"popularity\": 102136\n },\n {\n \"tag\": "extracapsular",\n \"popularity\": 101693\n },\n {\n \"tag\": "unsigneted",\n \"popularity\": 101253\n },\n {\n \"tag\": "fissural",\n \"popularity\": 100816\n },\n {\n \"tag\": "ayous",\n \"popularity\": 100381\n },\n {\n \"tag\": "crestfallenness odontograph",\n \"popularity\": 99950\n },\n {\n \"tag\": "monopodium",\n \"popularity\": 99522\n },\n {\n \"tag\": "germfree",\n \"popularity\": 99096\n },\n {\n \"tag\": "dauphin",\n \"popularity\": 98673\n },\n {\n \"tag\": "nonagesimal",\n \"popularity\": 98254\n },\n {\n \"tag\": "waterchat",\n \"popularity\": 97836\n },\n {\n \"tag\": "Entelodon",\n \"popularity\": 97422\n },\n {\n \"tag\": "semischolastic",\n \"popularity\": 97010\n },\n {\n \"tag\": "somata",\n \"popularity\": 96602\n },\n {\n \"tag\": "expositorily",\n \"popularity\": 96195\n },\n {\n \"tag\": "bass",\n \"popularity\": 95792\n },\n {\n \"tag\": "calorimetry",\n \"popularity\": 95391\n },\n {\n \"tag\": "entireness",\n \"popularity\": 94993\n },\n {\n \"tag\": "ratline soppiness",\n \"popularity\": 94597\n },\n {\n \"tag\": "shor",\n \"popularity\": 94204\n },\n {\n \"tag\": "coprecipitation",\n \"popularity\": 93813\n },\n {\n \"tag\": "unblushingly",\n \"popularity\": 93425\n },\n {\n \"tag\": "macarize",\n \"popularity\": 93040\n },\n {\n \"tag\": "scruplesomeness",\n \"popularity\": 92657\n },\n {\n \"tag\": "offsaddle",\n \"popularity\": 92276\n },\n {\n \"tag\": "hypertragical",\n \"popularity\": 91898\n },\n {\n \"tag\": "uncassock loined",\n \"popularity\": 91522\n },\n {\n \"tag\": "interlobate",\n \"popularity\": 91149\n },\n {\n \"tag\": "releasor orrisroot stoloniferously",\n \"popularity\": 90778\n },\n {\n \"tag\": "elementoid",\n \"popularity\": 90410\n },\n {\n \"tag\": "Lentilla",\n \"popularity\": 90043\n },\n {\n \"tag\": "distressing",\n \"popularity\": 89679\n },\n {\n \"tag\": "hydrodrome",\n \"popularity\": 89318\n },\n {\n \"tag\": "Jeannette",\n \"popularity\": 88958\n },\n {\n \"tag\": "Kuli",\n \"popularity\": 88601\n },\n {\n \"tag\": "taxinomist",\n \"popularity\": 88246\n },\n {\n \"tag\": "southwestwardly",\n \"popularity\": 87894\n },\n {\n \"tag\": "polyparia",\n \"popularity\": 87543\n },\n {\n \"tag\": "exmeridian",\n \"popularity\": 87195\n },\n {\n \"tag\": "splenius regimentaled",\n \"popularity\": 86849\n },\n {\n \"tag\": "Sphaeropsidaceae",\n \"popularity\": 86505\n },\n {\n \"tag\": "unbegun",\n \"popularity\": 86163\n },\n {\n \"tag\": "something",\n \"popularity\": 85823\n },\n {\n \"tag\": "contaminable nonexpulsion",\n \"popularity\": 85486\n },\n {\n \"tag\": "douser",\n \"popularity\": 85150\n },\n {\n \"tag\": "prostrike",\n \"popularity\": 84817\n },\n {\n \"tag\": "worky",\n \"popularity\": 84485\n },\n {\n \"tag\": "folliful",\n \"popularity\": 84156\n },\n {\n \"tag\": "prioracy",\n \"popularity\": 83828\n },\n {\n \"tag\": "undermentioned",\n \"popularity\": 83503\n },\n {\n \"tag\": "Judaica",\n \"popularity\": 83179\n },\n {\n \"tag\": "multifarious",\n \"popularity\": 82858\n },\n {\n \"tag\": "poogye",\n \"popularity\": 82538\n },\n {\n \"tag\": "Sparganium",\n \"popularity\": 82221\n },\n {\n \"tag\": "thurrock",\n \"popularity\": 81905\n },\n {\n \"tag\": "outblush",\n \"popularity\": 81591\n },\n {\n \"tag\": "Strophanthus supraordination",\n \"popularity\": 81279\n },\n {\n \"tag\": "gingerroot",\n \"popularity\": 80969\n },\n {\n \"tag\": "unconscient",\n \"popularity\": 80661\n },\n {\n \"tag\": "unconstitutionally",\n \"popularity\": 80354\n },\n {\n \"tag\": "plaguily",\n \"popularity\": 80050\n },\n {\n \"tag\": "waterily equatorwards",\n \"popularity\": 79747\n },\n {\n \"tag\": "nondeposition",\n \"popularity\": 79446\n },\n {\n \"tag\": "dronishly",\n \"popularity\": 79147\n },\n {\n \"tag\": "gateado",\n \"popularity\": 78849\n },\n {\n \"tag\": "dislink",\n \"popularity\": 78553\n },\n {\n \"tag\": "Joceline",\n \"popularity\": 78259\n },\n {\n \"tag\": "amphiboliferous",\n \"popularity\": 77967\n },\n {\n \"tag\": "bushrope",\n \"popularity\": 77676\n },\n {\n \"tag\": "plumicorn sulphosalicylic",\n \"popularity\": 77387\n },\n {\n \"tag\": "nonefficiency",\n \"popularity\": 77100\n },\n {\n \"tag\": "hieroscopy",\n \"popularity\": 76815\n },\n {\n \"tag\": "causativeness",\n \"popularity\": 76531\n },\n {\n \"tag\": "swird paleoeremology",\n \"popularity\": 76249\n },\n {\n \"tag\": "camphoric",\n \"popularity\": 75968\n },\n {\n \"tag\": "retaining",\n \"popularity\": 75689\n },\n {\n \"tag\": "thyreoprotein",\n \"popularity\": 75411\n },\n {\n \"tag\": "carbona",\n \"popularity\": 75136\n },\n {\n \"tag\": "protectively",\n \"popularity\": 74861\n },\n {\n \"tag\": "mosasaur",\n \"popularity\": 74589\n },\n {\n \"tag\": "reciprocator",\n \"popularity\": 74317\n },\n {\n \"tag\": "detentive",\n \"popularity\": 74048\n },\n {\n \"tag\": "supravital",\n \"popularity\": 73780\n },\n {\n \"tag\": "Vespertilionidae",\n \"popularity\": 73513\n },\n {\n \"tag\": "parka",\n \"popularity\": 73248\n },\n {\n \"tag\": "pickaway",\n \"popularity\": 72984\n },\n {\n \"tag\": "oleaceous",\n \"popularity\": 72722\n },\n {\n \"tag\": "anticogitative",\n \"popularity\": 72462\n },\n {\n \"tag\": "woe",\n \"popularity\": 72203\n },\n {\n \"tag\": "skeuomorph",\n \"popularity\": 71945\n },\n {\n \"tag\": "helpmeet",\n \"popularity\": 71689\n },\n {\n \"tag\": "Hexactinellida brickmaking",\n \"popularity\": 71434\n },\n {\n \"tag\": "resink",\n \"popularity\": 71180\n },\n {\n \"tag\": "diluter",\n \"popularity\": 70928\n },\n {\n \"tag\": "micromicron",\n \"popularity\": 70677\n },\n {\n \"tag\": "parentage",\n \"popularity\": 70428\n },\n {\n \"tag\": "galactorrhoea",\n \"popularity\": 70180\n },\n {\n \"tag\": "gey",\n \"popularity\": 69934\n },\n {\n \"tag\": "gesticulatory",\n \"popularity\": 69689\n },\n {\n \"tag\": "wergil",\n \"popularity\": 69445\n },\n {\n \"tag\": "Lecanora",\n \"popularity\": 69202\n },\n {\n \"tag\": "malanders karst",\n \"popularity\": 68961\n },\n {\n \"tag\": "vibetoite",\n \"popularity\": 68721\n },\n {\n \"tag\": "unrequitedness",\n \"popularity\": 68483\n },\n {\n \"tag\": "outwash",\n \"popularity\": 68245\n },\n {\n \"tag\": "unsacred",\n \"popularity\": 68009\n },\n {\n \"tag\": "unabetted dividend",\n \"popularity\": 67775\n },\n {\n \"tag\": "untraveling",\n \"popularity\": 67541\n },\n {\n \"tag\": "thermobattery",\n \"popularity\": 67309\n },\n {\n \"tag\": "polypragmist",\n \"popularity\": 67078\n },\n {\n \"tag\": "irrefutableness",\n \"popularity\": 66848\n },\n {\n \"tag\": "remiges",\n \"popularity\": 66620\n },\n {\n \"tag\": "implode",\n \"popularity\": 66393\n },\n {\n \"tag\": "superfluousness",\n \"popularity\": 66166\n },\n {\n \"tag\": "croakily unalleviated",\n \"popularity\": 65942\n },\n {\n \"tag\": "edicule",\n \"popularity\": 65718\n },\n {\n \"tag\": "entophytous",\n \"popularity\": 65495\n },\n {\n \"tag\": "benefactorship Toryish",\n \"popularity\": 65274\n },\n {\n \"tag\": "pseudoamateurish",\n \"popularity\": 65054\n },\n {\n \"tag\": "flueless Iguanodontoidea snipnose",\n \"popularity\": 64835\n },\n {\n \"tag\": "zealotical Zamicrus interpole",\n \"popularity\": 64617\n },\n {\n \"tag\": "whereabout",\n \"popularity\": 64401\n },\n {\n \"tag\": "benzazide",\n \"popularity\": 64185\n },\n {\n \"tag\": "pokeweed",\n \"popularity\": 63971\n },\n {\n \"tag\": "calamitoid",\n \"popularity\": 63757\n },\n {\n \"tag\": "sporozoal",\n \"popularity\": 63545\n },\n {\n \"tag\": "physcioid Welshwoman",\n \"popularity\": 63334\n },\n {\n \"tag\": "wanting",\n \"popularity\": 63124\n },\n {\n \"tag\": "unencumbering",\n \"popularity\": 62915\n },\n {\n \"tag\": "Tupi",\n \"popularity\": 62707\n },\n {\n \"tag\": "potbank",\n \"popularity\": 62501\n },\n {\n \"tag\": "bulked",\n \"popularity\": 62295\n },\n {\n \"tag\": "uparise",\n \"popularity\": 62090\n },\n {\n \"tag\": "Sudra",\n \"popularity\": 61887\n },\n {\n \"tag\": "hyperscrupulosity",\n \"popularity\": 61684\n },\n {\n \"tag\": "subterraneously unmaid",\n \"popularity\": 61483\n },\n {\n \"tag\": "poisonousness",\n \"popularity\": 61282\n },\n {\n \"tag\": "phare",\n \"popularity\": 61083\n },\n {\n \"tag\": "dicynodont",\n \"popularity\": 60884\n },\n {\n \"tag\": "chewer",\n \"popularity\": 60687\n },\n {\n \"tag\": "uliginous",\n \"popularity\": 60490\n },\n {\n \"tag\": "tinman",\n \"popularity\": 60295\n },\n {\n \"tag\": "coconut",\n \"popularity\": 60100\n },\n {\n \"tag\": "phryganeoid",\n \"popularity\": 59907\n },\n {\n \"tag\": "bismillah",\n \"popularity\": 59714\n },\n {\n \"tag\": "tautomeric",\n \"popularity\": 59523\n },\n {\n \"tag\": "jerquer",\n \"popularity\": 59332\n },\n {\n \"tag\": "Dryopithecinae",\n \"popularity\": 59143\n },\n {\n \"tag\": "ghizite",\n \"popularity\": 58954\n },\n {\n \"tag\": "unliveable",\n \"popularity\": 58766\n },\n {\n \"tag\": "craftsmaster",\n \"popularity\": 58579\n },\n {\n \"tag\": "semiscenic",\n \"popularity\": 58394\n },\n {\n \"tag\": "danaid",\n \"popularity\": 58209\n },\n {\n \"tag\": "flawful",\n \"popularity\": 58025\n },\n {\n \"tag\": "risibleness",\n \"popularity\": 57841\n },\n {\n \"tag\": "Muscovite",\n \"popularity\": 57659\n },\n {\n \"tag\": "snaringly",\n \"popularity\": 57478\n },\n {\n \"tag\": "brilliantwise",\n \"popularity\": 57297\n },\n {\n \"tag\": "plebeity",\n \"popularity\": 57118\n },\n {\n \"tag\": "historicalness",\n \"popularity\": 56939\n },\n {\n \"tag\": "piecemeal",\n \"popularity\": 56761\n },\n {\n \"tag\": "maxillipedary",\n \"popularity\": 56584\n },\n {\n \"tag\": "Hypenantron",\n \"popularity\": 56408\n },\n {\n \"tag\": "quaintness avigate",\n \"popularity\": 56233\n },\n {\n \"tag\": "ave",\n \"popularity\": 56059\n },\n {\n \"tag\": "mediaevally",\n \"popularity\": 55885\n },\n {\n \"tag\": "brucite",\n \"popularity\": 55712\n },\n {\n \"tag\": "Schwendenerian",\n \"popularity\": 55541\n },\n {\n \"tag\": "julole",\n \"popularity\": 55370\n },\n {\n \"tag\": "palaeolith",\n \"popularity\": 55199\n },\n {\n \"tag\": "cotyledonary",\n \"popularity\": 55030\n },\n {\n \"tag\": "rond",\n \"popularity\": 54861\n },\n {\n \"tag\": "boomster tassoo",\n \"popularity\": 54694\n },\n {\n \"tag\": "cattishly",\n \"popularity\": 54527\n },\n {\n \"tag\": "tonguefence",\n \"popularity\": 54360\n },\n {\n \"tag\": "hexastylar triskele",\n \"popularity\": 54195\n },\n {\n \"tag\": "ariot",\n \"popularity\": 54030\n },\n {\n \"tag\": "intarsist",\n \"popularity\": 53867\n },\n {\n \"tag\": "Oscines",\n \"popularity\": 53704\n },\n {\n \"tag\": "Spaniolize",\n \"popularity\": 53541\n },\n {\n \"tag\": "smellfungus",\n \"popularity\": 53380\n },\n {\n \"tag\": "redisplay",\n \"popularity\": 53219\n },\n {\n \"tag\": "phosphene",\n \"popularity\": 53059\n },\n {\n \"tag\": "phycomycete",\n \"popularity\": 52900\n },\n {\n \"tag\": "prophetic",\n \"popularity\": 52741\n },\n {\n \"tag\": "overtrustful",\n \"popularity\": 52584\n },\n {\n \"tag\": "pinitol",\n \"popularity\": 52427\n },\n {\n \"tag\": "asthmatic",\n \"popularity\": 52270\n },\n {\n \"tag\": "convulsive",\n \"popularity\": 52115\n },\n {\n \"tag\": "draughtswoman",\n \"popularity\": 51960\n },\n {\n \"tag\": "unetymologizable",\n \"popularity\": 51806\n },\n {\n \"tag\": "centrarchoid",\n \"popularity\": 51652\n },\n {\n \"tag\": "mesioincisal",\n \"popularity\": 51500\n },\n {\n \"tag\": "transbaikal",\n \"popularity\": 51348\n },\n {\n \"tag\": "silveriness",\n \"popularity\": 51196\n },\n {\n \"tag\": "costotomy",\n \"popularity\": 51046\n },\n {\n \"tag\": "caracore",\n \"popularity\": 50896\n },\n {\n \"tag\": "depotentiation",\n \"popularity\": 50747\n },\n {\n \"tag\": "glossoepiglottidean",\n \"popularity\": 50598\n },\n {\n \"tag\": "upswell",\n \"popularity\": 50450\n },\n {\n \"tag\": "flecnodal",\n \"popularity\": 50303\n },\n {\n \"tag\": "coventrate",\n \"popularity\": 50157\n },\n {\n \"tag\": "duchesse",\n \"popularity\": 50011\n },\n {\n \"tag\": "excisemanship trophied",\n \"popularity\": 49866\n },\n {\n \"tag\": "cytinaceous",\n \"popularity\": 49721\n },\n {\n \"tag\": "assuringly",\n \"popularity\": 49577\n },\n {\n \"tag\": "unconducted upliftitis",\n \"popularity\": 49434\n },\n {\n \"tag\": "rachicentesis",\n \"popularity\": 49292\n },\n {\n \"tag\": "antiangular",\n \"popularity\": 49150\n },\n {\n \"tag\": "advisal",\n \"popularity\": 49008\n },\n {\n \"tag\": "birdcatcher",\n \"popularity\": 48868\n },\n {\n \"tag\": "secularistic",\n \"popularity\": 48728\n },\n {\n \"tag\": "grandeeism superinformal",\n \"popularity\": 48588\n },\n {\n \"tag\": "unapprehension",\n \"popularity\": 48449\n },\n {\n \"tag\": "excipulum",\n \"popularity\": 48311\n },\n {\n \"tag\": "decimole",\n \"popularity\": 48174\n },\n {\n \"tag\": "semidrachm",\n \"popularity\": 48037\n },\n {\n \"tag\": "uvulotome",\n \"popularity\": 47901\n },\n {\n \"tag\": "Lemaneaceae",\n \"popularity\": 47765\n },\n {\n \"tag\": "corrade",\n \"popularity\": 47630\n },\n {\n \"tag\": "Kuroshio",\n \"popularity\": 47495\n },\n {\n \"tag\": "Araliophyllum",\n \"popularity\": 47361\n },\n {\n \"tag\": "victoriousness cardiosphygmograph",\n \"popularity\": 47228\n },\n {\n \"tag\": "reinvent",\n \"popularity\": 47095\n },\n {\n \"tag\": "Macrotolagus",\n \"popularity\": 46963\n },\n {\n \"tag\": "strenuousness",\n \"popularity\": 46831\n },\n {\n \"tag\": "deviability",\n \"popularity\": 46700\n },\n {\n \"tag\": "phyllospondylous",\n \"popularity\": 46570\n },\n {\n \"tag\": "bisect rudderhole",\n \"popularity\": 46440\n },\n {\n \"tag\": "crownwork",\n \"popularity\": 46311\n },\n {\n \"tag\": "Ascalabota",\n \"popularity\": 46182\n },\n {\n \"tag\": "prostatomyomectomy",\n \"popularity\": 46054\n },\n {\n \"tag\": "neurosyphilis",\n \"popularity\": 45926\n },\n {\n \"tag\": "tabloid scraplet",\n \"popularity\": 45799\n },\n {\n \"tag\": "nonmedullated servility",\n \"popularity\": 45673\n },\n {\n \"tag\": "melopoeic practicalization",\n \"popularity\": 45547\n },\n {\n \"tag\": "nonrhythmic",\n \"popularity\": 45421\n },\n {\n \"tag\": "deplorer",\n \"popularity\": 45296\n },\n {\n \"tag\": "Ophion",\n \"popularity\": 45172\n },\n {\n \"tag\": "subprioress",\n \"popularity\": 45048\n },\n {\n \"tag\": "semiregular",\n \"popularity\": 44925\n },\n {\n \"tag\": "praelection",\n \"popularity\": 44802\n },\n {\n \"tag\": "discinct",\n \"popularity\": 44680\n },\n {\n \"tag\": "preplace",\n \"popularity\": 44558\n },\n {\n \"tag\": "paternoster",\n \"popularity\": 44437\n },\n {\n \"tag\": "suboccipital",\n \"popularity\": 44316\n },\n {\n \"tag\": "Teutophil",\n \"popularity\": 44196\n },\n {\n \"tag\": "tracheole",\n \"popularity\": 44076\n },\n {\n \"tag\": "subsmile",\n \"popularity\": 43957\n },\n {\n \"tag\": "nonapostatizing",\n \"popularity\": 43839\n },\n {\n \"tag\": "cleidotomy",\n \"popularity\": 43720\n },\n {\n \"tag\": "hingle",\n \"popularity\": 43603\n },\n {\n \"tag\": "jocoque",\n \"popularity\": 43486\n },\n {\n \"tag\": "trundler notidanian",\n \"popularity\": 43369\n },\n {\n \"tag\": "strangling misdaub",\n \"popularity\": 43253\n },\n {\n \"tag\": "noncancellable",\n \"popularity\": 43137\n },\n {\n \"tag\": "lavabo",\n \"popularity\": 43022\n },\n {\n \"tag\": "lanterloo",\n \"popularity\": 42907\n },\n {\n \"tag\": "uncitizenly",\n \"popularity\": 42793\n },\n {\n \"tag\": "autoturning",\n \"popularity\": 42679\n },\n {\n \"tag\": "Haganah",\n \"popularity\": 42566\n },\n {\n \"tag\": "Glecoma",\n \"popularity\": 42453\n },\n {\n \"tag\": "membered",\n \"popularity\": 42341\n },\n {\n \"tag\": "consuetudinal",\n \"popularity\": 42229\n },\n {\n \"tag\": "gatehouse",\n \"popularity\": 42117\n },\n {\n \"tag\": "tetherball",\n \"popularity\": 42006\n },\n {\n \"tag\": "counterrevolutionist numismatical",\n \"popularity\": 41896\n },\n {\n \"tag\": "pagehood plateiasmus",\n \"popularity\": 41786\n },\n {\n \"tag\": "pelterer",\n \"popularity\": 41676\n },\n {\n \"tag\": "splenemphraxis",\n \"popularity\": 41567\n },\n {\n \"tag\": "Crypturidae",\n \"popularity\": 41458\n },\n {\n \"tag\": "caboodle",\n \"popularity\": 41350\n },\n {\n \"tag\": "Filaria",\n \"popularity\": 41242\n },\n {\n \"tag\": "noninvincibility",\n \"popularity\": 41135\n },\n {\n \"tag\": "preadvertisement",\n \"popularity\": 41028\n },\n {\n \"tag\": "bathrobe",\n \"popularity\": 40921\n },\n {\n \"tag\": "nitrifier",\n \"popularity\": 40815\n },\n {\n \"tag\": "furthermore",\n \"popularity\": 40709\n },\n {\n \"tag\": "recrate",\n \"popularity\": 40604\n },\n {\n \"tag\": "inexist",\n \"popularity\": 40499\n },\n {\n \"tag\": "Mocoan",\n \"popularity\": 40395\n },\n {\n \"tag\": "forint",\n \"popularity\": 40291\n },\n {\n \"tag\": "cardiomyoliposis",\n \"popularity\": 40187\n },\n {\n \"tag\": "channeling",\n \"popularity\": 40084\n },\n {\n \"tag\": "quebrachine",\n \"popularity\": 39981\n },\n {\n \"tag\": "magistery",\n \"popularity\": 39879\n },\n {\n \"tag\": "koko",\n \"popularity\": 39777\n },\n {\n \"tag\": "nobilify",\n \"popularity\": 39676\n },\n {\n \"tag\": "articulate taprooted",\n \"popularity\": 39575\n },\n {\n \"tag\": "cardiotonic Nicaragua",\n \"popularity\": 39474\n },\n {\n \"tag\": "assertiveness",\n \"popularity\": 39374\n },\n {\n \"tag\": "springtail",\n \"popularity\": 39274\n },\n {\n \"tag\": "spontoon",\n \"popularity\": 39174\n },\n {\n \"tag\": "plesiobiosis",\n \"popularity\": 39075\n },\n {\n \"tag\": "rooinek",\n \"popularity\": 38976\n },\n {\n \"tag\": "hairif falsehood",\n \"popularity\": 38878\n },\n {\n \"tag\": "synodally",\n \"popularity\": 38780\n },\n {\n \"tag\": "biodynamics",\n \"popularity\": 38683\n },\n {\n \"tag\": "trickling",\n \"popularity\": 38585\n },\n {\n \"tag\": "oxfly daystar",\n \"popularity\": 38489\n },\n {\n \"tag\": "epicycloidal",\n \"popularity\": 38392\n },\n {\n \"tag\": "shorthand",\n \"popularity\": 38296\n },\n {\n \"tag\": "herpolhode",\n \"popularity\": 38201\n },\n {\n \"tag\": "polysynthesism",\n \"popularity\": 38105\n },\n {\n \"tag\": "cany",\n \"popularity\": 38010\n },\n {\n \"tag\": "sideage",\n \"popularity\": 37916\n },\n {\n \"tag\": "strainableness",\n \"popularity\": 37822\n },\n {\n \"tag\": "superformidable",\n \"popularity\": 37728\n },\n {\n \"tag\": "slendang",\n \"popularity\": 37634\n },\n {\n \"tag\": "impropriation",\n \"popularity\": 37541\n },\n {\n \"tag\": "ficklehearted",\n \"popularity\": 37449\n },\n {\n \"tag\": "wintrify",\n \"popularity\": 37356\n },\n {\n \"tag\": "geomorphogenist",\n \"popularity\": 37264\n },\n {\n \"tag\": "smuggleable",\n \"popularity\": 37173\n },\n {\n \"tag\": "delapsion",\n \"popularity\": 37081\n },\n {\n \"tag\": "projective",\n \"popularity\": 36990\n },\n {\n \"tag\": "unglue exfoliation",\n \"popularity\": 36900\n },\n {\n \"tag\": "Acerae",\n \"popularity\": 36810\n },\n {\n \"tag\": "unstaged",\n \"popularity\": 36720\n },\n {\n \"tag\": "ranal",\n \"popularity\": 36630\n },\n {\n \"tag\": "worrier",\n \"popularity\": 36541\n },\n {\n \"tag\": "unhid",\n \"popularity\": 36452\n },\n {\n \"tag\": "adequation",\n \"popularity\": 36363\n },\n {\n \"tag\": "strongylid Sokotri",\n \"popularity\": 36275\n },\n {\n \"tag\": "fumingly",\n \"popularity\": 36187\n },\n {\n \"tag\": "gynosporangium phaenogenetic",\n \"popularity\": 36100\n },\n {\n \"tag\": "uniunguiculate",\n \"popularity\": 36012\n },\n {\n \"tag\": "prudelike",\n \"popularity\": 35926\n },\n {\n \"tag\": "seminomata",\n \"popularity\": 35839\n },\n {\n \"tag\": "trinklet",\n \"popularity\": 35753\n },\n {\n \"tag\": "risorial",\n \"popularity\": 35667\n },\n {\n \"tag\": "pericardiocentesis",\n \"popularity\": 35581\n },\n {\n \"tag\": "filmist",\n \"popularity\": 35496\n },\n {\n \"tag\": "Nana",\n \"popularity\": 35411\n },\n {\n \"tag\": "cynipoid",\n \"popularity\": 35326\n },\n {\n \"tag\": "cteniform",\n \"popularity\": 35242\n },\n {\n \"tag\": "semiflex",\n \"popularity\": 35158\n },\n {\n \"tag\": "solstitially",\n \"popularity\": 35074\n },\n {\n \"tag\": "Algarsife",\n \"popularity\": 34991\n },\n {\n \"tag\": "noncriminal",\n \"popularity\": 34908\n },\n {\n \"tag\": "compassion",\n \"popularity\": 34825\n },\n {\n \"tag\": "Buddhic",\n \"popularity\": 34743\n },\n {\n \"tag\": "vellicative dactylically hotfoot",\n \"popularity\": 34661\n },\n {\n \"tag\": "chicory",\n \"popularity\": 34579\n },\n {\n \"tag\": "transperitoneally",\n \"popularity\": 34497\n },\n {\n \"tag\": "pennae",\n \"popularity\": 34416\n },\n {\n \"tag\": "Flamandize",\n \"popularity\": 34335\n },\n {\n \"tag\": "underviewer",\n \"popularity\": 34254\n },\n {\n \"tag\": "assoil",\n \"popularity\": 34174\n },\n {\n \"tag\": "saccharobacillus",\n \"popularity\": 34094\n },\n {\n \"tag\": "biacetylene",\n \"popularity\": 34014\n },\n {\n \"tag\": "mouchardism",\n \"popularity\": 33935\n },\n {\n \"tag\": "anisomeric",\n \"popularity\": 33856\n },\n {\n \"tag\": "digestive",\n \"popularity\": 33777\n },\n {\n \"tag\": "darlingly",\n \"popularity\": 33698\n },\n {\n \"tag\": "liman",\n \"popularity\": 33620\n },\n {\n \"tag\": "soldanrie",\n \"popularity\": 33542\n },\n {\n \"tag\": "sully",\n \"popularity\": 33464\n },\n {\n \"tag\": "brightsmith",\n \"popularity\": 33387\n },\n {\n \"tag\": "inwrap antiliturgist ureterocervical",\n \"popularity\": 33309\n },\n {\n \"tag\": "discommodity",\n \"popularity\": 33232\n },\n {\n \"tag\": "typical aggrandizer",\n \"popularity\": 33156\n },\n {\n \"tag\": "xenogeny",\n \"popularity\": 33079\n },\n {\n \"tag\": "uncountrified",\n \"popularity\": 33003\n },\n {\n \"tag\": "Podarge",\n \"popularity\": 32928\n },\n {\n \"tag\": "uninterviewed",\n \"popularity\": 32852\n },\n {\n \"tag\": "underprior",\n \"popularity\": 32777\n },\n {\n \"tag\": "leiomyomatous",\n \"popularity\": 32702\n },\n {\n \"tag\": "postdysenteric",\n \"popularity\": 32627\n },\n {\n \"tag\": "Fusicladium",\n \"popularity\": 32553\n },\n {\n \"tag\": "Dulcinea",\n \"popularity\": 32478\n },\n {\n \"tag\": "interspersion",\n \"popularity\": 32404\n },\n {\n \"tag\": "preobligate",\n \"popularity\": 32331\n },\n {\n \"tag\": "subaggregate",\n \"popularity\": 32257\n },\n {\n \"tag\": "grammarianism",\n \"popularity\": 32184\n },\n {\n \"tag\": "palikar",\n \"popularity\": 32111\n },\n {\n \"tag\": "facileness",\n \"popularity\": 32039\n },\n {\n \"tag\": "deuterofibrinose",\n \"popularity\": 31966\n },\n {\n \"tag\": "pseudesthesia",\n \"popularity\": 31894\n },\n {\n \"tag\": "sedimentary",\n \"popularity\": 31822\n },\n {\n \"tag\": "typewrite",\n \"popularity\": 31751\n },\n {\n \"tag\": "immemorable",\n \"popularity\": 31679\n },\n {\n \"tag\": "Myrtus",\n \"popularity\": 31608\n },\n {\n \"tag\": "hauchecornite",\n \"popularity\": 31537\n },\n {\n \"tag\": "galleylike",\n \"popularity\": 31467\n },\n {\n \"tag\": "thimber",\n \"popularity\": 31396\n },\n {\n \"tag\": "Hegelianism",\n \"popularity\": 31326\n },\n {\n \"tag\": "strig",\n \"popularity\": 31256\n },\n {\n \"tag\": "skyre",\n \"popularity\": 31187\n },\n {\n \"tag\": "eupepticism",\n \"popularity\": 31117\n },\n {\n \"tag\": "eponymism",\n \"popularity\": 31048\n },\n {\n \"tag\": "flunkeyhood",\n \"popularity\": 30979\n },\n {\n \"tag\": "Abama",\n \"popularity\": 30911\n },\n {\n \"tag\": "adiadochokinesis",\n \"popularity\": 30842\n },\n {\n \"tag\": "spendthrifty",\n \"popularity\": 30774\n },\n {\n \"tag\": "chalcedony",\n \"popularity\": 30706\n },\n {\n \"tag\": "authorism",\n \"popularity\": 30638\n },\n {\n \"tag\": "nasturtium",\n \"popularity\": 30571\n },\n {\n \"tag\": "Acanthocereus",\n \"popularity\": 30504\n },\n {\n \"tag\": "uncollapsible",\n \"popularity\": 30437\n },\n {\n \"tag\": "excursionist",\n \"popularity\": 30370\n },\n {\n \"tag\": "fogbow",\n \"popularity\": 30303\n },\n {\n \"tag\": "overlie",\n \"popularity\": 30237\n },\n {\n \"tag\": "velours",\n \"popularity\": 30171\n },\n {\n \"tag\": "zoodendria madrigal stagbush",\n \"popularity\": 30105\n },\n {\n \"tag\": "imi",\n \"popularity\": 30039\n },\n {\n \"tag\": "cojudge",\n \"popularity\": 29974\n },\n {\n \"tag\": "depurate argal",\n \"popularity\": 29909\n },\n {\n \"tag\": "unrecognition",\n \"popularity\": 29844\n },\n {\n \"tag\": "paunchful",\n \"popularity\": 29779\n },\n {\n \"tag\": "invalued",\n \"popularity\": 29714\n },\n {\n \"tag\": "probang",\n \"popularity\": 29650\n },\n {\n \"tag\": "chetvert",\n \"popularity\": 29586\n },\n {\n \"tag\": "enactable",\n \"popularity\": 29522\n },\n {\n \"tag\": "detoxicate adhibit",\n \"popularity\": 29458\n },\n {\n \"tag\": "kullaite",\n \"popularity\": 29395\n },\n {\n \"tag\": "undazzling",\n \"popularity\": 29332\n },\n {\n \"tag\": "excalation",\n \"popularity\": 29269\n },\n {\n \"tag\": "sievings",\n \"popularity\": 29206\n },\n {\n \"tag\": "disenthral",\n \"popularity\": 29143\n },\n {\n \"tag\": "disinterestedly",\n \"popularity\": 29081\n },\n {\n \"tag\": "stanner",\n \"popularity\": 29018\n },\n {\n \"tag\": "recapitulative",\n \"popularity\": 28956\n },\n {\n \"tag\": "objectivist",\n \"popularity\": 28895\n },\n {\n \"tag\": "hypermetropia",\n \"popularity\": 28833\n },\n {\n \"tag\": "incumbency",\n \"popularity\": 28772\n },\n {\n \"tag\": "protegee",\n \"popularity\": 28711\n },\n {\n \"tag\": "zealotic",\n \"popularity\": 28650\n },\n {\n \"tag\": "predebit",\n \"popularity\": 28589\n },\n {\n \"tag\": "cupolar",\n \"popularity\": 28528\n },\n {\n \"tag\": "unattributed",\n \"popularity\": 28468\n },\n {\n \"tag\": "louisine",\n \"popularity\": 28408\n },\n {\n \"tag\": "illustrate",\n \"popularity\": 28348\n },\n {\n \"tag\": "inofficiousness",\n \"popularity\": 28288\n },\n {\n \"tag\": "Americawards",\n \"popularity\": 28228\n },\n {\n \"tag\": "foreflap",\n \"popularity\": 28169\n },\n {\n \"tag\": "eruditeness",\n \"popularity\": 28110\n },\n {\n \"tag\": "copiopsia",\n \"popularity\": 28051\n },\n {\n \"tag\": "sporuliferous",\n \"popularity\": 27992\n },\n {\n \"tag\": "muttering",\n \"popularity\": 27934\n },\n {\n \"tag\": "prepsychology adrip",\n \"popularity\": 27875\n },\n {\n \"tag\": "unfriendly",\n \"popularity\": 27817\n },\n {\n \"tag\": "sulphanilic",\n \"popularity\": 27759\n },\n {\n \"tag\": "Coelococcus",\n \"popularity\": 27701\n },\n {\n \"tag\": "undoubtfulness",\n \"popularity\": 27643\n },\n {\n \"tag\": "flaringly",\n \"popularity\": 27586\n },\n {\n \"tag\": "unordain",\n \"popularity\": 27529\n },\n {\n \"tag\": "fratchety",\n \"popularity\": 27472\n },\n {\n \"tag\": "decadentism dolefully",\n \"popularity\": 27415\n },\n {\n \"tag\": "synthronus",\n \"popularity\": 27358\n },\n {\n \"tag\": "maiid",\n \"popularity\": 27301\n },\n {\n \"tag\": "rhinobyon",\n \"popularity\": 27245\n },\n {\n \"tag\": "Didynamia",\n \"popularity\": 27189\n },\n {\n \"tag\": "millionairedom",\n \"popularity\": 27133\n },\n {\n \"tag\": "mulierine",\n \"popularity\": 27077\n },\n {\n \"tag\": "Mayo",\n \"popularity\": 27021\n },\n {\n \"tag\": "perceivedness",\n \"popularity\": 26966\n },\n {\n \"tag\": "unadoration",\n \"popularity\": 26911\n },\n {\n \"tag\": "regraft",\n \"popularity\": 26856\n },\n {\n \"tag\": "witch",\n \"popularity\": 26801\n },\n {\n \"tag\": "ungrow",\n \"popularity\": 26746\n },\n {\n \"tag\": "glossopharyngeus",\n \"popularity\": 26691\n },\n {\n \"tag\": "unstirrable",\n \"popularity\": 26637\n },\n {\n \"tag\": "synodsman",\n \"popularity\": 26583\n },\n {\n \"tag\": "placentalian",\n \"popularity\": 26529\n },\n {\n \"tag\": "corpulently",\n \"popularity\": 26475\n },\n {\n \"tag\": "photochromoscope",\n \"popularity\": 26421\n },\n {\n \"tag\": "indusiate retinasphaltum chokestrap",\n \"popularity\": 26368\n },\n {\n \"tag\": "murdrum",\n \"popularity\": 26314\n },\n {\n \"tag\": "belatedness",\n \"popularity\": 26261\n },\n {\n \"tag\": "Cochin",\n \"popularity\": 26208\n },\n {\n \"tag\": "Leonist",\n \"popularity\": 26155\n },\n {\n \"tag\": "keeker confined",\n \"popularity\": 26102\n },\n {\n \"tag\": "unintellectual",\n \"popularity\": 26050\n },\n {\n \"tag\": "nymphaline bait",\n \"popularity\": 25997\n },\n {\n \"tag\": "sarcosporidiosis",\n \"popularity\": 25945\n },\n {\n \"tag\": "catawamptiously",\n \"popularity\": 25893\n },\n {\n \"tag\": "outshame",\n \"popularity\": 25841\n },\n {\n \"tag\": "animalism",\n \"popularity\": 25790\n },\n {\n \"tag\": "epithalamial",\n \"popularity\": 25738\n },\n {\n \"tag\": "ganner",\n \"popularity\": 25687\n },\n {\n \"tag\": "desilicify",\n \"popularity\": 25635\n },\n {\n \"tag\": "dandyism",\n \"popularity\": 25584\n },\n {\n \"tag\": "hyleg",\n \"popularity\": 25533\n },\n {\n \"tag\": "photophysical",\n \"popularity\": 25483\n },\n {\n \"tag\": "underload",\n \"popularity\": 25432\n },\n {\n \"tag\": "unintrusive",\n \"popularity\": 25382\n },\n {\n \"tag\": "succinamic",\n \"popularity\": 25331\n },\n {\n \"tag\": "matchy",\n \"popularity\": 25281\n },\n {\n \"tag\": "concordal",\n \"popularity\": 25231\n },\n {\n \"tag\": "exteriority",\n \"popularity\": 25181\n },\n {\n \"tag\": "sterculiad",\n \"popularity\": 25132\n },\n {\n \"tag\": "sulfoxylic",\n \"popularity\": 25082\n },\n {\n \"tag\": "oversubscription",\n \"popularity\": 25033\n },\n {\n \"tag\": "chiasmic",\n \"popularity\": 24984\n },\n {\n \"tag\": "pseudoparthenogenesis",\n \"popularity\": 24935\n },\n {\n \"tag\": "indorse",\n \"popularity\": 24886\n },\n {\n \"tag\": "Krishnaite",\n \"popularity\": 24837\n },\n {\n \"tag\": "calcinize",\n \"popularity\": 24788\n },\n {\n \"tag\": "rhodium",\n \"popularity\": 24740\n },\n {\n \"tag\": "tragopan",\n \"popularity\": 24692\n },\n {\n \"tag\": "overwhelmingly",\n \"popularity\": 24643\n },\n {\n \"tag\": "procidence accorporate",\n \"popularity\": 24595\n },\n {\n \"tag\": "polemize speelless",\n \"popularity\": 24548\n },\n {\n \"tag\": "radiocarpal goran",\n \"popularity\": 24500\n },\n {\n \"tag\": "counteroffer Pelodytes",\n \"popularity\": 24452\n },\n {\n \"tag\": "lionhearted",\n \"popularity\": 24405\n },\n {\n \"tag\": "paramastoid",\n \"popularity\": 24358\n },\n {\n \"tag\": "murine",\n \"popularity\": 24310\n },\n {\n \"tag\": "woodbined",\n \"popularity\": 24263\n },\n {\n \"tag\": "packthread",\n \"popularity\": 24217\n },\n {\n \"tag\": "citreous",\n \"popularity\": 24170\n },\n {\n \"tag\": "unfallaciously",\n \"popularity\": 24123\n },\n {\n \"tag\": "tentwork reincarnadine",\n \"popularity\": 24077\n },\n {\n \"tag\": "verminousness",\n \"popularity\": 24030\n },\n {\n \"tag\": "sillometer",\n \"popularity\": 23984\n },\n {\n \"tag\": "jointy",\n \"popularity\": 23938\n },\n {\n \"tag\": "streptolysin",\n \"popularity\": 23892\n },\n {\n \"tag\": "Florentinism",\n \"popularity\": 23847\n },\n {\n \"tag\": "monosomatous",\n \"popularity\": 23801\n },\n {\n \"tag\": "capsulociliary",\n \"popularity\": 23756\n },\n {\n \"tag\": "organum",\n \"popularity\": 23710\n },\n {\n \"tag\": "overtly",\n \"popularity\": 23665\n },\n {\n \"tag\": "ophthalmoscopical",\n \"popularity\": 23620\n },\n {\n \"tag\": "supposititiously",\n \"popularity\": 23575\n },\n {\n \"tag\": "radiochemistry",\n \"popularity\": 23530\n },\n {\n \"tag\": "flaxtail",\n \"popularity\": 23486\n },\n {\n \"tag\": "pretympanic",\n \"popularity\": 23441\n },\n {\n \"tag\": "auscultation",\n \"popularity\": 23397\n },\n {\n \"tag\": "hairdresser",\n \"popularity\": 23352\n },\n {\n \"tag\": "chaffless",\n \"popularity\": 23308\n },\n {\n \"tag\": "polioencephalitis",\n \"popularity\": 23264\n },\n {\n \"tag\": "axolotl",\n \"popularity\": 23220\n },\n {\n \"tag\": "smous",\n \"popularity\": 23177\n },\n {\n \"tag\": "morgen disenamour toothed",\n \"popularity\": 23133\n },\n {\n \"tag\": "chaiseless",\n \"popularity\": 23089\n },\n {\n \"tag\": "frugally",\n \"popularity\": 23046\n },\n {\n \"tag\": "combustive antievolutionist cinenegative",\n \"popularity\": 23003\n },\n {\n \"tag\": "malacolite",\n \"popularity\": 22960\n },\n {\n \"tag\": "borne",\n \"popularity\": 22917\n },\n {\n \"tag\": "mercaptole",\n \"popularity\": 22874\n },\n {\n \"tag\": "judicatory",\n \"popularity\": 22831\n },\n {\n \"tag\": "noctivagation",\n \"popularity\": 22789\n },\n {\n \"tag\": "synthete",\n \"popularity\": 22746\n },\n {\n \"tag\": "tomboyism",\n \"popularity\": 22704\n },\n {\n \"tag\": "serranoid",\n \"popularity\": 22661\n },\n {\n \"tag\": "impostorism",\n \"popularity\": 22619\n },\n {\n \"tag\": "flagellosis Talitha",\n \"popularity\": 22577\n },\n {\n \"tag\": "pseudoviscous",\n \"popularity\": 22535\n },\n {\n \"tag\": "Galleriidae",\n \"popularity\": 22494\n },\n {\n \"tag\": "undulation didelph Comintern",\n \"popularity\": 22452\n },\n {\n \"tag\": "triangulopyramidal",\n \"popularity\": 22411\n },\n {\n \"tag\": "middlings",\n \"popularity\": 22369\n },\n {\n \"tag\": "piperazin",\n \"popularity\": 22328\n },\n {\n \"tag\": "endostitis",\n \"popularity\": 22287\n },\n {\n \"tag\": "swordlike",\n \"popularity\": 22246\n },\n {\n \"tag\": "forthwith",\n \"popularity\": 22205\n },\n {\n \"tag\": "menaceful",\n \"popularity\": 22164\n },\n {\n \"tag\": "explantation defective",\n \"popularity\": 22123\n },\n {\n \"tag\": "arrear",\n \"popularity\": 22083\n },\n {\n \"tag\": "engraft",\n \"popularity\": 22042\n },\n {\n \"tag\": "revolunteer",\n \"popularity\": 22002\n },\n {\n \"tag\": "foliaceous",\n \"popularity\": 21962\n },\n {\n \"tag\": "pseudograph",\n \"popularity\": 21922\n },\n {\n \"tag\": "maenaite",\n \"popularity\": 21882\n },\n {\n \"tag\": "interfinger",\n \"popularity\": 21842\n },\n {\n \"tag\": "macroscopically",\n \"popularity\": 21802\n },\n {\n \"tag\": "bluewood",\n \"popularity\": 21762\n },\n {\n \"tag\": "chikara",\n \"popularity\": 21723\n },\n {\n \"tag\": "reprehension diazeuxis nickelous",\n \"popularity\": 21683\n },\n {\n \"tag\": "vacuation",\n \"popularity\": 21644\n },\n {\n \"tag\": "Sartish",\n \"popularity\": 21605\n },\n {\n \"tag\": "pseudogyny",\n \"popularity\": 21566\n },\n {\n \"tag\": "friedcake",\n \"popularity\": 21527\n },\n {\n \"tag\": "thraw",\n \"popularity\": 21488\n },\n {\n \"tag\": "bifid",\n \"popularity\": 21449\n },\n {\n \"tag\": "truthlessly",\n \"popularity\": 21411\n },\n {\n \"tag\": "lungy",\n \"popularity\": 21372\n },\n {\n \"tag\": "fluoborite",\n \"popularity\": 21334\n },\n {\n \"tag\": "anthropolithic",\n \"popularity\": 21295\n },\n {\n \"tag\": "coachee straw",\n \"popularity\": 21257\n },\n {\n \"tag\": "dehorner Grecize",\n \"popularity\": 21219\n },\n {\n \"tag\": "spondylopyosis",\n \"popularity\": 21181\n },\n {\n \"tag\": "institutionary",\n \"popularity\": 21143\n },\n {\n \"tag\": "agentry",\n \"popularity\": 21105\n },\n {\n \"tag\": "musing bietle",\n \"popularity\": 21068\n },\n {\n \"tag\": "cormophyte",\n \"popularity\": 21030\n },\n {\n \"tag\": "semielliptic",\n \"popularity\": 20993\n },\n {\n \"tag\": "ependytes",\n \"popularity\": 20955\n },\n {\n \"tag\": "coachmaster",\n \"popularity\": 20918\n },\n {\n \"tag\": "overexuberant",\n \"popularity\": 20881\n },\n {\n \"tag\": "selectable",\n \"popularity\": 20844\n },\n {\n \"tag\": "saclike",\n \"popularity\": 20807\n },\n {\n \"tag\": "mullion",\n \"popularity\": 20770\n },\n {\n \"tag\": "pantheonize prevalency",\n \"popularity\": 20733\n },\n {\n \"tag\": "trophosperm",\n \"popularity\": 20697\n },\n {\n \"tag\": "paraphrasist",\n \"popularity\": 20660\n },\n {\n \"tag\": "undercarry",\n \"popularity\": 20624\n },\n {\n \"tag\": "thallogenic",\n \"popularity\": 20587\n },\n {\n \"tag\": "bulgy forbid",\n \"popularity\": 20551\n },\n {\n \"tag\": "proliquor gratulatory",\n \"popularity\": 20515\n },\n {\n \"tag\": "booker",\n \"popularity\": 20479\n },\n {\n \"tag\": "wizen",\n \"popularity\": 20443\n },\n {\n \"tag\": "synchondrosially",\n \"popularity\": 20407\n },\n {\n \"tag\": "herbless",\n \"popularity\": 20371\n },\n {\n \"tag\": "arfvedsonite",\n \"popularity\": 20336\n },\n {\n \"tag\": "Neuroptera",\n \"popularity\": 20300\n },\n {\n \"tag\": "fingerstone",\n \"popularity\": 20265\n },\n {\n \"tag\": "Odontoglossae",\n \"popularity\": 20229\n },\n {\n \"tag\": "transmigrator",\n \"popularity\": 20194\n },\n {\n \"tag\": "Dehaites",\n \"popularity\": 20159\n },\n {\n \"tag\": "Molinist",\n \"popularity\": 20124\n },\n {\n \"tag\": "novelistic",\n \"popularity\": 20089\n },\n {\n \"tag\": "astelic",\n \"popularity\": 20054\n },\n {\n \"tag\": "pyelometry",\n \"popularity\": 20019\n },\n {\n \"tag\": "pigmentation",\n \"popularity\": 19984\n },\n {\n \"tag\": "epinaos",\n \"popularity\": 19950\n },\n {\n \"tag\": "outdare",\n \"popularity\": 19915\n },\n {\n \"tag\": "Funje philaristocracy",\n \"popularity\": 19881\n },\n {\n \"tag\": "keddah",\n \"popularity\": 19846\n },\n {\n \"tag\": "axoidean",\n \"popularity\": 19812\n },\n {\n \"tag\": "ovule",\n \"popularity\": 19778\n },\n {\n \"tag\": "solidify",\n \"popularity\": 19744\n },\n {\n \"tag\": "noncelestial",\n \"popularity\": 19710\n },\n {\n \"tag\": "overmultiplication",\n \"popularity\": 19676\n },\n {\n \"tag\": "hexatetrahedron",\n \"popularity\": 19642\n },\n {\n \"tag\": "pliciform",\n \"popularity\": 19609\n },\n {\n \"tag\": "zimbalon",\n \"popularity\": 19575\n },\n {\n \"tag\": "annexational",\n \"popularity\": 19542\n },\n {\n \"tag\": "eurhodol",\n \"popularity\": 19508\n },\n {\n \"tag\": "yark",\n \"popularity\": 19475\n },\n {\n \"tag\": "illegality nitroalizarin",\n \"popularity\": 19442\n },\n {\n \"tag\": "quadratum",\n \"popularity\": 19409\n },\n {\n \"tag\": "saccharine",\n \"popularity\": 19376\n },\n {\n \"tag\": "unemploy",\n \"popularity\": 19343\n },\n {\n \"tag\": "uniclinal unipotent",\n \"popularity\": 19310\n },\n {\n \"tag\": "turbo",\n \"popularity\": 19277\n },\n {\n \"tag\": "sybarism",\n \"popularity\": 19244\n },\n {\n \"tag\": "motacilline",\n \"popularity\": 19212\n },\n {\n \"tag\": "weaselly",\n \"popularity\": 19179\n },\n {\n \"tag\": "plastid",\n \"popularity\": 19147\n },\n {\n \"tag\": "wasting",\n \"popularity\": 19114\n },\n {\n \"tag\": "begrime fluting",\n \"popularity\": 19082\n },\n {\n \"tag\": "Nephilinae",\n \"popularity\": 19050\n },\n {\n \"tag\": "disregardance",\n \"popularity\": 19018\n },\n {\n \"tag\": "Shakerlike",\n \"popularity\": 18986\n },\n {\n \"tag\": "uniped",\n \"popularity\": 18954\n },\n {\n \"tag\": "knap",\n \"popularity\": 18922\n },\n {\n \"tag\": "electivism undergardener",\n \"popularity\": 18890\n },\n {\n \"tag\": "hulverheaded",\n \"popularity\": 18858\n },\n {\n \"tag\": "unruptured",\n \"popularity\": 18827\n },\n {\n \"tag\": "solemnize credently",\n \"popularity\": 18795\n },\n {\n \"tag\": "pentastomoid possessingly",\n \"popularity\": 18764\n },\n {\n \"tag\": "octose",\n \"popularity\": 18733\n },\n {\n \"tag\": "psithurism indefensibility",\n \"popularity\": 18701\n },\n {\n \"tag\": "torrentuous cyanometer subcrenate",\n \"popularity\": 18670\n },\n {\n \"tag\": "photoplaywright tapaculo",\n \"popularity\": 18639\n },\n {\n \"tag\": "univalence",\n \"popularity\": 18608\n },\n {\n \"tag\": "Porthetria",\n \"popularity\": 18577\n },\n {\n \"tag\": "funambulo",\n \"popularity\": 18546\n },\n {\n \"tag\": "pedion",\n \"popularity\": 18515\n },\n {\n \"tag\": "horticulturally",\n \"popularity\": 18485\n },\n {\n \"tag\": "marennin",\n \"popularity\": 18454\n },\n {\n \"tag\": "horselaugh",\n \"popularity\": 18423\n },\n {\n \"tag\": "semiexecutive",\n \"popularity\": 18393\n },\n {\n \"tag\": "Monopteridae",\n \"popularity\": 18363\n },\n {\n \"tag\": "commonable",\n \"popularity\": 18332\n },\n {\n \"tag\": "dreariment",\n \"popularity\": 18302\n },\n {\n \"tag\": "disbud",\n \"popularity\": 18272\n },\n {\n \"tag\": "monocled",\n \"popularity\": 18242\n },\n {\n \"tag\": "hurlbarrow",\n \"popularity\": 18212\n },\n {\n \"tag\": "opiateproof",\n \"popularity\": 18182\n },\n {\n \"tag\": "Fahrenheit",\n \"popularity\": 18152\n },\n {\n \"tag\": "writhed",\n \"popularity\": 18122\n },\n {\n \"tag\": "Volstead",\n \"popularity\": 18093\n },\n {\n \"tag\": "yesternight",\n \"popularity\": 18063\n },\n {\n \"tag\": "readmittance",\n \"popularity\": 18033\n },\n {\n \"tag\": "reiterable",\n \"popularity\": 18004\n },\n {\n \"tag\": "triquetral",\n \"popularity\": 17975\n },\n {\n \"tag\": "guillotinement",\n \"popularity\": 17945\n },\n {\n \"tag\": "repermission",\n \"popularity\": 17916\n },\n {\n \"tag\": "assishly",\n \"popularity\": 17887\n },\n {\n \"tag\": "daidle",\n \"popularity\": 17858\n },\n {\n \"tag\": "prismatoid",\n \"popularity\": 17829\n },\n {\n \"tag\": "irreptitious",\n \"popularity\": 17800\n },\n {\n \"tag\": "sourdeline",\n \"popularity\": 17771\n },\n {\n \"tag\": "Austrian",\n \"popularity\": 17742\n },\n {\n \"tag\": "psychorrhagic",\n \"popularity\": 17713\n },\n {\n \"tag\": "Monumbo",\n \"popularity\": 17685\n },\n {\n \"tag\": "cloiochoanitic",\n \"popularity\": 17656\n },\n {\n \"tag\": "hant",\n \"popularity\": 17628\n },\n {\n \"tag\": "roily pulldown",\n \"popularity\": 17599\n },\n {\n \"tag\": "recongratulation",\n \"popularity\": 17571\n },\n {\n \"tag\": "Peking",\n \"popularity\": 17543\n },\n {\n \"tag\": "erdvark",\n \"popularity\": 17514\n },\n {\n \"tag\": "antimnemonic",\n \"popularity\": 17486\n },\n {\n \"tag\": "noncapillarity",\n \"popularity\": 17458\n },\n {\n \"tag\": "irrepressive",\n \"popularity\": 17430\n },\n {\n \"tag\": "Petromyzontes",\n \"popularity\": 17402\n },\n {\n \"tag\": "piscatorially",\n \"popularity\": 17374\n },\n {\n \"tag\": "cholesterosis",\n \"popularity\": 17346\n },\n {\n \"tag\": "denunciate",\n \"popularity\": 17319\n },\n {\n \"tag\": "unmetalled",\n \"popularity\": 17291\n },\n {\n \"tag\": "Tigris enruin",\n \"popularity\": 17263\n },\n {\n \"tag\": "anaspalin",\n \"popularity\": 17236\n },\n {\n \"tag\": "monodromy",\n \"popularity\": 17208\n },\n {\n \"tag\": "Canichanan",\n \"popularity\": 17181\n },\n {\n \"tag\": "mesolabe",\n \"popularity\": 17154\n },\n {\n \"tag\": "trichothallic overcunningness",\n \"popularity\": 17127\n },\n {\n \"tag\": "spinsterishly",\n \"popularity\": 17099\n },\n {\n \"tag\": "sensilla",\n \"popularity\": 17072\n },\n {\n \"tag\": "wifelkin",\n \"popularity\": 17045\n },\n {\n \"tag\": "suppositionless",\n \"popularity\": 17018\n },\n {\n \"tag\": "irksomeness",\n \"popularity\": 16991\n },\n {\n \"tag\": "sanbenito",\n \"popularity\": 16964\n },\n {\n \"tag\": "nonstatement",\n \"popularity\": 16938\n },\n {\n \"tag\": "phenoloid",\n \"popularity\": 16911\n },\n {\n \"tag\": "Steinberger",\n \"popularity\": 16884\n },\n {\n \"tag\": "replicated boom",\n \"popularity\": 16858\n },\n {\n \"tag\": "sciomachiology",\n \"popularity\": 16831\n },\n {\n \"tag\": "starwise",\n \"popularity\": 16805\n },\n {\n \"tag\": "prerich",\n \"popularity\": 16778\n },\n {\n \"tag\": "unspawned",\n \"popularity\": 16752\n },\n {\n \"tag\": "unindentable",\n \"popularity\": 16726\n },\n {\n \"tag\": "stromatic",\n \"popularity\": 16700\n },\n {\n \"tag\": "fetishize",\n \"popularity\": 16673\n },\n {\n \"tag\": "dihydroxy",\n \"popularity\": 16647\n },\n {\n \"tag\": "precaudal",\n \"popularity\": 16621\n },\n {\n \"tag\": "Madagascar",\n \"popularity\": 16595\n },\n {\n \"tag\": "repinement",\n \"popularity\": 16570\n },\n {\n \"tag\": "noncathedral wenzel",\n \"popularity\": 16544\n },\n {\n \"tag\": "corollike",\n \"popularity\": 16518\n },\n {\n \"tag\": "pubes unamortization",\n \"popularity\": 16492\n },\n {\n \"tag\": "brickcroft",\n \"popularity\": 16467\n },\n {\n \"tag\": "intertrabecular",\n \"popularity\": 16441\n },\n {\n \"tag\": "formulaic",\n \"popularity\": 16416\n },\n {\n \"tag\": "arienzo",\n \"popularity\": 16390\n },\n {\n \"tag\": "Mazzinian",\n \"popularity\": 16365\n },\n {\n \"tag\": "wallowishly",\n \"popularity\": 16339\n },\n {\n \"tag\": "sysselman",\n \"popularity\": 16314\n },\n {\n \"tag\": "seligmannite",\n \"popularity\": 16289\n },\n {\n \"tag\": "harlequinery",\n \"popularity\": 16264\n },\n {\n \"tag\": "zucchetto",\n \"popularity\": 16239\n },\n {\n \"tag\": "malonyl",\n \"popularity\": 16214\n },\n {\n \"tag\": "patwari",\n \"popularity\": 16189\n },\n {\n \"tag\": "neoholmia venturesomeness",\n \"popularity\": 16164\n },\n {\n \"tag\": "Dehwar",\n \"popularity\": 16139\n },\n {\n \"tag\": "fetiferous",\n \"popularity\": 16114\n },\n {\n \"tag\": "chromatophore",\n \"popularity\": 16090\n },\n {\n \"tag\": "reregistration",\n \"popularity\": 16065\n },\n {\n \"tag\": "alienor",\n \"popularity\": 16040\n },\n {\n \"tag\": "Hexagynia",\n \"popularity\": 16016\n },\n {\n \"tag\": "cerebrotonia",\n \"popularity\": 15991\n },\n {\n \"tag\": "deedbox",\n \"popularity\": 15967\n },\n {\n \"tag\": "staab",\n \"popularity\": 15943\n },\n {\n \"tag\": "uratemia",\n \"popularity\": 15918\n },\n {\n \"tag\": "flaunt",\n \"popularity\": 15894\n },\n {\n \"tag\": "bogy",\n \"popularity\": 15870\n },\n {\n \"tag\": "subcartilaginous",\n \"popularity\": 15846\n },\n {\n \"tag\": "protonephridial",\n \"popularity\": 15822\n },\n {\n \"tag\": "Boswellia",\n \"popularity\": 15798\n },\n {\n \"tag\": "relaxant untiaraed protoepiphyte",\n \"popularity\": 15774\n },\n {\n \"tag\": "nesslerization",\n \"popularity\": 15750\n },\n {\n \"tag\": "precession",\n \"popularity\": 15726\n },\n {\n \"tag\": "peat",\n \"popularity\": 15702\n },\n {\n \"tag\": "unbit",\n \"popularity\": 15678\n },\n {\n \"tag\": "snailish",\n \"popularity\": 15655\n },\n {\n \"tag\": "porismatical",\n \"popularity\": 15631\n },\n {\n \"tag\": "hooflike",\n \"popularity\": 15608\n },\n {\n \"tag\": "resuppose phene cranic",\n \"popularity\": 15584\n },\n {\n \"tag\": "peptonization kipskin",\n \"popularity\": 15561\n },\n {\n \"tag\": "birdstone",\n \"popularity\": 15537\n },\n {\n \"tag\": "empty inferoanterior",\n \"popularity\": 15514\n },\n {\n \"tag\": "androtauric",\n \"popularity\": 15491\n },\n {\n \"tag\": "triamide",\n \"popularity\": 15467\n },\n {\n \"tag\": "showmanry",\n \"popularity\": 15444\n },\n {\n \"tag\": "doing",\n \"popularity\": 15421\n },\n {\n \"tag\": "bouchaleen",\n \"popularity\": 15398\n },\n {\n \"tag\": "precollude",\n \"popularity\": 15375\n },\n {\n \"tag\": "finger",\n \"popularity\": 15352\n },\n {\n \"tag\": "limnetic intermessenger",\n \"popularity\": 15329\n },\n {\n \"tag\": "uncharitable picrotoxic",\n \"popularity\": 15306\n },\n {\n \"tag\": "nationalizer Phasmidae",\n \"popularity\": 15283\n },\n {\n \"tag\": "laughingstock",\n \"popularity\": 15261\n },\n {\n \"tag\": "nondeferential",\n \"popularity\": 15238\n },\n {\n \"tag\": "uproariously",\n \"popularity\": 15215\n },\n {\n \"tag\": "manzanilla",\n \"popularity\": 15193\n },\n {\n \"tag\": "khahoon",\n \"popularity\": 15170\n },\n {\n \"tag\": "olericulturally longshanks",\n \"popularity\": 15148\n },\n {\n \"tag\": "enthusiastically methionic",\n \"popularity\": 15125\n },\n {\n \"tag\": "pobs",\n \"popularity\": 15103\n },\n {\n \"tag\": "tricarpellate",\n \"popularity\": 15081\n },\n {\n \"tag\": "souterrain",\n \"popularity\": 15058\n },\n {\n \"tag\": "tethelin",\n \"popularity\": 15036\n },\n {\n \"tag\": "tartle",\n \"popularity\": 15014\n },\n {\n \"tag\": "tidelike",\n \"popularity\": 14992\n },\n {\n \"tag\": "cosmoramic",\n \"popularity\": 14970\n },\n {\n \"tag\": "pretardiness",\n \"popularity\": 14948\n },\n {\n \"tag\": "insoul",\n \"popularity\": 14926\n },\n {\n \"tag\": "anthroxan",\n \"popularity\": 14904\n },\n {\n \"tag\": "jilter",\n \"popularity\": 14882\n },\n {\n \"tag\": "pectinibranchian trematode",\n \"popularity\": 14860\n },\n {\n \"tag\": "Renaissancist",\n \"popularity\": 14838\n },\n {\n \"tag\": "imaginant",\n \"popularity\": 14817\n },\n {\n \"tag\": "supercensure",\n \"popularity\": 14795\n },\n {\n \"tag\": "festilogy",\n \"popularity\": 14773\n },\n {\n \"tag\": "regression",\n \"popularity\": 14752\n },\n {\n \"tag\": "mesobregmate languorously",\n \"popularity\": 14730\n },\n {\n \"tag\": "unsupernaturalized",\n \"popularity\": 14709\n },\n {\n \"tag\": "boobyish",\n \"popularity\": 14687\n },\n {\n \"tag\": "scopolamine",\n \"popularity\": 14666\n },\n {\n \"tag\": "reamputation unchristianly",\n \"popularity\": 14645\n },\n {\n \"tag\": "cuneatic",\n \"popularity\": 14623\n },\n {\n \"tag\": "heathberry",\n \"popularity\": 14602\n },\n {\n \"tag\": "hate",\n \"popularity\": 14581\n },\n {\n \"tag\": "redeemableness",\n \"popularity\": 14560\n },\n {\n \"tag\": "damasse",\n \"popularity\": 14539\n },\n {\n \"tag\": "thrillsome",\n \"popularity\": 14518\n },\n {\n \"tag\": "disseverment",\n \"popularity\": 14497\n },\n {\n \"tag\": "underbishopric Ostyak",\n \"popularity\": 14476\n },\n {\n \"tag\": "Exoascales",\n \"popularity\": 14455\n },\n {\n \"tag\": "soiled",\n \"popularity\": 14434\n },\n {\n \"tag\": "Cain",\n \"popularity\": 14413\n },\n {\n \"tag\": "mismanageable arenae",\n \"popularity\": 14392\n },\n {\n \"tag\": "manducate unhinderably",\n \"popularity\": 14372\n },\n {\n \"tag\": "peregrin",\n \"popularity\": 14351\n },\n {\n \"tag\": "musicianly",\n \"popularity\": 14330\n },\n {\n \"tag\": "aln",\n \"popularity\": 14310\n },\n {\n \"tag\": "intercentrum",\n \"popularity\": 14289\n },\n {\n \"tag\": "roothold",\n \"popularity\": 14269\n },\n {\n \"tag\": "jane aneurism",\n \"popularity\": 14248\n },\n {\n \"tag\": "insinuatively forefeel phytolatrous",\n \"popularity\": 14228\n },\n {\n \"tag\": "kanchil",\n \"popularity\": 14208\n },\n {\n \"tag\": "Austrophile",\n \"popularity\": 14187\n },\n {\n \"tag\": "unterrorized",\n \"popularity\": 14167\n },\n {\n \"tag\": "admeasure",\n \"popularity\": 14147\n },\n {\n \"tag\": "electrodissolution",\n \"popularity\": 14127\n },\n {\n \"tag\": "unweddedly",\n \"popularity\": 14107\n },\n {\n \"tag\": "unannoying",\n \"popularity\": 14087\n },\n {\n \"tag\": "uningenuous",\n \"popularity\": 14067\n },\n {\n \"tag\": "omnibenevolent",\n \"popularity\": 14047\n },\n {\n \"tag\": "commissure",\n \"popularity\": 14027\n },\n {\n \"tag\": "tellureted",\n \"popularity\": 14007\n },\n {\n \"tag\": "suffragan",\n \"popularity\": 13987\n },\n {\n \"tag\": "sphaeriaceous",\n \"popularity\": 13967\n },\n {\n \"tag\": "unfearing",\n \"popularity\": 13947\n },\n {\n \"tag\": "stentoriousness precounsellor",\n \"popularity\": 13928\n },\n {\n \"tag\": "haemaspectroscope",\n \"popularity\": 13908\n },\n {\n \"tag\": "teras",\n \"popularity\": 13888\n },\n {\n \"tag\": "pulicine",\n \"popularity\": 13869\n },\n {\n \"tag\": "colicystopyelitis",\n \"popularity\": 13849\n },\n {\n \"tag\": "Physalia",\n \"popularity\": 13830\n },\n {\n \"tag\": "Saxicolidae",\n \"popularity\": 13810\n },\n {\n \"tag\": "peritonital",\n \"popularity\": 13791\n },\n {\n \"tag\": "dysphotic",\n \"popularity\": 13771\n },\n {\n \"tag\": "unabandoned",\n \"popularity\": 13752\n },\n {\n \"tag\": "rashful",\n \"popularity\": 13733\n },\n {\n \"tag\": "goodyness Manobo",\n \"popularity\": 13714\n },\n {\n \"tag\": "glaring",\n \"popularity\": 13694\n },\n {\n \"tag\": "horrorful",\n \"popularity\": 13675\n },\n {\n \"tag\": "intercepting",\n \"popularity\": 13656\n },\n {\n \"tag\": "semifine",\n \"popularity\": 13637\n },\n {\n \"tag\": "Gaypoo",\n \"popularity\": 13618\n },\n {\n \"tag\": "Metrosideros",\n \"popularity\": 13599\n },\n {\n \"tag\": "thoracicolumbar",\n \"popularity\": 13580\n },\n {\n \"tag\": "unserried",\n \"popularity\": 13561\n },\n {\n \"tag\": "keeperess cauterization",\n \"popularity\": 13542\n },\n {\n \"tag\": "administrant",\n \"popularity\": 13523\n },\n {\n \"tag\": "unpropitiatedness",\n \"popularity\": 13505\n },\n {\n \"tag\": "pensileness",\n \"popularity\": 13486\n },\n {\n \"tag\": "quinaldic unreceivable",\n \"popularity\": 13467\n },\n {\n \"tag\": "Carnaria",\n \"popularity\": 13448\n },\n {\n \"tag\": "azothionium wurrus",\n \"popularity\": 13430\n },\n {\n \"tag\": "mistresshood",\n \"popularity\": 13411\n },\n {\n \"tag\": "Savara",\n \"popularity\": 13393\n },\n {\n \"tag\": "dasyurine",\n \"popularity\": 13374\n },\n {\n \"tag\": "superideal",\n \"popularity\": 13356\n },\n {\n \"tag\": "Parisianize",\n \"popularity\": 13337\n },\n {\n \"tag\": "underearth",\n \"popularity\": 13319\n },\n {\n \"tag\": "athrogenic",\n \"popularity\": 13301\n },\n {\n \"tag\": "communicate",\n \"popularity\": 13282\n },\n {\n \"tag\": "denervation enworthed",\n \"popularity\": 13264\n },\n {\n \"tag\": "subbromide",\n \"popularity\": 13246\n },\n {\n \"tag\": "stenocoriasis",\n \"popularity\": 13228\n },\n {\n \"tag\": "facetiousness",\n \"popularity\": 13209\n },\n {\n \"tag\": "twaddling",\n \"popularity\": 13191\n },\n {\n \"tag\": "tetartoconid",\n \"popularity\": 13173\n },\n {\n \"tag\": "audiophile",\n \"popularity\": 13155\n },\n {\n \"tag\": "fustigate",\n \"popularity\": 13137\n },\n {\n \"tag\": "Sorbian cacophonia",\n \"popularity\": 13119\n },\n {\n \"tag\": "fondish",\n \"popularity\": 13101\n },\n {\n \"tag\": "endomastoiditis",\n \"popularity\": 13084\n },\n {\n \"tag\": "sniptious",\n \"popularity\": 13066\n },\n {\n \"tag\": "glochidiate",\n \"popularity\": 13048\n },\n {\n \"tag\": "polycarboxylic",\n \"popularity\": 13030\n },\n {\n \"tag\": "stamp",\n \"popularity\": 13012\n },\n {\n \"tag\": "tritonymph endotoxoid",\n \"popularity\": 12995\n },\n {\n \"tag\": "wolfskin",\n \"popularity\": 12977\n },\n {\n \"tag\": "oncosimeter",\n \"popularity\": 12959\n },\n {\n \"tag\": "outward",\n \"popularity\": 12942\n },\n {\n \"tag\": "circumscribed",\n \"popularity\": 12924\n },\n {\n \"tag\": "autohemolytic",\n \"popularity\": 12907\n },\n {\n \"tag\": "isorhamnose",\n \"popularity\": 12889\n },\n {\n \"tag\": "monarchomachic",\n \"popularity\": 12872\n },\n {\n \"tag\": "phaenomenon",\n \"popularity\": 12855\n },\n {\n \"tag\": "angiopressure",\n \"popularity\": 12837\n },\n {\n \"tag\": "similarize",\n \"popularity\": 12820\n },\n {\n \"tag\": "unseeable",\n \"popularity\": 12803\n },\n {\n \"tag\": "Toryize",\n \"popularity\": 12785\n },\n {\n \"tag\": "fruitling",\n \"popularity\": 12768\n },\n {\n \"tag\": "axle",\n \"popularity\": 12751\n },\n {\n \"tag\": "priestal cocked",\n \"popularity\": 12734\n },\n {\n \"tag\": "serotoxin",\n \"popularity\": 12717\n },\n {\n \"tag\": "unmovably",\n \"popularity\": 12700\n },\n {\n \"tag\": "darbha",\n \"popularity\": 12683\n },\n {\n \"tag\": "Mongolize",\n \"popularity\": 12666\n },\n {\n \"tag\": "clusteringly",\n \"popularity\": 12649\n },\n {\n \"tag\": "tendence",\n \"popularity\": 12632\n },\n {\n \"tag\": "foziness",\n \"popularity\": 12615\n },\n {\n \"tag\": "brickkiln lithify",\n \"popularity\": 12598\n },\n {\n \"tag\": "unpriest",\n \"popularity\": 12581\n },\n {\n \"tag\": "convincer",\n \"popularity\": 12564\n },\n {\n \"tag\": "mornlike",\n \"popularity\": 12548\n },\n {\n \"tag\": "overaddiction ostentatiousness",\n \"popularity\": 12531\n },\n {\n \"tag\": "diffusively moccasin pendom",\n \"popularity\": 12514\n },\n {\n \"tag\": "boose",\n \"popularity\": 12498\n },\n {\n \"tag\": "myonosus",\n \"popularity\": 12481\n },\n {\n \"tag\": "handsome",\n \"popularity\": 12464\n },\n {\n \"tag\": "paroxysmic",\n \"popularity\": 12448\n },\n {\n \"tag\": "Ulidian",\n \"popularity\": 12431\n },\n {\n \"tag\": "heartache",\n \"popularity\": 12415\n },\n {\n \"tag\": "torporize",\n \"popularity\": 12398\n },\n {\n \"tag\": "hippish",\n \"popularity\": 12382\n },\n {\n \"tag\": "stigmal militation",\n \"popularity\": 12366\n },\n {\n \"tag\": "matmaker",\n \"popularity\": 12349\n },\n {\n \"tag\": "marantaceous bivoluminous",\n \"popularity\": 12333\n },\n {\n \"tag\": "Uraniidae",\n \"popularity\": 12317\n },\n {\n \"tag\": "risper",\n \"popularity\": 12301\n },\n {\n \"tag\": "tintinnabulation",\n \"popularity\": 12284\n },\n {\n \"tag\": "tributorian",\n \"popularity\": 12268\n },\n {\n \"tag\": "ashamedly",\n \"popularity\": 12252\n },\n {\n \"tag\": "Macrourus",\n \"popularity\": 12236\n },\n {\n \"tag\": "Chora",\n \"popularity\": 12220\n },\n {\n \"tag\": "caul",\n \"popularity\": 12204\n },\n {\n \"tag\": "exsector",\n \"popularity\": 12188\n },\n {\n \"tag\": "acutish",\n \"popularity\": 12172\n },\n {\n \"tag\": "amphichrome",\n \"popularity\": 12156\n },\n {\n \"tag\": "guarder",\n \"popularity\": 12140\n },\n {\n \"tag\": "sculpturally",\n \"popularity\": 12124\n },\n {\n \"tag\": "benightmare",\n \"popularity\": 12108\n },\n {\n \"tag\": "chucky",\n \"popularity\": 12093\n },\n {\n \"tag\": "Venetian",\n \"popularity\": 12077\n },\n {\n \"tag\": "autotheater",\n \"popularity\": 12061\n },\n {\n \"tag\": "planarioid",\n \"popularity\": 12045\n },\n {\n \"tag\": "handkerchiefful",\n \"popularity\": 12030\n },\n {\n \"tag\": "fuliginousness potentize",\n \"popularity\": 12014\n },\n {\n \"tag\": "pantheum",\n \"popularity\": 11998\n },\n {\n \"tag\": "heavyweight",\n \"popularity\": 11983\n },\n {\n \"tag\": "unbrick",\n \"popularity\": 11967\n },\n {\n \"tag\": "duomachy",\n \"popularity\": 11952\n },\n {\n \"tag\": "polyphyodont",\n \"popularity\": 11936\n },\n {\n \"tag\": "hibernacle",\n \"popularity\": 11921\n },\n {\n \"tag\": "undistend",\n \"popularity\": 11905\n },\n {\n \"tag\": "hystericky",\n \"popularity\": 11890\n },\n {\n \"tag\": "paleolimnology",\n \"popularity\": 11875\n },\n {\n \"tag\": "cedarware",\n \"popularity\": 11859\n },\n {\n \"tag\": "overwrested",\n \"popularity\": 11844\n },\n {\n \"tag\": "Syriacism",\n \"popularity\": 11829\n },\n {\n \"tag\": "pretan",\n \"popularity\": 11813\n },\n {\n \"tag\": "formant",\n \"popularity\": 11798\n },\n {\n \"tag\": "pharmacopoeist Fedia",\n \"popularity\": 11783\n },\n {\n \"tag\": "exorcist eerisome",\n \"popularity\": 11768\n },\n {\n \"tag\": "separation",\n \"popularity\": 11753\n },\n {\n \"tag\": "infancy",\n \"popularity\": 11738\n },\n {\n \"tag\": "ecrasite",\n \"popularity\": 11723\n },\n {\n \"tag\": "propolize",\n \"popularity\": 11708\n },\n {\n \"tag\": "uncram phyllin",\n \"popularity\": 11693\n },\n {\n \"tag\": "thymopathy",\n \"popularity\": 11678\n },\n {\n \"tag\": "omniscient",\n \"popularity\": 11663\n },\n {\n \"tag\": "coussinet hazer",\n \"popularity\": 11648\n },\n {\n \"tag\": "contributiveness",\n \"popularity\": 11633\n },\n {\n \"tag\": "septifluous",\n \"popularity\": 11618\n },\n {\n \"tag\": "halfness",\n \"popularity\": 11603\n },\n {\n \"tag\": "tocher",\n \"popularity\": 11589\n },\n {\n \"tag\": "monotonist",\n \"popularity\": 11574\n },\n {\n \"tag\": "headchair",\n \"popularity\": 11559\n },\n {\n \"tag\": "everywhence",\n \"popularity\": 11544\n },\n {\n \"tag\": "gerate",\n \"popularity\": 11530\n },\n {\n \"tag\": "unrepellent",\n \"popularity\": 11515\n },\n {\n \"tag\": "inidoneous",\n \"popularity\": 11500\n },\n {\n \"tag\": "Rifi",\n \"popularity\": 11486\n },\n {\n \"tag\": "unstop",\n \"popularity\": 11471\n },\n {\n \"tag\": "conformer",\n \"popularity\": 11457\n },\n {\n \"tag\": "vivisectionally",\n \"popularity\": 11442\n },\n {\n \"tag\": "nonfinishing",\n \"popularity\": 11428\n },\n {\n \"tag\": "tyranness",\n \"popularity\": 11413\n },\n {\n \"tag\": "shepherdage havoc",\n \"popularity\": 11399\n },\n {\n \"tag\": "coronale",\n \"popularity\": 11385\n },\n {\n \"tag\": "airmarker",\n \"popularity\": 11370\n },\n {\n \"tag\": "subpanel",\n \"popularity\": 11356\n },\n {\n \"tag\": "conciliation",\n \"popularity\": 11342\n },\n {\n \"tag\": "supergun",\n \"popularity\": 11327\n },\n {\n \"tag\": "photoheliography",\n \"popularity\": 11313\n },\n {\n \"tag\": "cacosmia",\n \"popularity\": 11299\n },\n {\n \"tag\": "caressant",\n \"popularity\": 11285\n },\n {\n \"tag\": "swivet",\n \"popularity\": 11270\n },\n {\n \"tag\": "coddler",\n \"popularity\": 11256\n },\n {\n \"tag\": "rakehellish",\n \"popularity\": 11242\n },\n {\n \"tag\": "recohabitation",\n \"popularity\": 11228\n },\n {\n \"tag\": "postillator",\n \"popularity\": 11214\n },\n {\n \"tag\": "receipt",\n \"popularity\": 11200\n },\n {\n \"tag\": "nonconformistical",\n \"popularity\": 11186\n },\n {\n \"tag\": "unglorified",\n \"popularity\": 11172\n },\n {\n \"tag\": "unordinariness",\n \"popularity\": 11158\n },\n {\n \"tag\": "tetrahydroxy",\n \"popularity\": 11144\n },\n {\n \"tag\": "haploperistomic corporeity",\n \"popularity\": 11130\n },\n {\n \"tag\": "varical",\n \"popularity\": 11117\n },\n {\n \"tag\": "pilferment",\n \"popularity\": 11103\n },\n {\n \"tag\": "reverentially playcraft",\n \"popularity\": 11089\n },\n {\n \"tag\": "unretentive",\n \"popularity\": 11075\n },\n {\n \"tag\": "readiness",\n \"popularity\": 11061\n },\n {\n \"tag\": "thermomagnetism",\n \"popularity\": 11048\n },\n {\n \"tag\": "spotless",\n \"popularity\": 11034\n },\n {\n \"tag\": "semishrubby",\n \"popularity\": 11020\n },\n {\n \"tag\": "metrotomy",\n \"popularity\": 11007\n },\n {\n \"tag\": "hocker",\n \"popularity\": 10993\n },\n {\n \"tag\": "anecdotal",\n \"popularity\": 10979\n },\n {\n \"tag\": "tetrabelodont",\n \"popularity\": 10966\n },\n {\n \"tag\": "Ramillied",\n \"popularity\": 10952\n },\n {\n \"tag\": "sympatheticism",\n \"popularity\": 10939\n },\n {\n \"tag\": "kiskatom",\n \"popularity\": 10925\n },\n {\n \"tag\": "concyclically",\n \"popularity\": 10912\n },\n {\n \"tag\": "tunicless",\n \"popularity\": 10899\n },\n {\n \"tag\": "formalistic",\n \"popularity\": 10885\n },\n {\n \"tag\": "thermacogenesis",\n \"popularity\": 10872\n },\n {\n \"tag\": "multimotored",\n \"popularity\": 10858\n },\n {\n \"tag\": "inversive",\n \"popularity\": 10845\n },\n {\n \"tag\": "Jatki",\n \"popularity\": 10832\n },\n {\n \"tag\": "highest",\n \"popularity\": 10818\n },\n {\n \"tag\": "rubidic",\n \"popularity\": 10805\n },\n {\n \"tag\": "acranial",\n \"popularity\": 10792\n },\n {\n \"tag\": "pulvinulus",\n \"popularity\": 10779\n },\n {\n \"tag\": "nattiness",\n \"popularity\": 10766\n },\n {\n \"tag\": "antisimoniacal",\n \"popularity\": 10752\n },\n {\n \"tag\": "tetanize",\n \"popularity\": 10739\n },\n {\n \"tag\": "spectrophobia",\n \"popularity\": 10726\n },\n {\n \"tag\": "monopolitical",\n \"popularity\": 10713\n },\n {\n \"tag\": "teallite",\n \"popularity\": 10700\n },\n {\n \"tag\": "alicyclic interpellator",\n \"popularity\": 10687\n },\n {\n \"tag\": "nonsynthesized",\n \"popularity\": 10674\n },\n {\n \"tag\": "wheelwrighting",\n \"popularity\": 10661\n },\n {\n \"tag\": "pelliculate",\n \"popularity\": 10648\n },\n {\n \"tag\": "Euphyllopoda",\n \"popularity\": 10635\n },\n {\n \"tag\": "graver",\n \"popularity\": 10622\n },\n {\n \"tag\": "automorph",\n \"popularity\": 10609\n },\n {\n \"tag\": "underhanded",\n \"popularity\": 10597\n },\n {\n \"tag\": "causal",\n \"popularity\": 10584\n },\n {\n \"tag\": "odoom",\n \"popularity\": 10571\n },\n {\n \"tag\": "apodictical",\n \"popularity\": 10558\n },\n {\n \"tag\": "foundery",\n \"popularity\": 10545\n },\n {\n \"tag\": "unneighbored",\n \"popularity\": 10533\n },\n {\n \"tag\": "woolshearing",\n \"popularity\": 10520\n },\n {\n \"tag\": "boschveld",\n \"popularity\": 10507\n },\n {\n \"tag\": "unhardened lipopod",\n \"popularity\": 10495\n },\n {\n \"tag\": "unenriching",\n \"popularity\": 10482\n },\n {\n \"tag\": "spak",\n \"popularity\": 10469\n },\n {\n \"tag\": "yogasana",\n \"popularity\": 10457\n },\n {\n \"tag\": "depoetize",\n \"popularity\": 10444\n },\n {\n \"tag\": "parousiamania",\n \"popularity\": 10432\n },\n {\n \"tag\": "longlegs",\n \"popularity\": 10419\n },\n {\n \"tag\": "gelatinizability",\n \"popularity\": 10407\n },\n {\n \"tag\": "edeology",\n \"popularity\": 10394\n },\n {\n \"tag\": "sodwork",\n \"popularity\": 10382\n },\n {\n \"tag\": "somnambule",\n \"popularity\": 10369\n },\n {\n \"tag\": "antiquing",\n \"popularity\": 10357\n },\n {\n \"tag\": "intaker",\n \"popularity\": 10344\n },\n {\n \"tag\": "Gerberia",\n \"popularity\": 10332\n },\n {\n \"tag\": "preadmit",\n \"popularity\": 10320\n },\n {\n \"tag\": "bullhorn",\n \"popularity\": 10307\n },\n {\n \"tag\": "sororal",\n \"popularity\": 10295\n },\n {\n \"tag\": "phaeophyceous",\n \"popularity\": 10283\n },\n {\n \"tag\": "omphalopsychite",\n \"popularity\": 10271\n },\n {\n \"tag\": "substantious",\n \"popularity\": 10258\n },\n {\n \"tag\": "undemonstratively",\n \"popularity\": 10246\n },\n {\n \"tag\": "corallike blackit",\n \"popularity\": 10234\n },\n {\n \"tag\": "amoebous",\n \"popularity\": 10222\n },\n {\n \"tag\": "Polypodium",\n \"popularity\": 10210\n },\n {\n \"tag\": "blodite",\n \"popularity\": 10198\n },\n {\n \"tag\": "hordarian",\n \"popularity\": 10186\n },\n {\n \"tag\": "nonmoral",\n \"popularity\": 10174\n },\n {\n \"tag\": "dredgeful",\n \"popularity\": 10162\n },\n {\n \"tag\": "nourishingly",\n \"popularity\": 10150\n },\n {\n \"tag\": "seamy",\n \"popularity\": 10138\n },\n {\n \"tag\": "vara",\n \"popularity\": 10126\n },\n {\n \"tag\": "incorruptibleness",\n \"popularity\": 10114\n },\n {\n \"tag\": "manipulator",\n \"popularity\": 10102\n },\n {\n \"tag\": "chromodiascope uncountably",\n \"popularity\": 10090\n },\n {\n \"tag\": "typhemia",\n \"popularity\": 10078\n },\n {\n \"tag\": "Smalcaldic",\n \"popularity\": 10066\n },\n {\n \"tag\": "precontrive",\n \"popularity\": 10054\n },\n {\n \"tag\": "sowarry",\n \"popularity\": 10042\n },\n {\n \"tag\": "monopodic",\n \"popularity\": 10031\n },\n {\n \"tag\": "recodify",\n \"popularity\": 10019\n },\n {\n \"tag\": "phosphowolframic rimple",\n \"popularity\": 10007\n },\n {\n \"tag\": "triconch",\n \"popularity\": 9995\n },\n {\n \"tag\": "pycnodontoid",\n \"popularity\": 9984\n },\n {\n \"tag\": "bradyspermatism",\n \"popularity\": 9972\n },\n {\n \"tag\": "extensionist",\n \"popularity\": 9960\n },\n {\n \"tag\": "characterize",\n \"popularity\": 9949\n },\n {\n \"tag\": "anatreptic proteolytic",\n \"popularity\": 9937\n },\n {\n \"tag\": "waterboard",\n \"popularity\": 9925\n },\n {\n \"tag\": "allopathically",\n \"popularity\": 9914\n },\n {\n \"tag\": "arithmetician",\n \"popularity\": 9902\n },\n {\n \"tag\": "subsist",\n \"popularity\": 9891\n },\n {\n \"tag\": "Islamitish",\n \"popularity\": 9879\n },\n {\n \"tag\": "biddy",\n \"popularity\": 9868\n },\n {\n \"tag\": "reverberation",\n \"popularity\": 9856\n },\n {\n \"tag\": "Zaporogue",\n \"popularity\": 9845\n },\n {\n \"tag\": "soapberry",\n \"popularity\": 9833\n },\n {\n \"tag\": "physiognomics",\n \"popularity\": 9822\n },\n {\n \"tag\": "hospitalization",\n \"popularity\": 9810\n },\n {\n \"tag\": "dissembler",\n \"popularity\": 9799\n },\n {\n \"tag\": "festinate",\n \"popularity\": 9788\n },\n {\n \"tag\": "angiectopia",\n \"popularity\": 9776\n },\n {\n \"tag\": "Pulicidae",\n \"popularity\": 9765\n },\n {\n \"tag\": "beslimer",\n \"popularity\": 9754\n },\n {\n \"tag\": "nontreaty",\n \"popularity\": 9743\n },\n {\n \"tag\": "unhaggled",\n \"popularity\": 9731\n },\n {\n \"tag\": "catfall",\n \"popularity\": 9720\n },\n {\n \"tag\": "stola",\n \"popularity\": 9709\n },\n {\n \"tag\": "pataco",\n \"popularity\": 9698\n },\n {\n \"tag\": "ontologistic",\n \"popularity\": 9686\n },\n {\n \"tag\": "aerosphere",\n \"popularity\": 9675\n },\n {\n \"tag\": "deobstruent",\n \"popularity\": 9664\n },\n {\n \"tag\": "threepence",\n \"popularity\": 9653\n },\n {\n \"tag\": "cyprinoid",\n \"popularity\": 9642\n },\n {\n \"tag\": "overbank",\n \"popularity\": 9631\n },\n {\n \"tag\": "prostyle",\n \"popularity\": 9620\n },\n {\n \"tag\": "photoactivation",\n \"popularity\": 9609\n },\n {\n \"tag\": "homothetic",\n \"popularity\": 9598\n },\n {\n \"tag\": "roguedom",\n \"popularity\": 9587\n },\n {\n \"tag\": "underschool",\n \"popularity\": 9576\n },\n {\n \"tag\": "tractility",\n \"popularity\": 9565\n },\n {\n \"tag\": "gardenin",\n \"popularity\": 9554\n },\n {\n \"tag\": "Micromastictora",\n \"popularity\": 9543\n },\n {\n \"tag\": "gossypine",\n \"popularity\": 9532\n },\n {\n \"tag\": "amylodyspepsia",\n \"popularity\": 9521\n },\n {\n \"tag\": "Luciana",\n \"popularity\": 9510\n },\n {\n \"tag\": "meetly nonfisherman",\n \"popularity\": 9500\n },\n {\n \"tag\": "backhanded",\n \"popularity\": 9489\n },\n {\n \"tag\": "decrustation",\n \"popularity\": 9478\n },\n {\n \"tag\": "pinrail",\n \"popularity\": 9467\n },\n {\n \"tag\": "Mahori",\n \"popularity\": 9456\n },\n {\n \"tag\": "unsizable",\n \"popularity\": 9446\n },\n {\n \"tag\": "disawa",\n \"popularity\": 9435\n },\n {\n \"tag\": "launderability inconsidered",\n \"popularity\": 9424\n },\n {\n \"tag\": "unclassical",\n \"popularity\": 9414\n },\n {\n \"tag\": "inobtrusiveness",\n \"popularity\": 9403\n },\n {\n \"tag\": "sialogenous",\n \"popularity\": 9392\n },\n {\n \"tag\": "sulphonamide",\n \"popularity\": 9382\n },\n {\n \"tag\": "diluvion",\n \"popularity\": 9371\n },\n {\n \"tag\": "deuteranope",\n \"popularity\": 9361\n },\n {\n \"tag\": "addition",\n \"popularity\": 9350\n },\n {\n \"tag\": "bockeret",\n \"popularity\": 9339\n },\n {\n \"tag\": "unidentified",\n \"popularity\": 9329\n },\n {\n \"tag\": "caryatic",\n \"popularity\": 9318\n },\n {\n \"tag\": "misattribution",\n \"popularity\": 9308\n },\n {\n \"tag\": "outray",\n \"popularity\": 9297\n },\n {\n \"tag\": "areometrical",\n \"popularity\": 9287\n },\n {\n \"tag\": "antilogism",\n \"popularity\": 9277\n },\n {\n \"tag\": "inadjustable",\n \"popularity\": 9266\n },\n {\n \"tag\": "byssus",\n \"popularity\": 9256\n },\n {\n \"tag\": "trun",\n \"popularity\": 9245\n },\n {\n \"tag\": "thereology",\n \"popularity\": 9235\n },\n {\n \"tag\": "extort",\n \"popularity\": 9225\n },\n {\n \"tag\": "bumpkin",\n \"popularity\": 9214\n },\n {\n \"tag\": "sulphobenzide",\n \"popularity\": 9204\n },\n {\n \"tag\": "hydrogeology",\n \"popularity\": 9194\n },\n {\n \"tag\": "nidulariaceous",\n \"popularity\": 9183\n },\n {\n \"tag\": "propodiale",\n \"popularity\": 9173\n },\n {\n \"tag\": "fierily",\n \"popularity\": 9163\n },\n {\n \"tag\": "aerotonometry",\n \"popularity\": 9153\n },\n {\n \"tag\": "pelobatid oversuperstitious",\n \"popularity\": 9142\n },\n {\n \"tag\": "restringent",\n \"popularity\": 9132\n },\n {\n \"tag\": "tetrapodic",\n \"popularity\": 9122\n },\n {\n \"tag\": "heroicness Vendidad",\n \"popularity\": 9112\n },\n {\n \"tag\": "Sphingurus",\n \"popularity\": 9102\n },\n {\n \"tag\": "sclerote",\n \"popularity\": 9092\n },\n {\n \"tag\": "unkeyed",\n \"popularity\": 9082\n },\n {\n \"tag\": "superparliamentary",\n \"popularity\": 9072\n },\n {\n \"tag\": "hetericism",\n \"popularity\": 9061\n },\n {\n \"tag\": "hucklebone",\n \"popularity\": 9051\n },\n {\n \"tag\": "yojan",\n \"popularity\": 9041\n },\n {\n \"tag\": "bossed",\n \"popularity\": 9031\n },\n {\n \"tag\": "spiderwork",\n \"popularity\": 9021\n },\n {\n \"tag\": "millfeed dullery",\n \"popularity\": 9011\n },\n {\n \"tag\": "adnoun",\n \"popularity\": 9001\n },\n {\n \"tag\": "mesometric",\n \"popularity\": 8992\n },\n {\n \"tag\": "doublehandedness",\n \"popularity\": 8982\n },\n {\n \"tag\": "suppurant",\n \"popularity\": 8972\n },\n {\n \"tag\": "Berlinize",\n \"popularity\": 8962\n },\n {\n \"tag\": "sontag",\n \"popularity\": 8952\n },\n {\n \"tag\": "biplane",\n \"popularity\": 8942\n },\n {\n \"tag\": "insula",\n \"popularity\": 8932\n },\n {\n \"tag\": "unbrand",\n \"popularity\": 8922\n },\n {\n \"tag\": "Basilosaurus",\n \"popularity\": 8913\n },\n {\n \"tag\": "prenomination",\n \"popularity\": 8903\n },\n {\n \"tag\": "untextual",\n \"popularity\": 8893\n },\n {\n \"tag\": "coleslaw",\n \"popularity\": 8883\n },\n {\n \"tag\": "langsyne",\n \"popularity\": 8874\n },\n {\n \"tag\": "impede",\n \"popularity\": 8864\n },\n {\n \"tag\": "irrigator",\n \"popularity\": 8854\n },\n {\n \"tag\": "deflocculation",\n \"popularity\": 8844\n },\n {\n \"tag\": "narghile",\n \"popularity\": 8835\n },\n {\n \"tag\": "unguardedly ebenaceous",\n \"popularity\": 8825\n },\n {\n \"tag\": "conversantly subocular",\n \"popularity\": 8815\n },\n {\n \"tag\": "hydroponic",\n \"popularity\": 8806\n },\n {\n \"tag\": "anthropopsychism",\n \"popularity\": 8796\n },\n {\n \"tag\": "panoptic",\n \"popularity\": 8787\n },\n {\n \"tag\": "insufferable",\n \"popularity\": 8777\n },\n {\n \"tag\": "salema",\n \"popularity\": 8768\n },\n {\n \"tag\": "Myriapoda",\n \"popularity\": 8758\n },\n {\n \"tag\": "regarrison",\n \"popularity\": 8748\n },\n {\n \"tag\": "overlearned",\n \"popularity\": 8739\n },\n {\n \"tag\": "ultraroyalist conventical bureaucratical",\n \"popularity\": 8729\n },\n {\n \"tag\": "epicaridan",\n \"popularity\": 8720\n },\n {\n \"tag\": "poetastress",\n \"popularity\": 8711\n },\n {\n \"tag\": "monophthalmus",\n \"popularity\": 8701\n },\n {\n \"tag\": "simnel",\n \"popularity\": 8692\n },\n {\n \"tag\": "compotor",\n \"popularity\": 8682\n },\n {\n \"tag\": "hydrolase",\n \"popularity\": 8673\n },\n {\n \"tag\": "attemptless",\n \"popularity\": 8663\n },\n {\n \"tag\": "visceroptosis",\n \"popularity\": 8654\n },\n {\n \"tag\": "unpreparedly",\n \"popularity\": 8645\n },\n {\n \"tag\": "mastage",\n \"popularity\": 8635\n },\n {\n \"tag\": "preinfluence",\n \"popularity\": 8626\n },\n {\n \"tag\": "Siwan",\n \"popularity\": 8617\n },\n {\n \"tag\": "ceratotheca belvedere",\n \"popularity\": 8607\n },\n {\n \"tag\": "disenablement",\n \"popularity\": 8598\n },\n {\n \"tag\": "nine",\n \"popularity\": 8589\n },\n {\n \"tag\": "spellingdown abridgment",\n \"popularity\": 8580\n },\n {\n \"tag\": "twilightless",\n \"popularity\": 8571\n },\n {\n \"tag\": "overflow",\n \"popularity\": 8561\n },\n {\n \"tag\": "mismeasurement",\n \"popularity\": 8552\n },\n {\n \"tag\": "nawabship",\n \"popularity\": 8543\n },\n {\n \"tag\": "Phrynosoma",\n \"popularity\": 8534\n },\n {\n \"tag\": "unanticipatingly",\n \"popularity\": 8525\n },\n {\n \"tag\": "blankite",\n \"popularity\": 8516\n },\n {\n \"tag\": "role",\n \"popularity\": 8506\n },\n {\n \"tag\": "peperine edelweiss",\n \"popularity\": 8497\n },\n {\n \"tag\": "unhysterical",\n \"popularity\": 8488\n },\n {\n \"tag\": "attentiveness",\n \"popularity\": 8479\n },\n {\n \"tag\": "scintillant",\n \"popularity\": 8470\n },\n {\n \"tag\": "stenostomatous",\n \"popularity\": 8461\n },\n {\n \"tag\": "pectinite",\n \"popularity\": 8452\n },\n {\n \"tag\": "herring",\n \"popularity\": 8443\n },\n {\n \"tag\": "interroom",\n \"popularity\": 8434\n },\n {\n \"tag\": "laccol",\n \"popularity\": 8425\n },\n {\n \"tag\": "unpartably kylite",\n \"popularity\": 8416\n },\n {\n \"tag\": "spirivalve",\n \"popularity\": 8407\n },\n {\n \"tag\": "hoosegow",\n \"popularity\": 8398\n },\n {\n \"tag\": "doat",\n \"popularity\": 8389\n },\n {\n \"tag\": "amphibian",\n \"popularity\": 8380\n },\n {\n \"tag\": "exposit",\n \"popularity\": 8371\n },\n {\n \"tag\": "canopy",\n \"popularity\": 8363\n },\n {\n \"tag\": "houndlike",\n \"popularity\": 8354\n },\n {\n \"tag\": "spikebill",\n \"popularity\": 8345\n },\n {\n \"tag\": "wiseacre pyrotechnic",\n \"popularity\": 8336\n },\n {\n \"tag\": "confessingly woodman",\n \"popularity\": 8327\n },\n {\n \"tag\": "overside",\n \"popularity\": 8318\n },\n {\n \"tag\": "oftwhiles",\n \"popularity\": 8310\n },\n {\n \"tag\": "Musophagidae",\n \"popularity\": 8301\n },\n {\n \"tag\": "slumberer",\n \"popularity\": 8292\n },\n {\n \"tag\": "leiotrichy",\n \"popularity\": 8283\n },\n {\n \"tag\": "Mantispidae",\n \"popularity\": 8275\n },\n {\n \"tag\": "perceptually",\n \"popularity\": 8266\n },\n {\n \"tag\": "biller",\n \"popularity\": 8257\n },\n {\n \"tag\": "eudaemonical",\n \"popularity\": 8249\n },\n {\n \"tag\": "underfiend",\n \"popularity\": 8240\n },\n {\n \"tag\": "impartible",\n \"popularity\": 8231\n },\n {\n \"tag\": "saxicavous",\n \"popularity\": 8223\n },\n {\n \"tag\": "yapster",\n \"popularity\": 8214\n },\n {\n \"tag\": "aliseptal",\n \"popularity\": 8205\n },\n {\n \"tag\": "omniparient",\n \"popularity\": 8197\n },\n {\n \"tag\": "nishiki",\n \"popularity\": 8188\n },\n {\n \"tag\": "yuzluk",\n \"popularity\": 8180\n },\n {\n \"tag\": "solderer",\n \"popularity\": 8171\n },\n {\n \"tag\": "Pinna",\n \"popularity\": 8162\n },\n {\n \"tag\": "reinterfere",\n \"popularity\": 8154\n },\n {\n \"tag\": "superepic",\n \"popularity\": 8145\n },\n {\n \"tag\": "ronquil",\n \"popularity\": 8137\n },\n {\n \"tag\": "bratstvo",\n \"popularity\": 8128\n },\n {\n \"tag\": "Thea",\n \"popularity\": 8120\n },\n {\n \"tag\": "hermaphroditical",\n \"popularity\": 8111\n },\n {\n \"tag\": "enlief",\n \"popularity\": 8103\n },\n {\n \"tag\": "Jesuate",\n \"popularity\": 8095\n },\n {\n \"tag\": "gaysome",\n \"popularity\": 8086\n },\n {\n \"tag\": "iliohypogastric",\n \"popularity\": 8078\n },\n {\n \"tag\": "regardance",\n \"popularity\": 8069\n },\n {\n \"tag\": "cumulately",\n \"popularity\": 8061\n },\n {\n \"tag\": "haustorial nucleolocentrosome",\n \"popularity\": 8053\n },\n {\n \"tag\": "cosmocrat",\n \"popularity\": 8044\n },\n {\n \"tag\": "onyxitis",\n \"popularity\": 8036\n },\n {\n \"tag\": "Cabinda",\n \"popularity\": 8028\n },\n {\n \"tag\": "coresort",\n \"popularity\": 8019\n },\n {\n \"tag\": "drusy preformant",\n \"popularity\": 8011\n },\n {\n \"tag\": "piningly",\n \"popularity\": 8003\n },\n {\n \"tag\": "bootlessly",\n \"popularity\": 7994\n },\n {\n \"tag\": "talari",\n \"popularity\": 7986\n },\n {\n \"tag\": "amidoacetal",\n \"popularity\": 7978\n },\n {\n \"tag\": "pschent",\n \"popularity\": 7970\n },\n {\n \"tag\": "consumptional scarer titivate",\n \"popularity\": 7962\n },\n {\n \"tag\": "Anserinae",\n \"popularity\": 7953\n },\n {\n \"tag\": "flaunter",\n \"popularity\": 7945\n },\n {\n \"tag\": "reindeer",\n \"popularity\": 7937\n },\n {\n \"tag\": "disparage",\n \"popularity\": 7929\n },\n {\n \"tag\": "superheat",\n \"popularity\": 7921\n },\n {\n \"tag\": "Chromatium",\n \"popularity\": 7912\n },\n {\n \"tag\": "Tina",\n \"popularity\": 7904\n },\n {\n \"tag\": "rededicatory",\n \"popularity\": 7896\n },\n {\n \"tag\": "nontransient",\n \"popularity\": 7888\n },\n {\n \"tag\": "Phocaean brinkless",\n \"popularity\": 7880\n },\n {\n \"tag\": "ventriculose",\n \"popularity\": 7872\n },\n {\n \"tag\": "upplough",\n \"popularity\": 7864\n },\n {\n \"tag\": "succorless",\n \"popularity\": 7856\n },\n {\n \"tag\": "hayrake",\n \"popularity\": 7848\n },\n {\n \"tag\": "merriness amorphia",\n \"popularity\": 7840\n },\n {\n \"tag\": "merycism",\n \"popularity\": 7832\n },\n {\n \"tag\": "checkrow",\n \"popularity\": 7824\n },\n {\n \"tag\": "scry",\n \"popularity\": 7816\n },\n {\n \"tag\": "obvolve",\n \"popularity\": 7808\n },\n {\n \"tag\": "orchard",\n \"popularity\": 7800\n },\n {\n \"tag\": "isomerize",\n \"popularity\": 7792\n },\n {\n \"tag\": "competitrix",\n \"popularity\": 7784\n },\n {\n \"tag\": "unbannered",\n \"popularity\": 7776\n },\n {\n \"tag\": "undoctrined",\n \"popularity\": 7768\n },\n {\n \"tag\": "theologian",\n \"popularity\": 7760\n },\n {\n \"tag\": "nebby",\n \"popularity\": 7752\n },\n {\n \"tag\": "Cardiazol",\n \"popularity\": 7745\n },\n {\n \"tag\": "phagedenic",\n \"popularity\": 7737\n },\n {\n \"tag\": "nostalgic",\n \"popularity\": 7729\n },\n {\n \"tag\": "orthodoxy",\n \"popularity\": 7721\n },\n {\n \"tag\": "oversanguine",\n \"popularity\": 7713\n },\n {\n \"tag\": "lish",\n \"popularity\": 7705\n },\n {\n \"tag\": "ketogenic",\n \"popularity\": 7698\n },\n {\n \"tag\": "syndicalize",\n \"popularity\": 7690\n },\n {\n \"tag\": "leeftail",\n \"popularity\": 7682\n },\n {\n \"tag\": "bulbomedullary",\n \"popularity\": 7674\n },\n {\n \"tag\": "reletter",\n \"popularity\": 7667\n },\n {\n \"tag\": "bitterly",\n \"popularity\": 7659\n },\n {\n \"tag\": "participatory",\n \"popularity\": 7651\n },\n {\n \"tag\": "baldberry",\n \"popularity\": 7643\n },\n {\n \"tag\": "prowaterpower",\n \"popularity\": 7636\n },\n {\n \"tag\": "lexicographical",\n \"popularity\": 7628\n },\n {\n \"tag\": "Anisodactyli",\n \"popularity\": 7620\n },\n {\n \"tag\": "amphipodous",\n \"popularity\": 7613\n },\n {\n \"tag\": "triglandular",\n \"popularity\": 7605\n },\n {\n \"tag\": "xanthopsin",\n \"popularity\": 7597\n },\n {\n \"tag\": "indefinitude",\n \"popularity\": 7590\n },\n {\n \"tag\": "bookworm",\n \"popularity\": 7582\n },\n {\n \"tag\": "suffocative",\n \"popularity\": 7574\n },\n {\n \"tag\": "uncongested tyrant",\n \"popularity\": 7567\n },\n {\n \"tag\": "alow harmoniously Pamir",\n \"popularity\": 7559\n },\n {\n \"tag\": "monander",\n \"popularity\": 7552\n },\n {\n \"tag\": "bagatelle",\n \"popularity\": 7544\n },\n {\n \"tag\": "membranology",\n \"popularity\": 7537\n },\n {\n \"tag\": "parturifacient",\n \"popularity\": 7529\n },\n {\n \"tag\": "excitovascular",\n \"popularity\": 7522\n },\n {\n \"tag\": "homopolar",\n \"popularity\": 7514\n },\n {\n \"tag\": "phobiac",\n \"popularity\": 7507\n },\n {\n \"tag\": "clype",\n \"popularity\": 7499\n },\n {\n \"tag\": "unsubversive",\n \"popularity\": 7492\n },\n {\n \"tag\": "bostrychoidal scorpionwort",\n \"popularity\": 7484\n },\n {\n \"tag\": "biliteralism",\n \"popularity\": 7477\n },\n {\n \"tag\": "dentatocostate",\n \"popularity\": 7469\n },\n {\n \"tag\": "Pici",\n \"popularity\": 7462\n },\n {\n \"tag\": "sideritic",\n \"popularity\": 7454\n },\n {\n \"tag\": "syntaxis",\n \"popularity\": 7447\n },\n {\n \"tag\": "ingest",\n \"popularity\": 7440\n },\n {\n \"tag\": "rigmarolish",\n \"popularity\": 7432\n },\n {\n \"tag\": "ocreaceous",\n \"popularity\": 7425\n },\n {\n \"tag\": "hyperbrachyskelic",\n \"popularity\": 7418\n },\n {\n \"tag\": "basophobia",\n \"popularity\": 7410\n },\n {\n \"tag\": "substantialness",\n \"popularity\": 7403\n },\n {\n \"tag\": "agglutinoid",\n \"popularity\": 7396\n },\n {\n \"tag\": "longleaf",\n \"popularity\": 7388\n },\n {\n \"tag\": "electroengraving",\n \"popularity\": 7381\n },\n {\n \"tag\": "laparoenterotomy",\n \"popularity\": 7374\n },\n {\n \"tag\": "oxalylurea",\n \"popularity\": 7366\n },\n {\n \"tag\": "unattaintedly",\n \"popularity\": 7359\n },\n {\n \"tag\": "pennystone",\n \"popularity\": 7352\n },\n {\n \"tag\": "Plumbaginaceae",\n \"popularity\": 7345\n },\n {\n \"tag\": "horntip",\n \"popularity\": 7337\n },\n {\n \"tag\": "begrudge",\n \"popularity\": 7330\n },\n {\n \"tag\": "bechignoned",\n \"popularity\": 7323\n },\n {\n \"tag\": "hologonidium",\n \"popularity\": 7316\n },\n {\n \"tag\": "Pulian",\n \"popularity\": 7309\n },\n {\n \"tag\": "gratulation",\n \"popularity\": 7301\n },\n {\n \"tag\": "Sebright",\n \"popularity\": 7294\n },\n {\n \"tag\": "coinstantaneous emotionally",\n \"popularity\": 7287\n },\n {\n \"tag\": "thoracostracan",\n \"popularity\": 7280\n },\n {\n \"tag\": "saurodont",\n \"popularity\": 7273\n },\n {\n \"tag\": "coseat",\n \"popularity\": 7266\n },\n {\n \"tag\": "irascibility",\n \"popularity\": 7259\n },\n {\n \"tag\": "occlude",\n \"popularity\": 7251\n },\n {\n \"tag\": "metallurgist",\n \"popularity\": 7244\n },\n {\n \"tag\": "extraviolet",\n \"popularity\": 7237\n },\n {\n \"tag\": "clinic",\n \"popularity\": 7230\n },\n {\n \"tag\": "skater",\n \"popularity\": 7223\n },\n {\n \"tag\": "linguistic",\n \"popularity\": 7216\n },\n {\n \"tag\": "attacheship",\n \"popularity\": 7209\n },\n {\n \"tag\": "Rachianectes",\n \"popularity\": 7202\n },\n {\n \"tag\": "foliolose",\n \"popularity\": 7195\n },\n {\n \"tag\": "claudetite",\n \"popularity\": 7188\n },\n {\n \"tag\": "aphidian scratching",\n \"popularity\": 7181\n },\n {\n \"tag\": "Carida",\n \"popularity\": 7174\n },\n {\n \"tag\": "tiepin polymicroscope",\n \"popularity\": 7167\n },\n {\n \"tag\": "telpherage",\n \"popularity\": 7160\n },\n {\n \"tag\": "meek",\n \"popularity\": 7153\n },\n {\n \"tag\": "swiftness",\n \"popularity\": 7146\n },\n {\n \"tag\": "gentes",\n \"popularity\": 7139\n },\n {\n \"tag\": "uncommemorated",\n \"popularity\": 7132\n },\n {\n \"tag\": "Lazarus",\n \"popularity\": 7125\n },\n {\n \"tag\": "redivive",\n \"popularity\": 7119\n },\n {\n \"tag\": "nonfebrile",\n \"popularity\": 7112\n },\n {\n \"tag\": "nymphet",\n \"popularity\": 7105\n },\n {\n \"tag\": "areologically",\n \"popularity\": 7098\n },\n {\n \"tag\": "undonkey",\n \"popularity\": 7091\n },\n {\n \"tag\": "projecting",\n \"popularity\": 7084\n },\n {\n \"tag\": "pinnigrade",\n \"popularity\": 7077\n },\n {\n \"tag\": "butylation",\n \"popularity\": 7071\n },\n {\n \"tag\": "philologistic lenticle",\n \"popularity\": 7064\n },\n {\n \"tag\": "nooky",\n \"popularity\": 7057\n },\n {\n \"tag\": "incestuousness",\n \"popularity\": 7050\n },\n {\n \"tag\": "palingenetically",\n \"popularity\": 7043\n },\n {\n \"tag\": "mitochondria",\n \"popularity\": 7037\n },\n {\n \"tag\": "truthify",\n \"popularity\": 7030\n },\n {\n \"tag\": "titanyl",\n \"popularity\": 7023\n },\n {\n \"tag\": "bestride",\n \"popularity\": 7016\n },\n {\n \"tag\": "chende",\n \"popularity\": 7010\n },\n {\n \"tag\": "Chaucerian monophote",\n \"popularity\": 7003\n },\n {\n \"tag\": "cutback",\n \"popularity\": 6996\n },\n {\n \"tag\": "unpatiently",\n \"popularity\": 6989\n },\n {\n \"tag\": "subvitreous",\n \"popularity\": 6983\n },\n {\n \"tag\": "organizable",\n \"popularity\": 6976\n },\n {\n \"tag\": "anniverse uncomprehensible",\n \"popularity\": 6969\n },\n {\n \"tag\": "hyalescence",\n \"popularity\": 6963\n },\n {\n \"tag\": "amniochorial",\n \"popularity\": 6956\n },\n {\n \"tag\": "Corybantian",\n \"popularity\": 6949\n },\n {\n \"tag\": "genocide Scaphitidae",\n \"popularity\": 6943\n },\n {\n \"tag\": "accordionist",\n \"popularity\": 6936\n },\n {\n \"tag\": "becheck",\n \"popularity\": 6930\n },\n {\n \"tag\": "overproduce",\n \"popularity\": 6923\n },\n {\n \"tag\": "unmaniac frijolillo",\n \"popularity\": 6916\n },\n {\n \"tag\": "multisulcated",\n \"popularity\": 6910\n },\n {\n \"tag\": "wennebergite",\n \"popularity\": 6903\n },\n {\n \"tag\": "tautousious mowth",\n \"popularity\": 6897\n },\n {\n \"tag\": "marigold",\n \"popularity\": 6890\n },\n {\n \"tag\": "affray",\n \"popularity\": 6884\n },\n {\n \"tag\": "nonidolatrous",\n \"popularity\": 6877\n },\n {\n \"tag\": "aphrasia",\n \"popularity\": 6871\n },\n {\n \"tag\": "muddlingly",\n \"popularity\": 6864\n },\n {\n \"tag\": "clear",\n \"popularity\": 6858\n },\n {\n \"tag\": "Clitoria",\n \"popularity\": 6851\n },\n {\n \"tag\": "apportionment underwaist",\n \"popularity\": 6845\n },\n {\n \"tag\": "kodakist",\n \"popularity\": 6838\n },\n {\n \"tag\": "Momotidae",\n \"popularity\": 6832\n },\n {\n \"tag\": "cryptovalency",\n \"popularity\": 6825\n },\n {\n \"tag\": "floe",\n \"popularity\": 6819\n },\n {\n \"tag\": "aphagia",\n \"popularity\": 6812\n },\n {\n \"tag\": "brontograph",\n \"popularity\": 6806\n },\n {\n \"tag\": "tubulous",\n \"popularity\": 6799\n },\n {\n \"tag\": "unhorse",\n \"popularity\": 6793\n },\n {\n \"tag\": "chlordane",\n \"popularity\": 6787\n },\n {\n \"tag\": "colloquy brochan",\n \"popularity\": 6780\n },\n {\n \"tag\": "sloosh",\n \"popularity\": 6774\n },\n {\n \"tag\": "battered",\n \"popularity\": 6767\n },\n {\n \"tag\": "monocularity pluriguttulate",\n \"popularity\": 6761\n },\n {\n \"tag\": "chiastoneury",\n \"popularity\": 6755\n },\n {\n \"tag\": "Sanguinaria",\n \"popularity\": 6748\n },\n {\n \"tag\": "confessionary",\n \"popularity\": 6742\n },\n {\n \"tag\": "enzymic",\n \"popularity\": 6736\n },\n {\n \"tag\": "cord",\n \"popularity\": 6729\n },\n {\n \"tag\": "oviducal",\n \"popularity\": 6723\n },\n {\n \"tag\": "crozzle outsea",\n \"popularity\": 6717\n },\n {\n \"tag\": "balladical",\n \"popularity\": 6710\n },\n {\n \"tag\": "uncollectibleness",\n \"popularity\": 6704\n },\n {\n \"tag\": "predorsal",\n \"popularity\": 6698\n },\n {\n \"tag\": "reauthenticate",\n \"popularity\": 6692\n },\n {\n \"tag\": "ravissant",\n \"popularity\": 6685\n },\n {\n \"tag\": "advantageousness",\n \"popularity\": 6679\n },\n {\n \"tag\": "rung",\n \"popularity\": 6673\n },\n {\n \"tag\": "duncedom",\n \"popularity\": 6667\n },\n {\n \"tag\": "hematolite",\n \"popularity\": 6660\n },\n {\n \"tag\": "thisness",\n \"popularity\": 6654\n },\n {\n \"tag\": "mapau",\n \"popularity\": 6648\n },\n {\n \"tag\": "Hecatic",\n \"popularity\": 6642\n },\n {\n \"tag\": "meningoencephalocele",\n \"popularity\": 6636\n },\n {\n \"tag\": "confection sorra",\n \"popularity\": 6630\n },\n {\n \"tag\": "unsedate",\n \"popularity\": 6623\n },\n {\n \"tag\": "meningocerebritis",\n \"popularity\": 6617\n },\n {\n \"tag\": "biopsychological",\n \"popularity\": 6611\n },\n {\n \"tag\": "clavicithern",\n \"popularity\": 6605\n },\n {\n \"tag\": "resun",\n \"popularity\": 6599\n },\n {\n \"tag\": "bayamo",\n \"popularity\": 6593\n },\n {\n \"tag\": "seeableness",\n \"popularity\": 6587\n },\n {\n \"tag\": "hypsidolichocephalism",\n \"popularity\": 6581\n },\n {\n \"tag\": "salivous",\n \"popularity\": 6574\n },\n {\n \"tag\": "neumatize",\n \"popularity\": 6568\n },\n {\n \"tag\": "stree",\n \"popularity\": 6562\n },\n {\n \"tag\": "markshot",\n \"popularity\": 6556\n },\n {\n \"tag\": "phraseologically",\n \"popularity\": 6550\n },\n {\n \"tag\": "yealing",\n \"popularity\": 6544\n },\n {\n \"tag\": "puggy",\n \"popularity\": 6538\n },\n {\n \"tag\": "sexadecimal",\n \"popularity\": 6532\n },\n {\n \"tag\": "unofficerlike",\n \"popularity\": 6526\n },\n {\n \"tag\": "curiosa",\n \"popularity\": 6520\n },\n {\n \"tag\": "pedomotor",\n \"popularity\": 6514\n },\n {\n \"tag\": "astrally",\n \"popularity\": 6508\n },\n {\n \"tag\": "prosomatic",\n \"popularity\": 6502\n },\n {\n \"tag\": "bulletheaded",\n \"popularity\": 6496\n },\n {\n \"tag\": "fortuned",\n \"popularity\": 6490\n },\n {\n \"tag\": "pixy",\n \"popularity\": 6484\n },\n {\n \"tag\": "protectrix",\n \"popularity\": 6478\n },\n {\n \"tag\": "arthritical",\n \"popularity\": 6472\n },\n {\n \"tag\": "coction",\n \"popularity\": 6466\n },\n {\n \"tag\": "Anthropos",\n \"popularity\": 6460\n },\n {\n \"tag\": "runer",\n \"popularity\": 6454\n },\n {\n \"tag\": "prenotify",\n \"popularity\": 6449\n },\n {\n \"tag\": "microspheric gastroparalysis",\n \"popularity\": 6443\n },\n {\n \"tag\": "Jovicentrical",\n \"popularity\": 6437\n },\n {\n \"tag\": "ceratopsid",\n \"popularity\": 6431\n },\n {\n \"tag\": "Theodoric",\n \"popularity\": 6425\n },\n {\n \"tag\": "Pactolus",\n \"popularity\": 6419\n },\n {\n \"tag\": "spawning",\n \"popularity\": 6413\n },\n {\n \"tag\": "nonconfidential",\n \"popularity\": 6407\n },\n {\n \"tag\": "halotrichite infumate",\n \"popularity\": 6402\n },\n {\n \"tag\": "undiscriminatingly",\n \"popularity\": 6396\n },\n {\n \"tag\": "unexasperated",\n \"popularity\": 6390\n },\n {\n \"tag\": "isoeugenol",\n \"popularity\": 6384\n },\n {\n \"tag\": "pressboard",\n \"popularity\": 6378\n },\n {\n \"tag\": "unshrew",\n \"popularity\": 6372\n },\n {\n \"tag\": "huffingly",\n \"popularity\": 6367\n },\n {\n \"tag\": "wagaun",\n \"popularity\": 6361\n },\n {\n \"tag\": "squirt Philistine",\n \"popularity\": 6355\n },\n {\n \"tag\": "kryptic",\n \"popularity\": 6349\n },\n {\n \"tag\": "paraform",\n \"popularity\": 6344\n },\n {\n \"tag\": "preverify",\n \"popularity\": 6338\n },\n {\n \"tag\": "dalar",\n \"popularity\": 6332\n },\n {\n \"tag\": "interdictor appraisingly",\n \"popularity\": 6326\n },\n {\n \"tag\": "chipped",\n \"popularity\": 6321\n },\n {\n \"tag\": "Pteropoda",\n \"popularity\": 6315\n },\n {\n \"tag\": "Bohairic",\n \"popularity\": 6309\n },\n {\n \"tag\": "felting",\n \"popularity\": 6303\n },\n {\n \"tag\": "compurgatorial",\n \"popularity\": 6298\n },\n {\n \"tag\": "unclead",\n \"popularity\": 6292\n },\n {\n \"tag\": "stockish",\n \"popularity\": 6286\n },\n {\n \"tag\": "mulligatawny",\n \"popularity\": 6281\n },\n {\n \"tag\": "Monotheletism",\n \"popularity\": 6275\n },\n {\n \"tag\": "lutanist",\n \"popularity\": 6269\n },\n {\n \"tag\": "gluttonize",\n \"popularity\": 6264\n },\n {\n \"tag\": "hackneyed",\n \"popularity\": 6258\n },\n {\n \"tag\": "yield",\n \"popularity\": 6253\n },\n {\n \"tag\": "sulphonamido",\n \"popularity\": 6247\n },\n {\n \"tag\": "granulative",\n \"popularity\": 6241\n },\n {\n \"tag\": "swingy",\n \"popularity\": 6236\n },\n {\n \"tag\": "Desmidiales",\n \"popularity\": 6230\n },\n {\n \"tag\": "tootlish",\n \"popularity\": 6224\n },\n {\n \"tag\": "unsatisfiedly",\n \"popularity\": 6219\n },\n {\n \"tag\": "burucha",\n \"popularity\": 6213\n },\n {\n \"tag\": "premeditatingly",\n \"popularity\": 6208\n },\n {\n \"tag\": "cowrie",\n \"popularity\": 6202\n },\n {\n \"tag\": "pleurolysis",\n \"popularity\": 6197\n },\n {\n \"tag\": "nationalist",\n \"popularity\": 6191\n },\n {\n \"tag\": "Pholadacea",\n \"popularity\": 6186\n },\n {\n \"tag\": "anakrousis",\n \"popularity\": 6180\n },\n {\n \"tag\": "proctorial",\n \"popularity\": 6175\n },\n {\n \"tag\": "cavillation",\n \"popularity\": 6169\n },\n {\n \"tag\": "cervicobregmatic",\n \"popularity\": 6163\n },\n {\n \"tag\": "interspecific",\n \"popularity\": 6158\n },\n {\n \"tag\": "Teutonity",\n \"popularity\": 6152\n },\n {\n \"tag\": "snakeholing",\n \"popularity\": 6147\n },\n {\n \"tag\": "balcony",\n \"popularity\": 6142\n },\n {\n \"tag\": "latchless",\n \"popularity\": 6136\n },\n {\n \"tag\": "Mithraea",\n \"popularity\": 6131\n },\n {\n \"tag\": "pseudepigraph",\n \"popularity\": 6125\n },\n {\n \"tag\": "flosser",\n \"popularity\": 6120\n },\n {\n \"tag\": "kotyle",\n \"popularity\": 6114\n },\n {\n \"tag\": "outdo",\n \"popularity\": 6109\n },\n {\n \"tag\": "interclerical",\n \"popularity\": 6103\n },\n {\n \"tag\": "aurar",\n \"popularity\": 6098\n },\n {\n \"tag\": "apophyseal",\n \"popularity\": 6093\n },\n {\n \"tag\": "Miro",\n \"popularity\": 6087\n },\n {\n \"tag\": "Priscillian",\n \"popularity\": 6082\n },\n {\n \"tag\": "alluvia",\n \"popularity\": 6076\n },\n {\n \"tag\": "exordize",\n \"popularity\": 6071\n },\n {\n \"tag\": "breakage",\n \"popularity\": 6066\n },\n {\n \"tag\": "unclosable",\n \"popularity\": 6060\n },\n {\n \"tag\": "monocondylous",\n \"popularity\": 6055\n },\n {\n \"tag\": "dyarchy",\n \"popularity\": 6050\n },\n {\n \"tag\": "subchelate",\n \"popularity\": 6044\n },\n {\n \"tag\": "hearsay",\n \"popularity\": 6039\n },\n {\n \"tag\": "prestigiously",\n \"popularity\": 6034\n },\n {\n \"tag\": "unimuscular",\n \"popularity\": 6028\n },\n {\n \"tag\": "lingwort",\n \"popularity\": 6023\n },\n {\n \"tag\": "jealous",\n \"popularity\": 6018\n },\n {\n \"tag\": "artilleryman",\n \"popularity\": 6012\n },\n {\n \"tag\": "phantasmagorially",\n \"popularity\": 6007\n },\n {\n \"tag\": "stagnum",\n \"popularity\": 6002\n },\n {\n \"tag\": "organotropism shatteringly",\n \"popularity\": 5997\n },\n {\n \"tag\": "Mytilus Hebraist",\n \"popularity\": 5991\n },\n {\n \"tag\": "returf",\n \"popularity\": 5986\n },\n {\n \"tag\": "townfolk",\n \"popularity\": 5981\n },\n {\n \"tag\": "propitiative",\n \"popularity\": 5976\n },\n {\n \"tag\": "Anita unsullied",\n \"popularity\": 5970\n },\n {\n \"tag\": "bandoleered",\n \"popularity\": 5965\n },\n {\n \"tag\": "cubby",\n \"popularity\": 5960\n },\n {\n \"tag\": "Hexanchus",\n \"popularity\": 5955\n },\n {\n \"tag\": "circuminsular",\n \"popularity\": 5949\n },\n {\n \"tag\": "chamberletted eumycete",\n \"popularity\": 5944\n },\n {\n \"tag\": "secure",\n \"popularity\": 5939\n },\n {\n \"tag\": "Edwardean",\n \"popularity\": 5934\n },\n {\n \"tag\": "strenth",\n \"popularity\": 5929\n },\n {\n \"tag\": "exhaustless",\n \"popularity\": 5923\n },\n {\n \"tag\": "electioneerer",\n \"popularity\": 5918\n },\n {\n \"tag\": "estoile",\n \"popularity\": 5913\n },\n {\n \"tag\": "redden",\n \"popularity\": 5908\n },\n {\n \"tag\": "solicitee",\n \"popularity\": 5903\n },\n {\n \"tag\": "nonpatented",\n \"popularity\": 5898\n },\n {\n \"tag\": "lemming",\n \"popularity\": 5893\n },\n {\n \"tag\": "marled subalate",\n \"popularity\": 5887\n },\n {\n \"tag\": "premial horizonward",\n \"popularity\": 5882\n },\n {\n \"tag\": "nonrefueling",\n \"popularity\": 5877\n },\n {\n \"tag\": "rupturewort",\n \"popularity\": 5872\n },\n {\n \"tag\": "unfed",\n \"popularity\": 5867\n },\n {\n \"tag\": "empanelment",\n \"popularity\": 5862\n },\n {\n \"tag\": "isoosmosis",\n \"popularity\": 5857\n },\n {\n \"tag\": "jipijapa",\n \"popularity\": 5852\n },\n {\n \"tag\": "Fiji",\n \"popularity\": 5847\n },\n {\n \"tag\": "interferant",\n \"popularity\": 5842\n },\n {\n \"tag\": "reconstitution",\n \"popularity\": 5837\n },\n {\n \"tag\": "dockyardman",\n \"popularity\": 5832\n },\n {\n \"tag\": "dolichopodous",\n \"popularity\": 5826\n },\n {\n \"tag\": "whiteworm",\n \"popularity\": 5821\n },\n {\n \"tag\": "atheistically",\n \"popularity\": 5816\n },\n {\n \"tag\": "nonconcern",\n \"popularity\": 5811\n },\n {\n \"tag\": "scarabaeidoid",\n \"popularity\": 5806\n },\n {\n \"tag\": "triumviri",\n \"popularity\": 5801\n },\n {\n \"tag\": "rakit",\n \"popularity\": 5796\n },\n {\n \"tag\": "leecheater",\n \"popularity\": 5791\n },\n {\n \"tag\": "Arthrostraca",\n \"popularity\": 5786\n },\n {\n \"tag\": "upknit",\n \"popularity\": 5781\n },\n {\n \"tag\": "tymbalon",\n \"popularity\": 5776\n },\n {\n \"tag\": "inventurous",\n \"popularity\": 5771\n },\n {\n \"tag\": "perradiate",\n \"popularity\": 5766\n },\n {\n \"tag\": "seer",\n \"popularity\": 5762\n },\n {\n \"tag\": "Auricularia",\n \"popularity\": 5757\n },\n {\n \"tag\": "wettish exclusivity",\n \"popularity\": 5752\n },\n {\n \"tag\": "arteriosympathectomy",\n \"popularity\": 5747\n },\n {\n \"tag\": "tunlike",\n \"popularity\": 5742\n },\n {\n \"tag\": "cephalocercal",\n \"popularity\": 5737\n },\n {\n \"tag\": "meaninglessness",\n \"popularity\": 5732\n },\n {\n \"tag\": "fountful",\n \"popularity\": 5727\n },\n {\n \"tag\": "appraisement",\n \"popularity\": 5722\n },\n {\n \"tag\": "geniculated",\n \"popularity\": 5717\n },\n {\n \"tag\": "rotator",\n \"popularity\": 5712\n },\n {\n \"tag\": "foremarch biography",\n \"popularity\": 5707\n },\n {\n \"tag\": "arid",\n \"popularity\": 5703\n },\n {\n \"tag\": "inapprehensible",\n \"popularity\": 5698\n },\n {\n \"tag\": "chlorosulphonic",\n \"popularity\": 5693\n },\n {\n \"tag\": "braguette",\n \"popularity\": 5688\n },\n {\n \"tag\": "panophthalmitis",\n \"popularity\": 5683\n },\n {\n \"tag\": "pro objurgatorily",\n \"popularity\": 5678\n },\n {\n \"tag\": "zooplasty",\n \"popularity\": 5673\n },\n {\n \"tag\": "Terebratulidae",\n \"popularity\": 5669\n },\n {\n \"tag\": "Mahran",\n \"popularity\": 5664\n },\n {\n \"tag\": "anthologize merocele",\n \"popularity\": 5659\n },\n {\n \"tag\": "firecracker chiropractic",\n \"popularity\": 5654\n },\n {\n \"tag\": "tenorist",\n \"popularity\": 5649\n },\n {\n \"tag\": "amphitene",\n \"popularity\": 5645\n },\n {\n \"tag\": "silverbush toadstone",\n \"popularity\": 5640\n },\n {\n \"tag\": "entozoological",\n \"popularity\": 5635\n },\n {\n \"tag\": "trustlessness",\n \"popularity\": 5630\n },\n {\n \"tag\": "reassay",\n \"popularity\": 5625\n },\n {\n \"tag\": "chrysalides",\n \"popularity\": 5621\n },\n {\n \"tag\": "truncation",\n \"popularity\": 5616\n },\n {\n \"tag\": "unwavered mausoleal",\n \"popularity\": 5611\n },\n {\n \"tag\": "unserrated",\n \"popularity\": 5606\n },\n {\n \"tag\": "frampler",\n \"popularity\": 5602\n },\n {\n \"tag\": "celestial",\n \"popularity\": 5597\n },\n {\n \"tag\": "depreter",\n \"popularity\": 5592\n },\n {\n \"tag\": "retaliate",\n \"popularity\": 5588\n },\n {\n \"tag\": "decempunctate",\n \"popularity\": 5583\n },\n {\n \"tag\": "submitter",\n \"popularity\": 5578\n },\n {\n \"tag\": "phenothiazine",\n \"popularity\": 5573\n },\n {\n \"tag\": "hobbledehoyish",\n \"popularity\": 5569\n },\n {\n \"tag\": "erraticness",\n \"popularity\": 5564\n },\n {\n \"tag\": "ovariodysneuria",\n \"popularity\": 5559\n },\n {\n \"tag\": "puja",\n \"popularity\": 5555\n },\n {\n \"tag\": "cesspool",\n \"popularity\": 5550\n },\n {\n \"tag\": "sonation",\n \"popularity\": 5545\n },\n {\n \"tag\": "moggan",\n \"popularity\": 5541\n },\n {\n \"tag\": "overjutting",\n \"popularity\": 5536\n },\n {\n \"tag\": "cohobate",\n \"popularity\": 5531\n },\n {\n \"tag\": "Distoma",\n \"popularity\": 5527\n },\n {\n \"tag\": "Plectognathi",\n \"popularity\": 5522\n },\n {\n \"tag\": "dumple caliphate",\n \"popularity\": 5517\n },\n {\n \"tag\": "shiko",\n \"popularity\": 5513\n },\n {\n \"tag\": "downness",\n \"popularity\": 5508\n },\n {\n \"tag\": "whippletree",\n \"popularity\": 5504\n },\n {\n \"tag\": "nymphaeum",\n \"popularity\": 5499\n },\n {\n \"tag\": "there trest",\n \"popularity\": 5494\n },\n {\n \"tag\": "psychrometer",\n \"popularity\": 5490\n },\n {\n \"tag\": "pyelograph",\n \"popularity\": 5485\n },\n {\n \"tag\": "unsalvable",\n \"popularity\": 5481\n },\n {\n \"tag\": "bescreen",\n \"popularity\": 5476\n },\n {\n \"tag\": "cushy",\n \"popularity\": 5471\n },\n {\n \"tag\": "plicatolobate",\n \"popularity\": 5467\n },\n {\n \"tag\": "lakie",\n \"popularity\": 5462\n },\n {\n \"tag\": "anthropodeoxycholic",\n \"popularity\": 5458\n },\n {\n \"tag\": "resatisfaction",\n \"popularity\": 5453\n },\n {\n \"tag\": "unravelment unaccidental",\n \"popularity\": 5449\n },\n {\n \"tag\": "telewriter monogeneous",\n \"popularity\": 5444\n },\n {\n \"tag\": "unsabred",\n \"popularity\": 5440\n },\n {\n \"tag\": "startlingly",\n \"popularity\": 5435\n },\n {\n \"tag\": "Aralia",\n \"popularity\": 5431\n },\n {\n \"tag\": "alamonti",\n \"popularity\": 5426\n },\n {\n \"tag\": "Franklinization",\n \"popularity\": 5422\n },\n {\n \"tag\": "parliament",\n \"popularity\": 5417\n },\n {\n \"tag\": "schoolkeeper",\n \"popularity\": 5413\n },\n {\n \"tag\": "nonsociety",\n \"popularity\": 5408\n },\n {\n \"tag\": "parenthetic",\n \"popularity\": 5404\n },\n {\n \"tag\": "stog",\n \"popularity\": 5399\n },\n {\n \"tag\": "Pristipomidae",\n \"popularity\": 5395\n },\n {\n \"tag\": "exocarp",\n \"popularity\": 5390\n },\n {\n \"tag\": "monaxonial",\n \"popularity\": 5386\n },\n {\n \"tag\": "tramroad",\n \"popularity\": 5381\n },\n {\n \"tag\": "hookah",\n \"popularity\": 5377\n },\n {\n \"tag\": "saccharonic",\n \"popularity\": 5372\n },\n {\n \"tag\": "perimetrium",\n \"popularity\": 5368\n },\n {\n \"tag\": "libelluloid",\n \"popularity\": 5364\n },\n {\n \"tag\": "overrunningly",\n \"popularity\": 5359\n },\n {\n \"tag\": "untwister",\n \"popularity\": 5355\n },\n {\n \"tag\": "ninnyhammer",\n \"popularity\": 5350\n },\n {\n \"tag\": "metranate",\n \"popularity\": 5346\n },\n {\n \"tag\": "sarcoblast",\n \"popularity\": 5341\n },\n {\n \"tag\": "porkish",\n \"popularity\": 5337\n },\n {\n \"tag\": "chauvinistic",\n \"popularity\": 5333\n },\n {\n \"tag\": "sexagesimal",\n \"popularity\": 5328\n },\n {\n \"tag\": "hematogenic",\n \"popularity\": 5324\n },\n {\n \"tag\": "selfpreservatory",\n \"popularity\": 5320\n },\n {\n \"tag\": "myelauxe",\n \"popularity\": 5315\n },\n {\n \"tag\": "triply",\n \"popularity\": 5311\n },\n {\n \"tag\": "metaphysicous",\n \"popularity\": 5306\n },\n {\n \"tag\": "vitrinoid",\n \"popularity\": 5302\n },\n {\n \"tag\": "glabellae",\n \"popularity\": 5298\n },\n {\n \"tag\": "moonlighter",\n \"popularity\": 5293\n },\n {\n \"tag\": "monotheistically epexegetical",\n \"popularity\": 5289\n },\n {\n \"tag\": "pseudolateral",\n \"popularity\": 5285\n },\n {\n \"tag\": "heptamethylene",\n \"popularity\": 5280\n },\n {\n \"tag\": "salvadora",\n \"popularity\": 5276\n },\n {\n \"tag\": "unjovial diphenylthiourea",\n \"popularity\": 5272\n },\n {\n \"tag\": "thievishness",\n \"popularity\": 5268\n },\n {\n \"tag\": "unridable",\n \"popularity\": 5263\n },\n {\n \"tag\": "underhandedly",\n \"popularity\": 5259\n },\n {\n \"tag\": "fungiform",\n \"popularity\": 5255\n },\n {\n \"tag\": "scruffle",\n \"popularity\": 5250\n },\n {\n \"tag\": "preindisposition",\n \"popularity\": 5246\n },\n {\n \"tag\": "Amadis",\n \"popularity\": 5242\n },\n {\n \"tag\": "Culex",\n \"popularity\": 5238\n },\n {\n \"tag\": "churning",\n \"popularity\": 5233\n },\n {\n \"tag\": "imperite",\n \"popularity\": 5229\n },\n {\n \"tag\": "levorotation",\n \"popularity\": 5225\n },\n {\n \"tag\": "barbate",\n \"popularity\": 5221\n },\n {\n \"tag\": "knotwort",\n \"popularity\": 5216\n },\n {\n \"tag\": "gypsiferous",\n \"popularity\": 5212\n },\n {\n \"tag\": "tourmalinic",\n \"popularity\": 5208\n },\n {\n \"tag\": "helleboric",\n \"popularity\": 5204\n },\n {\n \"tag\": "pneumograph",\n \"popularity\": 5199\n },\n {\n \"tag\": "Peltigeraceae",\n \"popularity\": 5195\n },\n {\n \"tag\": "busine",\n \"popularity\": 5191\n },\n {\n \"tag\": "Ailuridae",\n \"popularity\": 5187\n },\n {\n \"tag\": "azotate",\n \"popularity\": 5183\n },\n {\n \"tag\": "unlikable",\n \"popularity\": 5178\n },\n {\n \"tag\": "sloyd",\n \"popularity\": 5174\n },\n {\n \"tag\": "biblioclasm",\n \"popularity\": 5170\n },\n {\n \"tag\": "Seres",\n \"popularity\": 5166\n },\n {\n \"tag\": "unaccurateness",\n \"popularity\": 5162\n },\n {\n \"tag\": "scrollwise",\n \"popularity\": 5157\n },\n {\n \"tag\": "flandowser",\n \"popularity\": 5153\n },\n {\n \"tag\": "unblackened",\n \"popularity\": 5149\n },\n {\n \"tag\": "schistosternia",\n \"popularity\": 5145\n },\n {\n \"tag\": "fuse",\n \"popularity\": 5141\n },\n {\n \"tag\": "narthecal",\n \"popularity\": 5137\n },\n {\n \"tag\": "Cueva",\n \"popularity\": 5133\n },\n {\n \"tag\": "appositeness",\n \"popularity\": 5128\n },\n {\n \"tag\": "proindustrial",\n \"popularity\": 5124\n },\n {\n \"tag\": "dermatorrhoea",\n \"popularity\": 5120\n },\n {\n \"tag\": "oxyurous tendential",\n \"popularity\": 5116\n },\n {\n \"tag\": "isopurpurin",\n \"popularity\": 5112\n },\n {\n \"tag\": "impose",\n \"popularity\": 5108\n },\n {\n \"tag\": "wordsmanship",\n \"popularity\": 5104\n },\n {\n \"tag\": "saturator",\n \"popularity\": 5100\n },\n {\n \"tag\": "Nordicity",\n \"popularity\": 5096\n },\n {\n \"tag\": "interaccuse",\n \"popularity\": 5092\n },\n {\n \"tag\": "acridinic",\n \"popularity\": 5087\n },\n {\n \"tag\": "scholion",\n \"popularity\": 5083\n },\n {\n \"tag\": "pseudoaconitine",\n \"popularity\": 5079\n },\n {\n \"tag\": "doctorial",\n \"popularity\": 5075\n },\n {\n \"tag\": "Etchimin",\n \"popularity\": 5071\n },\n {\n \"tag\": "oliviform",\n \"popularity\": 5067\n },\n {\n \"tag\": "Pele",\n \"popularity\": 5063\n },\n {\n \"tag\": "Chiromantis Progymnasium",\n \"popularity\": 5059\n },\n {\n \"tag\": "toxosis",\n \"popularity\": 5055\n },\n {\n \"tag\": "spadilla",\n \"popularity\": 5051\n },\n {\n \"tag\": "Actinopterygii",\n \"popularity\": 5047\n },\n {\n \"tag\": "untiring",\n \"popularity\": 5043\n },\n {\n \"tag\": "butyral",\n \"popularity\": 5039\n },\n {\n \"tag\": "Gymnoderinae",\n \"popularity\": 5035\n },\n {\n \"tag\": "testudo",\n \"popularity\": 5031\n },\n {\n \"tag\": "frigorify",\n \"popularity\": 5027\n },\n {\n \"tag\": "aliency",\n \"popularity\": 5023\n },\n {\n \"tag\": "jargon",\n \"popularity\": 5019\n },\n {\n \"tag\": "counterservice",\n \"popularity\": 5015\n },\n {\n \"tag\": "isostrychnine",\n \"popularity\": 5011\n },\n {\n \"tag\": "tellership",\n \"popularity\": 5007\n },\n {\n \"tag\": "miscegenetic",\n \"popularity\": 5003\n },\n {\n \"tag\": "sorcer",\n \"popularity\": 4999\n },\n {\n \"tag\": "tilewright",\n \"popularity\": 4995\n },\n {\n \"tag\": "cyanoplastid",\n \"popularity\": 4991\n },\n {\n \"tag\": "fluxionally",\n \"popularity\": 4987\n },\n {\n \"tag\": "proudhearted",\n \"popularity\": 4983\n },\n {\n \"tag\": "blithely",\n \"popularity\": 4979\n },\n {\n \"tag\": "jestproof",\n \"popularity\": 4975\n },\n {\n \"tag\": "jestwise",\n \"popularity\": 4971\n },\n {\n \"tag\": "nonassimilable",\n \"popularity\": 4967\n },\n {\n \"tag\": "compurgation",\n \"popularity\": 4964\n },\n {\n \"tag\": "unhate",\n \"popularity\": 4960\n },\n {\n \"tag\": "haplodonty",\n \"popularity\": 4956\n },\n {\n \"tag\": "cardholder",\n \"popularity\": 4952\n },\n {\n \"tag\": "rainlight megohmmeter overstout",\n \"popularity\": 4948\n },\n {\n \"tag\": "itchless",\n \"popularity\": 4944\n },\n {\n \"tag\": "begiggle",\n \"popularity\": 4940\n },\n {\n \"tag\": "chromatosphere",\n \"popularity\": 4936\n },\n {\n \"tag\": "typicality",\n \"popularity\": 4932\n },\n {\n \"tag\": "overgrown",\n \"popularity\": 4928\n },\n {\n \"tag\": "envolume",\n \"popularity\": 4925\n },\n {\n \"tag\": "pachycholia",\n \"popularity\": 4921\n },\n {\n \"tag\": "passageable",\n \"popularity\": 4917\n },\n {\n \"tag\": "pathopoiesis",\n \"popularity\": 4913\n },\n {\n \"tag\": "overbreak",\n \"popularity\": 4909\n },\n {\n \"tag\": "satyric",\n \"popularity\": 4905\n },\n {\n \"tag\": "unaudited",\n \"popularity\": 4901\n },\n {\n \"tag\": "whimble",\n \"popularity\": 4898\n },\n {\n \"tag\": "pressureless",\n \"popularity\": 4894\n },\n {\n \"tag\": "Selene",\n \"popularity\": 4890\n },\n {\n \"tag\": "slithery",\n \"popularity\": 4886\n },\n {\n \"tag\": "nondisfigurement",\n \"popularity\": 4882\n },\n {\n \"tag\": "overdelicious",\n \"popularity\": 4878\n },\n {\n \"tag\": "Perca",\n \"popularity\": 4875\n },\n {\n \"tag\": "Palladium",\n \"popularity\": 4871\n },\n {\n \"tag\": "insagacity",\n \"popularity\": 4867\n },\n {\n \"tag\": "peristoma",\n \"popularity\": 4863\n },\n {\n \"tag\": "uncreativeness",\n \"popularity\": 4859\n },\n {\n \"tag\": "incomparability surfboarding",\n \"popularity\": 4856\n },\n {\n \"tag\": "bacillar",\n \"popularity\": 4852\n },\n {\n \"tag\": "ulcerative",\n \"popularity\": 4848\n },\n {\n \"tag\": "stychomythia",\n \"popularity\": 4844\n },\n {\n \"tag\": "sesma somatics nonentry",\n \"popularity\": 4840\n },\n {\n \"tag\": "unsepulchred",\n \"popularity\": 4837\n },\n {\n \"tag\": "cephalanthium",\n \"popularity\": 4833\n },\n {\n \"tag\": "Asiaticization",\n \"popularity\": 4829\n },\n {\n \"tag\": "killeen",\n \"popularity\": 4825\n },\n {\n \"tag\": "Pseudococcus",\n \"popularity\": 4822\n },\n {\n \"tag\": "untractable",\n \"popularity\": 4818\n },\n {\n \"tag\": "apolegamic",\n \"popularity\": 4814\n },\n {\n \"tag\": "hyperpnea",\n \"popularity\": 4810\n },\n {\n \"tag\": "martyrolatry",\n \"popularity\": 4807\n },\n {\n \"tag\": "Sarmatic",\n \"popularity\": 4803\n },\n {\n \"tag\": "nonsurface",\n \"popularity\": 4799\n },\n {\n \"tag\": "adjoined",\n \"popularity\": 4796\n },\n {\n \"tag\": "vasiform",\n \"popularity\": 4792\n },\n {\n \"tag\": "tastelessness",\n \"popularity\": 4788\n },\n {\n \"tag\": "rumbo",\n \"popularity\": 4784\n },\n {\n \"tag\": "subdititious",\n \"popularity\": 4781\n },\n {\n \"tag\": "reparticipation",\n \"popularity\": 4777\n },\n {\n \"tag\": "Yorkshireism",\n \"popularity\": 4773\n },\n {\n \"tag\": "outcrow",\n \"popularity\": 4770\n },\n {\n \"tag\": "casserole",\n \"popularity\": 4766\n },\n {\n \"tag\": "semideltaic",\n \"popularity\": 4762\n },\n {\n \"tag\": "freemason",\n \"popularity\": 4759\n },\n {\n \"tag\": "catkin",\n \"popularity\": 4755\n },\n {\n \"tag\": "conscient",\n \"popularity\": 4751\n },\n {\n \"tag\": "reliably",\n \"popularity\": 4748\n },\n {\n \"tag\": "Telembi",\n \"popularity\": 4744\n },\n {\n \"tag\": "hide",\n \"popularity\": 4740\n },\n {\n \"tag\": "social",\n \"popularity\": 4737\n },\n {\n \"tag\": "ichneutic",\n \"popularity\": 4733\n },\n {\n \"tag\": "polypotome blouse pentagrammatic",\n \"popularity\": 4729\n },\n {\n \"tag\": "airdrome pesthole",\n \"popularity\": 4726\n },\n {\n \"tag\": "unportended",\n \"popularity\": 4722\n },\n {\n \"tag\": "sheerly",\n \"popularity\": 4719\n },\n {\n \"tag\": "acardiac",\n \"popularity\": 4715\n },\n {\n \"tag\": "fetor",\n \"popularity\": 4711\n },\n {\n \"tag\": "storax",\n \"popularity\": 4708\n },\n {\n \"tag\": "syndactylic",\n \"popularity\": 4704\n },\n {\n \"tag\": "otiatrics",\n \"popularity\": 4700\n },\n {\n \"tag\": "range",\n \"popularity\": 4697\n },\n {\n \"tag\": "branchway",\n \"popularity\": 4693\n },\n {\n \"tag\": "beatific",\n \"popularity\": 4690\n },\n {\n \"tag\": "Rugosa",\n \"popularity\": 4686\n },\n {\n \"tag\": "rafty",\n \"popularity\": 4682\n },\n {\n \"tag\": "gapy",\n \"popularity\": 4679\n },\n {\n \"tag\": "heterocercal",\n \"popularity\": 4675\n },\n {\n \"tag\": "actinopterygious",\n \"popularity\": 4672\n },\n {\n \"tag\": "glauconite",\n \"popularity\": 4668\n },\n {\n \"tag\": "limbless priest",\n \"popularity\": 4665\n },\n {\n \"tag\": "chrysene",\n \"popularity\": 4661\n },\n {\n \"tag\": "isentropic",\n \"popularity\": 4658\n },\n {\n \"tag\": "lairdess",\n \"popularity\": 4654\n },\n {\n \"tag\": "butterhead choliambic",\n \"popularity\": 4650\n },\n {\n \"tag\": "hexaseme",\n \"popularity\": 4647\n },\n {\n \"tag\": "treeify",\n \"popularity\": 4643\n },\n {\n \"tag\": "coronetted fructify",\n \"popularity\": 4640\n },\n {\n \"tag\": "admiralty",\n \"popularity\": 4636\n },\n {\n \"tag\": "Flosculariidae",\n \"popularity\": 4633\n },\n {\n \"tag\": "limaceous",\n \"popularity\": 4629\n },\n {\n \"tag\": "subterconscious",\n \"popularity\": 4626\n },\n {\n \"tag\": "stayless",\n \"popularity\": 4622\n },\n {\n \"tag\": "psha",\n \"popularity\": 4619\n },\n {\n \"tag\": "Mediterraneanize",\n \"popularity\": 4615\n },\n {\n \"tag\": "impenetrably",\n \"popularity\": 4612\n },\n {\n \"tag\": "Myrmeleonidae",\n \"popularity\": 4608\n },\n {\n \"tag\": "germander",\n \"popularity\": 4605\n },\n {\n \"tag\": "Buri",\n \"popularity\": 4601\n },\n {\n \"tag\": "papyrotamia",\n \"popularity\": 4598\n },\n {\n \"tag\": "Toxylon",\n \"popularity\": 4594\n },\n {\n \"tag\": "batatilla",\n \"popularity\": 4591\n },\n {\n \"tag\": "fabella assumer",\n \"popularity\": 4587\n },\n {\n \"tag\": "macromethod",\n \"popularity\": 4584\n },\n {\n \"tag\": "Blechnum",\n \"popularity\": 4580\n },\n {\n \"tag\": "pantography",\n \"popularity\": 4577\n },\n {\n \"tag\": "seminovel",\n \"popularity\": 4574\n },\n {\n \"tag\": "disembarrassment",\n \"popularity\": 4570\n },\n {\n \"tag\": "bushmaking",\n \"popularity\": 4567\n },\n {\n \"tag\": "neurosis",\n \"popularity\": 4563\n },\n {\n \"tag\": "Animalia",\n \"popularity\": 4560\n },\n {\n \"tag\": "Bernice",\n \"popularity\": 4556\n },\n {\n \"tag\": "wisen",\n \"popularity\": 4553\n },\n {\n \"tag\": "subhymenium",\n \"popularity\": 4549\n },\n {\n \"tag\": "esophagomycosis",\n \"popularity\": 4546\n },\n {\n \"tag\": "wireworks",\n \"popularity\": 4543\n },\n {\n \"tag\": "Sabellidae",\n \"popularity\": 4539\n },\n {\n \"tag\": "fustianish",\n \"popularity\": 4536\n },\n {\n \"tag\": "professively",\n \"popularity\": 4532\n },\n {\n \"tag\": "overcorruptly",\n \"popularity\": 4529\n },\n {\n \"tag\": "overcreep",\n \"popularity\": 4526\n },\n {\n \"tag\": "Castilloa",\n \"popularity\": 4522\n },\n {\n \"tag\": "forelady Georgie",\n \"popularity\": 4519\n },\n {\n \"tag\": "outsider",\n \"popularity\": 4515\n },\n {\n \"tag\": "Enukki",\n \"popularity\": 4512\n },\n {\n \"tag\": "gypsy",\n \"popularity\": 4509\n },\n {\n \"tag\": "Passamaquoddy",\n \"popularity\": 4505\n },\n {\n \"tag\": "reposit",\n \"popularity\": 4502\n },\n {\n \"tag\": "overtenderness",\n \"popularity\": 4499\n },\n {\n \"tag\": "keratome",\n \"popularity\": 4495\n },\n {\n \"tag\": "interclavicular hypermonosyllable Susanna",\n \"popularity\": 4492\n },\n {\n \"tag\": "mispropose",\n \"popularity\": 4489\n },\n {\n \"tag\": "Membranipora",\n \"popularity\": 4485\n },\n {\n \"tag\": "lampad",\n \"popularity\": 4482\n },\n {\n \"tag\": "header",\n \"popularity\": 4479\n },\n {\n \"tag\": "triseriate",\n \"popularity\": 4475\n },\n {\n \"tag\": "distrainment",\n \"popularity\": 4472\n },\n {\n \"tag\": "staphyloplastic",\n \"popularity\": 4469\n },\n {\n \"tag\": "outscour",\n \"popularity\": 4465\n },\n {\n \"tag\": "tallowmaking",\n \"popularity\": 4462\n },\n {\n \"tag\": "plugger",\n \"popularity\": 4459\n },\n {\n \"tag\": "fashionize",\n \"popularity\": 4455\n },\n {\n \"tag\": "puzzle",\n \"popularity\": 4452\n },\n {\n \"tag\": "imbrue",\n \"popularity\": 4449\n },\n {\n \"tag\": "osteoblast",\n \"popularity\": 4445\n },\n {\n \"tag\": "Hydrocores",\n \"popularity\": 4442\n },\n {\n \"tag\": "Lutra",\n \"popularity\": 4439\n },\n {\n \"tag\": "upridge scarfy",\n \"popularity\": 4435\n },\n {\n \"tag\": "ancon taffle",\n \"popularity\": 4432\n },\n {\n \"tag\": "impest",\n \"popularity\": 4429\n },\n {\n \"tag\": "uncollatedness",\n \"popularity\": 4426\n },\n {\n \"tag\": "hypersensitize",\n \"popularity\": 4422\n },\n {\n \"tag\": "autographically",\n \"popularity\": 4419\n },\n {\n \"tag\": "louther",\n \"popularity\": 4416\n },\n {\n \"tag\": "Ollie",\n \"popularity\": 4413\n },\n {\n \"tag\": "recompensate",\n \"popularity\": 4409\n },\n {\n \"tag\": "Shan",\n \"popularity\": 4406\n },\n {\n \"tag\": "brachycnemic",\n \"popularity\": 4403\n },\n {\n \"tag\": "Carinatae",\n \"popularity\": 4399\n },\n {\n \"tag\": "geotherm",\n \"popularity\": 4396\n },\n {\n \"tag\": "sawback",\n \"popularity\": 4393\n },\n {\n \"tag\": "Novatianist",\n \"popularity\": 4390\n },\n {\n \"tag\": "reapproach",\n \"popularity\": 4387\n },\n {\n \"tag\": "myelopoietic",\n \"popularity\": 4383\n },\n {\n \"tag\": "cyanin",\n \"popularity\": 4380\n },\n {\n \"tag\": "unsmutted",\n \"popularity\": 4377\n },\n {\n \"tag\": "nonpapist",\n \"popularity\": 4374\n },\n {\n \"tag\": "transbaikalian",\n \"popularity\": 4370\n },\n {\n \"tag\": "connately",\n \"popularity\": 4367\n },\n {\n \"tag\": "tenderize iterance",\n \"popularity\": 4364\n },\n {\n \"tag\": "hydrostatical",\n \"popularity\": 4361\n },\n {\n \"tag\": "unflag",\n \"popularity\": 4358\n },\n {\n \"tag\": "translate",\n \"popularity\": 4354\n },\n {\n \"tag\": "Scorzonera",\n \"popularity\": 4351\n },\n {\n \"tag\": "uncomforted",\n \"popularity\": 4348\n },\n {\n \"tag\": "risser varied",\n \"popularity\": 4345\n },\n {\n \"tag\": "plumbate",\n \"popularity\": 4342\n },\n {\n \"tag\": "Usneaceae",\n \"popularity\": 4338\n },\n {\n \"tag\": "fohat",\n \"popularity\": 4335\n },\n {\n \"tag\": "slagging",\n \"popularity\": 4332\n },\n {\n \"tag\": "superserious",\n \"popularity\": 4329\n },\n {\n \"tag\": "theocracy",\n \"popularity\": 4326\n },\n {\n \"tag\": "valonia",\n \"popularity\": 4323\n },\n {\n \"tag\": "Sapindales",\n \"popularity\": 4319\n },\n {\n \"tag\": "palaeozoologist",\n \"popularity\": 4316\n },\n {\n \"tag\": "yalb",\n \"popularity\": 4313\n },\n {\n \"tag\": "unviewed",\n \"popularity\": 4310\n },\n {\n \"tag\": "polyarteritis",\n \"popularity\": 4307\n },\n {\n \"tag\": "vectorial",\n \"popularity\": 4304\n },\n {\n \"tag\": "skimpingly",\n \"popularity\": 4301\n },\n {\n \"tag\": "athort",\n \"popularity\": 4297\n },\n {\n \"tag\": "tribofluorescence",\n \"popularity\": 4294\n },\n {\n \"tag\": "benzonitrol",\n \"popularity\": 4291\n },\n {\n \"tag\": "swiller subobtuse subjacency",\n \"popularity\": 4288\n },\n {\n \"tag\": "uncompassed",\n \"popularity\": 4285\n },\n {\n \"tag\": "cacochymia",\n \"popularity\": 4282\n },\n {\n \"tag\": "commensalist butadiene",\n \"popularity\": 4279\n },\n {\n \"tag\": "culpable",\n \"popularity\": 4276\n },\n {\n \"tag\": "contributive",\n \"popularity\": 4273\n },\n {\n \"tag\": "attemperately",\n \"popularity\": 4269\n },\n {\n \"tag\": "spelt",\n \"popularity\": 4266\n },\n {\n \"tag\": "exoneration",\n \"popularity\": 4263\n },\n {\n \"tag\": "antivivisectionist",\n \"popularity\": 4260\n },\n {\n \"tag\": "granitification",\n \"popularity\": 4257\n },\n {\n \"tag\": "palladize",\n \"popularity\": 4254\n },\n {\n \"tag\": "marksmanship",\n \"popularity\": 4251\n },\n {\n \"tag\": "bullydom",\n \"popularity\": 4248\n },\n {\n \"tag\": "spirality",\n \"popularity\": 4245\n },\n {\n \"tag\": "caliginous",\n \"popularity\": 4242\n },\n {\n \"tag\": "reportedly",\n \"popularity\": 4239\n },\n {\n \"tag\": "polyad",\n \"popularity\": 4236\n },\n {\n \"tag\": "arthroempyesis",\n \"popularity\": 4233\n },\n {\n \"tag\": "semibay facultatively",\n \"popularity\": 4229\n },\n {\n \"tag\": "metastatically",\n \"popularity\": 4226\n },\n {\n \"tag\": "prophetically",\n \"popularity\": 4223\n },\n {\n \"tag\": "Linguatula elapid",\n \"popularity\": 4220\n },\n {\n \"tag\": "pyknatom",\n \"popularity\": 4217\n },\n {\n \"tag\": "centimeter",\n \"popularity\": 4214\n },\n {\n \"tag\": "mensurate",\n \"popularity\": 4211\n },\n {\n \"tag\": "migraine",\n \"popularity\": 4208\n },\n {\n \"tag\": "pentagamist",\n \"popularity\": 4205\n },\n {\n \"tag\": "querken",\n \"popularity\": 4202\n },\n {\n \"tag\": "ambulance",\n \"popularity\": 4199\n },\n {\n \"tag\": "Stokavian",\n \"popularity\": 4196\n },\n {\n \"tag\": "malvasian",\n \"popularity\": 4193\n },\n {\n \"tag\": "uncouthsome",\n \"popularity\": 4190\n },\n {\n \"tag\": "readable",\n \"popularity\": 4187\n },\n {\n \"tag\": "enlodge",\n \"popularity\": 4184\n },\n {\n \"tag\": "plasterwise Appendiculariidae perspectograph",\n \"popularity\": 4181\n },\n {\n \"tag\": "inkweed",\n \"popularity\": 4178\n },\n {\n \"tag\": "streep",\n \"popularity\": 4175\n },\n {\n \"tag\": "diadelphian cultured",\n \"popularity\": 4172\n },\n {\n \"tag\": "hymenopterous",\n \"popularity\": 4169\n },\n {\n \"tag\": "unexorableness",\n \"popularity\": 4166\n },\n {\n \"tag\": "cascaron",\n \"popularity\": 4163\n },\n {\n \"tag\": "undaintiness",\n \"popularity\": 4160\n },\n {\n \"tag\": "Curtana",\n \"popularity\": 4157\n },\n {\n \"tag\": "scurvied",\n \"popularity\": 4154\n },\n {\n \"tag\": "molluscoidal",\n \"popularity\": 4151\n },\n {\n \"tag\": "yurt",\n \"popularity\": 4148\n },\n {\n \"tag\": "deciduitis",\n \"popularity\": 4145\n },\n {\n \"tag\": "creephole",\n \"popularity\": 4142\n },\n {\n \"tag\": "quatrefeuille",\n \"popularity\": 4139\n },\n {\n \"tag\": "bicapitate adenomatome",\n \"popularity\": 4136\n },\n {\n \"tag\": "damassin",\n \"popularity\": 4134\n },\n {\n \"tag\": "planching",\n \"popularity\": 4131\n },\n {\n \"tag\": "dashedly inferential",\n \"popularity\": 4128\n },\n {\n \"tag\": "lobe",\n \"popularity\": 4125\n },\n {\n \"tag\": "Hyrachyus",\n \"popularity\": 4122\n },\n {\n \"tag\": "knab",\n \"popularity\": 4119\n },\n {\n \"tag\": "discohexaster",\n \"popularity\": 4116\n },\n {\n \"tag\": "malign",\n \"popularity\": 4113\n },\n {\n \"tag\": "pedagoguism",\n \"popularity\": 4110\n },\n {\n \"tag\": "shrubbery",\n \"popularity\": 4107\n },\n {\n \"tag\": "undershrub",\n \"popularity\": 4104\n },\n {\n \"tag\": "bureaucrat",\n \"popularity\": 4101\n },\n {\n \"tag\": "pantaleon",\n \"popularity\": 4098\n },\n {\n \"tag\": "mesoventral",\n \"popularity\": 4096\n }]'; - -var log2 = Math.log(2); -var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); - -function makeTagCloud(tagInfo) -{ - var output = '
'; - - tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; }); - - for (var i = 0; i < tagInfo.length; i++) { - var tag = tagInfo[i].tag; - - var validates = true; - for (var j = 0; j < tag.length; j++) { - var ch = tag.charCodeAt(j); - if (ch < 0x20 || ch >= 0x7f) { - validates = false; - break; - } - } - - if (!validates) - continue; - - var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); - var popularity = tagInfo[i].popularity; - var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; - output += ' ' + tag + ' \n'; - } - - output += '
'; - output.replace(" ", " "); - - return output; -} - -var tagcloud = makeTagCloud(tagInfo); -tagInfo = null; - -// The result string embeds floating-point numbers, which can vary a bit on different platforms, -// so we truncate them a bit before comparing. -var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) -assertEq(tagcloud_norm.length, 295906) diff --git a/js/src/tests/js1_8_1/jit/jstests.list b/js/src/tests/js1_8_1/jit/jstests.list deleted file mode 100644 index d21cf7d0743..00000000000 --- a/js/src/tests/js1_8_1/jit/jstests.list +++ /dev/null @@ -1,24 +0,0 @@ -url-prefix ../../jsreftest.html?test=js1_8_1/jit/ -script math-jit-tests.js -skip script regress-451673.js # bogus perf test (bug 540512) -skip script regress-451974-01.js # bogus perf test (bug 540512) -skip script regress-451974-02.js # bogus perf test (bug 540512) -skip script regress-452498-01.js # bogus perf test (bug 540512) -script regress-458838.js -script regress-462459-01.js -script regress-462459-02.js -script regress-462459-03.js -script regress-462459-04.js -script regress-462459-05.js -script regress-462459-06.js -script regress-462459-07.js -script regress-462459-08.js -script regress-462459-09.js -script regress-462459-10.js -script regress-462459-11.js -script regress-462459-12.js -skip script regress-469927.js # bogus perf test (bug 540512) -skip script regress-470739.js # bogus perf test (bug 540512) -script regress-471635.js -script regress-489682.js -script testDeepBailFromNonNative.js diff --git a/js/src/tests/js1_8_1/jit/regress-451673.js b/js/src/tests/js1_8_1/jit/regress-451673.js deleted file mode 100644 index 5c7202fe039..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451673.js +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarsky - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451673; -var summary = 'TM: Tracing prime number generation'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function doTest(enablejit) - { - if (enablejit) - jit(true); - else - jit(false); - - var n = 1000000; - var start = new Date(); - var i=0; - var j=0; - var numprimes=0; - var limit=0; - numprimes = 1; // 2 is prime - var mceil = Math.floor; - var msqrt = Math.sqrt; - var isPrime = 1; - - for (i = 3; i<= n; i+=2) - { - isPrime=1; - limit = mceil(msqrt(i)+1) + 1; - - for (j = 3; j < limit; j+=2) - { - if (i % j == 0) - { - isPrime = 0; - break; - } - } - - if (isPrime) - { - numprimes ++; - } - } - - var end = new Date(); - - var timetaken = end - start; - timetaken = timetaken / 1000; - - if (enablejit) - jit(false); - - print((enablejit ? ' JIT' : 'Non-JIT') + ": Number of primes up to: " + n + " is " + numprimes + ", counted in " + timetaken + " secs."); - - return timetaken; - } - - var timenonjit = doTest(false); - var timejit = doTest(true); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-451974-01.js b/js/src/tests/js1_8_1/jit/regress-451974-01.js deleted file mode 100644 index 59fc1415da3..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451974-01.js +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451974; -var summary = 'TM: loops with anon functions should not be slower with jit enabled'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var chars = '0123456789abcdef'; -var size = 10000; -var mult = 1000; -var densearray = []; -var lsize = size; - -while (lsize--) -{ - densearray.push(chars); -} - -function loop() -{ - var start = new Date(); - - for (var a = 0; a < mult; a++) - { - var f = (function(x){}); - for (var i = 0, len = densearray.length; i < len; i++) - { - f(densearray[i]); - } - } - - var stop = new Date(); - return stop - start; -} - -jit(false); -var timenonjit = loop(); -jit(true); -var timejit = loop(); -jit(false); - -print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - -expect = true; -actual = timejit < timenonjit/2; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-451974-02.js b/js/src/tests/js1_8_1/jit/regress-451974-02.js deleted file mode 100644 index f0de29d49bf..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-451974-02.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 451974; -var summary = 'TM: loops with anon functions should not be slower with jit enabled'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var chars = '0123456789abcdef'; - var size = 10000; - var mult = 1000; - var densearray = []; - var lsize = size; - - while (lsize--) - { - densearray.push(chars); - } - - function loop() - { - var start = new Date(); - - for (var a = 0; a < mult; a++) - { - var f = (function(x){}); - for (var i = 0, len = densearray.length; i < len; i++) - { - f(densearray[i]); - } - } - - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = loop(); - jit(true); - var timejit = loop(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit/2; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-452498-01.js b/js/src/tests/js1_8_1/jit/regress-452498-01.js deleted file mode 100644 index c857e2087af..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-452498-01.js +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarsky - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 452498; -var summary = 'TM: upvar2: jit heavyweight functions'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -function complex(aReal, aImag) { - this.r = aReal; - this.i = aImag; - this.square = function() { - return new complex(this.r * this.r - this.i * this.i, - 2 * this.r * this.i); - } - this.dist = function() { - return Math.sqrt(this.r * this.r + this.i * this.i); - } - this.add = function(aComplex) { - return new complex(this.r + aComplex.r, this.i + aComplex.i); - } -} - -function mandelbrotValueOO (aC, aIterMax) { - let Z = new complex(0.0, 0.0); - for (var iter = 0; iter < aIterMax; iter++) { - Z = Z.square().add(aC); - if (Z.r * Z.r + Z.i * Z.i > 256) { break; } - } - return iter; -} - -function f(trace) { - jit(trace); - var start = Date.now(); - const width = 60; - const height = 60; - const max_iters = 50; - var output = []; - for (let img_x = 0; img_x < width; img_x++) { - for (let img_y = 0; img_y < height; img_y++) { - let C = new complex(-2 + (img_x / width) * 3, - -1.5 + (img_y / height) * 3); - var res = mandelbrotValueOO(C, max_iters); - if (output.length > 0 && output[output.length -1][0] == res) { - output[output.length-1][1]++; - } else { - output.push([res, 1]); - } - } - } - jit(false); - const reference = "[[2, 6], [3, 17], [4, 6], [5, 1], [50, 1], [5, 1], [4, 6], [3, 17], [2, 10], [3, 17], [4, 6], [5, 1], [6, 1], [50, 1], [6, 1], [5, 1], [4, 6], [3, 17], [2, 8], [3, 17], [4, 6], [5, 2], [6, 1], [50, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 6], [3, 17], [4, 6], [5, 2], [6, 1], [7, 1], [50, 1], [7, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 4], [3, 17], [4, 7], [5, 2], [6, 1], [8, 1], [50, 1], [8, 1], [6, 1], [5, 2], [4, 7], [3, 17], [2, 2], [3, 17], [4, 7], [5, 3], [6, 1], [9, 1], [50, 1], [9, 1], [6, 1], [5, 3], [4, 7], [3, 17], [2, 1], [3, 16], [4, 7], [5, 3], [6, 2], [8, 1], [50, 1], [8, 1], [6, 2], [5, 3], [4, 7], [3, 32], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 31], [4, 7], [5, 3], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 30], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 28], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [10, 1], [50, 1], [10, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 26], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [11, 1], [50, 1], [11, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 25], [4, 6], [5, 3], [6, 3], [7, 1], [8, 1], [18, 1], [13, 1], [15, 1], [50, 1], [15, 1], [13, 1], [18, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 6], [3, 24], [4, 7], [5, 2], [6, 2], [7, 3], [8, 1], [10, 1], [14, 1], [50, 3], [14, 1], [10, 1], [8, 1], [7, 3], [6, 2], [5, 2], [4, 7], [3, 23], [4, 6], [5, 3], [7, 1], [8, 1], [9, 1], [8, 2], [10, 1], [11, 1], [15, 1], [50, 3], [15, 1], [11, 1], [10, 1], [8, 2], [9, 1], [8, 1], [7, 1], [5, 3], [4, 6], [3, 22], [4, 7], [5, 2], [6, 1], [7, 1], [14, 1], [16, 1], [11, 1], [10, 1], [12, 1], [20, 1], [23, 1], [46, 1], [50, 1], [46, 1], [23, 1], [20, 1], [12, 1], [10, 1], [11, 1], [16, 1], [14, 1], [7, 1], [6, 1], [5, 2], [4, 7], [3, 20], [4, 7], [5, 3], [6, 1], [7, 1], [8, 1], [10, 1], [17, 1], [16, 1], [20, 1], [50, 7], [20, 1], [16, 1], [17, 1], [10, 1], [8, 1], [7, 1], [6, 1], [5, 3], [4, 7], [3, 19], [4, 7], [5, 3], [6, 2], [7, 1], [10, 1], [21, 1], [50, 11], [21, 1], [10, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 18], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [9, 1], [13, 1], [25, 1], [50, 9], [25, 1], [13, 1], [9, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 17], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [14, 2], [50, 11], [14, 2], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 16], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [11, 1], [36, 1], [50, 11], [36, 1], [11, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 15], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [14, 1], [50, 11], [14, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 14], [4, 7], [5, 4], [6, 3], [7, 1], [8, 1], [9, 1], [12, 1], [26, 1], [50, 9], [26, 1], [12, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 4], [4, 7], [3, 13], [4, 7], [5, 4], [6, 2], [7, 2], [8, 1], [9, 1], [10, 1], [15, 1], [50, 9], [15, 1], [10, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 4], [4, 7], [3, 12], [4, 7], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [10, 1], [12, 1], [16, 1], [50, 7], [16, 1], [12, 1], [10, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 7], [3, 11], [4, 6], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [11, 1], [12, 1], [14, 1], [17, 1], [23, 1], [34, 1], [50, 3], [34, 1], [23, 1], [17, 1], [14, 1], [12, 1], [11, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 6], [3, 10], [4, 7], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [22, 1], [12, 1], [50, 1], [25, 1], [50, 11], [25, 1], [50, 1], [12, 1], [22, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 7], [3, 9], [4, 6], [5, 4], [6, 1], [7, 1], [8, 2], [9, 1], [14, 1], [50, 1], [21, 1], [50, 15], [21, 1], [50, 1], [14, 1], [9, 1], [8, 2], [7, 1], [6, 1], [5, 4], [4, 6], [3, 8], [4, 7], [5, 3], [6, 2], [9, 1], [14, 1], [13, 1], [11, 1], [13, 1], [26, 1], [50, 17], [26, 1], [13, 1], [11, 1], [13, 1], [14, 1], [9, 1], [6, 2], [5, 3], [4, 7], [3, 7], [4, 6], [5, 4], [6, 1], [7, 1], [9, 1], [49, 1], [43, 1], [50, 23], [43, 1], [49, 1], [9, 1], [7, 1], [6, 1], [5, 4], [4, 6], [3, 7], [4, 5], [5, 4], [6, 2], [7, 1], [9, 1], [13, 1], [50, 25], [13, 1], [9, 1], [7, 1], [6, 2], [5, 4], [4, 5], [3, 6], [4, 6], [5, 3], [6, 2], [7, 2], [9, 1], [11, 1], [17, 1], [50, 23], [17, 1], [11, 1], [9, 1], [7, 2], [6, 2], [5, 3], [4, 6], [3, 5], [4, 5], [5, 3], [6, 3], [7, 1], [8, 1], [9, 1], [50, 1], [26, 1], [50, 23], [26, 1], [50, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 5], [4, 4], [5, 3], [6, 3], [7, 1], [8, 2], [10, 1], [21, 1], [50, 25], [21, 1], [10, 1], [8, 2], [7, 1], [6, 3], [5, 3], [4, 4], [3, 5], [4, 4], [5, 2], [6, 3], [7, 1], [12, 1], [9, 1], [10, 1], [11, 1], [50, 27], [11, 1], [10, 1], [9, 1], [12, 1], [7, 1], [6, 3], [5, 2], [4, 4], [3, 5], [4, 3], [5, 2], [6, 2], [7, 2], [9, 1], [42, 1], [15, 1], [23, 1], [14, 1], [50, 27], [14, 1], [23, 1], [15, 1], [42, 1], [9, 1], [7, 2], [6, 2], [5, 2], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [20, 1], [9, 1], [8, 1], [9, 1], [10, 1], [16, 1], [50, 33], [16, 1], [10, 1], [9, 1], [8, 1], [9, 1], [20, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [9, 1], [13, 1], [12, 1], [11, 1], [38, 1], [25, 1], [50, 33], [25, 1], [38, 1], [11, 1], [12, 1], [13, 1], [9, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 2], [6, 1], [7, 1], [10, 1], [24, 1], [25, 1], [50, 35], [25, 1], [24, 1], [10, 1], [7, 1], [6, 1], [5, 2], [4, 3], [3, 5], [4, 4], [5, 1], [6, 1], [7, 1], [11, 2], [13, 1], [19, 1], [50, 33], [19, 1], [13, 1], [11, 2], [7, 1], [6, 1], [5, 1], [4, 4], [3, 5], [4, 4], [5, 2], [6, 1], [50, 1], [8, 2], [17, 1], [19, 1], [35, 1], [14, 1], [24, 1], [50, 25], [24, 1], [14, 1], [35, 1], [19, 1], [17, 1], [8, 2], [50, 1], [6, 1], [5, 2], [4, 4], [3, 5], [4, 5], [5, 2], [6, 2], [7, 1], [8, 1], [9, 2], [11, 1], [38, 1], [50, 25], [38, 1], [11, 1], [9, 2], [8, 1], [7, 1], [6, 2], [5, 2], [4, 5], [3, 6], [4, 4], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [15, 1], [50, 25], [15, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 4], [3, 7], [4, 5], [5, 3], [6, 3], [7, 1], [9, 1], [42, 1], [21, 1], [50, 23], [21, 1], [42, 1], [9, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 8], [4, 5], [5, 3], [6, 2], [7, 1], [8, 1], [9, 1], [13, 1], [50, 23], [13, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 5], [3, 9], [4, 6], [5, 3], [6, 2], [7, 1], [9, 1], [14, 1], [50, 23], [14, 1], [9, 1], [7, 1], [6, 2], [5, 3], [4, 6], [3, 10], [4, 6], [5, 3], [6, 1], [7, 1], [9, 1], [16, 1], [50, 2], [35, 1], [50, 8], [13, 1], [50, 8], [35, 1], [50, 2], [16, 1], [9, 1], [7, 1], [6, 1], [5, 3], [4, 6], [3, 12], [4, 6], [5, 2], [6, 1], [19, 1], [16, 1], [17, 1], [25, 1], [21, 1], [13, 1], [18, 1], [50, 6], [11, 1], [9, 1], [11, 1], [50, 6], [18, 1], [13, 1], [21, 1], [25, 1], [17, 1], [16, 1], [19, 1], [6, 1], [5, 2], [4, 6], [3, 14], [4, 5], [5, 3], [6, 1], [8, 1], [16, 1], [10, 1], [8, 2], [11, 1], [50, 1], [16, 1], [15, 1], [32, 1], [29, 1], [9, 1], [8, 1], [7, 1], [8, 1], [9, 1], [29, 1], [32, 1], [15, 1], [16, 1], [50, 1], [11, 1], [8, 2], [10, 1], [16, 1], [8, 1], [6, 1], [5, 3], [4, 5], [3, 15], [4, 6], [5, 3], [6, 4], [7, 1], [20, 1], [19, 1], [9, 3], [7, 3], [6, 1], [7, 3], [9, 3], [19, 1], [20, 1], [7, 1], [6, 4], [5, 3], [4, 6], [3, 16], [4, 7], [5, 4], [6, 3], [7, 1], [6, 13], [7, 1], [6, 3], [5, 4], [4, 7], [3, 18], [4, 7], [5, 27], [4, 7], [3, 20], [4, 9], [5, 21], [4, 9], [3, 23], [4, 12], [5, 11], [4, 12], [3, 26], [4, 33], [3, 29], [4, 29], [3, 33], [4, 25], [3, 38], [4, 19], [3, 20], [2, 1], [3, 26], [4, 7], [3, 26], [2, 2], [3, 57], [2, 1]]"; - reportCompare(reference, output.toSource(), summary + ': correctness jit=' + trace); - return (Date.now() - start); -} - - -var timenonjit = f(false); -var timejit = f(true); - -expect = true; -actual = timejit < timenonjit; - -print('time nonjit: ' + timenonjit + ', time jit: ' + timejit); - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-458838.js b/js/src/tests/js1_8_1/jit/regress-458838.js deleted file mode 100644 index 0cc6991eb78..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-458838.js +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarksy - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 458838; -var summary = 'TM: do not fall off trace when nested function accesses var of outer function'; -var actual = ''; -var expect = ''; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - jit(true); - - function f() { - var a = 1; - function g() { - var b = 0 - for (var i = 0; i < 10; ++i) { - b += a; - } - return b; - } - - return g(); - } - - expect = 10; - actual = f(); - - var recorderStarted; - var recorderAborted; - var traceCompleted; - var skip = true; - - if (this.tracemonkey && !this.tracemonkey.profiler) - { - recorderStarted = this.tracemonkey.recorderStarted; - recorderAborted = this.tracemonkey.recorderAborted; - traceCompleted = this.tracemonkey.traceCompleted; - skip = false; - } - - jit(false); - - reportCompare(expect, actual, summary + ': return value 10'); - - if (!skip) - { - expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; - actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; - reportCompare(expect, actual, summary + ': trace'); - } - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-462459-01.js b/js/src/tests/js1_8_1/jit/regress-462459-01.js deleted file mode 100644 index 7cfe2a90ba4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-01.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array()'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-02.js b/js/src/tests/js1_8_1/jit/regress-462459-02.js deleted file mode 100644 index 14cc20198c4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-02.js +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-03.js b/js/src/tests/js1_8_1/jit/regress-462459-03.js deleted file mode 100644 index a1d3db47083..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-03.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1, 2)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1, 2); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-04.js b/js/src/tests/js1_8_1/jit/regress-462459-04.js deleted file mode 100644 index 3bfe7278b1e..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-04.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace Array(1, 2, 3)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - Array(1, 2, 3); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-05.js b/js/src/tests/js1_8_1/jit/regress-462459-05.js deleted file mode 100644 index 5513b078e44..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-05.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array()'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-06.js b/js/src/tests/js1_8_1/jit/regress-462459-06.js deleted file mode 100644 index aab4093ab5a..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-06.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-07.js b/js/src/tests/js1_8_1/jit/regress-462459-07.js deleted file mode 100644 index 0a9632a723d..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-07.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1, 2)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1, 2); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-08.js b/js/src/tests/js1_8_1/jit/regress-462459-08.js deleted file mode 100644 index 2c57b27fde4..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-08.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace new Array(1, 2, 3)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - new Array(1, 2, 3); - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-09.js b/js/src/tests/js1_8_1/jit/regress-462459-09.js deleted file mode 100644 index 221fc19c429..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-09.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace []'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - []; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-10.js b/js/src/tests/js1_8_1/jit/regress-462459-10.js deleted file mode 100644 index 4917d5cf31b..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-10.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-11.js b/js/src/tests/js1_8_1/jit/regress-462459-11.js deleted file mode 100644 index 2f7cb1c5945..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-11.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1, 2]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1, 2]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-462459-12.js b/js/src/tests/js1_8_1/jit/regress-462459-12.js deleted file mode 100644 index 524a7e4ae4c..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-462459-12.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 462459; -var summary = 'TM: trace [1, 2, 3]'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -if (!this.tracemonkey || this.tracemonkey.profiler) -{ - jit(false); - expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; - reportCompare(expect, actual, summary); -} -else -{ - jit(true); - - expect = 'recorder started, recorder not aborted, trace completed'; - actual = ''; - - var recorderStartedStart = this.tracemonkey.recorderStarted; - var recorderAbortedStart = this.tracemonkey.recorderAborted; - var traceCompletedStart = this.tracemonkey.traceCompleted; - - - for (var i = 0; i < RUNLOOP; i++) - { - [1, 2, 3]; - } - - jit(false); - - var recorderStartedEnd = this.tracemonkey.recorderStarted; - var recorderAbortedEnd = this.tracemonkey.recorderAborted; - var traceCompletedEnd = this.tracemonkey.traceCompleted; - - if (recorderStartedEnd > recorderStartedStart) - { - actual = 'recorder started, '; - } - else - { - actual = 'recorder not started, '; - } - - if (recorderAbortedEnd > recorderAbortedStart) - { - actual += 'recorder aborted, '; - } - else - { - actual += 'recorder not aborted, '; - } - - if (traceCompletedEnd > traceCompletedStart) - { - actual += 'trace completed'; - } - else - { - actual += 'trace not completed'; - } - - reportCompare(expect, actual, summary); -} - diff --git a/js/src/tests/js1_8_1/jit/regress-469927.js b/js/src/tests/js1_8_1/jit/regress-469927.js deleted file mode 100644 index 17b893674b1..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-469927.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 469927; -var summary = 'TM: jit should not slow down short loop with let'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function letitbe() { - var start = new Date(); - for (let i = 0; i < 500000; ++i) { - for (let j = 0; j < 4; ++j) { } - } - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = letitbe(); - jit(true); - var timejit = letitbe(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-470739.js b/js/src/tests/js1_8_1/jit/regress-470739.js deleted file mode 100644 index b6b0e64e0f2..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-470739.js +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 470739; -var summary = 'TM: never abort on =='; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function loop() - { - var i; - var start = new Date(); - - for(i=0;i<500000;++i) { var r = (void 0) == null; } - - var stop = new Date(); - return stop - start; - } - - jit(false); - var timenonjit = loop(); - jit(true); - var timejit = loop(); - jit(false); - - print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); - - expect = true; - actual = timejit < timenonjit; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-471635.js b/js/src/tests/js1_8_1/jit/regress-471635.js deleted file mode 100644 index 76078649204..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-471635.js +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Boris Zbarksy - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 471635; -var summary = 'TM: trace js shell print()'; -var actual = ''; -var expect = ''; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - jit(true); - - (function(){ - for (var i = 1; i < 20; ++i) { - print("#"); - } - })(); - - var recorderStarted; - var recorderAborted; - var traceCompleted; - var skip = true; - - if (this.tracemonkey && !this.tracemonkey.profiler) - { - recorderStarted = this.tracemonkey.recorderStarted; - recorderAborted = this.tracemonkey.recorderAborted; - traceCompleted = this.tracemonkey.traceCompleted; - skip = false; - } - - jit(false); - - if (!skip) - { - expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; - actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; - } - else - { - expect = actual = 'Test skipped due to lack of tracemonkey jitstats object.'; - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/jit/regress-489682.js b/js/src/tests/js1_8_1/jit/regress-489682.js deleted file mode 100644 index b8b73ec1ca7..00000000000 --- a/js/src/tests/js1_8_1/jit/regress-489682.js +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Jesse Ruderman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 489682; -var summary = 'TM: wrong number with nested type-unstable loops'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -jit(true); - -var v = 0; - -for each (var a in [0, {}, {}, {}]) { - print(v); - v = v >>> 0; - for each (var b in [{}, {}, new String(''), 42, new String(''), {}, 42]) - { - } - } -print(v); - -jit(false); - -expect = '0'; -actual = v + ''; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/shell.js b/js/src/tests/js1_8_1/jit/shell.js deleted file mode 100644 index 63f283b96f8..00000000000 --- a/js/src/tests/js1_8_1/jit/shell.js +++ /dev/null @@ -1,4 +0,0 @@ -// The loop count at which we trace -const RECORDLOOP = this.tracemonkey ? tracemonkey.HOTLOOP : 8; -// The loop count at which we run the trace -const RUNLOOP = RECORDLOOP + 1; From 5fca90108b3e7ffd7049f32d323776bf0acb2d22 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 2 Nov 2010 13:34:09 -0700 Subject: [PATCH 165/263] Backed out changeset bcad241e5c22 --- .../test/tabview/browser_tabview_launch.js | 27 +- js/src/jit-test/README | 74 +++ js/src/jit-test/lib/prolog.js | 48 ++ js/src/jit-test/tests/arguments/args6.js | 22 + js/src/jit-test/tests/arguments/args8.js | 14 + js/src/jit-test/tests/arguments/argsx-4.js | 23 + js/src/jit-test/tests/basic/arith.js | 11 + js/src/jit-test/tests/basic/bug520498.js | 9 + js/src/jit-test/tests/basic/bug522136.js | 10 + js/src/jit-test/tests/basic/bug528644.js | 16 + js/src/jit-test/tests/basic/bug578041.js | 3 + js/src/jit-test/tests/basic/bug584565.js | 10 + .../tests/basic/delete-named-names.js | 17 + .../jit-test/tests/basic/jitstatsArchFlags.js | 14 + js/src/jit-test/tests/basic/parseIntTests.js | 23 + .../tests/basic/strictParseIntOctal.js | 16 + .../testAssignmentThatIgnoresSetterRetval.js | 10 + js/src/jit-test/tests/basic/testBug458838.js | 19 + js/src/jit-test/tests/basic/testBug504520.js | 11 + .../tests/basic/testBug504520Harder.js | 33 ++ js/src/jit-test/tests/basic/testBug552248.js | 36 ++ js/src/jit-test/tests/basic/testBug579602.js | 21 + js/src/jit-test/tests/basic/testBug579646.js | 22 + js/src/jit-test/tests/basic/testBug584650.js | 9 + js/src/jit-test/tests/basic/testBug597736.js | 32 ++ .../basic/testEliminatedGuardWithinAnchor.js | 12 + .../tests/basic/testHoleInDenseArray.js | 18 + .../jit-test/tests/basic/testIntOverflow.js | 15 + .../tests/basic/testMethodInitSafety.js | 14 + .../tests/basic/testNativeArgsRooting.js | 14 + .../tests/basic/testNestedDeepBail.js | 20 + .../tests/basic/testNestedExitStackOuter.js | 29 ++ .../jit-test/tests/basic/testNewArrayCount.js | 12 + .../tests/basic/testNewArrayCount2.js | 8 + .../tests/basic/testProxyConstructors.js | 9 + .../jit-test/tests/basic/testRebranding2.js | 21 + .../basic/testReconstructImacroPCStack.js | 28 ++ js/src/jit-test/tests/basic/testRegExpTest.js | 10 + .../basic/testScriptGetter_JSOP_CALLPROP.js | 11 + js/src/jit-test/tests/basic/testShiftLeft.js | 38 ++ .../tests/basic/testShiftRightArithmetic.js | 44 ++ .../tests/basic/testSideExitInConstructor.js | 39 ++ .../tests/basic/testSlowNativeBail.js | 10 + .../tests/basic/testStackQuotaExhausted.js | 29 ++ js/src/jit-test/tests/closures/bug540136.js | 17 + js/src/jit-test/tests/closures/bug540242.js | 17 + js/src/jit-test/tests/closures/bug540243.js | 10 + js/src/jit-test/tests/closures/bug541239.js | 16 + js/src/jit-test/tests/closures/lambda.js | 27 ++ .../tests/closures/setname-inner-heavy.js | 18 + js/src/jit-test/tests/jaeger/bug554580-5.js | 20 + js/src/jit-test/tests/jaeger/bug555155.js | 12 + js/src/jit-test/tests/jaeger/bug555543.js | 8 + js/src/jit-test/tests/jaeger/bug556525.js | 5 + .../tests/jaeger/bug563000/eif-trap-newvar.js | 9 + .../jaeger/bug563000/eif-trap-typechange.js | 10 + .../tests/jaeger/bug563000/eif-trap.js | 10 + .../tests/jaeger/bug563000/simple-trap-1.js | 9 + .../tests/jaeger/bug563000/simple-trap-2.js | 10 + .../tests/jaeger/bug563000/simple-untrap.js | 11 + .../jaeger/bug563000/trap-force-return-1.js | 7 + .../jaeger/bug563000/trap-force-return-2.js | 7 + .../jaeger/bug563000/trap-own-callsite.js | 15 + .../jaeger/bug563000/trap-parent-from-trap.js | 21 + .../tests/jaeger/bug563000/trap-parent.js | 16 + .../jaeger/bug563000/trap-self-as-parent.js | 18 + .../jaeger/bug563000/trap-self-from-trap.js | 23 + .../tests/jaeger/bug563000/trap-self.js | 11 + .../jaeger/bug563000/untrap-own-trapsite.js | 15 + .../tests/jaeger/bug563000/untrap-self.js | 13 + js/src/jit-test/tests/jaeger/bug573433.js | 7 + js/src/jit-test/tests/jaeger/bug580884.js | 8 + js/src/jit-test/tests/jaeger/bug582286.js | 3 + js/src/jit-test/tests/jaeger/bug583158.js | 9 + js/src/jit-test/tests/jaeger/bug585341.js | 6 + js/src/jit-test/tests/jaeger/bug588338.js | 14 + js/src/jit-test/tests/jaeger/bug588363-2.js | 7 + .../jit-test/tests/jaeger/crash-on-compare.js | 1 + js/src/jit-test/tests/jaeger/fused-eq-ifeq.js | 6 + js/src/jit-test/tests/pic/bug558099.js | 60 +++ .../sunspider/check-date-format-xparb.js | 422 ++++++++++++++++++ .../sunspider/check-math-partial-sums.js | 41 ++ .../tests/sunspider/check-string-tagcloud.js | 270 +++++++++++ js/src/tests/js1_8_1/jit/jstests.list | 24 + js/src/tests/js1_8_1/jit/regress-451673.js | 115 +++++ js/src/tests/js1_8_1/jit/regress-451974-01.js | 86 ++++ js/src/tests/js1_8_1/jit/regress-451974-02.js | 97 ++++ js/src/tests/js1_8_1/jit/regress-452498-01.js | 105 +++++ js/src/tests/js1_8_1/jit/regress-458838.js | 97 ++++ js/src/tests/js1_8_1/jit/regress-462459-01.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-02.js | 106 +++++ js/src/tests/js1_8_1/jit/regress-462459-03.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-04.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-05.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-06.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-07.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-08.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-09.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-10.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-11.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-462459-12.js | 107 +++++ js/src/tests/js1_8_1/jit/regress-469927.js | 78 ++++ js/src/tests/js1_8_1/jit/regress-470739.js | 80 ++++ js/src/tests/js1_8_1/jit/regress-471635.js | 90 ++++ js/src/tests/js1_8_1/jit/regress-489682.js | 65 +++ js/src/tests/js1_8_1/jit/shell.js | 4 + 106 files changed, 4223 insertions(+), 21 deletions(-) create mode 100644 js/src/jit-test/README create mode 100644 js/src/jit-test/lib/prolog.js create mode 100644 js/src/jit-test/tests/arguments/args6.js create mode 100644 js/src/jit-test/tests/arguments/args8.js create mode 100644 js/src/jit-test/tests/arguments/argsx-4.js create mode 100644 js/src/jit-test/tests/basic/arith.js create mode 100644 js/src/jit-test/tests/basic/bug520498.js create mode 100644 js/src/jit-test/tests/basic/bug522136.js create mode 100644 js/src/jit-test/tests/basic/bug528644.js create mode 100644 js/src/jit-test/tests/basic/bug578041.js create mode 100644 js/src/jit-test/tests/basic/bug584565.js create mode 100644 js/src/jit-test/tests/basic/delete-named-names.js create mode 100644 js/src/jit-test/tests/basic/jitstatsArchFlags.js create mode 100644 js/src/jit-test/tests/basic/parseIntTests.js create mode 100644 js/src/jit-test/tests/basic/strictParseIntOctal.js create mode 100644 js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js create mode 100644 js/src/jit-test/tests/basic/testBug458838.js create mode 100644 js/src/jit-test/tests/basic/testBug504520.js create mode 100644 js/src/jit-test/tests/basic/testBug504520Harder.js create mode 100644 js/src/jit-test/tests/basic/testBug552248.js create mode 100644 js/src/jit-test/tests/basic/testBug579602.js create mode 100644 js/src/jit-test/tests/basic/testBug579646.js create mode 100644 js/src/jit-test/tests/basic/testBug584650.js create mode 100644 js/src/jit-test/tests/basic/testBug597736.js create mode 100644 js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js create mode 100644 js/src/jit-test/tests/basic/testHoleInDenseArray.js create mode 100644 js/src/jit-test/tests/basic/testIntOverflow.js create mode 100644 js/src/jit-test/tests/basic/testMethodInitSafety.js create mode 100644 js/src/jit-test/tests/basic/testNativeArgsRooting.js create mode 100644 js/src/jit-test/tests/basic/testNestedDeepBail.js create mode 100644 js/src/jit-test/tests/basic/testNestedExitStackOuter.js create mode 100644 js/src/jit-test/tests/basic/testNewArrayCount.js create mode 100644 js/src/jit-test/tests/basic/testNewArrayCount2.js create mode 100644 js/src/jit-test/tests/basic/testProxyConstructors.js create mode 100644 js/src/jit-test/tests/basic/testRebranding2.js create mode 100644 js/src/jit-test/tests/basic/testReconstructImacroPCStack.js create mode 100644 js/src/jit-test/tests/basic/testRegExpTest.js create mode 100644 js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js create mode 100644 js/src/jit-test/tests/basic/testShiftLeft.js create mode 100644 js/src/jit-test/tests/basic/testShiftRightArithmetic.js create mode 100644 js/src/jit-test/tests/basic/testSideExitInConstructor.js create mode 100644 js/src/jit-test/tests/basic/testSlowNativeBail.js create mode 100644 js/src/jit-test/tests/basic/testStackQuotaExhausted.js create mode 100644 js/src/jit-test/tests/closures/bug540136.js create mode 100644 js/src/jit-test/tests/closures/bug540242.js create mode 100644 js/src/jit-test/tests/closures/bug540243.js create mode 100644 js/src/jit-test/tests/closures/bug541239.js create mode 100644 js/src/jit-test/tests/closures/lambda.js create mode 100644 js/src/jit-test/tests/closures/setname-inner-heavy.js create mode 100644 js/src/jit-test/tests/jaeger/bug554580-5.js create mode 100644 js/src/jit-test/tests/jaeger/bug555155.js create mode 100644 js/src/jit-test/tests/jaeger/bug555543.js create mode 100644 js/src/jit-test/tests/jaeger/bug556525.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/eif-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-parent.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/trap-self.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js create mode 100644 js/src/jit-test/tests/jaeger/bug563000/untrap-self.js create mode 100644 js/src/jit-test/tests/jaeger/bug573433.js create mode 100644 js/src/jit-test/tests/jaeger/bug580884.js create mode 100644 js/src/jit-test/tests/jaeger/bug582286.js create mode 100644 js/src/jit-test/tests/jaeger/bug583158.js create mode 100644 js/src/jit-test/tests/jaeger/bug585341.js create mode 100644 js/src/jit-test/tests/jaeger/bug588338.js create mode 100644 js/src/jit-test/tests/jaeger/bug588363-2.js create mode 100644 js/src/jit-test/tests/jaeger/crash-on-compare.js create mode 100644 js/src/jit-test/tests/jaeger/fused-eq-ifeq.js create mode 100644 js/src/jit-test/tests/pic/bug558099.js create mode 100644 js/src/jit-test/tests/sunspider/check-date-format-xparb.js create mode 100644 js/src/jit-test/tests/sunspider/check-math-partial-sums.js create mode 100644 js/src/jit-test/tests/sunspider/check-string-tagcloud.js create mode 100644 js/src/tests/js1_8_1/jit/jstests.list create mode 100644 js/src/tests/js1_8_1/jit/regress-451673.js create mode 100644 js/src/tests/js1_8_1/jit/regress-451974-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-451974-02.js create mode 100644 js/src/tests/js1_8_1/jit/regress-452498-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-458838.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-01.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-02.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-03.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-04.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-05.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-06.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-07.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-08.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-09.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-10.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-11.js create mode 100644 js/src/tests/js1_8_1/jit/regress-462459-12.js create mode 100644 js/src/tests/js1_8_1/jit/regress-469927.js create mode 100644 js/src/tests/js1_8_1/jit/regress-470739.js create mode 100644 js/src/tests/js1_8_1/jit/regress-471635.js create mode 100644 js/src/tests/js1_8_1/jit/regress-489682.js create mode 100644 js/src/tests/js1_8_1/jit/shell.js diff --git a/browser/base/content/test/tabview/browser_tabview_launch.js b/browser/base/content/test/tabview/browser_tabview_launch.js index c8673e9f1e6..661ecf3be38 100644 --- a/browser/base/content/test/tabview/browser_tabview_launch.js +++ b/browser/base/content/test/tabview/browser_tabview_launch.js @@ -55,28 +55,13 @@ function test() { function onTabViewLoadedAndShown() { window.removeEventListener("tabviewshown", onTabViewLoadedAndShown, false); - // Evidently sometimes isVisible (which is based on the selectedIndex of the - // tabview deck) isn't updated immediately when called from button.doCommand, - // so we add a little timeout here to get outside of the doCommand call. - // If the initial timeout isn't enough, we keep waiting in case it's taking - // longer than expected. - // See bug 594909. - let deck = document.getElementById("tab-view-deck"); - function waitForSwitch() { - if (deck.selectedIndex == 1) { - ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); - tabViewShownCount++; - - // kick off the series - window.addEventListener("tabviewshown", onTabViewShown, false); - window.addEventListener("tabviewhidden", onTabViewHidden, false); - TabView.toggle(); - } else { - setTimeout(waitForSwitch, 10); - } - } + ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); + tabViewShownCount++; - setTimeout(waitForSwitch, 1); + // kick off the series + window.addEventListener("tabviewshown", onTabViewShown, false); + window.addEventListener("tabviewhidden", onTabViewHidden, false); + TabView.toggle(); } // ---------- diff --git a/js/src/jit-test/README b/js/src/jit-test/README new file mode 100644 index 00000000000..ddde38dc962 --- /dev/null +++ b/js/src/jit-test/README @@ -0,0 +1,74 @@ +JS Trace Test Suite + +* PURPOSE + +This is a test suite for testing TraceMonkey. All tests are run in the JS shell +with tracing enabled (-j). + +* REQUIREMENTS + +Python 2.5. This is already a standard requirement for building our tree. + +* RUNNING THE TESTS + +Basic usage: + + python jit_test.py + +The progress bar shows [#tests passed, #tests failed, #tests run] at the left. +If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted +at any time with Ctrl+C and partial results will be printed. + +To run only the basic tests, not including the slow tests: + + python jit_test.py basic + +For more options: + + python jit_test.py -h + +* CREATING NEW TESTS + +Simply create a JS file under the 'tests/' directory. Most tests should go in +'tests/basic/'. + +All tests are run with 'lib/prolog.js' included first on the command line. The +command line also creates a global variable 'libdir' that is set to the path +of the 'lib' directory. To include a file 'foo.js' from the lib directory in a +test case: + + load(libdir + 'foo.js') + +* TEST METALINES + +The first line of a test case can contain a special comment controlling how the +test is run. For example: + + // |jit-test| allow-oom; + +The general format in EBNF is: + + metaline ::= cookie { item ";" } + cookie ::= "|jit-test|" + item ::= flag | attribute + + flag ::= "slow" | "allow-oom" + + attribute ::= name ":" value + name ::= "TMFLAGS" | "error" + value ::= + +The metaline may appear anywhere in the first line of the file: this allows it +to be placed inside any kind of comment. + +The meaning of the items: + + slow Test runs slowly. Do not run if the --no-slow option is given. + allow-oom If the test runs out of memory, it counts as passing. + valgrind Run test under valgrind. + + error The test should be considered to pass iff it throws the + given JS exception. + TMFLAGS Set the environment variable TMFLAGS to the given value. + +* END diff --git a/js/src/jit-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js new file mode 100644 index 00000000000..5d577b39bda --- /dev/null +++ b/js/src/jit-test/lib/prolog.js @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +const HAVE_TM = 'tracemonkey' in this; + +const HOTLOOP = HAVE_TM ? tracemonkey.HOTLOOP : 8; +const RECORDLOOP = HOTLOOP; +const RUNLOOP = HOTLOOP + 1; + +var checkStats; +if (HAVE_TM) { + checkStats = function(stats) + { + // Temporarily disabled while we work on heuristics. + return; + function jit(on) + { + if (on && !options().match(/tracejit/)) + { + options('tracejit'); + } + else if (!on && options().match(/tracejit/)) + { + options('tracejit'); + } + } + + jit(false); + for (var name in stats) { + var expected = stats[name]; + var actual = tracemonkey[name]; + if (expected != actual) { + print('Trace stats check failed: got ' + actual + ', expected ' + expected + ' for ' + name); + } + } + jit(true); + }; +} else { + checkStats = function() {}; +} + +var appendToActual = function(s) { + actual += s + ','; +} + +if (!("gczeal" in this)) { + gczeal = function() { } +} + diff --git a/js/src/jit-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js new file mode 100644 index 00000000000..a2fc60d36a8 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args6.js @@ -0,0 +1,22 @@ +actual = ''; +expected = '6,'; + +// tracing length + +var g = 0; + +function h(args) { + g = args.length; +} + +function f() { + h(arguments); +} + +for (var i = 0; i < 5; ++i) { + f(10, 20, 30, 40, 50, 60); +} +appendToActual(g); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js new file mode 100644 index 00000000000..57938d9e231 --- /dev/null +++ b/js/src/jit-test/tests/arguments/args8.js @@ -0,0 +1,14 @@ +actual = ''; +expected = '[object Arguments],[object Arguments],[object Arguments],[object Arguments],[object Arguments],'; + +function h() { + return arguments; +} + +for (var i = 0; i < 5; ++i) { + var p = h(i, i*2); + appendToActual(p); +} + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js new file mode 100644 index 00000000000..b52b14853cf --- /dev/null +++ b/js/src/jit-test/tests/arguments/argsx-4.js @@ -0,0 +1,23 @@ +actual = ''; +expected = '[object Arguments] undefined undefined,[object Arguments] undefined undefined,'; + +function f() { + g(arguments); +} + +function g(a, b, c) { + h(arguments); + a = 1; + b = 2; + c = 3; + h(arguments); +} + +function h(a, b, c) { + appendToActual(a + ' ' + b + ' ' + c); +} + +f(4, 5, 6); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/basic/arith.js b/js/src/jit-test/tests/basic/arith.js new file mode 100644 index 00000000000..b7f551dccd0 --- /dev/null +++ b/js/src/jit-test/tests/basic/arith.js @@ -0,0 +1,11 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis + +function arith() +{ + var accum = 0; + for (var i = 0; i < 100; i++) { + accum += (i * 2) - 1; + } + return accum; +} +assertEq(arith(), 9800); diff --git a/js/src/jit-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js new file mode 100644 index 00000000000..55324f6f30d --- /dev/null +++ b/js/src/jit-test/tests/basic/bug520498.js @@ -0,0 +1,9 @@ +var Q = 0; +try { + (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) +} catch (e) { +} + +if (Q == 100000) + assertEq(Q, "fail"); + diff --git a/js/src/jit-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js new file mode 100644 index 00000000000..9267c99ccfa --- /dev/null +++ b/js/src/jit-test/tests/basic/bug522136.js @@ -0,0 +1,10 @@ +var Q = 0; +try { + (function f(i) { Q = i; if (i == 100000) return; f(i+1); })(1) +} catch (e) { +} + +// Exact behavior of recursion check depends on which JIT we use. +var ok = (Q == 3000 || Q == 3001); +assertEq(ok, true); + diff --git a/js/src/jit-test/tests/basic/bug528644.js b/js/src/jit-test/tests/basic/bug528644.js new file mode 100644 index 00000000000..260e0d99590 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug528644.js @@ -0,0 +1,16 @@ +// Don't crash + +function g(foo) { + for (a in foo) { + } +} + +var makegen = eval("\n\ + (function(b) {\n\ + var h = \n\ + eval(\"new function() { yield print(b) }\" ); \n\ + return h\n\ + })\n\ +"); + +g(makegen()); diff --git a/js/src/jit-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js new file mode 100644 index 00000000000..7a81feb1800 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug578041.js @@ -0,0 +1,3 @@ +__defineGetter__('x', Float32Array); +with(this) + x; diff --git a/js/src/jit-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js new file mode 100644 index 00000000000..ad7d4b47577 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug584565.js @@ -0,0 +1,10 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ +// Contributor: Luke Wagner + +var x, f; +for (var i = 0; i < 100; i++) { + f = function() {}; + f.foo; + x = f.length; +} diff --git a/js/src/jit-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js new file mode 100644 index 00000000000..1e0ac407321 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-named-names.js @@ -0,0 +1,17 @@ +var a = ['p', 'q', 'r', 's', 't']; +var o = {p:1, q:2, r:3, s:4, t:5}; +for (var i in o) { + delete o.p; + delete o.q; + delete o.r; + delete o.s; + delete o.t; +} +for each (var i in a) + assertEq(o.hasOwnProperty(i), false); + +checkStats({ + recorderAborted:0, + traceCompleted:1, + sideExitIntoInterpreter:1 +}); diff --git a/js/src/jit-test/tests/basic/jitstatsArchFlags.js b/js/src/jit-test/tests/basic/jitstatsArchFlags.js new file mode 100644 index 00000000000..a4ec0c4ee4b --- /dev/null +++ b/js/src/jit-test/tests/basic/jitstatsArchFlags.js @@ -0,0 +1,14 @@ +// Make sure the arch flags are valid on startup, even if nothing has +// been traced yet. We don't know what arch the user is building on, +// but presumably we want at least 1 flag to be set on all supported +// platforms. + +if (HAVE_TM) { + assertEq(jitstats.archIsIA32 || + jitstats.archIs64BIT || + jitstats.archIsARM || + jitstats.archIsSPARC || + jitstats.archIsPPC || + jitstats.archIsAMD64, + 1); + } diff --git a/js/src/jit-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js new file mode 100644 index 00000000000..c8ecb366556 --- /dev/null +++ b/js/src/jit-test/tests/basic/parseIntTests.js @@ -0,0 +1,23 @@ +function parseIntHelper(n) { + var a; + for (var i = 0; i < 5; i++) + a = parseInt(n); + return a; +} +function doParseIntTests() { + var inputs = [0, -0, .1, -.1, .7, -.7, 1.3, -1.3]; + var outputs = new Array(8); + //avoid jit, unrolled + outputs[0] = outputs[1] = outputs[2] = outputs[4] = 0; + outputs[3] = outputs[5] = -0; + outputs[6] = 1; + outputs[7] = -1; + for (var i = 0; i < 8; i++) { + var testfn = new Function('return parseIntHelper(' + uneval(inputs[i]) + ');'); + assertEq(testfn(), outputs[i]); + } +} +doParseIntTests(); + +assertEq(parseInt("08"), 0); +assertEq(parseInt("09"), 0); diff --git a/js/src/jit-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js new file mode 100644 index 00000000000..536d2d7dd0c --- /dev/null +++ b/js/src/jit-test/tests/basic/strictParseIntOctal.js @@ -0,0 +1,16 @@ +"use strict"; + +assertEq(parseInt("08"), 0); +assertEq(parseInt("09"), 0); +assertEq(parseInt("014"), 12); +assertEq(parseInt("0xA"), 10); +assertEq(parseInt("00123"), 83); + +for (var i = 0; i < 5; i++) +{ + assertEq(parseInt("08"), 0); + assertEq(parseInt("09"), 0); + assertEq(parseInt("014"), 12); + assertEq(parseInt("0xA"), 10); + assertEq(parseInt("00123"), 83); +} diff --git a/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js new file mode 100644 index 00000000000..1c59113482d --- /dev/null +++ b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js @@ -0,0 +1,10 @@ +var o = { + set x(v) { + return 42; + } +}; + +for (var i = 0; i < 10; ++i) { + var z = o.x = "choose me"; + assertEq(z, "choose me"); +} diff --git a/js/src/jit-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js new file mode 100644 index 00000000000..cd1e05cf77b --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug458838.js @@ -0,0 +1,19 @@ +var escape; +function testBug458838() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); +} +assertEq(testBug458838(), 10); +checkStats({ + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1 +}); diff --git a/js/src/jit-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js new file mode 100644 index 00000000000..73e2e3013fb --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520.js @@ -0,0 +1,11 @@ +function testBug504520() { + // A bug involving comparisons. + var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 1/0, 0]; + assertEq(arr.length > RUNLOOP, true); + + var s = ''; + for (var i = 0; i < arr.length; i++) + arr[i] >= 1/0 ? null : (s += i); + assertEq(s, '9'); +} +testBug504520(); diff --git a/js/src/jit-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js new file mode 100644 index 00000000000..0a63ebf4075 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug504520Harder.js @@ -0,0 +1,33 @@ +function testBug504520Harder() { + // test 1024 similar cases + var vals = [1/0, -1/0, 0, 0/0]; + var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; + for each (var x in vals) { + for each (var y in vals) { + for each (var op in ops) { + for each (var z in vals) { + // Assume eval is correct. This depends on the global + // Infinity property not having been reassigned. + var xz = eval(x + op + z); + var yz = eval(y + op + z); + + var arr = [x, x, x, x, x, x, x, x, x, y]; + assertEq(arr.length > RUNLOOP, true); + var expected = [xz, xz, xz, xz, xz, xz, xz, xz, xz, yz]; + + // ?: looks superfluous but that's what we're testing here + var fun = eval( + '(function (arr, results) {\n' + + ' for (let i = 0; i < arr.length; i++)\n' + + ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + + '});\n'); + var actual = []; + fun(arr, actual); + print(x, y, op, z); + assertEq("" + actual, "" + expected); + } + } + } + } +} +testBug504520Harder(); diff --git a/js/src/jit-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js new file mode 100644 index 00000000000..28782b665bb --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug552248.js @@ -0,0 +1,36 @@ +setDebug(true); +var a = new Array(); + +function i(save) { + var x = 9; + evalInFrame(0, "a.push(x)", save); + evalInFrame(1, "a.push(z)", save); + evalInFrame(2, "a.push(z)", save); + evalInFrame(3, "a.push(y)", save); + evalInFrame(4, "a.push(x)", save); +} + +function h() { + var z = 5; + evalInFrame(0, "a.push(z)"); + evalInFrame(1, "a.push(y)"); + evalInFrame(2, "a.push(x)"); + evalInFrame(0, "i(false)"); + evalInFrame(0, "a.push(z)", true); + evalInFrame(1, "a.push(y)", true); + evalInFrame(2, "a.push(x)", true); + evalInFrame(0, "i(true)", true); +} + +function g() { + var y = 4; + h(); +} + +function f() { + var x = 3; + g(); +} + +f(); +assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+''); diff --git a/js/src/jit-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js new file mode 100644 index 00000000000..5871c24d46e --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug579602.js @@ -0,0 +1,21 @@ +// don't panic + +f = function() { + x = yield +} +rv = f() +for (a in rv) (function() {}) +x = Proxy.create((function() { + return { + defineProperty: gc + } +})(), x) +with({ + d: (({ + x: Object.defineProperty(x, "", ({ + set: Array.e + })) + })) +}) {} + +// don't crash diff --git a/js/src/jit-test/tests/basic/testBug579646.js b/js/src/jit-test/tests/basic/testBug579646.js new file mode 100644 index 00000000000..d034410f9cc --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug579646.js @@ -0,0 +1,22 @@ +if (typeof gczeal != "function") + gczeal = function() {} + +for (a = 0; a < 9; a++) + for (b = 0; b < 1; b++) + for (c = 0; c < 2; c++) + gczeal(); + +for each(e in [NaN]) + for (d = 0; d < 1; d++) + z = 0; + +for (w in [0, 0]) + {} + +x = 0; + +for (e = 0; e < 3; e++) + for (f = 0; f < 4; f++) + x = -x + +// don't crash diff --git a/js/src/jit-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js new file mode 100644 index 00000000000..b6c9d8ab7fd --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug584650.js @@ -0,0 +1,9 @@ +if (typeof gczeal != "function") + gczeal = function() {} + +// don't crash +x = (evalcx('lazy')) +x.watch("", function () {}) +gczeal(1) +for (w in x) {} + diff --git a/js/src/jit-test/tests/basic/testBug597736.js b/js/src/jit-test/tests/basic/testBug597736.js new file mode 100644 index 00000000000..ded33842776 --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug597736.js @@ -0,0 +1,32 @@ +function leak_test() { + // Create a reference loop function->script->traceFragment->object->function + // that GC must be able to break. To embedd object into the fragment the + // code use prototype chain of depth 2 which caches obj.__proto__.__proto__ + // into the fragment. + + // To make sure that we have no references to the function f after this + // function returns due via the conservative scan of the native stack we + // loop here multiple times overwriting the stack and registers with new garabge. + for (var j = 0; j != 8; ++j) { + var f = Function("a", "var s = 0; for (var i = 0; i != 100; ++i) s += a.b; return s;"); + var c = {b: 1, f: f, leakDetection: makeFinalizeObserver()}; + f({ __proto__: { __proto__: c}}); + f = c = a = null; + gc(); + } +} + +function test() +{ + if (typeof finalizeCount != "function") + return; + + var base = finalizeCount(); + leak_test(); + gc(); + gc(); + var n = finalizeCount(); + assertEq(base + 4 < finalizeCount(), true, "Some finalizations must happen"); +} + +test(); diff --git a/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js new file mode 100644 index 00000000000..cc80e779c37 --- /dev/null +++ b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js @@ -0,0 +1,12 @@ +function testEliminatedGuardWithinAnchor() { + for (let i = 0; i < 5; ++i) { i / (i * i); } + return "ok"; +} + +assertEq(testEliminatedGuardWithinAnchor(), "ok"); + +if (HAVE_TM) { + checkStats({ + sideExitIntoInterpreter: (jitstats.archIsARM ? 1 : 3) + }); +} diff --git a/js/src/jit-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js new file mode 100644 index 00000000000..ba7a2c01e16 --- /dev/null +++ b/js/src/jit-test/tests/basic/testHoleInDenseArray.js @@ -0,0 +1,18 @@ +var s; + +function f(i) { + if (i > 4) /* side exit when arr[i] changes from bool to undefined (via a hole) */ + assertEq(s, undefined); + else + assertEq(s, false); + return 1; +} + +/* trailing 'true' ensures array has capacity >= 10 */ +var arr = [ false, false, false, false, false, , , , , , true ]; + +for (var i = 0; i < 10; ++i) { + (s = arr[i]) + f(i); +} + +checkStats({ traceTriggered: 2, sideExitIntoInterpreter: 2 }) diff --git a/js/src/jit-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js new file mode 100644 index 00000000000..712ef0c6529 --- /dev/null +++ b/js/src/jit-test/tests/basic/testIntOverflow.js @@ -0,0 +1,15 @@ +function testIntOverflow() { + // int32_max - 7 + var ival = 2147483647 - 7; + for (var i = 0; i < 30; i++) { + ival += 30; + } + return (ival < 2147483647); +} +assertEq(testIntOverflow(), false); +checkStats({ + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1, + traceTriggered: 1, +}); diff --git a/js/src/jit-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js new file mode 100644 index 00000000000..ebd6309bdf9 --- /dev/null +++ b/js/src/jit-test/tests/basic/testMethodInitSafety.js @@ -0,0 +1,14 @@ +function testMethodInitSafety() { + function f() { return 'fail'; } + function g() { return 'ok'; } + + var s; + var arr = [f, f, f, f, g]; + //assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < arr.length; i++) { + var x = {m: arr[i]}; + s = x.m(); + } + return s; +} +assertEq(testMethodInitSafety(), "ok"); diff --git a/js/src/jit-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js new file mode 100644 index 00000000000..1ce8259f2d4 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNativeArgsRooting.js @@ -0,0 +1,14 @@ +if ('gczeal' in this) +(function () { + (eval("\ + (function () {\ + for (var y = 0; y < 16; ++y) {\ + if (y % 3 == 2) {\ + gczeal(1);\ + } else {\ + print(0 / 0);\ + }\ + }\ + });\ + "))() +})(); diff --git a/js/src/jit-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js new file mode 100644 index 00000000000..8e59b04cdaa --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedDeepBail.js @@ -0,0 +1,20 @@ +var _quit; +function testNestedDeepBail() +{ + _quit = false; + function loop() { + for (var i = 0; i < 4; i++) + ; + } + loop(); + + function f() { + loop(); + _quit = true; + } + + var stk = [[1], [], [], [], []]; + while (!_quit) + stk.pop().forEach(f); +} +testNestedDeepBail(); diff --git a/js/src/jit-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js new file mode 100644 index 00000000000..88b795e7cbc --- /dev/null +++ b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js @@ -0,0 +1,29 @@ +// Test stack reconstruction after a nested exit +function testNestedExitStackInner(j, counter) { + ++counter; + var b = 0; + for (var i = 1; i <= RUNLOOP; i++) { + ++b; + var a; + // Make sure that once everything has been traced we suddenly switch to + // a different control flow the first time we run the outermost tree, + // triggering a side exit. + if (j < RUNLOOP) + a = 1; + else + a = 0; + ++b; + b += a; + } + return counter + b; +} +function testNestedExitStackOuter() { + var counter = 0; + for (var j = 1; j <= RUNLOOP; ++j) { + for (var k = 1; k <= RUNLOOP; ++k) { + counter = testNestedExitStackInner(j, counter); + } + } + return counter; +} +//assertEq(testNestedExitStackOuter(), 81); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js new file mode 100644 index 00000000000..cb7e6d9843c --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount.js @@ -0,0 +1,12 @@ +function testNewArrayCount() +{ + function count(a) { var n = 0; for (var p in a) n++; return n; } + var a = []; + for (var i = 0; i < 5; i++) + a = [0]; + assertEq(count(a), 1); + for (var i = 0; i < 5; i++) + a = [0, , 2]; + assertEq(count(a), 2); +} +testNewArrayCount(); diff --git a/js/src/jit-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js new file mode 100644 index 00000000000..6318e4c25f3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testNewArrayCount2.js @@ -0,0 +1,8 @@ +function testNewArrayCount2() { + function count(a) { var n = 0; for (var p in a) n++; return n; } + var x = 0; + for (var i = 0; i < 10; ++i) + x = count(new Array(1,2,3)); + return x; +} +assertEq(testNewArrayCount2(), 3); diff --git a/js/src/jit-test/tests/basic/testProxyConstructors.js b/js/src/jit-test/tests/basic/testProxyConstructors.js new file mode 100644 index 00000000000..e716b361ef0 --- /dev/null +++ b/js/src/jit-test/tests/basic/testProxyConstructors.js @@ -0,0 +1,9 @@ +// proxies can return primitives +assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined); + +x = Proxy.createFunction((function () {}), Uint16Array, wrap) +new(wrap(x)) + +// proxies can return the callee +var x = Proxy.createFunction({}, function (q) { return q; }); +new x(x); diff --git a/js/src/jit-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js new file mode 100644 index 00000000000..2bf26eeaff5 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRebranding2.js @@ -0,0 +1,21 @@ +delete q; +delete g; +delete h; +delete a; +delete f; + +function testRebranding2() { + // Same as testRebranding, but the object to be rebranded isn't the global. + var x = "FAIL"; + function g(){} + function h(){ x = "ok"; } + var obj = {m: g}; + var arr = [g, g, g, g, h]; + //assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < 5; i++) { + obj.m = arr[i]; + obj.m(); + } + return x; +} +assertEq(testRebranding2(), "ok"); diff --git a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js new file mode 100644 index 00000000000..2dc51508d4f --- /dev/null +++ b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js @@ -0,0 +1,28 @@ +x = Proxy.create((function () { + return { + get: function () {} + } +}()), Object.e) + +var hit = false; + +try { + Function("\ + for(var a = 0; a < 2; ++a) {\ + if (a == 0) {}\ + else {\ + x > x\ + }\ + }\ + ")() +} catch (e) { + hit = true; + + var str = String(e); + var match = (str == "TypeError: x is not a function" || + str == "TypeError: can't convert x to number"); + + assertEq(match, true); +} + +assertEq(hit, true); diff --git a/js/src/jit-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js new file mode 100644 index 00000000000..78917ba9be3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testRegExpTest.js @@ -0,0 +1,10 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +function testRegExpTest() { + var r = /abc/; + var flag = false; + for (var i = 0; i < 10; ++i) + flag = r.test("abc"); + return flag; +} +assertEq(testRegExpTest(), true); diff --git a/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js new file mode 100644 index 00000000000..14574b146bf --- /dev/null +++ b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js @@ -0,0 +1,11 @@ +var a = {_val: 'q', + get p() { return f; }}; + +function f() { return this._val; } + +var g = ''; +for (var i = 0; i < 9; i++) + g += a.p(); +assertEq(g, 'qqqqqqqqq'); + +checkStats({recorderStarted: 1, recorderAborted: 0, traceCompleted: 1, traceTriggered: 1}); diff --git a/js/src/jit-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js new file mode 100644 index 00000000000..4a7f5d98289 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftLeft.js @@ -0,0 +1,38 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +/* Test the proper operation of the left shift operator. This is especially + * important on ARM as an explicit mask is required at the native instruction + * level. */ + +load(libdir + 'range.js'); + +function testShiftLeft() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 256); + + return r.join(","); +} + +assertEq(testShiftLeft(), + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648"); diff --git a/js/src/jit-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js new file mode 100644 index 00000000000..7268dc0bad3 --- /dev/null +++ b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js @@ -0,0 +1,44 @@ +/* Test the proper operation of the arithmetic right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ + +load(libdir + 'range.js'); + +/* Test different combinations of literals/variables. */ +var s = 4; +var t = 100; +assertEq(42 >> s, 2); +assertEq(s >> 1, 2); +assertEq(23 >> 3, 2); +assertEq(t >> s, 6); + + +function testShiftRightArithmetic() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 256); + + return r.join(","); +} +assertEq(testShiftRightArithmetic(), + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"); diff --git a/js/src/jit-test/tests/basic/testSideExitInConstructor.js b/js/src/jit-test/tests/basic/testSideExitInConstructor.js new file mode 100644 index 00000000000..d46543ef7bd --- /dev/null +++ b/js/src/jit-test/tests/basic/testSideExitInConstructor.js @@ -0,0 +1,39 @@ +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind + +function testSideExitInConstructor() { + var FCKConfig = {}; + FCKConfig.CoreStyles = + { + 'Bold': { }, + 'Italic': { }, + 'FontFace': { }, + 'Size' : + { + Overrides: [ ] + }, + + 'Color' : + { + Element: '', + Styles: { }, + Overrides: [ ] + }, + 'BackColor': { + Element : '', + Styles : { 'background-color' : '' } + }, + + }; + var FCKStyle = function(A) { + A.Element; + }; + + var pass = true; + for (var s in FCKConfig.CoreStyles) { + var x = new FCKStyle(FCKConfig.CoreStyles[s]); + if (!x) + pass = false; + } + return pass; +} +assertEq(testSideExitInConstructor(), true); diff --git a/js/src/jit-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js new file mode 100644 index 00000000000..f7a1443a71a --- /dev/null +++ b/js/src/jit-test/tests/basic/testSlowNativeBail.js @@ -0,0 +1,10 @@ +function testSlowNativeBail() { + var a = ['0', '1', '2', '3', '+']; + try { + for (var i = 0; i < a.length; i++) + new RegExp(a[i]); + } catch (exc) { + assertEq(""+exc, "SyntaxError: invalid quantifier"); + } +} +testSlowNativeBail(); diff --git a/js/src/jit-test/tests/basic/testStackQuotaExhausted.js b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js new file mode 100644 index 00000000000..f65957a74b7 --- /dev/null +++ b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js @@ -0,0 +1,29 @@ +const numFatArgs = Math.pow(2,19) - 1024; + +function fun(x) { + if (x <= 0) + return 0; + return fun(x-1); +} + +function fatStack() { + return fun(10000); +} + +function assertRightFailure(e) { + assertEq(e.toString() == "InternalError: script stack space quota is exhausted" || + e.toString() == "InternalError: too much recursion", + true); +} + +exception = false; +try { + fatStack.apply(null, new Array(numFatArgs)); +} catch (e) { + assertRightFailure(e); + exception = true; +} +assertEq(exception, true); + +// No more trace recursion w/ JM +checkStats({traceCompleted:0}); diff --git a/js/src/jit-test/tests/closures/bug540136.js b/js/src/jit-test/tests/closures/bug540136.js new file mode 100644 index 00000000000..54b57713a7f --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540136.js @@ -0,0 +1,17 @@ +// |jit-test| error: TypeError + +(eval("\ + (function () {\ + for (var[x] = function(){} in \ + (function m(a) {\ + if (a < 1) {\ + x;\ + return\ + }\ + return m(a - 1) + m(a - 2)\ + })(7)\ + (eval(\"\"))\ + )\ + ([])\ + })\ +"))() diff --git a/js/src/jit-test/tests/closures/bug540242.js b/js/src/jit-test/tests/closures/bug540242.js new file mode 100644 index 00000000000..56c1a5a3143 --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540242.js @@ -0,0 +1,17 @@ +for (j = 0; j < 1; j++) { + var f = eval("\ + (function() {\ + for (var a = 0; a < 8; ++a) {\ + if (a % 3 == 2) {\ + eval(\"\ + for(b in[0,0,0,0]) {\ + print()\ + }\ + \")\ + }\ + gc()\ + }\ + })\ + "); + f() +} diff --git a/js/src/jit-test/tests/closures/bug540243.js b/js/src/jit-test/tests/closures/bug540243.js new file mode 100644 index 00000000000..07faa26b6e7 --- /dev/null +++ b/js/src/jit-test/tests/closures/bug540243.js @@ -0,0 +1,10 @@ +for (a in (eval("\ + (function() {\ + return function() {\ + yield ((function() {\ + return d\ + })())\ + } ();\ + var d = []\ + })\ +"))()); diff --git a/js/src/jit-test/tests/closures/bug541239.js b/js/src/jit-test/tests/closures/bug541239.js new file mode 100644 index 00000000000..32e3af1565b --- /dev/null +++ b/js/src/jit-test/tests/closures/bug541239.js @@ -0,0 +1,16 @@ +function m() { + var d = 73; + + return (eval("\n\ + (function() {\n\ + return function() {\n\ + yield ((function() {\n\ + print(d);\n\ + return d\n\ + })())\n\ + } ();\n\ + })\n\ + "))(); +} + +m().next(); diff --git a/js/src/jit-test/tests/closures/lambda.js b/js/src/jit-test/tests/closures/lambda.js new file mode 100644 index 00000000000..fd7cbd16ed7 --- /dev/null +++ b/js/src/jit-test/tests/closures/lambda.js @@ -0,0 +1,27 @@ +function f() { + var k = 0; + + var g = function() { + return ++k; + } + + return g; +} + +function h() { + for (var i = 0; i < 10; ++i) { + var vf = f(); + assertEq(vf(), 1); + assertEq(vf(), 2); + for (var j = 0; j < 10; ++j) { + assertEq(vf(), j + 3); + } + } +} + +h(); + +checkStats({ + recorderAborted: 8, // Inner tree is trying to grow +}); + diff --git a/js/src/jit-test/tests/closures/setname-inner-heavy.js b/js/src/jit-test/tests/closures/setname-inner-heavy.js new file mode 100644 index 00000000000..9c1919dc2f3 --- /dev/null +++ b/js/src/jit-test/tests/closures/setname-inner-heavy.js @@ -0,0 +1,18 @@ +actual = ''; +expected = 'undefined,'; + +function f() { + (eval("\ + (function () {\ + for (var z = 0; z < 2; ++z) {\ + x = ''\ + }\ + })\ + "))(); +} +__defineSetter__("x", eval) +f() +appendToActual(x); + + +assertEq(actual, expected) diff --git a/js/src/jit-test/tests/jaeger/bug554580-5.js b/js/src/jit-test/tests/jaeger/bug554580-5.js new file mode 100644 index 00000000000..1d3ee522b07 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug554580-5.js @@ -0,0 +1,20 @@ +(function() { + (function g(m, n) { + if (m = n) { + return eval("x=this") + } + g(m, 1)[[]] + })() +})() +Function("\ + for (let b in [0]) {\ + for (var k = 0; k < 6; ++k) {\ + if (k == 1) {\ + print(x)\ + }\ + }\ + }\ +")() + +/* Don't crash/assert. */ + diff --git a/js/src/jit-test/tests/jaeger/bug555155.js b/js/src/jit-test/tests/jaeger/bug555155.js new file mode 100644 index 00000000000..db7b57aa1bc --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug555155.js @@ -0,0 +1,12 @@ +// |jit-test| error: undefined +(function() { + throw (function f(a, b) { + if (a.h == b) { + return eval("((function(){return 1})())!=this") + } + f(b) + })([], 0) +})() + +/* Don't assert/crash. */ + diff --git a/js/src/jit-test/tests/jaeger/bug555543.js b/js/src/jit-test/tests/jaeger/bug555543.js new file mode 100644 index 00000000000..b641c1b5832 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug555543.js @@ -0,0 +1,8 @@ +(function() { + for each(let z in [new String(''), new String('q'), new String('')]) { + if (uneval() < z) (function(){}) + } +})() + +/* Don't assert/crash. */ + diff --git a/js/src/jit-test/tests/jaeger/bug556525.js b/js/src/jit-test/tests/jaeger/bug556525.js new file mode 100644 index 00000000000..0b59f3274b0 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug556525.js @@ -0,0 +1,5 @@ +for each(x in [new Number]) + x.__proto__ = [] +++x[x] + +// don't assert diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js new file mode 100644 index 00000000000..2cde4fde8a9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js @@ -0,0 +1,9 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + return x; +} +trap(caller, 7, "var x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js new file mode 100644 index 00000000000..11f2ff0a659 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js @@ -0,0 +1,10 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + var x = ({ dana : "zuul" }); + return x; +} +trap(caller, 23, "x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js new file mode 100644 index 00000000000..9eeb76d07eb --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js @@ -0,0 +1,10 @@ +setDebug(true); + +function nop(){} +function caller(obj) { + assertJit(); + var x = "failure"; + return x; +} +trap(caller, 14, "x = 'success'; nop()"); +assertEq(caller(this), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js new file mode 100644 index 00000000000..266db65090d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js @@ -0,0 +1,9 @@ +setDebug(true); +var x = "failure"; +function main() { x = "success"; } + +/* The JSOP_STOP in a. */ +trap(main, 8, ""); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js new file mode 100644 index 00000000000..db7e4b82b2a --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js @@ -0,0 +1,10 @@ +setDebug(true); +var x = "notset"; +function main() { x = "failure"; } +function success() { x = "success"; } + +/* The JSOP_STOP in a. */ +trap(main, 7, "success()"); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js new file mode 100644 index 00000000000..2f89f58bc3d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js @@ -0,0 +1,11 @@ +setDebug(true); +var x = "notset"; +function main() { x = "success"; } +function failure() { x = "failure"; } + +/* The JSOP_STOP in a. */ +trap(main, 8, "failure()"); +untrap(main, 8); +main(); + +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js new file mode 100644 index 00000000000..1d19aeebeb1 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js @@ -0,0 +1,7 @@ +setDebug(true); +function main() { + return "failure"; +} +/* JSOP_RETURN in main. */ +trap(main, 3, "'success'"); +assertEq(main(), "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js new file mode 100644 index 00000000000..b2b516826a9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js @@ -0,0 +1,7 @@ +setDebug(true); +function main() { + return 1; +} +/* JSOP_RETURN in main. */ +trap(main, 1, "0"); +assertEq(main(), 0); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js new file mode 100644 index 00000000000..18378b7808f --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js @@ -0,0 +1,15 @@ +setDebug(true); +x = "notset"; +function myparent(nested) { + if (nested) { + /* myparent call in myparent. */ + trap(myparent, 39, "failure()"); + } else { + x = "success"; + myparent(true); + } +} +function failure() { x = "failure"; } + +myparent(false); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js new file mode 100644 index 00000000000..d6ded288128 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js @@ -0,0 +1,21 @@ +setDebug(true); +x = "notset"; + +function child() { + x = "failure1"; + /* JSOP_STOP in parent. */ + trap(parent, 10, "success()"); +} + +function parent() { + x = "failure2"; +} +/* First op in parent. */ +trap(parent, 0, "child()"); + +function success() { + x = "success"; +} + +parent(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js new file mode 100644 index 00000000000..2209f946af9 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js @@ -0,0 +1,16 @@ +setDebug(true); +x = "notset"; +function child() { + /* JSOP_STOP in parent. */ + trap(parent, 17, "success()"); +} +function parent() { + child(); + x = "failure"; +} +function success() { + x = "success"; +} + +parent() +assertEq(x, "success"); diff --git 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 new file mode 100644 index 00000000000..65d3e73135e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js @@ -0,0 +1,18 @@ +setDebug(true); +x = "notset"; + +function myparent(nested) { + if (nested) { + /* noop call in myparent */ + trap(myparent, 50, "success()"); + } else { + myparent(true); + x = "failure"; + noop(); + } +} +function noop() { } +function success() { x = "success"; } + +myparent(); +assertEq(x, "success"); diff --git 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 new file mode 100644 index 00000000000..8a9caaaafda --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js @@ -0,0 +1,23 @@ +setDebug(true); +x = "notset"; + +function doNothing() { } + +function myparent(nested) { + if (nested) { + /* JSOP_CALL to doNothing in myparent with nested = true. */ + trap(myparent, 24, "success()"); + doNothing(); + } else { + doNothing(); + } +} +/* JSOP_CALL to doNothing in myparent with nested = false. */ +trap(myparent, 35, "myparent(true)"); + +function success() { + x = "success"; +} + +myparent(false); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js new file mode 100644 index 00000000000..9b94fd1c8cc --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js @@ -0,0 +1,11 @@ +setDebug(true); +x = "notset"; +function main() { + /* The JSOP_STOP in a. */ + trap(main, 25, "success()"); + x = "failure"; +} +function success() { x = "success"; } + +main(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js new file mode 100644 index 00000000000..e4dd9d7dc97 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js @@ -0,0 +1,15 @@ +setDebug(true); +x = "notset"; +function child() { + /* JSOP_STOP in parent */ + untrap(parent, 10); + x = "success"; +} +function parent() { + x = "failure"; +} +/* JSOP_STOP in parent */ +trap(parent, 10, "child()"); + +parent(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js new file mode 100644 index 00000000000..4c18db52e8e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js @@ -0,0 +1,13 @@ +setDebug(true); +x = "notset"; +function main() { + /* JSOP_STOP in main. */ + untrap(main, 23); + x = "success"; +} +function failure() { x = "failure"; } + +/* JSOP_STOP in main. */ +trap(main, 23, "failure()"); +main(); +assertEq(x, "success"); diff --git a/js/src/jit-test/tests/jaeger/bug573433.js b/js/src/jit-test/tests/jaeger/bug573433.js new file mode 100644 index 00000000000..aa39022bb74 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug573433.js @@ -0,0 +1,7 @@ +// |jit-test| error: TypeError +function f() { + eval("(function() \n{\nfor(x in[])\n{}\n})"); + ("")() +} +f() + diff --git a/js/src/jit-test/tests/jaeger/bug580884.js b/js/src/jit-test/tests/jaeger/bug580884.js new file mode 100644 index 00000000000..b7a26f70566 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug580884.js @@ -0,0 +1,8 @@ +// |jit-test| error: ReferenceError +for (let a in [0]) +a = e +for (let a in [0]) +(function () { + a +}) + diff --git a/js/src/jit-test/tests/jaeger/bug582286.js b/js/src/jit-test/tests/jaeger/bug582286.js new file mode 100644 index 00000000000..094366a3c79 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug582286.js @@ -0,0 +1,3 @@ +evalcx("function s(){}",evalcx('lazy')) + + diff --git a/js/src/jit-test/tests/jaeger/bug583158.js b/js/src/jit-test/tests/jaeger/bug583158.js new file mode 100644 index 00000000000..6d8c124487d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug583158.js @@ -0,0 +1,9 @@ +// |jit-test| error: ReferenceError +function g() { + var rv = (function() { + this << 1 + })() + if (a) (function() {}) +} +g() + diff --git a/js/src/jit-test/tests/jaeger/bug585341.js b/js/src/jit-test/tests/jaeger/bug585341.js new file mode 100644 index 00000000000..fb96b92c3c3 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug585341.js @@ -0,0 +1,6 @@ +__defineGetter__("x", Float64Array) +Function("\ + with(this) {\ + eval(\"x\")\ + }\ +")() diff --git a/js/src/jit-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js new file mode 100644 index 00000000000..65c30952077 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug588338.js @@ -0,0 +1,14 @@ +// |jit-test| error: is not a function +function f() { (e) +} (x = Proxy.createFunction((function(x) { + return { + get: function(r, b) { + return x[b] + } + } +})(/x/), wrap)) +for (z = 0; z < 100; x.unwatch(), z++) +for (e in [0]) { + gczeal(2) +} ( )("") + diff --git a/js/src/jit-test/tests/jaeger/bug588363-2.js b/js/src/jit-test/tests/jaeger/bug588363-2.js new file mode 100644 index 00000000000..5550be3ea8d --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug588363-2.js @@ -0,0 +1,7 @@ +with(evalcx('')) { + delete eval; + eval("x", this.__defineGetter__("x", Function)); +} + +/* Don't assert or crash. */ + diff --git a/js/src/jit-test/tests/jaeger/crash-on-compare.js b/js/src/jit-test/tests/jaeger/crash-on-compare.js new file mode 100644 index 00000000000..5abd7aa045e --- /dev/null +++ b/js/src/jit-test/tests/jaeger/crash-on-compare.js @@ -0,0 +1 @@ +assertEq(Infinity >= Infinity ? true : false, true); diff --git a/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js new file mode 100644 index 00000000000..b5d2bf2f61b --- /dev/null +++ b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js @@ -0,0 +1,6 @@ +function ack(m,n){ + if (m==0) { return n+1; } + if (n==0) { return ack(m-1,1); } + return ack(m-1, ack(m,n-1) ); +} +assertEq(ack(3, 3), 61); diff --git a/js/src/jit-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js new file mode 100644 index 00000000000..5d8c68fa590 --- /dev/null +++ b/js/src/jit-test/tests/pic/bug558099.js @@ -0,0 +1,60 @@ +(function()[function() function() function() function() function() function() {}]); +foo = [{ + text: "(function(){if(d){(1)}})", + s: function() {}, + test: function() { + try { + f + } catch(e) {} + } +}, +{ + text: "(function(){t})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){if(0){}})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){if(1){}(2)})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){g})", + b: function() {}, + test: function() {} +}, +{ + text: "(function(){})", + s: function() {}, + test: function() {} +}, +{ + text: "(function(){1})", + s: function() {}, + test: function() {} +}]; (function() { + for (i = 0; i < foo.length; ++i) { + a = foo[i] + text = a.text + eval(text.replace(/@/, "")); + if (a.test()) {} + } +} ()); +s = [function() function() function() function() function() function() {}] +[function() function() function() function() {}]; +(function() { [function() function() {}] }); +(function() {}); +(eval("\ + (function(){\ + for each(d in[\ + 0,0,0,0,0,0,0,0,0,0,0,0,0,null,NaN,1,Boolean(false),Boolean(false)\ + ]){\ + [].filter(new Function,gczeal(2))\ + }\ + })\ +"))(); diff --git a/js/src/jit-test/tests/sunspider/check-date-format-xparb.js b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js new file mode 100644 index 00000000000..41f44fed50c --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2004 Baron Schwartz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, version 2.1. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ + +Date.parseFunctions = {count:0}; +Date.parseRegexes = []; +Date.formatFunctions = {count:0}; + +Date.prototype.dateFormat = function(format) { + if (Date.formatFunctions[format] == null) { + Date.createNewFormat(format); + } + var func = Date.formatFunctions[format]; + return this[func](); +} + +Date.createNewFormat = function(format) { + var funcName = "format" + Date.formatFunctions.count++; + Date.formatFunctions[format] = funcName; + var code = "Date.prototype." + funcName + " = function(){return "; + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + code += "'" + String.escape(ch) + "' + "; + } + else { + code += Date.getFormatCode(ch); + } + } + eval(code.substring(0, code.length - 3) + ";}"); +} + +Date.getFormatCode = function(character) { + switch (character) { + case "d": + return "String.leftPad(this.getDate(), 2, '0') + "; + case "D": + return "Date.dayNames[this.getDay()].substring(0, 3) + "; + case "j": + return "this.getDate() + "; + case "l": + return "Date.dayNames[this.getDay()] + "; + case "S": + return "this.getSuffix() + "; + case "w": + return "this.getDay() + "; + case "z": + return "this.getDayOfYear() + "; + case "W": + return "this.getWeekOfYear() + "; + case "F": + return "Date.monthNames[this.getMonth()] + "; + case "m": + return "String.leftPad(this.getMonth() + 1, 2, '0') + "; + case "M": + return "Date.monthNames[this.getMonth()].substring(0, 3) + "; + case "n": + return "(this.getMonth() + 1) + "; + case "t": + return "this.getDaysInMonth() + "; + case "L": + return "(this.isLeapYear() ? 1 : 0) + "; + case "Y": + return "this.getFullYear() + "; + case "y": + return "('' + this.getFullYear()).substring(2, 4) + "; + case "a": + return "(this.getHours() < 12 ? 'am' : 'pm') + "; + case "A": + return "(this.getHours() < 12 ? 'AM' : 'PM') + "; + case "g": + return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; + case "G": + return "this.getHours() + "; + case "h": + return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; + case "H": + return "String.leftPad(this.getHours(), 2, '0') + "; + case "i": + return "String.leftPad(this.getMinutes(), 2, '0') + "; + case "s": + return "String.leftPad(this.getSeconds(), 2, '0') + "; + case "O": + return "this.getGMTOffset() + "; + case "T": + return "this.getTimezone() + "; + case "Z": + return "(this.getTimezoneOffset() * -60) + "; + default: + return "'" + String.escape(character) + "' + "; + } +} + +Date.parseDate = function(input, format) { + if (Date.parseFunctions[format] == null) { + Date.createParser(format); + } + var func = Date.parseFunctions[format]; + return Date[func](input); +} + +Date.createParser = function(format) { + var funcName = "parse" + Date.parseFunctions.count++; + var regexNum = Date.parseRegexes.length; + var currentGroup = 1; + Date.parseFunctions[format] = funcName; + + var code = "Date." + funcName + " = function(input){\n" + + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" + + "var d = new Date();\n" + + "y = d.getFullYear();\n" + + "m = d.getMonth();\n" + + "d = d.getDate();\n" + + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" + + "if (results && results.length > 0) {" + var regex = ""; + + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + regex += String.escape(ch); + } + else { + obj = Date.formatCodeToRegex(ch, currentGroup); + currentGroup += obj.g; + regex += obj.s; + if (obj.g && obj.c) { + code += obj.c; + } + } + } + + code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" + + "{return new Date(y, m, d, h, i, s);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" + + "{return new Date(y, m, d, h, i);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" + + "{return new Date(y, m, d, h);}\n" + + "else if (y > 0 && m >= 0 && d > 0)\n" + + "{return new Date(y, m, d);}\n" + + "else if (y > 0 && m >= 0)\n" + + "{return new Date(y, m);}\n" + + "else if (y > 0)\n" + + "{return new Date(y);}\n" + + "}return null;}"; + + Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); + eval(code); +} + +Date.formatCodeToRegex = function(character, currentGroup) { + switch (character) { + case "D": + return {g:0, + c:null, + s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; + case "j": + case "d": + return {g:1, + c:"d = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "l": + return {g:0, + c:null, + s:"(?:" + Date.dayNames.join("|") + ")"}; + case "S": + return {g:0, + c:null, + s:"(?:st|nd|rd|th)"}; + case "w": + return {g:0, + c:null, + s:"\\d"}; + case "z": + return {g:0, + c:null, + s:"(?:\\d{1,3})"}; + case "W": + return {g:0, + c:null, + s:"(?:\\d{2})"}; + case "F": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", + s:"(" + Date.monthNames.join("|") + ")"}; + case "M": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", + s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; + case "n": + case "m": + return {g:1, + c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", + s:"(\\d{1,2})"}; + case "t": + return {g:0, + c:null, + s:"\\d{1,2}"}; + case "L": + return {g:0, + c:null, + s:"(?:1|0)"}; + case "Y": + return {g:1, + c:"y = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{4})"}; + case "y": + return {g:1, + c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" + + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", + s:"(\\d{1,2})"}; + case "a": + return {g:1, + c:"if (results[" + currentGroup + "] == 'am') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(am|pm)"}; + case "A": + return {g:1, + c:"if (results[" + currentGroup + "] == 'AM') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(AM|PM)"}; + case "g": + case "G": + case "h": + case "H": + return {g:1, + c:"h = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "i": + return {g:1, + c:"i = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "s": + return {g:1, + c:"s = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "O": + return {g:0, + c:null, + s:"[+-]\\d{4}"}; + case "T": + return {g:0, + c:null, + s:"[A-Z]{3}"}; + case "Z": + return {g:0, + c:null, + s:"[+-]\\d{1,5}"}; + default: + return {g:0, + c:null, + s:String.escape(character)}; + } +} + +Date.prototype.getTimezone = function() { + return this.toString().replace( + /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( + /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); +} + +Date.prototype.getGMTOffset = function() { + return (this.getTimezoneOffset() > 0 ? "-" : "+") + + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") + + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); +} + +Date.prototype.getDayOfYear = function() { + var num = 0; + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + for (var i = 0; i < this.getMonth(); ++i) { + num += Date.daysInMonth[i]; + } + return num + this.getDate() - 1; +} + +Date.prototype.getWeekOfYear = function() { + // Skip to Thursday of this week + var now = this.getDayOfYear() + (4 - this.getDay()); + // Find the first Thursday of the year + var jan1 = new Date(this.getFullYear(), 0, 1); + var then = (7 - jan1.getDay() + 4); + document.write(then); + return String.leftPad(((now - then) / 7) + 1, 2, "0"); +} + +Date.prototype.isLeapYear = function() { + var year = this.getFullYear(); + return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); +} + +Date.prototype.getFirstDayOfMonth = function() { + var day = (this.getDay() - (this.getDate() - 1)) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getLastDayOfMonth = function() { + var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getDaysInMonth = function() { + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + return Date.daysInMonth[this.getMonth()]; +} + +Date.prototype.getSuffix = function() { + switch (this.getDate()) { + case 1: + case 21: + case 31: + return "st"; + case 2: + case 22: + return "nd"; + case 3: + case 23: + return "rd"; + default: + return "th"; + } +} + +String.escape = function(string) { + return string.replace(/('|\\)/g, "\\$1"); +} + +String.leftPad = function (val, size, ch) { + var result = new String(val); + if (ch == null) { + ch = " "; + } + while (result.length < size) { + result = ch + result; + } + return result; +} + +Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; +Date.monthNames = + ["January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"]; +Date.dayNames = + ["Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday"]; +Date.y2kYear = 50; +Date.monthNumbers = { + Jan:0, + Feb:1, + Mar:2, + Apr:3, + May:4, + Jun:5, + Jul:6, + Aug:7, + Sep:8, + Oct:9, + Nov:10, + Dec:11}; +Date.patterns = { + ISO8601LongPattern:"Y-m-d H:i:s", + ISO8601ShortPattern:"Y-m-d", + ShortDatePattern: "n/j/Y", + LongDatePattern: "l, F d, Y", + FullDateTimePattern: "l, F d, Y g:i:s A", + MonthDayPattern: "F d", + ShortTimePattern: "g:i A", + LongTimePattern: "g:i:s A", + SortableDateTimePattern: "Y-m-d\\TH:i:s", + UniversalSortableDateTimePattern: "Y-m-d H:i:sO", + YearMonthPattern: "F, Y"}; + +var date = new Date("1/1/2007 1:11:11"); + +var ret; +for (i = 0; i < 4000; ++i) { + var shortFormat = date.dateFormat("Y-m-d"); + var longFormat = date.dateFormat("l, F d, Y g:i:s A"); + ret = shortFormat + longFormat; + date.setTime(date.getTime() + 84266956); +} + +// No exact match because the output depends on the locale's time zone. See bug 524490. +assertEq(/^2017-09-05Tuesday, September 05, 2017 [0-9:]* AM$/.exec(ret) != null, true); diff --git a/js/src/jit-test/tests/sunspider/check-math-partial-sums.js b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js new file mode 100644 index 00000000000..a9082702ccf --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js @@ -0,0 +1,41 @@ +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// contributed by Isaac Gouy + +function partial(n){ + var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; + var twothirds = 2.0/3.0; + var alt = -1.0; + var k2 = k3 = sk = ck = 0.0; + + for (var k = 1; k <= n; k++){ + k2 = k*k; + k3 = k2*k; + sk = Math.sin(k); + ck = Math.cos(k); + alt = -alt; + + a1 += Math.pow(twothirds,k-1); + a2 += Math.pow(k,-0.5); + a3 += 1.0/(k*(k+1.0)); + a4 += 1.0/(k3 * sk*sk); + a5 += 1.0/(k3 * ck*ck); + a6 += 1.0/k; + a7 += 1.0/k2; + a8 += alt/k; + a9 += alt/(2*k -1); + } + + return [ a1, a2, a3, a4, a5, a6, a7, a8, a9 ]; +} + +var actual = []; +for (var i = 1024; i <= 16384; i *= 2) + Array.prototype.push.apply(actual, partial(i)); + +var eps = 1e-12; +var expect = [2.9999999999999987,62.555269219624684,0.9990243902439033,30.174793391263677,42.99468748637077,7.509175672278132,1.6439579810301654,0.6926591377284127,0.785154022830656,2.9999999999999987,89.06036157695789,0.9995119570522216,30.30796333494624,42.99485339033617,8.202078771817716,1.6444459047881168,0.6929030995395857,0.7852760930922243,2.9999999999999987,126.54745783224483,0.999755918965097,30.314167756318135,42.994888939123,8.89510389696629,1.6446899560231332,0.6930251251486118,0.7853371282421086,2.9999999999999987,179.56450569047874,0.9998779445868421,30.314499725429847,42.99489723774016,9.588190046095265,1.644812003986005,0.693086149128997,0.785367645819433,2.9999999999999987,254.54355172132264,0.9999389685688135,30.31451920492601,42.99489939769195,10.281306710008463,1.6448730335545856,0.6931166639131536,0.7853829046083998]; + +assertEq(actual.length, expect.length); +for (var i = 0; i < expect.length; ++i) + assertEq(Math.abs(actual[i] - expect[i]) < eps, true); diff --git a/js/src/jit-test/tests/sunspider/check-string-tagcloud.js b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js new file mode 100644 index 00000000000..f446e46ed5c --- /dev/null +++ b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js @@ -0,0 +1,270 @@ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + Portions from: + json.js + 2007-10-10 + + Public Domain +*/ + +// This test parses a JSON string giving tag names and popularity, and +// generates html markup for a "tagcloud" view. + +if (!Object.prototype.toJSONString) { + + Array.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + i, // Loop counter. + l = this.length, + v; // The value to be stringified. + + for (i = 0; i < l; i += 1) { + v = this[i]; + switch (typeof v) { + case 'object': + + if (v && typeof v.toJSONString === 'function') { + a.push(v.toJSONString(w)); + } else { + a.push('null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(v.toJSONString()); + break; + default: + a.push('null'); + } + } + + return '[' + a.join(',') + ']'; + }; + + + Boolean.prototype.toJSONString = function () { + return String(this); + }; + + + Date.prototype.toJSONString = function () { + + function f(n) { + + return n < 10 ? '0' + n : n; + } + + return '"' + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z"'; + }; + + + Number.prototype.toJSONString = function () { + + return isFinite(this) ? String(this) : 'null'; + }; + + + Object.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + k, // The current key. + i, // The loop counter. + v; // The current value. + + if (w) { + for (i = 0; i < w.length; i += 1) { + k = w[i]; + if (typeof k === 'string') { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString(w)); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } else { + + for (k in this) { + if (typeof k === 'string' && + Object.prototype.hasOwnProperty.apply(this, [k])) { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString()); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } + + return '{' + a.join(',') + '}'; + }; + + + (function (s) { + + var m = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }; + + + s.parseJSON = function (filter) { + var j; + + function walk(k, v) { + var i, n; + if (v && typeof v === 'object') { + for (i in v) { + if (Object.prototype.hasOwnProperty.apply(v, [i])) { + n = walk(i, v[i]); + if (n !== undefined) { + v[i] = n; + } + } + } + } + return filter(k, v); + } + + if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + j = eval('(' + this + ')'); + + return typeof filter === 'function' ? walk('', j) : j; + } + + throw new SyntaxError('parseJSON'); + }; + + + s.toJSONString = function () { + + if (/["\\\x00-\x1f]/.test(this)) { + return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) { + var c = m[a]; + if (c) { + return c; + } + c = a.charCodeAt(); + return '\\u00' + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }) + '"'; + } + return '"' + this + '"'; + }; + })(String.prototype); +} + +var tagInfoJSON = '[\n {\n \"tag\": "titillation",\n \"popularity\": 4294967296\n },\n {\n \"tag\": "foamless",\n \"popularity\": 1257718401\n },\n {\n \"tag\": "snarler",\n \"popularity\": 613166183\n },\n {\n \"tag\": "multangularness",\n \"popularity\": 368304452\n },\n {\n \"tag\": "Fesapo unventurous",\n \"popularity\": 248026512\n },\n {\n \"tag\": "esthesioblast",\n \"popularity\": 179556755\n },\n {\n \"tag\": "echeneidoid",\n \"popularity\": 136641578\n },\n {\n \"tag\": "embryoctony",\n \"popularity\": 107852576\n },\n {\n \"tag\": "undilatory",\n \"popularity\": 87537981\n },\n {\n \"tag\": "predisregard",\n \"popularity\": 72630939\n },\n {\n \"tag\": "allergenic",\n \"popularity\": 61345190\n },\n {\n \"tag\": "uncloudy",\n \"popularity\": 52580571\n },\n {\n \"tag\": "unforeseeably",\n \"popularity\": 45628109\n },\n {\n \"tag\": "sturniform",\n \"popularity\": 40013489\n },\n {\n \"tag\": "anesthetize",\n \"popularity\": 35409226\n },\n {\n \"tag\": "ametabolia",\n \"popularity\": 31583050\n },\n {\n \"tag\": "angiopathy",\n \"popularity\": 28366350\n },\n {\n \"tag\": "sultanaship",\n \"popularity\": 25634218\n },\n {\n \"tag\": "Frenchwise",\n \"popularity\": 23292461\n },\n {\n \"tag\": "cerviconasal",\n \"popularity\": 21268909\n },\n {\n \"tag\": "mercurialness",\n \"popularity\": 19507481\n },\n {\n \"tag\": "glutelin venditate",\n \"popularity\": 17964042\n },\n {\n \"tag\": "acred overblack",\n \"popularity\": 16603454\n },\n {\n \"tag\": "Atik",\n \"popularity\": 15397451\n },\n {\n \"tag\": "puncturer",\n \"popularity\": 14323077\n },\n {\n \"tag\": "pukatea",\n \"popularity\": 13361525\n },\n {\n \"tag\": "suberize",\n \"popularity\": 12497261\n },\n {\n \"tag\": "Godfrey",\n \"popularity\": 11717365\n },\n {\n \"tag\": "tetraptote",\n \"popularity\": 11011011\n },\n {\n \"tag\": "lucidness",\n \"popularity\": 10369074\n },\n {\n \"tag\": "tartness",\n \"popularity\": 9783815\n },\n {\n \"tag\": "axfetch",\n \"popularity\": 9248634\n },\n {\n \"tag\": "preacquittal",\n \"popularity\": 8757877\n },\n {\n \"tag\": "matris",\n \"popularity\": 8306671\n },\n {\n \"tag\": "hyphenate",\n \"popularity\": 7890801\n },\n {\n \"tag\": "semifabulous",\n \"popularity\": 7506606\n },\n {\n \"tag\": "oppressiveness",\n \"popularity\": 7150890\n },\n {\n \"tag\": "Protococcales",\n \"popularity\": 6820856\n },\n {\n \"tag\": "unpreventive",\n \"popularity\": 6514045\n },\n {\n \"tag\": "Cordia",\n \"popularity\": 6228289\n },\n {\n \"tag\": "Wakamba leaflike",\n \"popularity\": 5961668\n },\n {\n \"tag\": "dacryoma",\n \"popularity\": 5712480\n },\n {\n \"tag\": "inguinal",\n \"popularity\": 5479211\n },\n {\n \"tag\": "responseless",\n \"popularity\": 5260507\n },\n {\n \"tag\": "supplementarily",\n \"popularity\": 5055158\n },\n {\n \"tag\": "emu",\n \"popularity\": 4862079\n },\n {\n \"tag\": "countermeet",\n \"popularity\": 4680292\n },\n {\n \"tag\": "purrer",\n \"popularity\": 4508918\n },\n {\n \"tag\": "Corallinaceae",\n \"popularity\": 4347162\n },\n {\n \"tag\": "speculum",\n \"popularity\": 4194304\n },\n {\n \"tag\": "crimpness",\n \"popularity\": 4049690\n },\n {\n \"tag\": "antidetonant",\n \"popularity\": 3912727\n },\n {\n \"tag\": "topeewallah",\n \"popularity\": 3782875\n },\n {\n \"tag\": "fidalgo ballant",\n \"popularity\": 3659640\n },\n {\n \"tag\": "utriculose",\n \"popularity\": 3542572\n },\n {\n \"tag\": "testata",\n \"popularity\": 3431259\n },\n {\n \"tag\": "beltmaking",\n \"popularity\": 3325322\n },\n {\n \"tag\": "necrotype",\n \"popularity\": 3224413\n },\n {\n \"tag\": "ovistic",\n \"popularity\": 3128215\n },\n {\n \"tag\": "swindlership",\n \"popularity\": 3036431\n },\n {\n \"tag\": "augustal",\n \"popularity\": 2948792\n },\n {\n \"tag\": "Titoist",\n \"popularity\": 2865047\n },\n {\n \"tag\": "trisoctahedral",\n \"popularity\": 2784963\n },\n {\n \"tag\": "sequestrator",\n \"popularity\": 2708327\n },\n {\n \"tag\": "sideburns",\n \"popularity\": 2634939\n },\n {\n \"tag\": "paraphrasia",\n \"popularity\": 2564616\n },\n {\n \"tag\": "graminology unbay",\n \"popularity\": 2497185\n },\n {\n \"tag\": "acaridomatium emargination",\n \"popularity\": 2432487\n },\n {\n \"tag\": "roofward",\n \"popularity\": 2370373\n },\n {\n \"tag\": "lauder",\n \"popularity\": 2310705\n },\n {\n \"tag\": "subjunctive",\n \"popularity\": 2253354\n },\n {\n \"tag\": "subelongate",\n \"popularity\": 2198199\n },\n {\n \"tag\": "guacimo",\n \"popularity\": 2145128\n },\n {\n \"tag\": "cockade",\n \"popularity\": 2094033\n },\n {\n \"tag\": "misgauge",\n \"popularity\": 2044818\n },\n {\n \"tag\": "unexpensive",\n \"popularity\": 1997388\n },\n {\n \"tag\": "chebel",\n \"popularity\": 1951657\n },\n {\n \"tag\": "unpursuing",\n \"popularity\": 1907543\n },\n {\n \"tag\": "kilobar",\n \"popularity\": 1864969\n },\n {\n \"tag\": "obsecration",\n \"popularity\": 1823863\n },\n {\n \"tag\": "nacarine",\n \"popularity\": 1784157\n },\n {\n \"tag\": "spirituosity",\n \"popularity\": 1745787\n },\n {\n \"tag\": "movableness deity",\n \"popularity\": 1708692\n },\n {\n \"tag\": "exostracism",\n \"popularity\": 1672816\n },\n {\n \"tag\": "archipterygium",\n \"popularity\": 1638104\n },\n {\n \"tag\": "monostrophic",\n \"popularity\": 1604506\n },\n {\n \"tag\": "gynecide",\n \"popularity\": 1571974\n },\n {\n \"tag\": "gladden",\n \"popularity\": 1540462\n },\n {\n \"tag\": "throughbred",\n \"popularity\": 1509927\n },\n {\n \"tag\": "groper",\n \"popularity\": 1480329\n },\n {\n \"tag\": "Xenosaurus",\n \"popularity\": 1451628\n },\n {\n \"tag\": "photoetcher",\n \"popularity\": 1423788\n },\n {\n \"tag\": "glucosid",\n \"popularity\": 1396775\n },\n {\n \"tag\": "Galtonian",\n \"popularity\": 1370555\n },\n {\n \"tag\": "mesosporic",\n \"popularity\": 1345097\n },\n {\n \"tag\": "theody",\n \"popularity\": 1320370\n },\n {\n \"tag\": "zaffer",\n \"popularity\": 1296348\n },\n {\n \"tag\": "probiology",\n \"popularity\": 1273003\n },\n {\n \"tag\": "rhizomic",\n \"popularity\": 1250308\n },\n {\n \"tag\": "superphosphate",\n \"popularity\": 1228240\n },\n {\n \"tag\": "Hippolytan",\n \"popularity\": 1206776\n },\n {\n \"tag\": "garget",\n \"popularity\": 1185892\n },\n {\n \"tag\": "diploplacula",\n \"popularity\": 1165568\n },\n {\n \"tag\": "orohydrographical",\n \"popularity\": 1145785\n },\n {\n \"tag\": "enhypostatize",\n \"popularity\": 1126521\n },\n {\n \"tag\": "polisman",\n \"popularity\": 1107759\n },\n {\n \"tag\": "acetometer",\n \"popularity\": 1089482\n },\n {\n \"tag\": "unsnatched",\n \"popularity\": 1071672\n },\n {\n \"tag\": "yabber",\n \"popularity\": 1054313\n },\n {\n \"tag\": "demiwolf",\n \"popularity\": 1037390\n },\n {\n \"tag\": "chromascope",\n \"popularity\": 1020888\n },\n {\n \"tag\": "seamanship",\n \"popularity\": 1004794\n },\n {\n \"tag\": "nonfenestrated",\n \"popularity\": 989092\n },\n {\n \"tag\": "hydrophytism",\n \"popularity\": 973771\n },\n {\n \"tag\": "dotter",\n \"popularity\": 958819\n },\n {\n \"tag\": "thermoperiodism",\n \"popularity\": 944222\n },\n {\n \"tag\": "unlawyerlike",\n \"popularity\": 929970\n },\n {\n \"tag\": "enantiomeride citywards",\n \"popularity\": 916052\n },\n {\n \"tag\": "unmetallurgical",\n \"popularity\": 902456\n },\n {\n \"tag\": "prickled",\n \"popularity\": 889174\n },\n {\n \"tag\": "strangerwise manioc",\n \"popularity\": 876195\n },\n {\n \"tag\": "incisorial",\n \"popularity\": 863510\n },\n {\n \"tag\": "irrationalize",\n \"popularity\": 851110\n },\n {\n \"tag\": "nasology",\n \"popularity\": 838987\n },\n {\n \"tag\": "fatuism",\n \"popularity\": 827131\n },\n {\n \"tag\": "Huk",\n \"popularity\": 815535\n },\n {\n \"tag\": "properispomenon",\n \"popularity\": 804192\n },\n {\n \"tag\": "unpummelled",\n \"popularity\": 793094\n },\n {\n \"tag\": "technographically",\n \"popularity\": 782233\n },\n {\n \"tag\": "underfurnish",\n \"popularity\": 771603\n },\n {\n \"tag\": "sinter",\n \"popularity\": 761198\n },\n {\n \"tag\": "lateroanterior",\n \"popularity\": 751010\n },\n {\n \"tag\": "nonpersonification",\n \"popularity\": 741034\n },\n {\n \"tag\": "Sitophilus",\n \"popularity\": 731264\n },\n {\n \"tag\": "unstudded overexerted",\n \"popularity\": 721694\n },\n {\n \"tag\": "tracheation",\n \"popularity\": 712318\n },\n {\n \"tag\": "thirteenth begloze",\n \"popularity\": 703131\n },\n {\n \"tag\": "bespice",\n \"popularity\": 694129\n },\n {\n \"tag\": "doppia",\n \"popularity\": 685305\n },\n {\n \"tag\": "unadorned",\n \"popularity\": 676656\n },\n {\n \"tag\": "dovelet engraff",\n \"popularity\": 668176\n },\n {\n \"tag\": "diphyozooid",\n \"popularity\": 659862\n },\n {\n \"tag\": "mure",\n \"popularity\": 651708\n },\n {\n \"tag\": "Tripitaka",\n \"popularity\": 643710\n },\n {\n \"tag\": "Billjim",\n \"popularity\": 635865\n },\n {\n \"tag\": "pyramidical",\n \"popularity\": 628169\n },\n {\n \"tag\": "circumlocutionist",\n \"popularity\": 620617\n },\n {\n \"tag\": "slapstick",\n \"popularity\": 613207\n },\n {\n \"tag\": "preobedience",\n \"popularity\": 605934\n },\n {\n \"tag\": "unfriarlike",\n \"popularity\": 598795\n },\n {\n \"tag\": "microchromosome",\n \"popularity\": 591786\n },\n {\n \"tag\": "Orphicism",\n \"popularity\": 584905\n },\n {\n \"tag\": "peel",\n \"popularity\": 578149\n },\n {\n \"tag\": "obediential",\n \"popularity\": 571514\n },\n {\n \"tag\": "Peripatidea",\n \"popularity\": 564997\n },\n {\n \"tag\": "undoubtful",\n \"popularity\": 558596\n },\n {\n \"tag\": "lodgeable",\n \"popularity\": 552307\n },\n {\n \"tag\": "pustulated woodchat",\n \"popularity\": 546129\n },\n {\n \"tag\": "antepast",\n \"popularity\": 540057\n },\n {\n \"tag\": "sagittoid matrimoniously",\n \"popularity\": 534091\n },\n {\n \"tag\": "Albizzia",\n \"popularity\": 528228\n },\n {\n \"tag\": "Elateridae unnewness",\n \"popularity\": 522464\n },\n {\n \"tag\": "convertingness",\n \"popularity\": 516798\n },\n {\n \"tag\": "Pelew",\n \"popularity\": 511228\n },\n {\n \"tag\": "recapitulation",\n \"popularity\": 505751\n },\n {\n \"tag\": "shack",\n \"popularity\": 500365\n },\n {\n \"tag\": "unmellowed",\n \"popularity\": 495069\n },\n {\n \"tag\": "pavis capering",\n \"popularity\": 489859\n },\n {\n \"tag\": "fanfare",\n \"popularity\": 484735\n },\n {\n \"tag\": "sole",\n \"popularity\": 479695\n },\n {\n \"tag\": "subarcuate",\n \"popularity\": 474735\n },\n {\n \"tag\": "multivious",\n \"popularity\": 469856\n },\n {\n \"tag\": "squandermania",\n \"popularity\": 465054\n },\n {\n \"tag\": "scintle",\n \"popularity\": 460329\n },\n {\n \"tag\": "hash chirognomic",\n \"popularity\": 455679\n },\n {\n \"tag\": "linseed",\n \"popularity\": 451101\n },\n {\n \"tag\": "redoubtable",\n \"popularity\": 446596\n },\n {\n \"tag\": "poachy reimpact",\n \"popularity\": 442160\n },\n {\n \"tag\": "limestone",\n \"popularity\": 437792\n },\n {\n \"tag\": "serranid",\n \"popularity\": 433492\n },\n {\n \"tag\": "pohna",\n \"popularity\": 429258\n },\n {\n \"tag\": "warwolf",\n \"popularity\": 425088\n },\n {\n \"tag\": "ruthenous",\n \"popularity\": 420981\n },\n {\n \"tag\": "dover",\n \"popularity\": 416935\n },\n {\n \"tag\": "deuteroalbumose",\n \"popularity\": 412950\n },\n {\n \"tag\": "pseudoprophetic",\n \"popularity\": 409025\n },\n {\n \"tag\": "dissoluteness",\n \"popularity\": 405157\n },\n {\n \"tag\": "preinvention",\n \"popularity\": 401347\n },\n {\n \"tag\": "swagbellied",\n \"popularity\": 397592\n },\n {\n \"tag\": "Ophidia",\n \"popularity\": 393892\n },\n {\n \"tag\": "equanimity",\n \"popularity\": 390245\n },\n {\n \"tag\": "troutful",\n \"popularity\": 386651\n },\n {\n \"tag\": "uke",\n \"popularity\": 383108\n },\n {\n \"tag\": "preacquaint",\n \"popularity\": 379616\n },\n {\n \"tag\": "shoq",\n \"popularity\": 376174\n },\n {\n \"tag\": "yox",\n \"popularity\": 372780\n },\n {\n \"tag\": "unelemental",\n \"popularity\": 369434\n },\n {\n \"tag\": "Yavapai",\n \"popularity\": 366134\n },\n {\n \"tag\": "joulean",\n \"popularity\": 362880\n },\n {\n \"tag\": "dracontine",\n \"popularity\": 359672\n },\n {\n \"tag\": "hardmouth",\n \"popularity\": 356507\n },\n {\n \"tag\": "sylvanize",\n \"popularity\": 353386\n },\n {\n \"tag\": "intraparenchymatous meadowbur",\n \"popularity\": 350308\n },\n {\n \"tag\": "uncharily",\n \"popularity\": 347271\n },\n {\n \"tag\": "redtab flexibly",\n \"popularity\": 344275\n },\n {\n \"tag\": "centervelic",\n \"popularity\": 341319\n },\n {\n \"tag\": "unravellable",\n \"popularity\": 338403\n },\n {\n \"tag\": "infortunately",\n \"popularity\": 335526\n },\n {\n \"tag\": "cannel",\n \"popularity\": 332687\n },\n {\n \"tag\": "oxyblepsia",\n \"popularity\": 329885\n },\n {\n \"tag\": "Damon",\n \"popularity\": 327120\n },\n {\n \"tag\": "etherin",\n \"popularity\": 324391\n },\n {\n \"tag\": "luminal",\n \"popularity\": 321697\n },\n {\n \"tag\": "interrogatorily presbyte",\n \"popularity\": 319038\n },\n {\n \"tag\": "hemiclastic",\n \"popularity\": 316414\n },\n {\n \"tag\": "poh flush",\n \"popularity\": 313823\n },\n {\n \"tag\": "Psoroptes",\n \"popularity\": 311265\n },\n {\n \"tag\": "dispirit",\n \"popularity\": 308740\n },\n {\n \"tag\": "nashgab",\n \"popularity\": 306246\n },\n {\n \"tag\": "Aphidiinae",\n \"popularity\": 303784\n },\n {\n \"tag\": "rhapsody nonconstruction",\n \"popularity\": 301353\n },\n {\n \"tag\": "Osmond",\n \"popularity\": 298952\n },\n {\n \"tag\": "Leonis",\n \"popularity\": 296581\n },\n {\n \"tag\": "Lemnian",\n \"popularity\": 294239\n },\n {\n \"tag\": "acetonic gnathonic",\n \"popularity\": 291926\n },\n {\n \"tag\": "surculus",\n \"popularity\": 289641\n },\n {\n \"tag\": "diagonally",\n \"popularity\": 287384\n },\n {\n \"tag\": "counterpenalty",\n \"popularity\": 285154\n },\n {\n \"tag\": "Eugenie",\n \"popularity\": 282952\n },\n {\n \"tag\": "hornbook",\n \"popularity\": 280776\n },\n {\n \"tag\": "miscoin",\n \"popularity\": 278626\n },\n {\n \"tag\": "admi",\n \"popularity\": 276501\n },\n {\n \"tag\": "Tarmac",\n \"popularity\": 274402\n },\n {\n \"tag\": "inexplicable",\n \"popularity\": 272328\n },\n {\n \"tag\": "rascallion",\n \"popularity\": 270278\n },\n {\n \"tag\": "dusterman",\n \"popularity\": 268252\n },\n {\n \"tag\": "osteostomous unhoroscopic",\n \"popularity\": 266250\n },\n {\n \"tag\": "spinibulbar",\n \"popularity\": 264271\n },\n {\n \"tag\": "phototelegraphically",\n \"popularity\": 262315\n },\n {\n \"tag\": "Manihot",\n \"popularity\": 260381\n },\n {\n \"tag\": "neighborhood",\n \"popularity\": 258470\n },\n {\n \"tag\": "Vincetoxicum",\n \"popularity\": 256581\n },\n {\n \"tag\": "khirka",\n \"popularity\": 254713\n },\n {\n \"tag\": "conscriptive",\n \"popularity\": 252866\n },\n {\n \"tag\": "synechthran",\n \"popularity\": 251040\n },\n {\n \"tag\": "Guttiferales",\n \"popularity\": 249235\n },\n {\n \"tag\": "roomful",\n \"popularity\": 247450\n },\n {\n \"tag\": "germinal",\n \"popularity\": 245685\n },\n {\n \"tag\": "untraitorous",\n \"popularity\": 243939\n },\n {\n \"tag\": "nondissenting",\n \"popularity\": 242213\n },\n {\n \"tag\": "amotion",\n \"popularity\": 240506\n },\n {\n \"tag\": "badious",\n \"popularity\": 238817\n },\n {\n \"tag\": "sumpit",\n \"popularity\": 237147\n },\n {\n \"tag\": "ectozoic",\n \"popularity\": 235496\n },\n {\n \"tag\": "elvet",\n \"popularity\": 233862\n },\n {\n \"tag\": "underclerk",\n \"popularity\": 232246\n },\n {\n \"tag\": "reticency",\n \"popularity\": 230647\n },\n {\n \"tag\": "neutroclusion",\n \"popularity\": 229065\n },\n {\n \"tag\": "unbelieving",\n \"popularity\": 227500\n },\n {\n \"tag\": "histogenetic",\n \"popularity\": 225952\n },\n {\n \"tag\": "dermamyiasis",\n \"popularity\": 224421\n },\n {\n \"tag\": "telenergy",\n \"popularity\": 222905\n },\n {\n \"tag\": "axiomatic",\n \"popularity\": 221406\n },\n {\n \"tag\": "undominoed",\n \"popularity\": 219922\n },\n {\n \"tag\": "periosteoma",\n \"popularity\": 218454\n },\n {\n \"tag\": "justiciaryship",\n \"popularity\": 217001\n },\n {\n \"tag\": "autoluminescence",\n \"popularity\": 215563\n },\n {\n \"tag\": "osmous",\n \"popularity\": 214140\n },\n {\n \"tag\": "borgh",\n \"popularity\": 212731\n },\n {\n \"tag\": "bedebt",\n \"popularity\": 211337\n },\n {\n \"tag\": "considerableness adenoidism",\n \"popularity\": 209957\n },\n {\n \"tag\": "sailorizing",\n \"popularity\": 208592\n },\n {\n \"tag\": "Montauk",\n \"popularity\": 207240\n },\n {\n \"tag\": "Bridget",\n \"popularity\": 205901\n },\n {\n \"tag\": "Gekkota",\n \"popularity\": 204577\n },\n {\n \"tag\": "subcorymbose",\n \"popularity\": 203265\n },\n {\n \"tag\": "undersap",\n \"popularity\": 201967\n },\n {\n \"tag\": "poikilothermic",\n \"popularity\": 200681\n },\n {\n \"tag\": "enneatical",\n \"popularity\": 199409\n },\n {\n \"tag\": "martinetism",\n \"popularity\": 198148\n },\n {\n \"tag\": "sustanedly",\n \"popularity\": 196901\n },\n {\n \"tag\": "declaration",\n \"popularity\": 195665\n },\n {\n \"tag\": "myringoplasty",\n \"popularity\": 194442\n },\n {\n \"tag\": "Ginkgo",\n \"popularity\": 193230\n },\n {\n \"tag\": "unrecurrent",\n \"popularity\": 192031\n },\n {\n \"tag\": "proprecedent",\n \"popularity\": 190843\n },\n {\n \"tag\": "roadman",\n \"popularity\": 189666\n },\n {\n \"tag\": "elemin",\n \"popularity\": 188501\n },\n {\n \"tag\": "maggot",\n \"popularity\": 187347\n },\n {\n \"tag\": "alitrunk",\n \"popularity\": 186204\n },\n {\n \"tag\": "introspection",\n \"popularity\": 185071\n },\n {\n \"tag\": "batiker",\n \"popularity\": 183950\n },\n {\n \"tag\": "backhatch oversettle",\n \"popularity\": 182839\n },\n {\n \"tag\": "thresherman",\n \"popularity\": 181738\n },\n {\n \"tag\": "protemperance",\n \"popularity\": 180648\n },\n {\n \"tag\": "undern",\n \"popularity\": 179568\n },\n {\n \"tag\": "tweeg",\n \"popularity\": 178498\n },\n {\n \"tag\": "crosspath",\n \"popularity\": 177438\n },\n {\n \"tag\": "Tangaridae",\n \"popularity\": 176388\n },\n {\n \"tag\": "scrutation",\n \"popularity\": 175348\n },\n {\n \"tag\": "piecemaker",\n \"popularity\": 174317\n },\n {\n \"tag\": "paster",\n \"popularity\": 173296\n },\n {\n \"tag\": "unpretendingness",\n \"popularity\": 172284\n },\n {\n \"tag\": "inframundane",\n \"popularity\": 171281\n },\n {\n \"tag\": "kiblah",\n \"popularity\": 170287\n },\n {\n \"tag\": "playwrighting",\n \"popularity\": 169302\n },\n {\n \"tag\": "gonepoiesis snowslip",\n \"popularity\": 168326\n },\n {\n \"tag\": "hoodwise",\n \"popularity\": 167359\n },\n {\n \"tag\": "postseason",\n \"popularity\": 166401\n },\n {\n \"tag\": "equivocality",\n \"popularity\": 165451\n },\n {\n \"tag\": "Opiliaceae nuclease",\n \"popularity\": 164509\n },\n {\n \"tag\": "sextipara",\n \"popularity\": 163576\n },\n {\n \"tag\": "weeper",\n \"popularity\": 162651\n },\n {\n \"tag\": "frambesia",\n \"popularity\": 161735\n },\n {\n \"tag\": "answerable",\n \"popularity\": 160826\n },\n {\n \"tag\": "Trichosporum",\n \"popularity\": 159925\n },\n {\n \"tag\": "cajuputol",\n \"popularity\": 159033\n },\n {\n \"tag\": "pleomorphous",\n \"popularity\": 158148\n },\n {\n \"tag\": "aculeolate",\n \"popularity\": 157270\n },\n {\n \"tag\": "wherever",\n \"popularity\": 156400\n },\n {\n \"tag\": "collapse",\n \"popularity\": 155538\n },\n {\n \"tag\": "porky",\n \"popularity\": 154683\n },\n {\n \"tag\": "perule",\n \"popularity\": 153836\n },\n {\n \"tag\": "Nevada",\n \"popularity\": 152996\n },\n {\n \"tag\": "conalbumin",\n \"popularity\": 152162\n },\n {\n \"tag\": "tsunami",\n \"popularity\": 151336\n },\n {\n \"tag\": "Gulf",\n \"popularity\": 150517\n },\n {\n \"tag\": "hertz",\n \"popularity\": 149705\n },\n {\n \"tag\": "limmock",\n \"popularity\": 148900\n },\n {\n \"tag\": "Tartarize",\n \"popularity\": 148101\n },\n {\n \"tag\": "entosphenoid",\n \"popularity\": 147310\n },\n {\n \"tag\": "ibis",\n \"popularity\": 146524\n },\n {\n \"tag\": "unyeaned",\n \"popularity\": 145746\n },\n {\n \"tag\": "tritural",\n \"popularity\": 144973\n },\n {\n \"tag\": "hundredary",\n \"popularity\": 144207\n },\n {\n \"tag\": "stolonlike",\n \"popularity\": 143448\n },\n {\n \"tag\": "chorister",\n \"popularity\": 142694\n },\n {\n \"tag\": "mismove",\n \"popularity\": 141947\n },\n {\n \"tag\": "Andine",\n \"popularity\": 141206\n },\n {\n \"tag\": "Annette proneur escribe",\n \"popularity\": 140471\n },\n {\n \"tag\": "exoperidium",\n \"popularity\": 139742\n },\n {\n \"tag\": "disedge",\n \"popularity\": 139019\n },\n {\n \"tag\": "hypochloruria",\n \"popularity\": 138302\n },\n {\n \"tag\": "prepupa",\n \"popularity\": 137590\n },\n {\n \"tag\": "assent",\n \"popularity\": 136884\n },\n {\n \"tag\": "hydrazobenzene",\n \"popularity\": 136184\n },\n {\n \"tag\": "emballonurid",\n \"popularity\": 135489\n },\n {\n \"tag\": "roselle",\n \"popularity\": 134800\n },\n {\n \"tag\": "unifiedly",\n \"popularity\": 134117\n },\n {\n \"tag\": "clang",\n \"popularity\": 133439\n },\n {\n \"tag\": "acetolytic",\n \"popularity\": 132766\n },\n {\n \"tag\": "cladodont",\n \"popularity\": 132098\n },\n {\n \"tag\": "recoast",\n \"popularity\": 131436\n },\n {\n \"tag\": "celebrated tydie Eocarboniferous",\n \"popularity\": 130779\n },\n {\n \"tag\": "superconsciousness",\n \"popularity\": 130127\n },\n {\n \"tag\": "soberness",\n \"popularity\": 129480\n },\n {\n \"tag\": "panoramist",\n \"popularity\": 128838\n },\n {\n \"tag\": "Orbitolina",\n \"popularity\": 128201\n },\n {\n \"tag\": "overlewd",\n \"popularity\": 127569\n },\n {\n \"tag\": "demiquaver",\n \"popularity\": 126942\n },\n {\n \"tag\": "kamelaukion",\n \"popularity\": 126319\n },\n {\n \"tag\": "flancard",\n \"popularity\": 125702\n },\n {\n \"tag\": "tricuspid",\n \"popularity\": 125089\n },\n {\n \"tag\": "bepelt",\n \"popularity\": 124480\n },\n {\n \"tag\": "decuplet",\n \"popularity\": 123877\n },\n {\n \"tag\": "Rockies",\n \"popularity\": 123278\n },\n {\n \"tag\": "unforgeability",\n \"popularity\": 122683\n },\n {\n \"tag\": "mocha",\n \"popularity\": 122093\n },\n {\n \"tag\": "scrunge",\n \"popularity\": 121507\n },\n {\n \"tag\": "delighter",\n \"popularity\": 120926\n },\n {\n \"tag\": "willey Microtinae",\n \"popularity\": 120349\n },\n {\n \"tag\": "unhuntable",\n \"popularity\": 119777\n },\n {\n \"tag\": "historically",\n \"popularity\": 119208\n },\n {\n \"tag\": "vicegerentship",\n \"popularity\": 118644\n },\n {\n \"tag\": "hemangiosarcoma",\n \"popularity\": 118084\n },\n {\n \"tag\": "harpago",\n \"popularity\": 117528\n },\n {\n \"tag\": "unionoid",\n \"popularity\": 116976\n },\n {\n \"tag\": "wiseman",\n \"popularity\": 116429\n },\n {\n \"tag\": "diclinism",\n \"popularity\": 115885\n },\n {\n \"tag\": "Maud",\n \"popularity\": 115345\n },\n {\n \"tag\": "scaphocephalism",\n \"popularity\": 114809\n },\n {\n \"tag\": "obtenebration",\n \"popularity\": 114277\n },\n {\n \"tag\": "cymar predreadnought",\n \"popularity\": 113749\n },\n {\n \"tag\": "discommend",\n \"popularity\": 113225\n },\n {\n \"tag\": "crude",\n \"popularity\": 112704\n },\n {\n \"tag\": "upflash",\n \"popularity\": 112187\n },\n {\n \"tag\": "saltimbank",\n \"popularity\": 111674\n },\n {\n \"tag\": "posthysterical",\n \"popularity\": 111165\n },\n {\n \"tag\": "trample",\n \"popularity\": 110659\n },\n {\n \"tag\": "ungirthed",\n \"popularity\": 110157\n },\n {\n \"tag\": "unshakable",\n \"popularity\": 109658\n },\n {\n \"tag\": "hepatocystic",\n \"popularity\": 109163\n },\n {\n \"tag\": "psammophyte",\n \"popularity\": 108671\n },\n {\n \"tag\": "millionfold",\n \"popularity\": 108183\n },\n {\n \"tag\": "outtaste",\n \"popularity\": 107698\n },\n {\n \"tag\": "poppycockish",\n \"popularity\": 107217\n },\n {\n \"tag\": "viduine",\n \"popularity\": 106739\n },\n {\n \"tag\": "pleasureman",\n \"popularity\": 106264\n },\n {\n \"tag\": "cholesterolemia",\n \"popularity\": 105792\n },\n {\n \"tag\": "hostlerwife",\n \"popularity\": 105324\n },\n {\n \"tag\": "figure undergrass",\n \"popularity\": 104859\n },\n {\n \"tag\": "bedrape",\n \"popularity\": 104398\n },\n {\n \"tag\": "nuttishness",\n \"popularity\": 103939\n },\n {\n \"tag\": "fow",\n \"popularity\": 103484\n },\n {\n \"tag\": "rachianesthesia",\n \"popularity\": 103031\n },\n {\n \"tag\": "recruitable",\n \"popularity\": 102582\n },\n {\n \"tag\": "semianatomical Oenotheraceae",\n \"popularity\": 102136\n },\n {\n \"tag\": "extracapsular",\n \"popularity\": 101693\n },\n {\n \"tag\": "unsigneted",\n \"popularity\": 101253\n },\n {\n \"tag\": "fissural",\n \"popularity\": 100816\n },\n {\n \"tag\": "ayous",\n \"popularity\": 100381\n },\n {\n \"tag\": "crestfallenness odontograph",\n \"popularity\": 99950\n },\n {\n \"tag\": "monopodium",\n \"popularity\": 99522\n },\n {\n \"tag\": "germfree",\n \"popularity\": 99096\n },\n {\n \"tag\": "dauphin",\n \"popularity\": 98673\n },\n {\n \"tag\": "nonagesimal",\n \"popularity\": 98254\n },\n {\n \"tag\": "waterchat",\n \"popularity\": 97836\n },\n {\n \"tag\": "Entelodon",\n \"popularity\": 97422\n },\n {\n \"tag\": "semischolastic",\n \"popularity\": 97010\n },\n {\n \"tag\": "somata",\n \"popularity\": 96602\n },\n {\n \"tag\": "expositorily",\n \"popularity\": 96195\n },\n {\n \"tag\": "bass",\n \"popularity\": 95792\n },\n {\n \"tag\": "calorimetry",\n \"popularity\": 95391\n },\n {\n \"tag\": "entireness",\n \"popularity\": 94993\n },\n {\n \"tag\": "ratline soppiness",\n \"popularity\": 94597\n },\n {\n \"tag\": "shor",\n \"popularity\": 94204\n },\n {\n \"tag\": "coprecipitation",\n \"popularity\": 93813\n },\n {\n \"tag\": "unblushingly",\n \"popularity\": 93425\n },\n {\n \"tag\": "macarize",\n \"popularity\": 93040\n },\n {\n \"tag\": "scruplesomeness",\n \"popularity\": 92657\n },\n {\n \"tag\": "offsaddle",\n \"popularity\": 92276\n },\n {\n \"tag\": "hypertragical",\n \"popularity\": 91898\n },\n {\n \"tag\": "uncassock loined",\n \"popularity\": 91522\n },\n {\n \"tag\": "interlobate",\n \"popularity\": 91149\n },\n {\n \"tag\": "releasor orrisroot stoloniferously",\n \"popularity\": 90778\n },\n {\n \"tag\": "elementoid",\n \"popularity\": 90410\n },\n {\n \"tag\": "Lentilla",\n \"popularity\": 90043\n },\n {\n \"tag\": "distressing",\n \"popularity\": 89679\n },\n {\n \"tag\": "hydrodrome",\n \"popularity\": 89318\n },\n {\n \"tag\": "Jeannette",\n \"popularity\": 88958\n },\n {\n \"tag\": "Kuli",\n \"popularity\": 88601\n },\n {\n \"tag\": "taxinomist",\n \"popularity\": 88246\n },\n {\n \"tag\": "southwestwardly",\n \"popularity\": 87894\n },\n {\n \"tag\": "polyparia",\n \"popularity\": 87543\n },\n {\n \"tag\": "exmeridian",\n \"popularity\": 87195\n },\n {\n \"tag\": "splenius regimentaled",\n \"popularity\": 86849\n },\n {\n \"tag\": "Sphaeropsidaceae",\n \"popularity\": 86505\n },\n {\n \"tag\": "unbegun",\n \"popularity\": 86163\n },\n {\n \"tag\": "something",\n \"popularity\": 85823\n },\n {\n \"tag\": "contaminable nonexpulsion",\n \"popularity\": 85486\n },\n {\n \"tag\": "douser",\n \"popularity\": 85150\n },\n {\n \"tag\": "prostrike",\n \"popularity\": 84817\n },\n {\n \"tag\": "worky",\n \"popularity\": 84485\n },\n {\n \"tag\": "folliful",\n \"popularity\": 84156\n },\n {\n \"tag\": "prioracy",\n \"popularity\": 83828\n },\n {\n \"tag\": "undermentioned",\n \"popularity\": 83503\n },\n {\n \"tag\": "Judaica",\n \"popularity\": 83179\n },\n {\n \"tag\": "multifarious",\n \"popularity\": 82858\n },\n {\n \"tag\": "poogye",\n \"popularity\": 82538\n },\n {\n \"tag\": "Sparganium",\n \"popularity\": 82221\n },\n {\n \"tag\": "thurrock",\n \"popularity\": 81905\n },\n {\n \"tag\": "outblush",\n \"popularity\": 81591\n },\n {\n \"tag\": "Strophanthus supraordination",\n \"popularity\": 81279\n },\n {\n \"tag\": "gingerroot",\n \"popularity\": 80969\n },\n {\n \"tag\": "unconscient",\n \"popularity\": 80661\n },\n {\n \"tag\": "unconstitutionally",\n \"popularity\": 80354\n },\n {\n \"tag\": "plaguily",\n \"popularity\": 80050\n },\n {\n \"tag\": "waterily equatorwards",\n \"popularity\": 79747\n },\n {\n \"tag\": "nondeposition",\n \"popularity\": 79446\n },\n {\n \"tag\": "dronishly",\n \"popularity\": 79147\n },\n {\n \"tag\": "gateado",\n \"popularity\": 78849\n },\n {\n \"tag\": "dislink",\n \"popularity\": 78553\n },\n {\n \"tag\": "Joceline",\n \"popularity\": 78259\n },\n {\n \"tag\": "amphiboliferous",\n \"popularity\": 77967\n },\n {\n \"tag\": "bushrope",\n \"popularity\": 77676\n },\n {\n \"tag\": "plumicorn sulphosalicylic",\n \"popularity\": 77387\n },\n {\n \"tag\": "nonefficiency",\n \"popularity\": 77100\n },\n {\n \"tag\": "hieroscopy",\n \"popularity\": 76815\n },\n {\n \"tag\": "causativeness",\n \"popularity\": 76531\n },\n {\n \"tag\": "swird paleoeremology",\n \"popularity\": 76249\n },\n {\n \"tag\": "camphoric",\n \"popularity\": 75968\n },\n {\n \"tag\": "retaining",\n \"popularity\": 75689\n },\n {\n \"tag\": "thyreoprotein",\n \"popularity\": 75411\n },\n {\n \"tag\": "carbona",\n \"popularity\": 75136\n },\n {\n \"tag\": "protectively",\n \"popularity\": 74861\n },\n {\n \"tag\": "mosasaur",\n \"popularity\": 74589\n },\n {\n \"tag\": "reciprocator",\n \"popularity\": 74317\n },\n {\n \"tag\": "detentive",\n \"popularity\": 74048\n },\n {\n \"tag\": "supravital",\n \"popularity\": 73780\n },\n {\n \"tag\": "Vespertilionidae",\n \"popularity\": 73513\n },\n {\n \"tag\": "parka",\n \"popularity\": 73248\n },\n {\n \"tag\": "pickaway",\n \"popularity\": 72984\n },\n {\n \"tag\": "oleaceous",\n \"popularity\": 72722\n },\n {\n \"tag\": "anticogitative",\n \"popularity\": 72462\n },\n {\n \"tag\": "woe",\n \"popularity\": 72203\n },\n {\n \"tag\": "skeuomorph",\n \"popularity\": 71945\n },\n {\n \"tag\": "helpmeet",\n \"popularity\": 71689\n },\n {\n \"tag\": "Hexactinellida brickmaking",\n \"popularity\": 71434\n },\n {\n \"tag\": "resink",\n \"popularity\": 71180\n },\n {\n \"tag\": "diluter",\n \"popularity\": 70928\n },\n {\n \"tag\": "micromicron",\n \"popularity\": 70677\n },\n {\n \"tag\": "parentage",\n \"popularity\": 70428\n },\n {\n \"tag\": "galactorrhoea",\n \"popularity\": 70180\n },\n {\n \"tag\": "gey",\n \"popularity\": 69934\n },\n {\n \"tag\": "gesticulatory",\n \"popularity\": 69689\n },\n {\n \"tag\": "wergil",\n \"popularity\": 69445\n },\n {\n \"tag\": "Lecanora",\n \"popularity\": 69202\n },\n {\n \"tag\": "malanders karst",\n \"popularity\": 68961\n },\n {\n \"tag\": "vibetoite",\n \"popularity\": 68721\n },\n {\n \"tag\": "unrequitedness",\n \"popularity\": 68483\n },\n {\n \"tag\": "outwash",\n \"popularity\": 68245\n },\n {\n \"tag\": "unsacred",\n \"popularity\": 68009\n },\n {\n \"tag\": "unabetted dividend",\n \"popularity\": 67775\n },\n {\n \"tag\": "untraveling",\n \"popularity\": 67541\n },\n {\n \"tag\": "thermobattery",\n \"popularity\": 67309\n },\n {\n \"tag\": "polypragmist",\n \"popularity\": 67078\n },\n {\n \"tag\": "irrefutableness",\n \"popularity\": 66848\n },\n {\n \"tag\": "remiges",\n \"popularity\": 66620\n },\n {\n \"tag\": "implode",\n \"popularity\": 66393\n },\n {\n \"tag\": "superfluousness",\n \"popularity\": 66166\n },\n {\n \"tag\": "croakily unalleviated",\n \"popularity\": 65942\n },\n {\n \"tag\": "edicule",\n \"popularity\": 65718\n },\n {\n \"tag\": "entophytous",\n \"popularity\": 65495\n },\n {\n \"tag\": "benefactorship Toryish",\n \"popularity\": 65274\n },\n {\n \"tag\": "pseudoamateurish",\n \"popularity\": 65054\n },\n {\n \"tag\": "flueless Iguanodontoidea snipnose",\n \"popularity\": 64835\n },\n {\n \"tag\": "zealotical Zamicrus interpole",\n \"popularity\": 64617\n },\n {\n \"tag\": "whereabout",\n \"popularity\": 64401\n },\n {\n \"tag\": "benzazide",\n \"popularity\": 64185\n },\n {\n \"tag\": "pokeweed",\n \"popularity\": 63971\n },\n {\n \"tag\": "calamitoid",\n \"popularity\": 63757\n },\n {\n \"tag\": "sporozoal",\n \"popularity\": 63545\n },\n {\n \"tag\": "physcioid Welshwoman",\n \"popularity\": 63334\n },\n {\n \"tag\": "wanting",\n \"popularity\": 63124\n },\n {\n \"tag\": "unencumbering",\n \"popularity\": 62915\n },\n {\n \"tag\": "Tupi",\n \"popularity\": 62707\n },\n {\n \"tag\": "potbank",\n \"popularity\": 62501\n },\n {\n \"tag\": "bulked",\n \"popularity\": 62295\n },\n {\n \"tag\": "uparise",\n \"popularity\": 62090\n },\n {\n \"tag\": "Sudra",\n \"popularity\": 61887\n },\n {\n \"tag\": "hyperscrupulosity",\n \"popularity\": 61684\n },\n {\n \"tag\": "subterraneously unmaid",\n \"popularity\": 61483\n },\n {\n \"tag\": "poisonousness",\n \"popularity\": 61282\n },\n {\n \"tag\": "phare",\n \"popularity\": 61083\n },\n {\n \"tag\": "dicynodont",\n \"popularity\": 60884\n },\n {\n \"tag\": "chewer",\n \"popularity\": 60687\n },\n {\n \"tag\": "uliginous",\n \"popularity\": 60490\n },\n {\n \"tag\": "tinman",\n \"popularity\": 60295\n },\n {\n \"tag\": "coconut",\n \"popularity\": 60100\n },\n {\n \"tag\": "phryganeoid",\n \"popularity\": 59907\n },\n {\n \"tag\": "bismillah",\n \"popularity\": 59714\n },\n {\n \"tag\": "tautomeric",\n \"popularity\": 59523\n },\n {\n \"tag\": "jerquer",\n \"popularity\": 59332\n },\n {\n \"tag\": "Dryopithecinae",\n \"popularity\": 59143\n },\n {\n \"tag\": "ghizite",\n \"popularity\": 58954\n },\n {\n \"tag\": "unliveable",\n \"popularity\": 58766\n },\n {\n \"tag\": "craftsmaster",\n \"popularity\": 58579\n },\n {\n \"tag\": "semiscenic",\n \"popularity\": 58394\n },\n {\n \"tag\": "danaid",\n \"popularity\": 58209\n },\n {\n \"tag\": "flawful",\n \"popularity\": 58025\n },\n {\n \"tag\": "risibleness",\n \"popularity\": 57841\n },\n {\n \"tag\": "Muscovite",\n \"popularity\": 57659\n },\n {\n \"tag\": "snaringly",\n \"popularity\": 57478\n },\n {\n \"tag\": "brilliantwise",\n \"popularity\": 57297\n },\n {\n \"tag\": "plebeity",\n \"popularity\": 57118\n },\n {\n \"tag\": "historicalness",\n \"popularity\": 56939\n },\n {\n \"tag\": "piecemeal",\n \"popularity\": 56761\n },\n {\n \"tag\": "maxillipedary",\n \"popularity\": 56584\n },\n {\n \"tag\": "Hypenantron",\n \"popularity\": 56408\n },\n {\n \"tag\": "quaintness avigate",\n \"popularity\": 56233\n },\n {\n \"tag\": "ave",\n \"popularity\": 56059\n },\n {\n \"tag\": "mediaevally",\n \"popularity\": 55885\n },\n {\n \"tag\": "brucite",\n \"popularity\": 55712\n },\n {\n \"tag\": "Schwendenerian",\n \"popularity\": 55541\n },\n {\n \"tag\": "julole",\n \"popularity\": 55370\n },\n {\n \"tag\": "palaeolith",\n \"popularity\": 55199\n },\n {\n \"tag\": "cotyledonary",\n \"popularity\": 55030\n },\n {\n \"tag\": "rond",\n \"popularity\": 54861\n },\n {\n \"tag\": "boomster tassoo",\n \"popularity\": 54694\n },\n {\n \"tag\": "cattishly",\n \"popularity\": 54527\n },\n {\n \"tag\": "tonguefence",\n \"popularity\": 54360\n },\n {\n \"tag\": "hexastylar triskele",\n \"popularity\": 54195\n },\n {\n \"tag\": "ariot",\n \"popularity\": 54030\n },\n {\n \"tag\": "intarsist",\n \"popularity\": 53867\n },\n {\n \"tag\": "Oscines",\n \"popularity\": 53704\n },\n {\n \"tag\": "Spaniolize",\n \"popularity\": 53541\n },\n {\n \"tag\": "smellfungus",\n \"popularity\": 53380\n },\n {\n \"tag\": "redisplay",\n \"popularity\": 53219\n },\n {\n \"tag\": "phosphene",\n \"popularity\": 53059\n },\n {\n \"tag\": "phycomycete",\n \"popularity\": 52900\n },\n {\n \"tag\": "prophetic",\n \"popularity\": 52741\n },\n {\n \"tag\": "overtrustful",\n \"popularity\": 52584\n },\n {\n \"tag\": "pinitol",\n \"popularity\": 52427\n },\n {\n \"tag\": "asthmatic",\n \"popularity\": 52270\n },\n {\n \"tag\": "convulsive",\n \"popularity\": 52115\n },\n {\n \"tag\": "draughtswoman",\n \"popularity\": 51960\n },\n {\n \"tag\": "unetymologizable",\n \"popularity\": 51806\n },\n {\n \"tag\": "centrarchoid",\n \"popularity\": 51652\n },\n {\n \"tag\": "mesioincisal",\n \"popularity\": 51500\n },\n {\n \"tag\": "transbaikal",\n \"popularity\": 51348\n },\n {\n \"tag\": "silveriness",\n \"popularity\": 51196\n },\n {\n \"tag\": "costotomy",\n \"popularity\": 51046\n },\n {\n \"tag\": "caracore",\n \"popularity\": 50896\n },\n {\n \"tag\": "depotentiation",\n \"popularity\": 50747\n },\n {\n \"tag\": "glossoepiglottidean",\n \"popularity\": 50598\n },\n {\n \"tag\": "upswell",\n \"popularity\": 50450\n },\n {\n \"tag\": "flecnodal",\n \"popularity\": 50303\n },\n {\n \"tag\": "coventrate",\n \"popularity\": 50157\n },\n {\n \"tag\": "duchesse",\n \"popularity\": 50011\n },\n {\n \"tag\": "excisemanship trophied",\n \"popularity\": 49866\n },\n {\n \"tag\": "cytinaceous",\n \"popularity\": 49721\n },\n {\n \"tag\": "assuringly",\n \"popularity\": 49577\n },\n {\n \"tag\": "unconducted upliftitis",\n \"popularity\": 49434\n },\n {\n \"tag\": "rachicentesis",\n \"popularity\": 49292\n },\n {\n \"tag\": "antiangular",\n \"popularity\": 49150\n },\n {\n \"tag\": "advisal",\n \"popularity\": 49008\n },\n {\n \"tag\": "birdcatcher",\n \"popularity\": 48868\n },\n {\n \"tag\": "secularistic",\n \"popularity\": 48728\n },\n {\n \"tag\": "grandeeism superinformal",\n \"popularity\": 48588\n },\n {\n \"tag\": "unapprehension",\n \"popularity\": 48449\n },\n {\n \"tag\": "excipulum",\n \"popularity\": 48311\n },\n {\n \"tag\": "decimole",\n \"popularity\": 48174\n },\n {\n \"tag\": "semidrachm",\n \"popularity\": 48037\n },\n {\n \"tag\": "uvulotome",\n \"popularity\": 47901\n },\n {\n \"tag\": "Lemaneaceae",\n \"popularity\": 47765\n },\n {\n \"tag\": "corrade",\n \"popularity\": 47630\n },\n {\n \"tag\": "Kuroshio",\n \"popularity\": 47495\n },\n {\n \"tag\": "Araliophyllum",\n \"popularity\": 47361\n },\n {\n \"tag\": "victoriousness cardiosphygmograph",\n \"popularity\": 47228\n },\n {\n \"tag\": "reinvent",\n \"popularity\": 47095\n },\n {\n \"tag\": "Macrotolagus",\n \"popularity\": 46963\n },\n {\n \"tag\": "strenuousness",\n \"popularity\": 46831\n },\n {\n \"tag\": "deviability",\n \"popularity\": 46700\n },\n {\n \"tag\": "phyllospondylous",\n \"popularity\": 46570\n },\n {\n \"tag\": "bisect rudderhole",\n \"popularity\": 46440\n },\n {\n \"tag\": "crownwork",\n \"popularity\": 46311\n },\n {\n \"tag\": "Ascalabota",\n \"popularity\": 46182\n },\n {\n \"tag\": "prostatomyomectomy",\n \"popularity\": 46054\n },\n {\n \"tag\": "neurosyphilis",\n \"popularity\": 45926\n },\n {\n \"tag\": "tabloid scraplet",\n \"popularity\": 45799\n },\n {\n \"tag\": "nonmedullated servility",\n \"popularity\": 45673\n },\n {\n \"tag\": "melopoeic practicalization",\n \"popularity\": 45547\n },\n {\n \"tag\": "nonrhythmic",\n \"popularity\": 45421\n },\n {\n \"tag\": "deplorer",\n \"popularity\": 45296\n },\n {\n \"tag\": "Ophion",\n \"popularity\": 45172\n },\n {\n \"tag\": "subprioress",\n \"popularity\": 45048\n },\n {\n \"tag\": "semiregular",\n \"popularity\": 44925\n },\n {\n \"tag\": "praelection",\n \"popularity\": 44802\n },\n {\n \"tag\": "discinct",\n \"popularity\": 44680\n },\n {\n \"tag\": "preplace",\n \"popularity\": 44558\n },\n {\n \"tag\": "paternoster",\n \"popularity\": 44437\n },\n {\n \"tag\": "suboccipital",\n \"popularity\": 44316\n },\n {\n \"tag\": "Teutophil",\n \"popularity\": 44196\n },\n {\n \"tag\": "tracheole",\n \"popularity\": 44076\n },\n {\n \"tag\": "subsmile",\n \"popularity\": 43957\n },\n {\n \"tag\": "nonapostatizing",\n \"popularity\": 43839\n },\n {\n \"tag\": "cleidotomy",\n \"popularity\": 43720\n },\n {\n \"tag\": "hingle",\n \"popularity\": 43603\n },\n {\n \"tag\": "jocoque",\n \"popularity\": 43486\n },\n {\n \"tag\": "trundler notidanian",\n \"popularity\": 43369\n },\n {\n \"tag\": "strangling misdaub",\n \"popularity\": 43253\n },\n {\n \"tag\": "noncancellable",\n \"popularity\": 43137\n },\n {\n \"tag\": "lavabo",\n \"popularity\": 43022\n },\n {\n \"tag\": "lanterloo",\n \"popularity\": 42907\n },\n {\n \"tag\": "uncitizenly",\n \"popularity\": 42793\n },\n {\n \"tag\": "autoturning",\n \"popularity\": 42679\n },\n {\n \"tag\": "Haganah",\n \"popularity\": 42566\n },\n {\n \"tag\": "Glecoma",\n \"popularity\": 42453\n },\n {\n \"tag\": "membered",\n \"popularity\": 42341\n },\n {\n \"tag\": "consuetudinal",\n \"popularity\": 42229\n },\n {\n \"tag\": "gatehouse",\n \"popularity\": 42117\n },\n {\n \"tag\": "tetherball",\n \"popularity\": 42006\n },\n {\n \"tag\": "counterrevolutionist numismatical",\n \"popularity\": 41896\n },\n {\n \"tag\": "pagehood plateiasmus",\n \"popularity\": 41786\n },\n {\n \"tag\": "pelterer",\n \"popularity\": 41676\n },\n {\n \"tag\": "splenemphraxis",\n \"popularity\": 41567\n },\n {\n \"tag\": "Crypturidae",\n \"popularity\": 41458\n },\n {\n \"tag\": "caboodle",\n \"popularity\": 41350\n },\n {\n \"tag\": "Filaria",\n \"popularity\": 41242\n },\n {\n \"tag\": "noninvincibility",\n \"popularity\": 41135\n },\n {\n \"tag\": "preadvertisement",\n \"popularity\": 41028\n },\n {\n \"tag\": "bathrobe",\n \"popularity\": 40921\n },\n {\n \"tag\": "nitrifier",\n \"popularity\": 40815\n },\n {\n \"tag\": "furthermore",\n \"popularity\": 40709\n },\n {\n \"tag\": "recrate",\n \"popularity\": 40604\n },\n {\n \"tag\": "inexist",\n \"popularity\": 40499\n },\n {\n \"tag\": "Mocoan",\n \"popularity\": 40395\n },\n {\n \"tag\": "forint",\n \"popularity\": 40291\n },\n {\n \"tag\": "cardiomyoliposis",\n \"popularity\": 40187\n },\n {\n \"tag\": "channeling",\n \"popularity\": 40084\n },\n {\n \"tag\": "quebrachine",\n \"popularity\": 39981\n },\n {\n \"tag\": "magistery",\n \"popularity\": 39879\n },\n {\n \"tag\": "koko",\n \"popularity\": 39777\n },\n {\n \"tag\": "nobilify",\n \"popularity\": 39676\n },\n {\n \"tag\": "articulate taprooted",\n \"popularity\": 39575\n },\n {\n \"tag\": "cardiotonic Nicaragua",\n \"popularity\": 39474\n },\n {\n \"tag\": "assertiveness",\n \"popularity\": 39374\n },\n {\n \"tag\": "springtail",\n \"popularity\": 39274\n },\n {\n \"tag\": "spontoon",\n \"popularity\": 39174\n },\n {\n \"tag\": "plesiobiosis",\n \"popularity\": 39075\n },\n {\n \"tag\": "rooinek",\n \"popularity\": 38976\n },\n {\n \"tag\": "hairif falsehood",\n \"popularity\": 38878\n },\n {\n \"tag\": "synodally",\n \"popularity\": 38780\n },\n {\n \"tag\": "biodynamics",\n \"popularity\": 38683\n },\n {\n \"tag\": "trickling",\n \"popularity\": 38585\n },\n {\n \"tag\": "oxfly daystar",\n \"popularity\": 38489\n },\n {\n \"tag\": "epicycloidal",\n \"popularity\": 38392\n },\n {\n \"tag\": "shorthand",\n \"popularity\": 38296\n },\n {\n \"tag\": "herpolhode",\n \"popularity\": 38201\n },\n {\n \"tag\": "polysynthesism",\n \"popularity\": 38105\n },\n {\n \"tag\": "cany",\n \"popularity\": 38010\n },\n {\n \"tag\": "sideage",\n \"popularity\": 37916\n },\n {\n \"tag\": "strainableness",\n \"popularity\": 37822\n },\n {\n \"tag\": "superformidable",\n \"popularity\": 37728\n },\n {\n \"tag\": "slendang",\n \"popularity\": 37634\n },\n {\n \"tag\": "impropriation",\n \"popularity\": 37541\n },\n {\n \"tag\": "ficklehearted",\n \"popularity\": 37449\n },\n {\n \"tag\": "wintrify",\n \"popularity\": 37356\n },\n {\n \"tag\": "geomorphogenist",\n \"popularity\": 37264\n },\n {\n \"tag\": "smuggleable",\n \"popularity\": 37173\n },\n {\n \"tag\": "delapsion",\n \"popularity\": 37081\n },\n {\n \"tag\": "projective",\n \"popularity\": 36990\n },\n {\n \"tag\": "unglue exfoliation",\n \"popularity\": 36900\n },\n {\n \"tag\": "Acerae",\n \"popularity\": 36810\n },\n {\n \"tag\": "unstaged",\n \"popularity\": 36720\n },\n {\n \"tag\": "ranal",\n \"popularity\": 36630\n },\n {\n \"tag\": "worrier",\n \"popularity\": 36541\n },\n {\n \"tag\": "unhid",\n \"popularity\": 36452\n },\n {\n \"tag\": "adequation",\n \"popularity\": 36363\n },\n {\n \"tag\": "strongylid Sokotri",\n \"popularity\": 36275\n },\n {\n \"tag\": "fumingly",\n \"popularity\": 36187\n },\n {\n \"tag\": "gynosporangium phaenogenetic",\n \"popularity\": 36100\n },\n {\n \"tag\": "uniunguiculate",\n \"popularity\": 36012\n },\n {\n \"tag\": "prudelike",\n \"popularity\": 35926\n },\n {\n \"tag\": "seminomata",\n \"popularity\": 35839\n },\n {\n \"tag\": "trinklet",\n \"popularity\": 35753\n },\n {\n \"tag\": "risorial",\n \"popularity\": 35667\n },\n {\n \"tag\": "pericardiocentesis",\n \"popularity\": 35581\n },\n {\n \"tag\": "filmist",\n \"popularity\": 35496\n },\n {\n \"tag\": "Nana",\n \"popularity\": 35411\n },\n {\n \"tag\": "cynipoid",\n \"popularity\": 35326\n },\n {\n \"tag\": "cteniform",\n \"popularity\": 35242\n },\n {\n \"tag\": "semiflex",\n \"popularity\": 35158\n },\n {\n \"tag\": "solstitially",\n \"popularity\": 35074\n },\n {\n \"tag\": "Algarsife",\n \"popularity\": 34991\n },\n {\n \"tag\": "noncriminal",\n \"popularity\": 34908\n },\n {\n \"tag\": "compassion",\n \"popularity\": 34825\n },\n {\n \"tag\": "Buddhic",\n \"popularity\": 34743\n },\n {\n \"tag\": "vellicative dactylically hotfoot",\n \"popularity\": 34661\n },\n {\n \"tag\": "chicory",\n \"popularity\": 34579\n },\n {\n \"tag\": "transperitoneally",\n \"popularity\": 34497\n },\n {\n \"tag\": "pennae",\n \"popularity\": 34416\n },\n {\n \"tag\": "Flamandize",\n \"popularity\": 34335\n },\n {\n \"tag\": "underviewer",\n \"popularity\": 34254\n },\n {\n \"tag\": "assoil",\n \"popularity\": 34174\n },\n {\n \"tag\": "saccharobacillus",\n \"popularity\": 34094\n },\n {\n \"tag\": "biacetylene",\n \"popularity\": 34014\n },\n {\n \"tag\": "mouchardism",\n \"popularity\": 33935\n },\n {\n \"tag\": "anisomeric",\n \"popularity\": 33856\n },\n {\n \"tag\": "digestive",\n \"popularity\": 33777\n },\n {\n \"tag\": "darlingly",\n \"popularity\": 33698\n },\n {\n \"tag\": "liman",\n \"popularity\": 33620\n },\n {\n \"tag\": "soldanrie",\n \"popularity\": 33542\n },\n {\n \"tag\": "sully",\n \"popularity\": 33464\n },\n {\n \"tag\": "brightsmith",\n \"popularity\": 33387\n },\n {\n \"tag\": "inwrap antiliturgist ureterocervical",\n \"popularity\": 33309\n },\n {\n \"tag\": "discommodity",\n \"popularity\": 33232\n },\n {\n \"tag\": "typical aggrandizer",\n \"popularity\": 33156\n },\n {\n \"tag\": "xenogeny",\n \"popularity\": 33079\n },\n {\n \"tag\": "uncountrified",\n \"popularity\": 33003\n },\n {\n \"tag\": "Podarge",\n \"popularity\": 32928\n },\n {\n \"tag\": "uninterviewed",\n \"popularity\": 32852\n },\n {\n \"tag\": "underprior",\n \"popularity\": 32777\n },\n {\n \"tag\": "leiomyomatous",\n \"popularity\": 32702\n },\n {\n \"tag\": "postdysenteric",\n \"popularity\": 32627\n },\n {\n \"tag\": "Fusicladium",\n \"popularity\": 32553\n },\n {\n \"tag\": "Dulcinea",\n \"popularity\": 32478\n },\n {\n \"tag\": "interspersion",\n \"popularity\": 32404\n },\n {\n \"tag\": "preobligate",\n \"popularity\": 32331\n },\n {\n \"tag\": "subaggregate",\n \"popularity\": 32257\n },\n {\n \"tag\": "grammarianism",\n \"popularity\": 32184\n },\n {\n \"tag\": "palikar",\n \"popularity\": 32111\n },\n {\n \"tag\": "facileness",\n \"popularity\": 32039\n },\n {\n \"tag\": "deuterofibrinose",\n \"popularity\": 31966\n },\n {\n \"tag\": "pseudesthesia",\n \"popularity\": 31894\n },\n {\n \"tag\": "sedimentary",\n \"popularity\": 31822\n },\n {\n \"tag\": "typewrite",\n \"popularity\": 31751\n },\n {\n \"tag\": "immemorable",\n \"popularity\": 31679\n },\n {\n \"tag\": "Myrtus",\n \"popularity\": 31608\n },\n {\n \"tag\": "hauchecornite",\n \"popularity\": 31537\n },\n {\n \"tag\": "galleylike",\n \"popularity\": 31467\n },\n {\n \"tag\": "thimber",\n \"popularity\": 31396\n },\n {\n \"tag\": "Hegelianism",\n \"popularity\": 31326\n },\n {\n \"tag\": "strig",\n \"popularity\": 31256\n },\n {\n \"tag\": "skyre",\n \"popularity\": 31187\n },\n {\n \"tag\": "eupepticism",\n \"popularity\": 31117\n },\n {\n \"tag\": "eponymism",\n \"popularity\": 31048\n },\n {\n \"tag\": "flunkeyhood",\n \"popularity\": 30979\n },\n {\n \"tag\": "Abama",\n \"popularity\": 30911\n },\n {\n \"tag\": "adiadochokinesis",\n \"popularity\": 30842\n },\n {\n \"tag\": "spendthrifty",\n \"popularity\": 30774\n },\n {\n \"tag\": "chalcedony",\n \"popularity\": 30706\n },\n {\n \"tag\": "authorism",\n \"popularity\": 30638\n },\n {\n \"tag\": "nasturtium",\n \"popularity\": 30571\n },\n {\n \"tag\": "Acanthocereus",\n \"popularity\": 30504\n },\n {\n \"tag\": "uncollapsible",\n \"popularity\": 30437\n },\n {\n \"tag\": "excursionist",\n \"popularity\": 30370\n },\n {\n \"tag\": "fogbow",\n \"popularity\": 30303\n },\n {\n \"tag\": "overlie",\n \"popularity\": 30237\n },\n {\n \"tag\": "velours",\n \"popularity\": 30171\n },\n {\n \"tag\": "zoodendria madrigal stagbush",\n \"popularity\": 30105\n },\n {\n \"tag\": "imi",\n \"popularity\": 30039\n },\n {\n \"tag\": "cojudge",\n \"popularity\": 29974\n },\n {\n \"tag\": "depurate argal",\n \"popularity\": 29909\n },\n {\n \"tag\": "unrecognition",\n \"popularity\": 29844\n },\n {\n \"tag\": "paunchful",\n \"popularity\": 29779\n },\n {\n \"tag\": "invalued",\n \"popularity\": 29714\n },\n {\n \"tag\": "probang",\n \"popularity\": 29650\n },\n {\n \"tag\": "chetvert",\n \"popularity\": 29586\n },\n {\n \"tag\": "enactable",\n \"popularity\": 29522\n },\n {\n \"tag\": "detoxicate adhibit",\n \"popularity\": 29458\n },\n {\n \"tag\": "kullaite",\n \"popularity\": 29395\n },\n {\n \"tag\": "undazzling",\n \"popularity\": 29332\n },\n {\n \"tag\": "excalation",\n \"popularity\": 29269\n },\n {\n \"tag\": "sievings",\n \"popularity\": 29206\n },\n {\n \"tag\": "disenthral",\n \"popularity\": 29143\n },\n {\n \"tag\": "disinterestedly",\n \"popularity\": 29081\n },\n {\n \"tag\": "stanner",\n \"popularity\": 29018\n },\n {\n \"tag\": "recapitulative",\n \"popularity\": 28956\n },\n {\n \"tag\": "objectivist",\n \"popularity\": 28895\n },\n {\n \"tag\": "hypermetropia",\n \"popularity\": 28833\n },\n {\n \"tag\": "incumbency",\n \"popularity\": 28772\n },\n {\n \"tag\": "protegee",\n \"popularity\": 28711\n },\n {\n \"tag\": "zealotic",\n \"popularity\": 28650\n },\n {\n \"tag\": "predebit",\n \"popularity\": 28589\n },\n {\n \"tag\": "cupolar",\n \"popularity\": 28528\n },\n {\n \"tag\": "unattributed",\n \"popularity\": 28468\n },\n {\n \"tag\": "louisine",\n \"popularity\": 28408\n },\n {\n \"tag\": "illustrate",\n \"popularity\": 28348\n },\n {\n \"tag\": "inofficiousness",\n \"popularity\": 28288\n },\n {\n \"tag\": "Americawards",\n \"popularity\": 28228\n },\n {\n \"tag\": "foreflap",\n \"popularity\": 28169\n },\n {\n \"tag\": "eruditeness",\n \"popularity\": 28110\n },\n {\n \"tag\": "copiopsia",\n \"popularity\": 28051\n },\n {\n \"tag\": "sporuliferous",\n \"popularity\": 27992\n },\n {\n \"tag\": "muttering",\n \"popularity\": 27934\n },\n {\n \"tag\": "prepsychology adrip",\n \"popularity\": 27875\n },\n {\n \"tag\": "unfriendly",\n \"popularity\": 27817\n },\n {\n \"tag\": "sulphanilic",\n \"popularity\": 27759\n },\n {\n \"tag\": "Coelococcus",\n \"popularity\": 27701\n },\n {\n \"tag\": "undoubtfulness",\n \"popularity\": 27643\n },\n {\n \"tag\": "flaringly",\n \"popularity\": 27586\n },\n {\n \"tag\": "unordain",\n \"popularity\": 27529\n },\n {\n \"tag\": "fratchety",\n \"popularity\": 27472\n },\n {\n \"tag\": "decadentism dolefully",\n \"popularity\": 27415\n },\n {\n \"tag\": "synthronus",\n \"popularity\": 27358\n },\n {\n \"tag\": "maiid",\n \"popularity\": 27301\n },\n {\n \"tag\": "rhinobyon",\n \"popularity\": 27245\n },\n {\n \"tag\": "Didynamia",\n \"popularity\": 27189\n },\n {\n \"tag\": "millionairedom",\n \"popularity\": 27133\n },\n {\n \"tag\": "mulierine",\n \"popularity\": 27077\n },\n {\n \"tag\": "Mayo",\n \"popularity\": 27021\n },\n {\n \"tag\": "perceivedness",\n \"popularity\": 26966\n },\n {\n \"tag\": "unadoration",\n \"popularity\": 26911\n },\n {\n \"tag\": "regraft",\n \"popularity\": 26856\n },\n {\n \"tag\": "witch",\n \"popularity\": 26801\n },\n {\n \"tag\": "ungrow",\n \"popularity\": 26746\n },\n {\n \"tag\": "glossopharyngeus",\n \"popularity\": 26691\n },\n {\n \"tag\": "unstirrable",\n \"popularity\": 26637\n },\n {\n \"tag\": "synodsman",\n \"popularity\": 26583\n },\n {\n \"tag\": "placentalian",\n \"popularity\": 26529\n },\n {\n \"tag\": "corpulently",\n \"popularity\": 26475\n },\n {\n \"tag\": "photochromoscope",\n \"popularity\": 26421\n },\n {\n \"tag\": "indusiate retinasphaltum chokestrap",\n \"popularity\": 26368\n },\n {\n \"tag\": "murdrum",\n \"popularity\": 26314\n },\n {\n \"tag\": "belatedness",\n \"popularity\": 26261\n },\n {\n \"tag\": "Cochin",\n \"popularity\": 26208\n },\n {\n \"tag\": "Leonist",\n \"popularity\": 26155\n },\n {\n \"tag\": "keeker confined",\n \"popularity\": 26102\n },\n {\n \"tag\": "unintellectual",\n \"popularity\": 26050\n },\n {\n \"tag\": "nymphaline bait",\n \"popularity\": 25997\n },\n {\n \"tag\": "sarcosporidiosis",\n \"popularity\": 25945\n },\n {\n \"tag\": "catawamptiously",\n \"popularity\": 25893\n },\n {\n \"tag\": "outshame",\n \"popularity\": 25841\n },\n {\n \"tag\": "animalism",\n \"popularity\": 25790\n },\n {\n \"tag\": "epithalamial",\n \"popularity\": 25738\n },\n {\n \"tag\": "ganner",\n \"popularity\": 25687\n },\n {\n \"tag\": "desilicify",\n \"popularity\": 25635\n },\n {\n \"tag\": "dandyism",\n \"popularity\": 25584\n },\n {\n \"tag\": "hyleg",\n \"popularity\": 25533\n },\n {\n \"tag\": "photophysical",\n \"popularity\": 25483\n },\n {\n \"tag\": "underload",\n \"popularity\": 25432\n },\n {\n \"tag\": "unintrusive",\n \"popularity\": 25382\n },\n {\n \"tag\": "succinamic",\n \"popularity\": 25331\n },\n {\n \"tag\": "matchy",\n \"popularity\": 25281\n },\n {\n \"tag\": "concordal",\n \"popularity\": 25231\n },\n {\n \"tag\": "exteriority",\n \"popularity\": 25181\n },\n {\n \"tag\": "sterculiad",\n \"popularity\": 25132\n },\n {\n \"tag\": "sulfoxylic",\n \"popularity\": 25082\n },\n {\n \"tag\": "oversubscription",\n \"popularity\": 25033\n },\n {\n \"tag\": "chiasmic",\n \"popularity\": 24984\n },\n {\n \"tag\": "pseudoparthenogenesis",\n \"popularity\": 24935\n },\n {\n \"tag\": "indorse",\n \"popularity\": 24886\n },\n {\n \"tag\": "Krishnaite",\n \"popularity\": 24837\n },\n {\n \"tag\": "calcinize",\n \"popularity\": 24788\n },\n {\n \"tag\": "rhodium",\n \"popularity\": 24740\n },\n {\n \"tag\": "tragopan",\n \"popularity\": 24692\n },\n {\n \"tag\": "overwhelmingly",\n \"popularity\": 24643\n },\n {\n \"tag\": "procidence accorporate",\n \"popularity\": 24595\n },\n {\n \"tag\": "polemize speelless",\n \"popularity\": 24548\n },\n {\n \"tag\": "radiocarpal goran",\n \"popularity\": 24500\n },\n {\n \"tag\": "counteroffer Pelodytes",\n \"popularity\": 24452\n },\n {\n \"tag\": "lionhearted",\n \"popularity\": 24405\n },\n {\n \"tag\": "paramastoid",\n \"popularity\": 24358\n },\n {\n \"tag\": "murine",\n \"popularity\": 24310\n },\n {\n \"tag\": "woodbined",\n \"popularity\": 24263\n },\n {\n \"tag\": "packthread",\n \"popularity\": 24217\n },\n {\n \"tag\": "citreous",\n \"popularity\": 24170\n },\n {\n \"tag\": "unfallaciously",\n \"popularity\": 24123\n },\n {\n \"tag\": "tentwork reincarnadine",\n \"popularity\": 24077\n },\n {\n \"tag\": "verminousness",\n \"popularity\": 24030\n },\n {\n \"tag\": "sillometer",\n \"popularity\": 23984\n },\n {\n \"tag\": "jointy",\n \"popularity\": 23938\n },\n {\n \"tag\": "streptolysin",\n \"popularity\": 23892\n },\n {\n \"tag\": "Florentinism",\n \"popularity\": 23847\n },\n {\n \"tag\": "monosomatous",\n \"popularity\": 23801\n },\n {\n \"tag\": "capsulociliary",\n \"popularity\": 23756\n },\n {\n \"tag\": "organum",\n \"popularity\": 23710\n },\n {\n \"tag\": "overtly",\n \"popularity\": 23665\n },\n {\n \"tag\": "ophthalmoscopical",\n \"popularity\": 23620\n },\n {\n \"tag\": "supposititiously",\n \"popularity\": 23575\n },\n {\n \"tag\": "radiochemistry",\n \"popularity\": 23530\n },\n {\n \"tag\": "flaxtail",\n \"popularity\": 23486\n },\n {\n \"tag\": "pretympanic",\n \"popularity\": 23441\n },\n {\n \"tag\": "auscultation",\n \"popularity\": 23397\n },\n {\n \"tag\": "hairdresser",\n \"popularity\": 23352\n },\n {\n \"tag\": "chaffless",\n \"popularity\": 23308\n },\n {\n \"tag\": "polioencephalitis",\n \"popularity\": 23264\n },\n {\n \"tag\": "axolotl",\n \"popularity\": 23220\n },\n {\n \"tag\": "smous",\n \"popularity\": 23177\n },\n {\n \"tag\": "morgen disenamour toothed",\n \"popularity\": 23133\n },\n {\n \"tag\": "chaiseless",\n \"popularity\": 23089\n },\n {\n \"tag\": "frugally",\n \"popularity\": 23046\n },\n {\n \"tag\": "combustive antievolutionist cinenegative",\n \"popularity\": 23003\n },\n {\n \"tag\": "malacolite",\n \"popularity\": 22960\n },\n {\n \"tag\": "borne",\n \"popularity\": 22917\n },\n {\n \"tag\": "mercaptole",\n \"popularity\": 22874\n },\n {\n \"tag\": "judicatory",\n \"popularity\": 22831\n },\n {\n \"tag\": "noctivagation",\n \"popularity\": 22789\n },\n {\n \"tag\": "synthete",\n \"popularity\": 22746\n },\n {\n \"tag\": "tomboyism",\n \"popularity\": 22704\n },\n {\n \"tag\": "serranoid",\n \"popularity\": 22661\n },\n {\n \"tag\": "impostorism",\n \"popularity\": 22619\n },\n {\n \"tag\": "flagellosis Talitha",\n \"popularity\": 22577\n },\n {\n \"tag\": "pseudoviscous",\n \"popularity\": 22535\n },\n {\n \"tag\": "Galleriidae",\n \"popularity\": 22494\n },\n {\n \"tag\": "undulation didelph Comintern",\n \"popularity\": 22452\n },\n {\n \"tag\": "triangulopyramidal",\n \"popularity\": 22411\n },\n {\n \"tag\": "middlings",\n \"popularity\": 22369\n },\n {\n \"tag\": "piperazin",\n \"popularity\": 22328\n },\n {\n \"tag\": "endostitis",\n \"popularity\": 22287\n },\n {\n \"tag\": "swordlike",\n \"popularity\": 22246\n },\n {\n \"tag\": "forthwith",\n \"popularity\": 22205\n },\n {\n \"tag\": "menaceful",\n \"popularity\": 22164\n },\n {\n \"tag\": "explantation defective",\n \"popularity\": 22123\n },\n {\n \"tag\": "arrear",\n \"popularity\": 22083\n },\n {\n \"tag\": "engraft",\n \"popularity\": 22042\n },\n {\n \"tag\": "revolunteer",\n \"popularity\": 22002\n },\n {\n \"tag\": "foliaceous",\n \"popularity\": 21962\n },\n {\n \"tag\": "pseudograph",\n \"popularity\": 21922\n },\n {\n \"tag\": "maenaite",\n \"popularity\": 21882\n },\n {\n \"tag\": "interfinger",\n \"popularity\": 21842\n },\n {\n \"tag\": "macroscopically",\n \"popularity\": 21802\n },\n {\n \"tag\": "bluewood",\n \"popularity\": 21762\n },\n {\n \"tag\": "chikara",\n \"popularity\": 21723\n },\n {\n \"tag\": "reprehension diazeuxis nickelous",\n \"popularity\": 21683\n },\n {\n \"tag\": "vacuation",\n \"popularity\": 21644\n },\n {\n \"tag\": "Sartish",\n \"popularity\": 21605\n },\n {\n \"tag\": "pseudogyny",\n \"popularity\": 21566\n },\n {\n \"tag\": "friedcake",\n \"popularity\": 21527\n },\n {\n \"tag\": "thraw",\n \"popularity\": 21488\n },\n {\n \"tag\": "bifid",\n \"popularity\": 21449\n },\n {\n \"tag\": "truthlessly",\n \"popularity\": 21411\n },\n {\n \"tag\": "lungy",\n \"popularity\": 21372\n },\n {\n \"tag\": "fluoborite",\n \"popularity\": 21334\n },\n {\n \"tag\": "anthropolithic",\n \"popularity\": 21295\n },\n {\n \"tag\": "coachee straw",\n \"popularity\": 21257\n },\n {\n \"tag\": "dehorner Grecize",\n \"popularity\": 21219\n },\n {\n \"tag\": "spondylopyosis",\n \"popularity\": 21181\n },\n {\n \"tag\": "institutionary",\n \"popularity\": 21143\n },\n {\n \"tag\": "agentry",\n \"popularity\": 21105\n },\n {\n \"tag\": "musing bietle",\n \"popularity\": 21068\n },\n {\n \"tag\": "cormophyte",\n \"popularity\": 21030\n },\n {\n \"tag\": "semielliptic",\n \"popularity\": 20993\n },\n {\n \"tag\": "ependytes",\n \"popularity\": 20955\n },\n {\n \"tag\": "coachmaster",\n \"popularity\": 20918\n },\n {\n \"tag\": "overexuberant",\n \"popularity\": 20881\n },\n {\n \"tag\": "selectable",\n \"popularity\": 20844\n },\n {\n \"tag\": "saclike",\n \"popularity\": 20807\n },\n {\n \"tag\": "mullion",\n \"popularity\": 20770\n },\n {\n \"tag\": "pantheonize prevalency",\n \"popularity\": 20733\n },\n {\n \"tag\": "trophosperm",\n \"popularity\": 20697\n },\n {\n \"tag\": "paraphrasist",\n \"popularity\": 20660\n },\n {\n \"tag\": "undercarry",\n \"popularity\": 20624\n },\n {\n \"tag\": "thallogenic",\n \"popularity\": 20587\n },\n {\n \"tag\": "bulgy forbid",\n \"popularity\": 20551\n },\n {\n \"tag\": "proliquor gratulatory",\n \"popularity\": 20515\n },\n {\n \"tag\": "booker",\n \"popularity\": 20479\n },\n {\n \"tag\": "wizen",\n \"popularity\": 20443\n },\n {\n \"tag\": "synchondrosially",\n \"popularity\": 20407\n },\n {\n \"tag\": "herbless",\n \"popularity\": 20371\n },\n {\n \"tag\": "arfvedsonite",\n \"popularity\": 20336\n },\n {\n \"tag\": "Neuroptera",\n \"popularity\": 20300\n },\n {\n \"tag\": "fingerstone",\n \"popularity\": 20265\n },\n {\n \"tag\": "Odontoglossae",\n \"popularity\": 20229\n },\n {\n \"tag\": "transmigrator",\n \"popularity\": 20194\n },\n {\n \"tag\": "Dehaites",\n \"popularity\": 20159\n },\n {\n \"tag\": "Molinist",\n \"popularity\": 20124\n },\n {\n \"tag\": "novelistic",\n \"popularity\": 20089\n },\n {\n \"tag\": "astelic",\n \"popularity\": 20054\n },\n {\n \"tag\": "pyelometry",\n \"popularity\": 20019\n },\n {\n \"tag\": "pigmentation",\n \"popularity\": 19984\n },\n {\n \"tag\": "epinaos",\n \"popularity\": 19950\n },\n {\n \"tag\": "outdare",\n \"popularity\": 19915\n },\n {\n \"tag\": "Funje philaristocracy",\n \"popularity\": 19881\n },\n {\n \"tag\": "keddah",\n \"popularity\": 19846\n },\n {\n \"tag\": "axoidean",\n \"popularity\": 19812\n },\n {\n \"tag\": "ovule",\n \"popularity\": 19778\n },\n {\n \"tag\": "solidify",\n \"popularity\": 19744\n },\n {\n \"tag\": "noncelestial",\n \"popularity\": 19710\n },\n {\n \"tag\": "overmultiplication",\n \"popularity\": 19676\n },\n {\n \"tag\": "hexatetrahedron",\n \"popularity\": 19642\n },\n {\n \"tag\": "pliciform",\n \"popularity\": 19609\n },\n {\n \"tag\": "zimbalon",\n \"popularity\": 19575\n },\n {\n \"tag\": "annexational",\n \"popularity\": 19542\n },\n {\n \"tag\": "eurhodol",\n \"popularity\": 19508\n },\n {\n \"tag\": "yark",\n \"popularity\": 19475\n },\n {\n \"tag\": "illegality nitroalizarin",\n \"popularity\": 19442\n },\n {\n \"tag\": "quadratum",\n \"popularity\": 19409\n },\n {\n \"tag\": "saccharine",\n \"popularity\": 19376\n },\n {\n \"tag\": "unemploy",\n \"popularity\": 19343\n },\n {\n \"tag\": "uniclinal unipotent",\n \"popularity\": 19310\n },\n {\n \"tag\": "turbo",\n \"popularity\": 19277\n },\n {\n \"tag\": "sybarism",\n \"popularity\": 19244\n },\n {\n \"tag\": "motacilline",\n \"popularity\": 19212\n },\n {\n \"tag\": "weaselly",\n \"popularity\": 19179\n },\n {\n \"tag\": "plastid",\n \"popularity\": 19147\n },\n {\n \"tag\": "wasting",\n \"popularity\": 19114\n },\n {\n \"tag\": "begrime fluting",\n \"popularity\": 19082\n },\n {\n \"tag\": "Nephilinae",\n \"popularity\": 19050\n },\n {\n \"tag\": "disregardance",\n \"popularity\": 19018\n },\n {\n \"tag\": "Shakerlike",\n \"popularity\": 18986\n },\n {\n \"tag\": "uniped",\n \"popularity\": 18954\n },\n {\n \"tag\": "knap",\n \"popularity\": 18922\n },\n {\n \"tag\": "electivism undergardener",\n \"popularity\": 18890\n },\n {\n \"tag\": "hulverheaded",\n \"popularity\": 18858\n },\n {\n \"tag\": "unruptured",\n \"popularity\": 18827\n },\n {\n \"tag\": "solemnize credently",\n \"popularity\": 18795\n },\n {\n \"tag\": "pentastomoid possessingly",\n \"popularity\": 18764\n },\n {\n \"tag\": "octose",\n \"popularity\": 18733\n },\n {\n \"tag\": "psithurism indefensibility",\n \"popularity\": 18701\n },\n {\n \"tag\": "torrentuous cyanometer subcrenate",\n \"popularity\": 18670\n },\n {\n \"tag\": "photoplaywright tapaculo",\n \"popularity\": 18639\n },\n {\n \"tag\": "univalence",\n \"popularity\": 18608\n },\n {\n \"tag\": "Porthetria",\n \"popularity\": 18577\n },\n {\n \"tag\": "funambulo",\n \"popularity\": 18546\n },\n {\n \"tag\": "pedion",\n \"popularity\": 18515\n },\n {\n \"tag\": "horticulturally",\n \"popularity\": 18485\n },\n {\n \"tag\": "marennin",\n \"popularity\": 18454\n },\n {\n \"tag\": "horselaugh",\n \"popularity\": 18423\n },\n {\n \"tag\": "semiexecutive",\n \"popularity\": 18393\n },\n {\n \"tag\": "Monopteridae",\n \"popularity\": 18363\n },\n {\n \"tag\": "commonable",\n \"popularity\": 18332\n },\n {\n \"tag\": "dreariment",\n \"popularity\": 18302\n },\n {\n \"tag\": "disbud",\n \"popularity\": 18272\n },\n {\n \"tag\": "monocled",\n \"popularity\": 18242\n },\n {\n \"tag\": "hurlbarrow",\n \"popularity\": 18212\n },\n {\n \"tag\": "opiateproof",\n \"popularity\": 18182\n },\n {\n \"tag\": "Fahrenheit",\n \"popularity\": 18152\n },\n {\n \"tag\": "writhed",\n \"popularity\": 18122\n },\n {\n \"tag\": "Volstead",\n \"popularity\": 18093\n },\n {\n \"tag\": "yesternight",\n \"popularity\": 18063\n },\n {\n \"tag\": "readmittance",\n \"popularity\": 18033\n },\n {\n \"tag\": "reiterable",\n \"popularity\": 18004\n },\n {\n \"tag\": "triquetral",\n \"popularity\": 17975\n },\n {\n \"tag\": "guillotinement",\n \"popularity\": 17945\n },\n {\n \"tag\": "repermission",\n \"popularity\": 17916\n },\n {\n \"tag\": "assishly",\n \"popularity\": 17887\n },\n {\n \"tag\": "daidle",\n \"popularity\": 17858\n },\n {\n \"tag\": "prismatoid",\n \"popularity\": 17829\n },\n {\n \"tag\": "irreptitious",\n \"popularity\": 17800\n },\n {\n \"tag\": "sourdeline",\n \"popularity\": 17771\n },\n {\n \"tag\": "Austrian",\n \"popularity\": 17742\n },\n {\n \"tag\": "psychorrhagic",\n \"popularity\": 17713\n },\n {\n \"tag\": "Monumbo",\n \"popularity\": 17685\n },\n {\n \"tag\": "cloiochoanitic",\n \"popularity\": 17656\n },\n {\n \"tag\": "hant",\n \"popularity\": 17628\n },\n {\n \"tag\": "roily pulldown",\n \"popularity\": 17599\n },\n {\n \"tag\": "recongratulation",\n \"popularity\": 17571\n },\n {\n \"tag\": "Peking",\n \"popularity\": 17543\n },\n {\n \"tag\": "erdvark",\n \"popularity\": 17514\n },\n {\n \"tag\": "antimnemonic",\n \"popularity\": 17486\n },\n {\n \"tag\": "noncapillarity",\n \"popularity\": 17458\n },\n {\n \"tag\": "irrepressive",\n \"popularity\": 17430\n },\n {\n \"tag\": "Petromyzontes",\n \"popularity\": 17402\n },\n {\n \"tag\": "piscatorially",\n \"popularity\": 17374\n },\n {\n \"tag\": "cholesterosis",\n \"popularity\": 17346\n },\n {\n \"tag\": "denunciate",\n \"popularity\": 17319\n },\n {\n \"tag\": "unmetalled",\n \"popularity\": 17291\n },\n {\n \"tag\": "Tigris enruin",\n \"popularity\": 17263\n },\n {\n \"tag\": "anaspalin",\n \"popularity\": 17236\n },\n {\n \"tag\": "monodromy",\n \"popularity\": 17208\n },\n {\n \"tag\": "Canichanan",\n \"popularity\": 17181\n },\n {\n \"tag\": "mesolabe",\n \"popularity\": 17154\n },\n {\n \"tag\": "trichothallic overcunningness",\n \"popularity\": 17127\n },\n {\n \"tag\": "spinsterishly",\n \"popularity\": 17099\n },\n {\n \"tag\": "sensilla",\n \"popularity\": 17072\n },\n {\n \"tag\": "wifelkin",\n \"popularity\": 17045\n },\n {\n \"tag\": "suppositionless",\n \"popularity\": 17018\n },\n {\n \"tag\": "irksomeness",\n \"popularity\": 16991\n },\n {\n \"tag\": "sanbenito",\n \"popularity\": 16964\n },\n {\n \"tag\": "nonstatement",\n \"popularity\": 16938\n },\n {\n \"tag\": "phenoloid",\n \"popularity\": 16911\n },\n {\n \"tag\": "Steinberger",\n \"popularity\": 16884\n },\n {\n \"tag\": "replicated boom",\n \"popularity\": 16858\n },\n {\n \"tag\": "sciomachiology",\n \"popularity\": 16831\n },\n {\n \"tag\": "starwise",\n \"popularity\": 16805\n },\n {\n \"tag\": "prerich",\n \"popularity\": 16778\n },\n {\n \"tag\": "unspawned",\n \"popularity\": 16752\n },\n {\n \"tag\": "unindentable",\n \"popularity\": 16726\n },\n {\n \"tag\": "stromatic",\n \"popularity\": 16700\n },\n {\n \"tag\": "fetishize",\n \"popularity\": 16673\n },\n {\n \"tag\": "dihydroxy",\n \"popularity\": 16647\n },\n {\n \"tag\": "precaudal",\n \"popularity\": 16621\n },\n {\n \"tag\": "Madagascar",\n \"popularity\": 16595\n },\n {\n \"tag\": "repinement",\n \"popularity\": 16570\n },\n {\n \"tag\": "noncathedral wenzel",\n \"popularity\": 16544\n },\n {\n \"tag\": "corollike",\n \"popularity\": 16518\n },\n {\n \"tag\": "pubes unamortization",\n \"popularity\": 16492\n },\n {\n \"tag\": "brickcroft",\n \"popularity\": 16467\n },\n {\n \"tag\": "intertrabecular",\n \"popularity\": 16441\n },\n {\n \"tag\": "formulaic",\n \"popularity\": 16416\n },\n {\n \"tag\": "arienzo",\n \"popularity\": 16390\n },\n {\n \"tag\": "Mazzinian",\n \"popularity\": 16365\n },\n {\n \"tag\": "wallowishly",\n \"popularity\": 16339\n },\n {\n \"tag\": "sysselman",\n \"popularity\": 16314\n },\n {\n \"tag\": "seligmannite",\n \"popularity\": 16289\n },\n {\n \"tag\": "harlequinery",\n \"popularity\": 16264\n },\n {\n \"tag\": "zucchetto",\n \"popularity\": 16239\n },\n {\n \"tag\": "malonyl",\n \"popularity\": 16214\n },\n {\n \"tag\": "patwari",\n \"popularity\": 16189\n },\n {\n \"tag\": "neoholmia venturesomeness",\n \"popularity\": 16164\n },\n {\n \"tag\": "Dehwar",\n \"popularity\": 16139\n },\n {\n \"tag\": "fetiferous",\n \"popularity\": 16114\n },\n {\n \"tag\": "chromatophore",\n \"popularity\": 16090\n },\n {\n \"tag\": "reregistration",\n \"popularity\": 16065\n },\n {\n \"tag\": "alienor",\n \"popularity\": 16040\n },\n {\n \"tag\": "Hexagynia",\n \"popularity\": 16016\n },\n {\n \"tag\": "cerebrotonia",\n \"popularity\": 15991\n },\n {\n \"tag\": "deedbox",\n \"popularity\": 15967\n },\n {\n \"tag\": "staab",\n \"popularity\": 15943\n },\n {\n \"tag\": "uratemia",\n \"popularity\": 15918\n },\n {\n \"tag\": "flaunt",\n \"popularity\": 15894\n },\n {\n \"tag\": "bogy",\n \"popularity\": 15870\n },\n {\n \"tag\": "subcartilaginous",\n \"popularity\": 15846\n },\n {\n \"tag\": "protonephridial",\n \"popularity\": 15822\n },\n {\n \"tag\": "Boswellia",\n \"popularity\": 15798\n },\n {\n \"tag\": "relaxant untiaraed protoepiphyte",\n \"popularity\": 15774\n },\n {\n \"tag\": "nesslerization",\n \"popularity\": 15750\n },\n {\n \"tag\": "precession",\n \"popularity\": 15726\n },\n {\n \"tag\": "peat",\n \"popularity\": 15702\n },\n {\n \"tag\": "unbit",\n \"popularity\": 15678\n },\n {\n \"tag\": "snailish",\n \"popularity\": 15655\n },\n {\n \"tag\": "porismatical",\n \"popularity\": 15631\n },\n {\n \"tag\": "hooflike",\n \"popularity\": 15608\n },\n {\n \"tag\": "resuppose phene cranic",\n \"popularity\": 15584\n },\n {\n \"tag\": "peptonization kipskin",\n \"popularity\": 15561\n },\n {\n \"tag\": "birdstone",\n \"popularity\": 15537\n },\n {\n \"tag\": "empty inferoanterior",\n \"popularity\": 15514\n },\n {\n \"tag\": "androtauric",\n \"popularity\": 15491\n },\n {\n \"tag\": "triamide",\n \"popularity\": 15467\n },\n {\n \"tag\": "showmanry",\n \"popularity\": 15444\n },\n {\n \"tag\": "doing",\n \"popularity\": 15421\n },\n {\n \"tag\": "bouchaleen",\n \"popularity\": 15398\n },\n {\n \"tag\": "precollude",\n \"popularity\": 15375\n },\n {\n \"tag\": "finger",\n \"popularity\": 15352\n },\n {\n \"tag\": "limnetic intermessenger",\n \"popularity\": 15329\n },\n {\n \"tag\": "uncharitable picrotoxic",\n \"popularity\": 15306\n },\n {\n \"tag\": "nationalizer Phasmidae",\n \"popularity\": 15283\n },\n {\n \"tag\": "laughingstock",\n \"popularity\": 15261\n },\n {\n \"tag\": "nondeferential",\n \"popularity\": 15238\n },\n {\n \"tag\": "uproariously",\n \"popularity\": 15215\n },\n {\n \"tag\": "manzanilla",\n \"popularity\": 15193\n },\n {\n \"tag\": "khahoon",\n \"popularity\": 15170\n },\n {\n \"tag\": "olericulturally longshanks",\n \"popularity\": 15148\n },\n {\n \"tag\": "enthusiastically methionic",\n \"popularity\": 15125\n },\n {\n \"tag\": "pobs",\n \"popularity\": 15103\n },\n {\n \"tag\": "tricarpellate",\n \"popularity\": 15081\n },\n {\n \"tag\": "souterrain",\n \"popularity\": 15058\n },\n {\n \"tag\": "tethelin",\n \"popularity\": 15036\n },\n {\n \"tag\": "tartle",\n \"popularity\": 15014\n },\n {\n \"tag\": "tidelike",\n \"popularity\": 14992\n },\n {\n \"tag\": "cosmoramic",\n \"popularity\": 14970\n },\n {\n \"tag\": "pretardiness",\n \"popularity\": 14948\n },\n {\n \"tag\": "insoul",\n \"popularity\": 14926\n },\n {\n \"tag\": "anthroxan",\n \"popularity\": 14904\n },\n {\n \"tag\": "jilter",\n \"popularity\": 14882\n },\n {\n \"tag\": "pectinibranchian trematode",\n \"popularity\": 14860\n },\n {\n \"tag\": "Renaissancist",\n \"popularity\": 14838\n },\n {\n \"tag\": "imaginant",\n \"popularity\": 14817\n },\n {\n \"tag\": "supercensure",\n \"popularity\": 14795\n },\n {\n \"tag\": "festilogy",\n \"popularity\": 14773\n },\n {\n \"tag\": "regression",\n \"popularity\": 14752\n },\n {\n \"tag\": "mesobregmate languorously",\n \"popularity\": 14730\n },\n {\n \"tag\": "unsupernaturalized",\n \"popularity\": 14709\n },\n {\n \"tag\": "boobyish",\n \"popularity\": 14687\n },\n {\n \"tag\": "scopolamine",\n \"popularity\": 14666\n },\n {\n \"tag\": "reamputation unchristianly",\n \"popularity\": 14645\n },\n {\n \"tag\": "cuneatic",\n \"popularity\": 14623\n },\n {\n \"tag\": "heathberry",\n \"popularity\": 14602\n },\n {\n \"tag\": "hate",\n \"popularity\": 14581\n },\n {\n \"tag\": "redeemableness",\n \"popularity\": 14560\n },\n {\n \"tag\": "damasse",\n \"popularity\": 14539\n },\n {\n \"tag\": "thrillsome",\n \"popularity\": 14518\n },\n {\n \"tag\": "disseverment",\n \"popularity\": 14497\n },\n {\n \"tag\": "underbishopric Ostyak",\n \"popularity\": 14476\n },\n {\n \"tag\": "Exoascales",\n \"popularity\": 14455\n },\n {\n \"tag\": "soiled",\n \"popularity\": 14434\n },\n {\n \"tag\": "Cain",\n \"popularity\": 14413\n },\n {\n \"tag\": "mismanageable arenae",\n \"popularity\": 14392\n },\n {\n \"tag\": "manducate unhinderably",\n \"popularity\": 14372\n },\n {\n \"tag\": "peregrin",\n \"popularity\": 14351\n },\n {\n \"tag\": "musicianly",\n \"popularity\": 14330\n },\n {\n \"tag\": "aln",\n \"popularity\": 14310\n },\n {\n \"tag\": "intercentrum",\n \"popularity\": 14289\n },\n {\n \"tag\": "roothold",\n \"popularity\": 14269\n },\n {\n \"tag\": "jane aneurism",\n \"popularity\": 14248\n },\n {\n \"tag\": "insinuatively forefeel phytolatrous",\n \"popularity\": 14228\n },\n {\n \"tag\": "kanchil",\n \"popularity\": 14208\n },\n {\n \"tag\": "Austrophile",\n \"popularity\": 14187\n },\n {\n \"tag\": "unterrorized",\n \"popularity\": 14167\n },\n {\n \"tag\": "admeasure",\n \"popularity\": 14147\n },\n {\n \"tag\": "electrodissolution",\n \"popularity\": 14127\n },\n {\n \"tag\": "unweddedly",\n \"popularity\": 14107\n },\n {\n \"tag\": "unannoying",\n \"popularity\": 14087\n },\n {\n \"tag\": "uningenuous",\n \"popularity\": 14067\n },\n {\n \"tag\": "omnibenevolent",\n \"popularity\": 14047\n },\n {\n \"tag\": "commissure",\n \"popularity\": 14027\n },\n {\n \"tag\": "tellureted",\n \"popularity\": 14007\n },\n {\n \"tag\": "suffragan",\n \"popularity\": 13987\n },\n {\n \"tag\": "sphaeriaceous",\n \"popularity\": 13967\n },\n {\n \"tag\": "unfearing",\n \"popularity\": 13947\n },\n {\n \"tag\": "stentoriousness precounsellor",\n \"popularity\": 13928\n },\n {\n \"tag\": "haemaspectroscope",\n \"popularity\": 13908\n },\n {\n \"tag\": "teras",\n \"popularity\": 13888\n },\n {\n \"tag\": "pulicine",\n \"popularity\": 13869\n },\n {\n \"tag\": "colicystopyelitis",\n \"popularity\": 13849\n },\n {\n \"tag\": "Physalia",\n \"popularity\": 13830\n },\n {\n \"tag\": "Saxicolidae",\n \"popularity\": 13810\n },\n {\n \"tag\": "peritonital",\n \"popularity\": 13791\n },\n {\n \"tag\": "dysphotic",\n \"popularity\": 13771\n },\n {\n \"tag\": "unabandoned",\n \"popularity\": 13752\n },\n {\n \"tag\": "rashful",\n \"popularity\": 13733\n },\n {\n \"tag\": "goodyness Manobo",\n \"popularity\": 13714\n },\n {\n \"tag\": "glaring",\n \"popularity\": 13694\n },\n {\n \"tag\": "horrorful",\n \"popularity\": 13675\n },\n {\n \"tag\": "intercepting",\n \"popularity\": 13656\n },\n {\n \"tag\": "semifine",\n \"popularity\": 13637\n },\n {\n \"tag\": "Gaypoo",\n \"popularity\": 13618\n },\n {\n \"tag\": "Metrosideros",\n \"popularity\": 13599\n },\n {\n \"tag\": "thoracicolumbar",\n \"popularity\": 13580\n },\n {\n \"tag\": "unserried",\n \"popularity\": 13561\n },\n {\n \"tag\": "keeperess cauterization",\n \"popularity\": 13542\n },\n {\n \"tag\": "administrant",\n \"popularity\": 13523\n },\n {\n \"tag\": "unpropitiatedness",\n \"popularity\": 13505\n },\n {\n \"tag\": "pensileness",\n \"popularity\": 13486\n },\n {\n \"tag\": "quinaldic unreceivable",\n \"popularity\": 13467\n },\n {\n \"tag\": "Carnaria",\n \"popularity\": 13448\n },\n {\n \"tag\": "azothionium wurrus",\n \"popularity\": 13430\n },\n {\n \"tag\": "mistresshood",\n \"popularity\": 13411\n },\n {\n \"tag\": "Savara",\n \"popularity\": 13393\n },\n {\n \"tag\": "dasyurine",\n \"popularity\": 13374\n },\n {\n \"tag\": "superideal",\n \"popularity\": 13356\n },\n {\n \"tag\": "Parisianize",\n \"popularity\": 13337\n },\n {\n \"tag\": "underearth",\n \"popularity\": 13319\n },\n {\n \"tag\": "athrogenic",\n \"popularity\": 13301\n },\n {\n \"tag\": "communicate",\n \"popularity\": 13282\n },\n {\n \"tag\": "denervation enworthed",\n \"popularity\": 13264\n },\n {\n \"tag\": "subbromide",\n \"popularity\": 13246\n },\n {\n \"tag\": "stenocoriasis",\n \"popularity\": 13228\n },\n {\n \"tag\": "facetiousness",\n \"popularity\": 13209\n },\n {\n \"tag\": "twaddling",\n \"popularity\": 13191\n },\n {\n \"tag\": "tetartoconid",\n \"popularity\": 13173\n },\n {\n \"tag\": "audiophile",\n \"popularity\": 13155\n },\n {\n \"tag\": "fustigate",\n \"popularity\": 13137\n },\n {\n \"tag\": "Sorbian cacophonia",\n \"popularity\": 13119\n },\n {\n \"tag\": "fondish",\n \"popularity\": 13101\n },\n {\n \"tag\": "endomastoiditis",\n \"popularity\": 13084\n },\n {\n \"tag\": "sniptious",\n \"popularity\": 13066\n },\n {\n \"tag\": "glochidiate",\n \"popularity\": 13048\n },\n {\n \"tag\": "polycarboxylic",\n \"popularity\": 13030\n },\n {\n \"tag\": "stamp",\n \"popularity\": 13012\n },\n {\n \"tag\": "tritonymph endotoxoid",\n \"popularity\": 12995\n },\n {\n \"tag\": "wolfskin",\n \"popularity\": 12977\n },\n {\n \"tag\": "oncosimeter",\n \"popularity\": 12959\n },\n {\n \"tag\": "outward",\n \"popularity\": 12942\n },\n {\n \"tag\": "circumscribed",\n \"popularity\": 12924\n },\n {\n \"tag\": "autohemolytic",\n \"popularity\": 12907\n },\n {\n \"tag\": "isorhamnose",\n \"popularity\": 12889\n },\n {\n \"tag\": "monarchomachic",\n \"popularity\": 12872\n },\n {\n \"tag\": "phaenomenon",\n \"popularity\": 12855\n },\n {\n \"tag\": "angiopressure",\n \"popularity\": 12837\n },\n {\n \"tag\": "similarize",\n \"popularity\": 12820\n },\n {\n \"tag\": "unseeable",\n \"popularity\": 12803\n },\n {\n \"tag\": "Toryize",\n \"popularity\": 12785\n },\n {\n \"tag\": "fruitling",\n \"popularity\": 12768\n },\n {\n \"tag\": "axle",\n \"popularity\": 12751\n },\n {\n \"tag\": "priestal cocked",\n \"popularity\": 12734\n },\n {\n \"tag\": "serotoxin",\n \"popularity\": 12717\n },\n {\n \"tag\": "unmovably",\n \"popularity\": 12700\n },\n {\n \"tag\": "darbha",\n \"popularity\": 12683\n },\n {\n \"tag\": "Mongolize",\n \"popularity\": 12666\n },\n {\n \"tag\": "clusteringly",\n \"popularity\": 12649\n },\n {\n \"tag\": "tendence",\n \"popularity\": 12632\n },\n {\n \"tag\": "foziness",\n \"popularity\": 12615\n },\n {\n \"tag\": "brickkiln lithify",\n \"popularity\": 12598\n },\n {\n \"tag\": "unpriest",\n \"popularity\": 12581\n },\n {\n \"tag\": "convincer",\n \"popularity\": 12564\n },\n {\n \"tag\": "mornlike",\n \"popularity\": 12548\n },\n {\n \"tag\": "overaddiction ostentatiousness",\n \"popularity\": 12531\n },\n {\n \"tag\": "diffusively moccasin pendom",\n \"popularity\": 12514\n },\n {\n \"tag\": "boose",\n \"popularity\": 12498\n },\n {\n \"tag\": "myonosus",\n \"popularity\": 12481\n },\n {\n \"tag\": "handsome",\n \"popularity\": 12464\n },\n {\n \"tag\": "paroxysmic",\n \"popularity\": 12448\n },\n {\n \"tag\": "Ulidian",\n \"popularity\": 12431\n },\n {\n \"tag\": "heartache",\n \"popularity\": 12415\n },\n {\n \"tag\": "torporize",\n \"popularity\": 12398\n },\n {\n \"tag\": "hippish",\n \"popularity\": 12382\n },\n {\n \"tag\": "stigmal militation",\n \"popularity\": 12366\n },\n {\n \"tag\": "matmaker",\n \"popularity\": 12349\n },\n {\n \"tag\": "marantaceous bivoluminous",\n \"popularity\": 12333\n },\n {\n \"tag\": "Uraniidae",\n \"popularity\": 12317\n },\n {\n \"tag\": "risper",\n \"popularity\": 12301\n },\n {\n \"tag\": "tintinnabulation",\n \"popularity\": 12284\n },\n {\n \"tag\": "tributorian",\n \"popularity\": 12268\n },\n {\n \"tag\": "ashamedly",\n \"popularity\": 12252\n },\n {\n \"tag\": "Macrourus",\n \"popularity\": 12236\n },\n {\n \"tag\": "Chora",\n \"popularity\": 12220\n },\n {\n \"tag\": "caul",\n \"popularity\": 12204\n },\n {\n \"tag\": "exsector",\n \"popularity\": 12188\n },\n {\n \"tag\": "acutish",\n \"popularity\": 12172\n },\n {\n \"tag\": "amphichrome",\n \"popularity\": 12156\n },\n {\n \"tag\": "guarder",\n \"popularity\": 12140\n },\n {\n \"tag\": "sculpturally",\n \"popularity\": 12124\n },\n {\n \"tag\": "benightmare",\n \"popularity\": 12108\n },\n {\n \"tag\": "chucky",\n \"popularity\": 12093\n },\n {\n \"tag\": "Venetian",\n \"popularity\": 12077\n },\n {\n \"tag\": "autotheater",\n \"popularity\": 12061\n },\n {\n \"tag\": "planarioid",\n \"popularity\": 12045\n },\n {\n \"tag\": "handkerchiefful",\n \"popularity\": 12030\n },\n {\n \"tag\": "fuliginousness potentize",\n \"popularity\": 12014\n },\n {\n \"tag\": "pantheum",\n \"popularity\": 11998\n },\n {\n \"tag\": "heavyweight",\n \"popularity\": 11983\n },\n {\n \"tag\": "unbrick",\n \"popularity\": 11967\n },\n {\n \"tag\": "duomachy",\n \"popularity\": 11952\n },\n {\n \"tag\": "polyphyodont",\n \"popularity\": 11936\n },\n {\n \"tag\": "hibernacle",\n \"popularity\": 11921\n },\n {\n \"tag\": "undistend",\n \"popularity\": 11905\n },\n {\n \"tag\": "hystericky",\n \"popularity\": 11890\n },\n {\n \"tag\": "paleolimnology",\n \"popularity\": 11875\n },\n {\n \"tag\": "cedarware",\n \"popularity\": 11859\n },\n {\n \"tag\": "overwrested",\n \"popularity\": 11844\n },\n {\n \"tag\": "Syriacism",\n \"popularity\": 11829\n },\n {\n \"tag\": "pretan",\n \"popularity\": 11813\n },\n {\n \"tag\": "formant",\n \"popularity\": 11798\n },\n {\n \"tag\": "pharmacopoeist Fedia",\n \"popularity\": 11783\n },\n {\n \"tag\": "exorcist eerisome",\n \"popularity\": 11768\n },\n {\n \"tag\": "separation",\n \"popularity\": 11753\n },\n {\n \"tag\": "infancy",\n \"popularity\": 11738\n },\n {\n \"tag\": "ecrasite",\n \"popularity\": 11723\n },\n {\n \"tag\": "propolize",\n \"popularity\": 11708\n },\n {\n \"tag\": "uncram phyllin",\n \"popularity\": 11693\n },\n {\n \"tag\": "thymopathy",\n \"popularity\": 11678\n },\n {\n \"tag\": "omniscient",\n \"popularity\": 11663\n },\n {\n \"tag\": "coussinet hazer",\n \"popularity\": 11648\n },\n {\n \"tag\": "contributiveness",\n \"popularity\": 11633\n },\n {\n \"tag\": "septifluous",\n \"popularity\": 11618\n },\n {\n \"tag\": "halfness",\n \"popularity\": 11603\n },\n {\n \"tag\": "tocher",\n \"popularity\": 11589\n },\n {\n \"tag\": "monotonist",\n \"popularity\": 11574\n },\n {\n \"tag\": "headchair",\n \"popularity\": 11559\n },\n {\n \"tag\": "everywhence",\n \"popularity\": 11544\n },\n {\n \"tag\": "gerate",\n \"popularity\": 11530\n },\n {\n \"tag\": "unrepellent",\n \"popularity\": 11515\n },\n {\n \"tag\": "inidoneous",\n \"popularity\": 11500\n },\n {\n \"tag\": "Rifi",\n \"popularity\": 11486\n },\n {\n \"tag\": "unstop",\n \"popularity\": 11471\n },\n {\n \"tag\": "conformer",\n \"popularity\": 11457\n },\n {\n \"tag\": "vivisectionally",\n \"popularity\": 11442\n },\n {\n \"tag\": "nonfinishing",\n \"popularity\": 11428\n },\n {\n \"tag\": "tyranness",\n \"popularity\": 11413\n },\n {\n \"tag\": "shepherdage havoc",\n \"popularity\": 11399\n },\n {\n \"tag\": "coronale",\n \"popularity\": 11385\n },\n {\n \"tag\": "airmarker",\n \"popularity\": 11370\n },\n {\n \"tag\": "subpanel",\n \"popularity\": 11356\n },\n {\n \"tag\": "conciliation",\n \"popularity\": 11342\n },\n {\n \"tag\": "supergun",\n \"popularity\": 11327\n },\n {\n \"tag\": "photoheliography",\n \"popularity\": 11313\n },\n {\n \"tag\": "cacosmia",\n \"popularity\": 11299\n },\n {\n \"tag\": "caressant",\n \"popularity\": 11285\n },\n {\n \"tag\": "swivet",\n \"popularity\": 11270\n },\n {\n \"tag\": "coddler",\n \"popularity\": 11256\n },\n {\n \"tag\": "rakehellish",\n \"popularity\": 11242\n },\n {\n \"tag\": "recohabitation",\n \"popularity\": 11228\n },\n {\n \"tag\": "postillator",\n \"popularity\": 11214\n },\n {\n \"tag\": "receipt",\n \"popularity\": 11200\n },\n {\n \"tag\": "nonconformistical",\n \"popularity\": 11186\n },\n {\n \"tag\": "unglorified",\n \"popularity\": 11172\n },\n {\n \"tag\": "unordinariness",\n \"popularity\": 11158\n },\n {\n \"tag\": "tetrahydroxy",\n \"popularity\": 11144\n },\n {\n \"tag\": "haploperistomic corporeity",\n \"popularity\": 11130\n },\n {\n \"tag\": "varical",\n \"popularity\": 11117\n },\n {\n \"tag\": "pilferment",\n \"popularity\": 11103\n },\n {\n \"tag\": "reverentially playcraft",\n \"popularity\": 11089\n },\n {\n \"tag\": "unretentive",\n \"popularity\": 11075\n },\n {\n \"tag\": "readiness",\n \"popularity\": 11061\n },\n {\n \"tag\": "thermomagnetism",\n \"popularity\": 11048\n },\n {\n \"tag\": "spotless",\n \"popularity\": 11034\n },\n {\n \"tag\": "semishrubby",\n \"popularity\": 11020\n },\n {\n \"tag\": "metrotomy",\n \"popularity\": 11007\n },\n {\n \"tag\": "hocker",\n \"popularity\": 10993\n },\n {\n \"tag\": "anecdotal",\n \"popularity\": 10979\n },\n {\n \"tag\": "tetrabelodont",\n \"popularity\": 10966\n },\n {\n \"tag\": "Ramillied",\n \"popularity\": 10952\n },\n {\n \"tag\": "sympatheticism",\n \"popularity\": 10939\n },\n {\n \"tag\": "kiskatom",\n \"popularity\": 10925\n },\n {\n \"tag\": "concyclically",\n \"popularity\": 10912\n },\n {\n \"tag\": "tunicless",\n \"popularity\": 10899\n },\n {\n \"tag\": "formalistic",\n \"popularity\": 10885\n },\n {\n \"tag\": "thermacogenesis",\n \"popularity\": 10872\n },\n {\n \"tag\": "multimotored",\n \"popularity\": 10858\n },\n {\n \"tag\": "inversive",\n \"popularity\": 10845\n },\n {\n \"tag\": "Jatki",\n \"popularity\": 10832\n },\n {\n \"tag\": "highest",\n \"popularity\": 10818\n },\n {\n \"tag\": "rubidic",\n \"popularity\": 10805\n },\n {\n \"tag\": "acranial",\n \"popularity\": 10792\n },\n {\n \"tag\": "pulvinulus",\n \"popularity\": 10779\n },\n {\n \"tag\": "nattiness",\n \"popularity\": 10766\n },\n {\n \"tag\": "antisimoniacal",\n \"popularity\": 10752\n },\n {\n \"tag\": "tetanize",\n \"popularity\": 10739\n },\n {\n \"tag\": "spectrophobia",\n \"popularity\": 10726\n },\n {\n \"tag\": "monopolitical",\n \"popularity\": 10713\n },\n {\n \"tag\": "teallite",\n \"popularity\": 10700\n },\n {\n \"tag\": "alicyclic interpellator",\n \"popularity\": 10687\n },\n {\n \"tag\": "nonsynthesized",\n \"popularity\": 10674\n },\n {\n \"tag\": "wheelwrighting",\n \"popularity\": 10661\n },\n {\n \"tag\": "pelliculate",\n \"popularity\": 10648\n },\n {\n \"tag\": "Euphyllopoda",\n \"popularity\": 10635\n },\n {\n \"tag\": "graver",\n \"popularity\": 10622\n },\n {\n \"tag\": "automorph",\n \"popularity\": 10609\n },\n {\n \"tag\": "underhanded",\n \"popularity\": 10597\n },\n {\n \"tag\": "causal",\n \"popularity\": 10584\n },\n {\n \"tag\": "odoom",\n \"popularity\": 10571\n },\n {\n \"tag\": "apodictical",\n \"popularity\": 10558\n },\n {\n \"tag\": "foundery",\n \"popularity\": 10545\n },\n {\n \"tag\": "unneighbored",\n \"popularity\": 10533\n },\n {\n \"tag\": "woolshearing",\n \"popularity\": 10520\n },\n {\n \"tag\": "boschveld",\n \"popularity\": 10507\n },\n {\n \"tag\": "unhardened lipopod",\n \"popularity\": 10495\n },\n {\n \"tag\": "unenriching",\n \"popularity\": 10482\n },\n {\n \"tag\": "spak",\n \"popularity\": 10469\n },\n {\n \"tag\": "yogasana",\n \"popularity\": 10457\n },\n {\n \"tag\": "depoetize",\n \"popularity\": 10444\n },\n {\n \"tag\": "parousiamania",\n \"popularity\": 10432\n },\n {\n \"tag\": "longlegs",\n \"popularity\": 10419\n },\n {\n \"tag\": "gelatinizability",\n \"popularity\": 10407\n },\n {\n \"tag\": "edeology",\n \"popularity\": 10394\n },\n {\n \"tag\": "sodwork",\n \"popularity\": 10382\n },\n {\n \"tag\": "somnambule",\n \"popularity\": 10369\n },\n {\n \"tag\": "antiquing",\n \"popularity\": 10357\n },\n {\n \"tag\": "intaker",\n \"popularity\": 10344\n },\n {\n \"tag\": "Gerberia",\n \"popularity\": 10332\n },\n {\n \"tag\": "preadmit",\n \"popularity\": 10320\n },\n {\n \"tag\": "bullhorn",\n \"popularity\": 10307\n },\n {\n \"tag\": "sororal",\n \"popularity\": 10295\n },\n {\n \"tag\": "phaeophyceous",\n \"popularity\": 10283\n },\n {\n \"tag\": "omphalopsychite",\n \"popularity\": 10271\n },\n {\n \"tag\": "substantious",\n \"popularity\": 10258\n },\n {\n \"tag\": "undemonstratively",\n \"popularity\": 10246\n },\n {\n \"tag\": "corallike blackit",\n \"popularity\": 10234\n },\n {\n \"tag\": "amoebous",\n \"popularity\": 10222\n },\n {\n \"tag\": "Polypodium",\n \"popularity\": 10210\n },\n {\n \"tag\": "blodite",\n \"popularity\": 10198\n },\n {\n \"tag\": "hordarian",\n \"popularity\": 10186\n },\n {\n \"tag\": "nonmoral",\n \"popularity\": 10174\n },\n {\n \"tag\": "dredgeful",\n \"popularity\": 10162\n },\n {\n \"tag\": "nourishingly",\n \"popularity\": 10150\n },\n {\n \"tag\": "seamy",\n \"popularity\": 10138\n },\n {\n \"tag\": "vara",\n \"popularity\": 10126\n },\n {\n \"tag\": "incorruptibleness",\n \"popularity\": 10114\n },\n {\n \"tag\": "manipulator",\n \"popularity\": 10102\n },\n {\n \"tag\": "chromodiascope uncountably",\n \"popularity\": 10090\n },\n {\n \"tag\": "typhemia",\n \"popularity\": 10078\n },\n {\n \"tag\": "Smalcaldic",\n \"popularity\": 10066\n },\n {\n \"tag\": "precontrive",\n \"popularity\": 10054\n },\n {\n \"tag\": "sowarry",\n \"popularity\": 10042\n },\n {\n \"tag\": "monopodic",\n \"popularity\": 10031\n },\n {\n \"tag\": "recodify",\n \"popularity\": 10019\n },\n {\n \"tag\": "phosphowolframic rimple",\n \"popularity\": 10007\n },\n {\n \"tag\": "triconch",\n \"popularity\": 9995\n },\n {\n \"tag\": "pycnodontoid",\n \"popularity\": 9984\n },\n {\n \"tag\": "bradyspermatism",\n \"popularity\": 9972\n },\n {\n \"tag\": "extensionist",\n \"popularity\": 9960\n },\n {\n \"tag\": "characterize",\n \"popularity\": 9949\n },\n {\n \"tag\": "anatreptic proteolytic",\n \"popularity\": 9937\n },\n {\n \"tag\": "waterboard",\n \"popularity\": 9925\n },\n {\n \"tag\": "allopathically",\n \"popularity\": 9914\n },\n {\n \"tag\": "arithmetician",\n \"popularity\": 9902\n },\n {\n \"tag\": "subsist",\n \"popularity\": 9891\n },\n {\n \"tag\": "Islamitish",\n \"popularity\": 9879\n },\n {\n \"tag\": "biddy",\n \"popularity\": 9868\n },\n {\n \"tag\": "reverberation",\n \"popularity\": 9856\n },\n {\n \"tag\": "Zaporogue",\n \"popularity\": 9845\n },\n {\n \"tag\": "soapberry",\n \"popularity\": 9833\n },\n {\n \"tag\": "physiognomics",\n \"popularity\": 9822\n },\n {\n \"tag\": "hospitalization",\n \"popularity\": 9810\n },\n {\n \"tag\": "dissembler",\n \"popularity\": 9799\n },\n {\n \"tag\": "festinate",\n \"popularity\": 9788\n },\n {\n \"tag\": "angiectopia",\n \"popularity\": 9776\n },\n {\n \"tag\": "Pulicidae",\n \"popularity\": 9765\n },\n {\n \"tag\": "beslimer",\n \"popularity\": 9754\n },\n {\n \"tag\": "nontreaty",\n \"popularity\": 9743\n },\n {\n \"tag\": "unhaggled",\n \"popularity\": 9731\n },\n {\n \"tag\": "catfall",\n \"popularity\": 9720\n },\n {\n \"tag\": "stola",\n \"popularity\": 9709\n },\n {\n \"tag\": "pataco",\n \"popularity\": 9698\n },\n {\n \"tag\": "ontologistic",\n \"popularity\": 9686\n },\n {\n \"tag\": "aerosphere",\n \"popularity\": 9675\n },\n {\n \"tag\": "deobstruent",\n \"popularity\": 9664\n },\n {\n \"tag\": "threepence",\n \"popularity\": 9653\n },\n {\n \"tag\": "cyprinoid",\n \"popularity\": 9642\n },\n {\n \"tag\": "overbank",\n \"popularity\": 9631\n },\n {\n \"tag\": "prostyle",\n \"popularity\": 9620\n },\n {\n \"tag\": "photoactivation",\n \"popularity\": 9609\n },\n {\n \"tag\": "homothetic",\n \"popularity\": 9598\n },\n {\n \"tag\": "roguedom",\n \"popularity\": 9587\n },\n {\n \"tag\": "underschool",\n \"popularity\": 9576\n },\n {\n \"tag\": "tractility",\n \"popularity\": 9565\n },\n {\n \"tag\": "gardenin",\n \"popularity\": 9554\n },\n {\n \"tag\": "Micromastictora",\n \"popularity\": 9543\n },\n {\n \"tag\": "gossypine",\n \"popularity\": 9532\n },\n {\n \"tag\": "amylodyspepsia",\n \"popularity\": 9521\n },\n {\n \"tag\": "Luciana",\n \"popularity\": 9510\n },\n {\n \"tag\": "meetly nonfisherman",\n \"popularity\": 9500\n },\n {\n \"tag\": "backhanded",\n \"popularity\": 9489\n },\n {\n \"tag\": "decrustation",\n \"popularity\": 9478\n },\n {\n \"tag\": "pinrail",\n \"popularity\": 9467\n },\n {\n \"tag\": "Mahori",\n \"popularity\": 9456\n },\n {\n \"tag\": "unsizable",\n \"popularity\": 9446\n },\n {\n \"tag\": "disawa",\n \"popularity\": 9435\n },\n {\n \"tag\": "launderability inconsidered",\n \"popularity\": 9424\n },\n {\n \"tag\": "unclassical",\n \"popularity\": 9414\n },\n {\n \"tag\": "inobtrusiveness",\n \"popularity\": 9403\n },\n {\n \"tag\": "sialogenous",\n \"popularity\": 9392\n },\n {\n \"tag\": "sulphonamide",\n \"popularity\": 9382\n },\n {\n \"tag\": "diluvion",\n \"popularity\": 9371\n },\n {\n \"tag\": "deuteranope",\n \"popularity\": 9361\n },\n {\n \"tag\": "addition",\n \"popularity\": 9350\n },\n {\n \"tag\": "bockeret",\n \"popularity\": 9339\n },\n {\n \"tag\": "unidentified",\n \"popularity\": 9329\n },\n {\n \"tag\": "caryatic",\n \"popularity\": 9318\n },\n {\n \"tag\": "misattribution",\n \"popularity\": 9308\n },\n {\n \"tag\": "outray",\n \"popularity\": 9297\n },\n {\n \"tag\": "areometrical",\n \"popularity\": 9287\n },\n {\n \"tag\": "antilogism",\n \"popularity\": 9277\n },\n {\n \"tag\": "inadjustable",\n \"popularity\": 9266\n },\n {\n \"tag\": "byssus",\n \"popularity\": 9256\n },\n {\n \"tag\": "trun",\n \"popularity\": 9245\n },\n {\n \"tag\": "thereology",\n \"popularity\": 9235\n },\n {\n \"tag\": "extort",\n \"popularity\": 9225\n },\n {\n \"tag\": "bumpkin",\n \"popularity\": 9214\n },\n {\n \"tag\": "sulphobenzide",\n \"popularity\": 9204\n },\n {\n \"tag\": "hydrogeology",\n \"popularity\": 9194\n },\n {\n \"tag\": "nidulariaceous",\n \"popularity\": 9183\n },\n {\n \"tag\": "propodiale",\n \"popularity\": 9173\n },\n {\n \"tag\": "fierily",\n \"popularity\": 9163\n },\n {\n \"tag\": "aerotonometry",\n \"popularity\": 9153\n },\n {\n \"tag\": "pelobatid oversuperstitious",\n \"popularity\": 9142\n },\n {\n \"tag\": "restringent",\n \"popularity\": 9132\n },\n {\n \"tag\": "tetrapodic",\n \"popularity\": 9122\n },\n {\n \"tag\": "heroicness Vendidad",\n \"popularity\": 9112\n },\n {\n \"tag\": "Sphingurus",\n \"popularity\": 9102\n },\n {\n \"tag\": "sclerote",\n \"popularity\": 9092\n },\n {\n \"tag\": "unkeyed",\n \"popularity\": 9082\n },\n {\n \"tag\": "superparliamentary",\n \"popularity\": 9072\n },\n {\n \"tag\": "hetericism",\n \"popularity\": 9061\n },\n {\n \"tag\": "hucklebone",\n \"popularity\": 9051\n },\n {\n \"tag\": "yojan",\n \"popularity\": 9041\n },\n {\n \"tag\": "bossed",\n \"popularity\": 9031\n },\n {\n \"tag\": "spiderwork",\n \"popularity\": 9021\n },\n {\n \"tag\": "millfeed dullery",\n \"popularity\": 9011\n },\n {\n \"tag\": "adnoun",\n \"popularity\": 9001\n },\n {\n \"tag\": "mesometric",\n \"popularity\": 8992\n },\n {\n \"tag\": "doublehandedness",\n \"popularity\": 8982\n },\n {\n \"tag\": "suppurant",\n \"popularity\": 8972\n },\n {\n \"tag\": "Berlinize",\n \"popularity\": 8962\n },\n {\n \"tag\": "sontag",\n \"popularity\": 8952\n },\n {\n \"tag\": "biplane",\n \"popularity\": 8942\n },\n {\n \"tag\": "insula",\n \"popularity\": 8932\n },\n {\n \"tag\": "unbrand",\n \"popularity\": 8922\n },\n {\n \"tag\": "Basilosaurus",\n \"popularity\": 8913\n },\n {\n \"tag\": "prenomination",\n \"popularity\": 8903\n },\n {\n \"tag\": "untextual",\n \"popularity\": 8893\n },\n {\n \"tag\": "coleslaw",\n \"popularity\": 8883\n },\n {\n \"tag\": "langsyne",\n \"popularity\": 8874\n },\n {\n \"tag\": "impede",\n \"popularity\": 8864\n },\n {\n \"tag\": "irrigator",\n \"popularity\": 8854\n },\n {\n \"tag\": "deflocculation",\n \"popularity\": 8844\n },\n {\n \"tag\": "narghile",\n \"popularity\": 8835\n },\n {\n \"tag\": "unguardedly ebenaceous",\n \"popularity\": 8825\n },\n {\n \"tag\": "conversantly subocular",\n \"popularity\": 8815\n },\n {\n \"tag\": "hydroponic",\n \"popularity\": 8806\n },\n {\n \"tag\": "anthropopsychism",\n \"popularity\": 8796\n },\n {\n \"tag\": "panoptic",\n \"popularity\": 8787\n },\n {\n \"tag\": "insufferable",\n \"popularity\": 8777\n },\n {\n \"tag\": "salema",\n \"popularity\": 8768\n },\n {\n \"tag\": "Myriapoda",\n \"popularity\": 8758\n },\n {\n \"tag\": "regarrison",\n \"popularity\": 8748\n },\n {\n \"tag\": "overlearned",\n \"popularity\": 8739\n },\n {\n \"tag\": "ultraroyalist conventical bureaucratical",\n \"popularity\": 8729\n },\n {\n \"tag\": "epicaridan",\n \"popularity\": 8720\n },\n {\n \"tag\": "poetastress",\n \"popularity\": 8711\n },\n {\n \"tag\": "monophthalmus",\n \"popularity\": 8701\n },\n {\n \"tag\": "simnel",\n \"popularity\": 8692\n },\n {\n \"tag\": "compotor",\n \"popularity\": 8682\n },\n {\n \"tag\": "hydrolase",\n \"popularity\": 8673\n },\n {\n \"tag\": "attemptless",\n \"popularity\": 8663\n },\n {\n \"tag\": "visceroptosis",\n \"popularity\": 8654\n },\n {\n \"tag\": "unpreparedly",\n \"popularity\": 8645\n },\n {\n \"tag\": "mastage",\n \"popularity\": 8635\n },\n {\n \"tag\": "preinfluence",\n \"popularity\": 8626\n },\n {\n \"tag\": "Siwan",\n \"popularity\": 8617\n },\n {\n \"tag\": "ceratotheca belvedere",\n \"popularity\": 8607\n },\n {\n \"tag\": "disenablement",\n \"popularity\": 8598\n },\n {\n \"tag\": "nine",\n \"popularity\": 8589\n },\n {\n \"tag\": "spellingdown abridgment",\n \"popularity\": 8580\n },\n {\n \"tag\": "twilightless",\n \"popularity\": 8571\n },\n {\n \"tag\": "overflow",\n \"popularity\": 8561\n },\n {\n \"tag\": "mismeasurement",\n \"popularity\": 8552\n },\n {\n \"tag\": "nawabship",\n \"popularity\": 8543\n },\n {\n \"tag\": "Phrynosoma",\n \"popularity\": 8534\n },\n {\n \"tag\": "unanticipatingly",\n \"popularity\": 8525\n },\n {\n \"tag\": "blankite",\n \"popularity\": 8516\n },\n {\n \"tag\": "role",\n \"popularity\": 8506\n },\n {\n \"tag\": "peperine edelweiss",\n \"popularity\": 8497\n },\n {\n \"tag\": "unhysterical",\n \"popularity\": 8488\n },\n {\n \"tag\": "attentiveness",\n \"popularity\": 8479\n },\n {\n \"tag\": "scintillant",\n \"popularity\": 8470\n },\n {\n \"tag\": "stenostomatous",\n \"popularity\": 8461\n },\n {\n \"tag\": "pectinite",\n \"popularity\": 8452\n },\n {\n \"tag\": "herring",\n \"popularity\": 8443\n },\n {\n \"tag\": "interroom",\n \"popularity\": 8434\n },\n {\n \"tag\": "laccol",\n \"popularity\": 8425\n },\n {\n \"tag\": "unpartably kylite",\n \"popularity\": 8416\n },\n {\n \"tag\": "spirivalve",\n \"popularity\": 8407\n },\n {\n \"tag\": "hoosegow",\n \"popularity\": 8398\n },\n {\n \"tag\": "doat",\n \"popularity\": 8389\n },\n {\n \"tag\": "amphibian",\n \"popularity\": 8380\n },\n {\n \"tag\": "exposit",\n \"popularity\": 8371\n },\n {\n \"tag\": "canopy",\n \"popularity\": 8363\n },\n {\n \"tag\": "houndlike",\n \"popularity\": 8354\n },\n {\n \"tag\": "spikebill",\n \"popularity\": 8345\n },\n {\n \"tag\": "wiseacre pyrotechnic",\n \"popularity\": 8336\n },\n {\n \"tag\": "confessingly woodman",\n \"popularity\": 8327\n },\n {\n \"tag\": "overside",\n \"popularity\": 8318\n },\n {\n \"tag\": "oftwhiles",\n \"popularity\": 8310\n },\n {\n \"tag\": "Musophagidae",\n \"popularity\": 8301\n },\n {\n \"tag\": "slumberer",\n \"popularity\": 8292\n },\n {\n \"tag\": "leiotrichy",\n \"popularity\": 8283\n },\n {\n \"tag\": "Mantispidae",\n \"popularity\": 8275\n },\n {\n \"tag\": "perceptually",\n \"popularity\": 8266\n },\n {\n \"tag\": "biller",\n \"popularity\": 8257\n },\n {\n \"tag\": "eudaemonical",\n \"popularity\": 8249\n },\n {\n \"tag\": "underfiend",\n \"popularity\": 8240\n },\n {\n \"tag\": "impartible",\n \"popularity\": 8231\n },\n {\n \"tag\": "saxicavous",\n \"popularity\": 8223\n },\n {\n \"tag\": "yapster",\n \"popularity\": 8214\n },\n {\n \"tag\": "aliseptal",\n \"popularity\": 8205\n },\n {\n \"tag\": "omniparient",\n \"popularity\": 8197\n },\n {\n \"tag\": "nishiki",\n \"popularity\": 8188\n },\n {\n \"tag\": "yuzluk",\n \"popularity\": 8180\n },\n {\n \"tag\": "solderer",\n \"popularity\": 8171\n },\n {\n \"tag\": "Pinna",\n \"popularity\": 8162\n },\n {\n \"tag\": "reinterfere",\n \"popularity\": 8154\n },\n {\n \"tag\": "superepic",\n \"popularity\": 8145\n },\n {\n \"tag\": "ronquil",\n \"popularity\": 8137\n },\n {\n \"tag\": "bratstvo",\n \"popularity\": 8128\n },\n {\n \"tag\": "Thea",\n \"popularity\": 8120\n },\n {\n \"tag\": "hermaphroditical",\n \"popularity\": 8111\n },\n {\n \"tag\": "enlief",\n \"popularity\": 8103\n },\n {\n \"tag\": "Jesuate",\n \"popularity\": 8095\n },\n {\n \"tag\": "gaysome",\n \"popularity\": 8086\n },\n {\n \"tag\": "iliohypogastric",\n \"popularity\": 8078\n },\n {\n \"tag\": "regardance",\n \"popularity\": 8069\n },\n {\n \"tag\": "cumulately",\n \"popularity\": 8061\n },\n {\n \"tag\": "haustorial nucleolocentrosome",\n \"popularity\": 8053\n },\n {\n \"tag\": "cosmocrat",\n \"popularity\": 8044\n },\n {\n \"tag\": "onyxitis",\n \"popularity\": 8036\n },\n {\n \"tag\": "Cabinda",\n \"popularity\": 8028\n },\n {\n \"tag\": "coresort",\n \"popularity\": 8019\n },\n {\n \"tag\": "drusy preformant",\n \"popularity\": 8011\n },\n {\n \"tag\": "piningly",\n \"popularity\": 8003\n },\n {\n \"tag\": "bootlessly",\n \"popularity\": 7994\n },\n {\n \"tag\": "talari",\n \"popularity\": 7986\n },\n {\n \"tag\": "amidoacetal",\n \"popularity\": 7978\n },\n {\n \"tag\": "pschent",\n \"popularity\": 7970\n },\n {\n \"tag\": "consumptional scarer titivate",\n \"popularity\": 7962\n },\n {\n \"tag\": "Anserinae",\n \"popularity\": 7953\n },\n {\n \"tag\": "flaunter",\n \"popularity\": 7945\n },\n {\n \"tag\": "reindeer",\n \"popularity\": 7937\n },\n {\n \"tag\": "disparage",\n \"popularity\": 7929\n },\n {\n \"tag\": "superheat",\n \"popularity\": 7921\n },\n {\n \"tag\": "Chromatium",\n \"popularity\": 7912\n },\n {\n \"tag\": "Tina",\n \"popularity\": 7904\n },\n {\n \"tag\": "rededicatory",\n \"popularity\": 7896\n },\n {\n \"tag\": "nontransient",\n \"popularity\": 7888\n },\n {\n \"tag\": "Phocaean brinkless",\n \"popularity\": 7880\n },\n {\n \"tag\": "ventriculose",\n \"popularity\": 7872\n },\n {\n \"tag\": "upplough",\n \"popularity\": 7864\n },\n {\n \"tag\": "succorless",\n \"popularity\": 7856\n },\n {\n \"tag\": "hayrake",\n \"popularity\": 7848\n },\n {\n \"tag\": "merriness amorphia",\n \"popularity\": 7840\n },\n {\n \"tag\": "merycism",\n \"popularity\": 7832\n },\n {\n \"tag\": "checkrow",\n \"popularity\": 7824\n },\n {\n \"tag\": "scry",\n \"popularity\": 7816\n },\n {\n \"tag\": "obvolve",\n \"popularity\": 7808\n },\n {\n \"tag\": "orchard",\n \"popularity\": 7800\n },\n {\n \"tag\": "isomerize",\n \"popularity\": 7792\n },\n {\n \"tag\": "competitrix",\n \"popularity\": 7784\n },\n {\n \"tag\": "unbannered",\n \"popularity\": 7776\n },\n {\n \"tag\": "undoctrined",\n \"popularity\": 7768\n },\n {\n \"tag\": "theologian",\n \"popularity\": 7760\n },\n {\n \"tag\": "nebby",\n \"popularity\": 7752\n },\n {\n \"tag\": "Cardiazol",\n \"popularity\": 7745\n },\n {\n \"tag\": "phagedenic",\n \"popularity\": 7737\n },\n {\n \"tag\": "nostalgic",\n \"popularity\": 7729\n },\n {\n \"tag\": "orthodoxy",\n \"popularity\": 7721\n },\n {\n \"tag\": "oversanguine",\n \"popularity\": 7713\n },\n {\n \"tag\": "lish",\n \"popularity\": 7705\n },\n {\n \"tag\": "ketogenic",\n \"popularity\": 7698\n },\n {\n \"tag\": "syndicalize",\n \"popularity\": 7690\n },\n {\n \"tag\": "leeftail",\n \"popularity\": 7682\n },\n {\n \"tag\": "bulbomedullary",\n \"popularity\": 7674\n },\n {\n \"tag\": "reletter",\n \"popularity\": 7667\n },\n {\n \"tag\": "bitterly",\n \"popularity\": 7659\n },\n {\n \"tag\": "participatory",\n \"popularity\": 7651\n },\n {\n \"tag\": "baldberry",\n \"popularity\": 7643\n },\n {\n \"tag\": "prowaterpower",\n \"popularity\": 7636\n },\n {\n \"tag\": "lexicographical",\n \"popularity\": 7628\n },\n {\n \"tag\": "Anisodactyli",\n \"popularity\": 7620\n },\n {\n \"tag\": "amphipodous",\n \"popularity\": 7613\n },\n {\n \"tag\": "triglandular",\n \"popularity\": 7605\n },\n {\n \"tag\": "xanthopsin",\n \"popularity\": 7597\n },\n {\n \"tag\": "indefinitude",\n \"popularity\": 7590\n },\n {\n \"tag\": "bookworm",\n \"popularity\": 7582\n },\n {\n \"tag\": "suffocative",\n \"popularity\": 7574\n },\n {\n \"tag\": "uncongested tyrant",\n \"popularity\": 7567\n },\n {\n \"tag\": "alow harmoniously Pamir",\n \"popularity\": 7559\n },\n {\n \"tag\": "monander",\n \"popularity\": 7552\n },\n {\n \"tag\": "bagatelle",\n \"popularity\": 7544\n },\n {\n \"tag\": "membranology",\n \"popularity\": 7537\n },\n {\n \"tag\": "parturifacient",\n \"popularity\": 7529\n },\n {\n \"tag\": "excitovascular",\n \"popularity\": 7522\n },\n {\n \"tag\": "homopolar",\n \"popularity\": 7514\n },\n {\n \"tag\": "phobiac",\n \"popularity\": 7507\n },\n {\n \"tag\": "clype",\n \"popularity\": 7499\n },\n {\n \"tag\": "unsubversive",\n \"popularity\": 7492\n },\n {\n \"tag\": "bostrychoidal scorpionwort",\n \"popularity\": 7484\n },\n {\n \"tag\": "biliteralism",\n \"popularity\": 7477\n },\n {\n \"tag\": "dentatocostate",\n \"popularity\": 7469\n },\n {\n \"tag\": "Pici",\n \"popularity\": 7462\n },\n {\n \"tag\": "sideritic",\n \"popularity\": 7454\n },\n {\n \"tag\": "syntaxis",\n \"popularity\": 7447\n },\n {\n \"tag\": "ingest",\n \"popularity\": 7440\n },\n {\n \"tag\": "rigmarolish",\n \"popularity\": 7432\n },\n {\n \"tag\": "ocreaceous",\n \"popularity\": 7425\n },\n {\n \"tag\": "hyperbrachyskelic",\n \"popularity\": 7418\n },\n {\n \"tag\": "basophobia",\n \"popularity\": 7410\n },\n {\n \"tag\": "substantialness",\n \"popularity\": 7403\n },\n {\n \"tag\": "agglutinoid",\n \"popularity\": 7396\n },\n {\n \"tag\": "longleaf",\n \"popularity\": 7388\n },\n {\n \"tag\": "electroengraving",\n \"popularity\": 7381\n },\n {\n \"tag\": "laparoenterotomy",\n \"popularity\": 7374\n },\n {\n \"tag\": "oxalylurea",\n \"popularity\": 7366\n },\n {\n \"tag\": "unattaintedly",\n \"popularity\": 7359\n },\n {\n \"tag\": "pennystone",\n \"popularity\": 7352\n },\n {\n \"tag\": "Plumbaginaceae",\n \"popularity\": 7345\n },\n {\n \"tag\": "horntip",\n \"popularity\": 7337\n },\n {\n \"tag\": "begrudge",\n \"popularity\": 7330\n },\n {\n \"tag\": "bechignoned",\n \"popularity\": 7323\n },\n {\n \"tag\": "hologonidium",\n \"popularity\": 7316\n },\n {\n \"tag\": "Pulian",\n \"popularity\": 7309\n },\n {\n \"tag\": "gratulation",\n \"popularity\": 7301\n },\n {\n \"tag\": "Sebright",\n \"popularity\": 7294\n },\n {\n \"tag\": "coinstantaneous emotionally",\n \"popularity\": 7287\n },\n {\n \"tag\": "thoracostracan",\n \"popularity\": 7280\n },\n {\n \"tag\": "saurodont",\n \"popularity\": 7273\n },\n {\n \"tag\": "coseat",\n \"popularity\": 7266\n },\n {\n \"tag\": "irascibility",\n \"popularity\": 7259\n },\n {\n \"tag\": "occlude",\n \"popularity\": 7251\n },\n {\n \"tag\": "metallurgist",\n \"popularity\": 7244\n },\n {\n \"tag\": "extraviolet",\n \"popularity\": 7237\n },\n {\n \"tag\": "clinic",\n \"popularity\": 7230\n },\n {\n \"tag\": "skater",\n \"popularity\": 7223\n },\n {\n \"tag\": "linguistic",\n \"popularity\": 7216\n },\n {\n \"tag\": "attacheship",\n \"popularity\": 7209\n },\n {\n \"tag\": "Rachianectes",\n \"popularity\": 7202\n },\n {\n \"tag\": "foliolose",\n \"popularity\": 7195\n },\n {\n \"tag\": "claudetite",\n \"popularity\": 7188\n },\n {\n \"tag\": "aphidian scratching",\n \"popularity\": 7181\n },\n {\n \"tag\": "Carida",\n \"popularity\": 7174\n },\n {\n \"tag\": "tiepin polymicroscope",\n \"popularity\": 7167\n },\n {\n \"tag\": "telpherage",\n \"popularity\": 7160\n },\n {\n \"tag\": "meek",\n \"popularity\": 7153\n },\n {\n \"tag\": "swiftness",\n \"popularity\": 7146\n },\n {\n \"tag\": "gentes",\n \"popularity\": 7139\n },\n {\n \"tag\": "uncommemorated",\n \"popularity\": 7132\n },\n {\n \"tag\": "Lazarus",\n \"popularity\": 7125\n },\n {\n \"tag\": "redivive",\n \"popularity\": 7119\n },\n {\n \"tag\": "nonfebrile",\n \"popularity\": 7112\n },\n {\n \"tag\": "nymphet",\n \"popularity\": 7105\n },\n {\n \"tag\": "areologically",\n \"popularity\": 7098\n },\n {\n \"tag\": "undonkey",\n \"popularity\": 7091\n },\n {\n \"tag\": "projecting",\n \"popularity\": 7084\n },\n {\n \"tag\": "pinnigrade",\n \"popularity\": 7077\n },\n {\n \"tag\": "butylation",\n \"popularity\": 7071\n },\n {\n \"tag\": "philologistic lenticle",\n \"popularity\": 7064\n },\n {\n \"tag\": "nooky",\n \"popularity\": 7057\n },\n {\n \"tag\": "incestuousness",\n \"popularity\": 7050\n },\n {\n \"tag\": "palingenetically",\n \"popularity\": 7043\n },\n {\n \"tag\": "mitochondria",\n \"popularity\": 7037\n },\n {\n \"tag\": "truthify",\n \"popularity\": 7030\n },\n {\n \"tag\": "titanyl",\n \"popularity\": 7023\n },\n {\n \"tag\": "bestride",\n \"popularity\": 7016\n },\n {\n \"tag\": "chende",\n \"popularity\": 7010\n },\n {\n \"tag\": "Chaucerian monophote",\n \"popularity\": 7003\n },\n {\n \"tag\": "cutback",\n \"popularity\": 6996\n },\n {\n \"tag\": "unpatiently",\n \"popularity\": 6989\n },\n {\n \"tag\": "subvitreous",\n \"popularity\": 6983\n },\n {\n \"tag\": "organizable",\n \"popularity\": 6976\n },\n {\n \"tag\": "anniverse uncomprehensible",\n \"popularity\": 6969\n },\n {\n \"tag\": "hyalescence",\n \"popularity\": 6963\n },\n {\n \"tag\": "amniochorial",\n \"popularity\": 6956\n },\n {\n \"tag\": "Corybantian",\n \"popularity\": 6949\n },\n {\n \"tag\": "genocide Scaphitidae",\n \"popularity\": 6943\n },\n {\n \"tag\": "accordionist",\n \"popularity\": 6936\n },\n {\n \"tag\": "becheck",\n \"popularity\": 6930\n },\n {\n \"tag\": "overproduce",\n \"popularity\": 6923\n },\n {\n \"tag\": "unmaniac frijolillo",\n \"popularity\": 6916\n },\n {\n \"tag\": "multisulcated",\n \"popularity\": 6910\n },\n {\n \"tag\": "wennebergite",\n \"popularity\": 6903\n },\n {\n \"tag\": "tautousious mowth",\n \"popularity\": 6897\n },\n {\n \"tag\": "marigold",\n \"popularity\": 6890\n },\n {\n \"tag\": "affray",\n \"popularity\": 6884\n },\n {\n \"tag\": "nonidolatrous",\n \"popularity\": 6877\n },\n {\n \"tag\": "aphrasia",\n \"popularity\": 6871\n },\n {\n \"tag\": "muddlingly",\n \"popularity\": 6864\n },\n {\n \"tag\": "clear",\n \"popularity\": 6858\n },\n {\n \"tag\": "Clitoria",\n \"popularity\": 6851\n },\n {\n \"tag\": "apportionment underwaist",\n \"popularity\": 6845\n },\n {\n \"tag\": "kodakist",\n \"popularity\": 6838\n },\n {\n \"tag\": "Momotidae",\n \"popularity\": 6832\n },\n {\n \"tag\": "cryptovalency",\n \"popularity\": 6825\n },\n {\n \"tag\": "floe",\n \"popularity\": 6819\n },\n {\n \"tag\": "aphagia",\n \"popularity\": 6812\n },\n {\n \"tag\": "brontograph",\n \"popularity\": 6806\n },\n {\n \"tag\": "tubulous",\n \"popularity\": 6799\n },\n {\n \"tag\": "unhorse",\n \"popularity\": 6793\n },\n {\n \"tag\": "chlordane",\n \"popularity\": 6787\n },\n {\n \"tag\": "colloquy brochan",\n \"popularity\": 6780\n },\n {\n \"tag\": "sloosh",\n \"popularity\": 6774\n },\n {\n \"tag\": "battered",\n \"popularity\": 6767\n },\n {\n \"tag\": "monocularity pluriguttulate",\n \"popularity\": 6761\n },\n {\n \"tag\": "chiastoneury",\n \"popularity\": 6755\n },\n {\n \"tag\": "Sanguinaria",\n \"popularity\": 6748\n },\n {\n \"tag\": "confessionary",\n \"popularity\": 6742\n },\n {\n \"tag\": "enzymic",\n \"popularity\": 6736\n },\n {\n \"tag\": "cord",\n \"popularity\": 6729\n },\n {\n \"tag\": "oviducal",\n \"popularity\": 6723\n },\n {\n \"tag\": "crozzle outsea",\n \"popularity\": 6717\n },\n {\n \"tag\": "balladical",\n \"popularity\": 6710\n },\n {\n \"tag\": "uncollectibleness",\n \"popularity\": 6704\n },\n {\n \"tag\": "predorsal",\n \"popularity\": 6698\n },\n {\n \"tag\": "reauthenticate",\n \"popularity\": 6692\n },\n {\n \"tag\": "ravissant",\n \"popularity\": 6685\n },\n {\n \"tag\": "advantageousness",\n \"popularity\": 6679\n },\n {\n \"tag\": "rung",\n \"popularity\": 6673\n },\n {\n \"tag\": "duncedom",\n \"popularity\": 6667\n },\n {\n \"tag\": "hematolite",\n \"popularity\": 6660\n },\n {\n \"tag\": "thisness",\n \"popularity\": 6654\n },\n {\n \"tag\": "mapau",\n \"popularity\": 6648\n },\n {\n \"tag\": "Hecatic",\n \"popularity\": 6642\n },\n {\n \"tag\": "meningoencephalocele",\n \"popularity\": 6636\n },\n {\n \"tag\": "confection sorra",\n \"popularity\": 6630\n },\n {\n \"tag\": "unsedate",\n \"popularity\": 6623\n },\n {\n \"tag\": "meningocerebritis",\n \"popularity\": 6617\n },\n {\n \"tag\": "biopsychological",\n \"popularity\": 6611\n },\n {\n \"tag\": "clavicithern",\n \"popularity\": 6605\n },\n {\n \"tag\": "resun",\n \"popularity\": 6599\n },\n {\n \"tag\": "bayamo",\n \"popularity\": 6593\n },\n {\n \"tag\": "seeableness",\n \"popularity\": 6587\n },\n {\n \"tag\": "hypsidolichocephalism",\n \"popularity\": 6581\n },\n {\n \"tag\": "salivous",\n \"popularity\": 6574\n },\n {\n \"tag\": "neumatize",\n \"popularity\": 6568\n },\n {\n \"tag\": "stree",\n \"popularity\": 6562\n },\n {\n \"tag\": "markshot",\n \"popularity\": 6556\n },\n {\n \"tag\": "phraseologically",\n \"popularity\": 6550\n },\n {\n \"tag\": "yealing",\n \"popularity\": 6544\n },\n {\n \"tag\": "puggy",\n \"popularity\": 6538\n },\n {\n \"tag\": "sexadecimal",\n \"popularity\": 6532\n },\n {\n \"tag\": "unofficerlike",\n \"popularity\": 6526\n },\n {\n \"tag\": "curiosa",\n \"popularity\": 6520\n },\n {\n \"tag\": "pedomotor",\n \"popularity\": 6514\n },\n {\n \"tag\": "astrally",\n \"popularity\": 6508\n },\n {\n \"tag\": "prosomatic",\n \"popularity\": 6502\n },\n {\n \"tag\": "bulletheaded",\n \"popularity\": 6496\n },\n {\n \"tag\": "fortuned",\n \"popularity\": 6490\n },\n {\n \"tag\": "pixy",\n \"popularity\": 6484\n },\n {\n \"tag\": "protectrix",\n \"popularity\": 6478\n },\n {\n \"tag\": "arthritical",\n \"popularity\": 6472\n },\n {\n \"tag\": "coction",\n \"popularity\": 6466\n },\n {\n \"tag\": "Anthropos",\n \"popularity\": 6460\n },\n {\n \"tag\": "runer",\n \"popularity\": 6454\n },\n {\n \"tag\": "prenotify",\n \"popularity\": 6449\n },\n {\n \"tag\": "microspheric gastroparalysis",\n \"popularity\": 6443\n },\n {\n \"tag\": "Jovicentrical",\n \"popularity\": 6437\n },\n {\n \"tag\": "ceratopsid",\n \"popularity\": 6431\n },\n {\n \"tag\": "Theodoric",\n \"popularity\": 6425\n },\n {\n \"tag\": "Pactolus",\n \"popularity\": 6419\n },\n {\n \"tag\": "spawning",\n \"popularity\": 6413\n },\n {\n \"tag\": "nonconfidential",\n \"popularity\": 6407\n },\n {\n \"tag\": "halotrichite infumate",\n \"popularity\": 6402\n },\n {\n \"tag\": "undiscriminatingly",\n \"popularity\": 6396\n },\n {\n \"tag\": "unexasperated",\n \"popularity\": 6390\n },\n {\n \"tag\": "isoeugenol",\n \"popularity\": 6384\n },\n {\n \"tag\": "pressboard",\n \"popularity\": 6378\n },\n {\n \"tag\": "unshrew",\n \"popularity\": 6372\n },\n {\n \"tag\": "huffingly",\n \"popularity\": 6367\n },\n {\n \"tag\": "wagaun",\n \"popularity\": 6361\n },\n {\n \"tag\": "squirt Philistine",\n \"popularity\": 6355\n },\n {\n \"tag\": "kryptic",\n \"popularity\": 6349\n },\n {\n \"tag\": "paraform",\n \"popularity\": 6344\n },\n {\n \"tag\": "preverify",\n \"popularity\": 6338\n },\n {\n \"tag\": "dalar",\n \"popularity\": 6332\n },\n {\n \"tag\": "interdictor appraisingly",\n \"popularity\": 6326\n },\n {\n \"tag\": "chipped",\n \"popularity\": 6321\n },\n {\n \"tag\": "Pteropoda",\n \"popularity\": 6315\n },\n {\n \"tag\": "Bohairic",\n \"popularity\": 6309\n },\n {\n \"tag\": "felting",\n \"popularity\": 6303\n },\n {\n \"tag\": "compurgatorial",\n \"popularity\": 6298\n },\n {\n \"tag\": "unclead",\n \"popularity\": 6292\n },\n {\n \"tag\": "stockish",\n \"popularity\": 6286\n },\n {\n \"tag\": "mulligatawny",\n \"popularity\": 6281\n },\n {\n \"tag\": "Monotheletism",\n \"popularity\": 6275\n },\n {\n \"tag\": "lutanist",\n \"popularity\": 6269\n },\n {\n \"tag\": "gluttonize",\n \"popularity\": 6264\n },\n {\n \"tag\": "hackneyed",\n \"popularity\": 6258\n },\n {\n \"tag\": "yield",\n \"popularity\": 6253\n },\n {\n \"tag\": "sulphonamido",\n \"popularity\": 6247\n },\n {\n \"tag\": "granulative",\n \"popularity\": 6241\n },\n {\n \"tag\": "swingy",\n \"popularity\": 6236\n },\n {\n \"tag\": "Desmidiales",\n \"popularity\": 6230\n },\n {\n \"tag\": "tootlish",\n \"popularity\": 6224\n },\n {\n \"tag\": "unsatisfiedly",\n \"popularity\": 6219\n },\n {\n \"tag\": "burucha",\n \"popularity\": 6213\n },\n {\n \"tag\": "premeditatingly",\n \"popularity\": 6208\n },\n {\n \"tag\": "cowrie",\n \"popularity\": 6202\n },\n {\n \"tag\": "pleurolysis",\n \"popularity\": 6197\n },\n {\n \"tag\": "nationalist",\n \"popularity\": 6191\n },\n {\n \"tag\": "Pholadacea",\n \"popularity\": 6186\n },\n {\n \"tag\": "anakrousis",\n \"popularity\": 6180\n },\n {\n \"tag\": "proctorial",\n \"popularity\": 6175\n },\n {\n \"tag\": "cavillation",\n \"popularity\": 6169\n },\n {\n \"tag\": "cervicobregmatic",\n \"popularity\": 6163\n },\n {\n \"tag\": "interspecific",\n \"popularity\": 6158\n },\n {\n \"tag\": "Teutonity",\n \"popularity\": 6152\n },\n {\n \"tag\": "snakeholing",\n \"popularity\": 6147\n },\n {\n \"tag\": "balcony",\n \"popularity\": 6142\n },\n {\n \"tag\": "latchless",\n \"popularity\": 6136\n },\n {\n \"tag\": "Mithraea",\n \"popularity\": 6131\n },\n {\n \"tag\": "pseudepigraph",\n \"popularity\": 6125\n },\n {\n \"tag\": "flosser",\n \"popularity\": 6120\n },\n {\n \"tag\": "kotyle",\n \"popularity\": 6114\n },\n {\n \"tag\": "outdo",\n \"popularity\": 6109\n },\n {\n \"tag\": "interclerical",\n \"popularity\": 6103\n },\n {\n \"tag\": "aurar",\n \"popularity\": 6098\n },\n {\n \"tag\": "apophyseal",\n \"popularity\": 6093\n },\n {\n \"tag\": "Miro",\n \"popularity\": 6087\n },\n {\n \"tag\": "Priscillian",\n \"popularity\": 6082\n },\n {\n \"tag\": "alluvia",\n \"popularity\": 6076\n },\n {\n \"tag\": "exordize",\n \"popularity\": 6071\n },\n {\n \"tag\": "breakage",\n \"popularity\": 6066\n },\n {\n \"tag\": "unclosable",\n \"popularity\": 6060\n },\n {\n \"tag\": "monocondylous",\n \"popularity\": 6055\n },\n {\n \"tag\": "dyarchy",\n \"popularity\": 6050\n },\n {\n \"tag\": "subchelate",\n \"popularity\": 6044\n },\n {\n \"tag\": "hearsay",\n \"popularity\": 6039\n },\n {\n \"tag\": "prestigiously",\n \"popularity\": 6034\n },\n {\n \"tag\": "unimuscular",\n \"popularity\": 6028\n },\n {\n \"tag\": "lingwort",\n \"popularity\": 6023\n },\n {\n \"tag\": "jealous",\n \"popularity\": 6018\n },\n {\n \"tag\": "artilleryman",\n \"popularity\": 6012\n },\n {\n \"tag\": "phantasmagorially",\n \"popularity\": 6007\n },\n {\n \"tag\": "stagnum",\n \"popularity\": 6002\n },\n {\n \"tag\": "organotropism shatteringly",\n \"popularity\": 5997\n },\n {\n \"tag\": "Mytilus Hebraist",\n \"popularity\": 5991\n },\n {\n \"tag\": "returf",\n \"popularity\": 5986\n },\n {\n \"tag\": "townfolk",\n \"popularity\": 5981\n },\n {\n \"tag\": "propitiative",\n \"popularity\": 5976\n },\n {\n \"tag\": "Anita unsullied",\n \"popularity\": 5970\n },\n {\n \"tag\": "bandoleered",\n \"popularity\": 5965\n },\n {\n \"tag\": "cubby",\n \"popularity\": 5960\n },\n {\n \"tag\": "Hexanchus",\n \"popularity\": 5955\n },\n {\n \"tag\": "circuminsular",\n \"popularity\": 5949\n },\n {\n \"tag\": "chamberletted eumycete",\n \"popularity\": 5944\n },\n {\n \"tag\": "secure",\n \"popularity\": 5939\n },\n {\n \"tag\": "Edwardean",\n \"popularity\": 5934\n },\n {\n \"tag\": "strenth",\n \"popularity\": 5929\n },\n {\n \"tag\": "exhaustless",\n \"popularity\": 5923\n },\n {\n \"tag\": "electioneerer",\n \"popularity\": 5918\n },\n {\n \"tag\": "estoile",\n \"popularity\": 5913\n },\n {\n \"tag\": "redden",\n \"popularity\": 5908\n },\n {\n \"tag\": "solicitee",\n \"popularity\": 5903\n },\n {\n \"tag\": "nonpatented",\n \"popularity\": 5898\n },\n {\n \"tag\": "lemming",\n \"popularity\": 5893\n },\n {\n \"tag\": "marled subalate",\n \"popularity\": 5887\n },\n {\n \"tag\": "premial horizonward",\n \"popularity\": 5882\n },\n {\n \"tag\": "nonrefueling",\n \"popularity\": 5877\n },\n {\n \"tag\": "rupturewort",\n \"popularity\": 5872\n },\n {\n \"tag\": "unfed",\n \"popularity\": 5867\n },\n {\n \"tag\": "empanelment",\n \"popularity\": 5862\n },\n {\n \"tag\": "isoosmosis",\n \"popularity\": 5857\n },\n {\n \"tag\": "jipijapa",\n \"popularity\": 5852\n },\n {\n \"tag\": "Fiji",\n \"popularity\": 5847\n },\n {\n \"tag\": "interferant",\n \"popularity\": 5842\n },\n {\n \"tag\": "reconstitution",\n \"popularity\": 5837\n },\n {\n \"tag\": "dockyardman",\n \"popularity\": 5832\n },\n {\n \"tag\": "dolichopodous",\n \"popularity\": 5826\n },\n {\n \"tag\": "whiteworm",\n \"popularity\": 5821\n },\n {\n \"tag\": "atheistically",\n \"popularity\": 5816\n },\n {\n \"tag\": "nonconcern",\n \"popularity\": 5811\n },\n {\n \"tag\": "scarabaeidoid",\n \"popularity\": 5806\n },\n {\n \"tag\": "triumviri",\n \"popularity\": 5801\n },\n {\n \"tag\": "rakit",\n \"popularity\": 5796\n },\n {\n \"tag\": "leecheater",\n \"popularity\": 5791\n },\n {\n \"tag\": "Arthrostraca",\n \"popularity\": 5786\n },\n {\n \"tag\": "upknit",\n \"popularity\": 5781\n },\n {\n \"tag\": "tymbalon",\n \"popularity\": 5776\n },\n {\n \"tag\": "inventurous",\n \"popularity\": 5771\n },\n {\n \"tag\": "perradiate",\n \"popularity\": 5766\n },\n {\n \"tag\": "seer",\n \"popularity\": 5762\n },\n {\n \"tag\": "Auricularia",\n \"popularity\": 5757\n },\n {\n \"tag\": "wettish exclusivity",\n \"popularity\": 5752\n },\n {\n \"tag\": "arteriosympathectomy",\n \"popularity\": 5747\n },\n {\n \"tag\": "tunlike",\n \"popularity\": 5742\n },\n {\n \"tag\": "cephalocercal",\n \"popularity\": 5737\n },\n {\n \"tag\": "meaninglessness",\n \"popularity\": 5732\n },\n {\n \"tag\": "fountful",\n \"popularity\": 5727\n },\n {\n \"tag\": "appraisement",\n \"popularity\": 5722\n },\n {\n \"tag\": "geniculated",\n \"popularity\": 5717\n },\n {\n \"tag\": "rotator",\n \"popularity\": 5712\n },\n {\n \"tag\": "foremarch biography",\n \"popularity\": 5707\n },\n {\n \"tag\": "arid",\n \"popularity\": 5703\n },\n {\n \"tag\": "inapprehensible",\n \"popularity\": 5698\n },\n {\n \"tag\": "chlorosulphonic",\n \"popularity\": 5693\n },\n {\n \"tag\": "braguette",\n \"popularity\": 5688\n },\n {\n \"tag\": "panophthalmitis",\n \"popularity\": 5683\n },\n {\n \"tag\": "pro objurgatorily",\n \"popularity\": 5678\n },\n {\n \"tag\": "zooplasty",\n \"popularity\": 5673\n },\n {\n \"tag\": "Terebratulidae",\n \"popularity\": 5669\n },\n {\n \"tag\": "Mahran",\n \"popularity\": 5664\n },\n {\n \"tag\": "anthologize merocele",\n \"popularity\": 5659\n },\n {\n \"tag\": "firecracker chiropractic",\n \"popularity\": 5654\n },\n {\n \"tag\": "tenorist",\n \"popularity\": 5649\n },\n {\n \"tag\": "amphitene",\n \"popularity\": 5645\n },\n {\n \"tag\": "silverbush toadstone",\n \"popularity\": 5640\n },\n {\n \"tag\": "entozoological",\n \"popularity\": 5635\n },\n {\n \"tag\": "trustlessness",\n \"popularity\": 5630\n },\n {\n \"tag\": "reassay",\n \"popularity\": 5625\n },\n {\n \"tag\": "chrysalides",\n \"popularity\": 5621\n },\n {\n \"tag\": "truncation",\n \"popularity\": 5616\n },\n {\n \"tag\": "unwavered mausoleal",\n \"popularity\": 5611\n },\n {\n \"tag\": "unserrated",\n \"popularity\": 5606\n },\n {\n \"tag\": "frampler",\n \"popularity\": 5602\n },\n {\n \"tag\": "celestial",\n \"popularity\": 5597\n },\n {\n \"tag\": "depreter",\n \"popularity\": 5592\n },\n {\n \"tag\": "retaliate",\n \"popularity\": 5588\n },\n {\n \"tag\": "decempunctate",\n \"popularity\": 5583\n },\n {\n \"tag\": "submitter",\n \"popularity\": 5578\n },\n {\n \"tag\": "phenothiazine",\n \"popularity\": 5573\n },\n {\n \"tag\": "hobbledehoyish",\n \"popularity\": 5569\n },\n {\n \"tag\": "erraticness",\n \"popularity\": 5564\n },\n {\n \"tag\": "ovariodysneuria",\n \"popularity\": 5559\n },\n {\n \"tag\": "puja",\n \"popularity\": 5555\n },\n {\n \"tag\": "cesspool",\n \"popularity\": 5550\n },\n {\n \"tag\": "sonation",\n \"popularity\": 5545\n },\n {\n \"tag\": "moggan",\n \"popularity\": 5541\n },\n {\n \"tag\": "overjutting",\n \"popularity\": 5536\n },\n {\n \"tag\": "cohobate",\n \"popularity\": 5531\n },\n {\n \"tag\": "Distoma",\n \"popularity\": 5527\n },\n {\n \"tag\": "Plectognathi",\n \"popularity\": 5522\n },\n {\n \"tag\": "dumple caliphate",\n \"popularity\": 5517\n },\n {\n \"tag\": "shiko",\n \"popularity\": 5513\n },\n {\n \"tag\": "downness",\n \"popularity\": 5508\n },\n {\n \"tag\": "whippletree",\n \"popularity\": 5504\n },\n {\n \"tag\": "nymphaeum",\n \"popularity\": 5499\n },\n {\n \"tag\": "there trest",\n \"popularity\": 5494\n },\n {\n \"tag\": "psychrometer",\n \"popularity\": 5490\n },\n {\n \"tag\": "pyelograph",\n \"popularity\": 5485\n },\n {\n \"tag\": "unsalvable",\n \"popularity\": 5481\n },\n {\n \"tag\": "bescreen",\n \"popularity\": 5476\n },\n {\n \"tag\": "cushy",\n \"popularity\": 5471\n },\n {\n \"tag\": "plicatolobate",\n \"popularity\": 5467\n },\n {\n \"tag\": "lakie",\n \"popularity\": 5462\n },\n {\n \"tag\": "anthropodeoxycholic",\n \"popularity\": 5458\n },\n {\n \"tag\": "resatisfaction",\n \"popularity\": 5453\n },\n {\n \"tag\": "unravelment unaccidental",\n \"popularity\": 5449\n },\n {\n \"tag\": "telewriter monogeneous",\n \"popularity\": 5444\n },\n {\n \"tag\": "unsabred",\n \"popularity\": 5440\n },\n {\n \"tag\": "startlingly",\n \"popularity\": 5435\n },\n {\n \"tag\": "Aralia",\n \"popularity\": 5431\n },\n {\n \"tag\": "alamonti",\n \"popularity\": 5426\n },\n {\n \"tag\": "Franklinization",\n \"popularity\": 5422\n },\n {\n \"tag\": "parliament",\n \"popularity\": 5417\n },\n {\n \"tag\": "schoolkeeper",\n \"popularity\": 5413\n },\n {\n \"tag\": "nonsociety",\n \"popularity\": 5408\n },\n {\n \"tag\": "parenthetic",\n \"popularity\": 5404\n },\n {\n \"tag\": "stog",\n \"popularity\": 5399\n },\n {\n \"tag\": "Pristipomidae",\n \"popularity\": 5395\n },\n {\n \"tag\": "exocarp",\n \"popularity\": 5390\n },\n {\n \"tag\": "monaxonial",\n \"popularity\": 5386\n },\n {\n \"tag\": "tramroad",\n \"popularity\": 5381\n },\n {\n \"tag\": "hookah",\n \"popularity\": 5377\n },\n {\n \"tag\": "saccharonic",\n \"popularity\": 5372\n },\n {\n \"tag\": "perimetrium",\n \"popularity\": 5368\n },\n {\n \"tag\": "libelluloid",\n \"popularity\": 5364\n },\n {\n \"tag\": "overrunningly",\n \"popularity\": 5359\n },\n {\n \"tag\": "untwister",\n \"popularity\": 5355\n },\n {\n \"tag\": "ninnyhammer",\n \"popularity\": 5350\n },\n {\n \"tag\": "metranate",\n \"popularity\": 5346\n },\n {\n \"tag\": "sarcoblast",\n \"popularity\": 5341\n },\n {\n \"tag\": "porkish",\n \"popularity\": 5337\n },\n {\n \"tag\": "chauvinistic",\n \"popularity\": 5333\n },\n {\n \"tag\": "sexagesimal",\n \"popularity\": 5328\n },\n {\n \"tag\": "hematogenic",\n \"popularity\": 5324\n },\n {\n \"tag\": "selfpreservatory",\n \"popularity\": 5320\n },\n {\n \"tag\": "myelauxe",\n \"popularity\": 5315\n },\n {\n \"tag\": "triply",\n \"popularity\": 5311\n },\n {\n \"tag\": "metaphysicous",\n \"popularity\": 5306\n },\n {\n \"tag\": "vitrinoid",\n \"popularity\": 5302\n },\n {\n \"tag\": "glabellae",\n \"popularity\": 5298\n },\n {\n \"tag\": "moonlighter",\n \"popularity\": 5293\n },\n {\n \"tag\": "monotheistically epexegetical",\n \"popularity\": 5289\n },\n {\n \"tag\": "pseudolateral",\n \"popularity\": 5285\n },\n {\n \"tag\": "heptamethylene",\n \"popularity\": 5280\n },\n {\n \"tag\": "salvadora",\n \"popularity\": 5276\n },\n {\n \"tag\": "unjovial diphenylthiourea",\n \"popularity\": 5272\n },\n {\n \"tag\": "thievishness",\n \"popularity\": 5268\n },\n {\n \"tag\": "unridable",\n \"popularity\": 5263\n },\n {\n \"tag\": "underhandedly",\n \"popularity\": 5259\n },\n {\n \"tag\": "fungiform",\n \"popularity\": 5255\n },\n {\n \"tag\": "scruffle",\n \"popularity\": 5250\n },\n {\n \"tag\": "preindisposition",\n \"popularity\": 5246\n },\n {\n \"tag\": "Amadis",\n \"popularity\": 5242\n },\n {\n \"tag\": "Culex",\n \"popularity\": 5238\n },\n {\n \"tag\": "churning",\n \"popularity\": 5233\n },\n {\n \"tag\": "imperite",\n \"popularity\": 5229\n },\n {\n \"tag\": "levorotation",\n \"popularity\": 5225\n },\n {\n \"tag\": "barbate",\n \"popularity\": 5221\n },\n {\n \"tag\": "knotwort",\n \"popularity\": 5216\n },\n {\n \"tag\": "gypsiferous",\n \"popularity\": 5212\n },\n {\n \"tag\": "tourmalinic",\n \"popularity\": 5208\n },\n {\n \"tag\": "helleboric",\n \"popularity\": 5204\n },\n {\n \"tag\": "pneumograph",\n \"popularity\": 5199\n },\n {\n \"tag\": "Peltigeraceae",\n \"popularity\": 5195\n },\n {\n \"tag\": "busine",\n \"popularity\": 5191\n },\n {\n \"tag\": "Ailuridae",\n \"popularity\": 5187\n },\n {\n \"tag\": "azotate",\n \"popularity\": 5183\n },\n {\n \"tag\": "unlikable",\n \"popularity\": 5178\n },\n {\n \"tag\": "sloyd",\n \"popularity\": 5174\n },\n {\n \"tag\": "biblioclasm",\n \"popularity\": 5170\n },\n {\n \"tag\": "Seres",\n \"popularity\": 5166\n },\n {\n \"tag\": "unaccurateness",\n \"popularity\": 5162\n },\n {\n \"tag\": "scrollwise",\n \"popularity\": 5157\n },\n {\n \"tag\": "flandowser",\n \"popularity\": 5153\n },\n {\n \"tag\": "unblackened",\n \"popularity\": 5149\n },\n {\n \"tag\": "schistosternia",\n \"popularity\": 5145\n },\n {\n \"tag\": "fuse",\n \"popularity\": 5141\n },\n {\n \"tag\": "narthecal",\n \"popularity\": 5137\n },\n {\n \"tag\": "Cueva",\n \"popularity\": 5133\n },\n {\n \"tag\": "appositeness",\n \"popularity\": 5128\n },\n {\n \"tag\": "proindustrial",\n \"popularity\": 5124\n },\n {\n \"tag\": "dermatorrhoea",\n \"popularity\": 5120\n },\n {\n \"tag\": "oxyurous tendential",\n \"popularity\": 5116\n },\n {\n \"tag\": "isopurpurin",\n \"popularity\": 5112\n },\n {\n \"tag\": "impose",\n \"popularity\": 5108\n },\n {\n \"tag\": "wordsmanship",\n \"popularity\": 5104\n },\n {\n \"tag\": "saturator",\n \"popularity\": 5100\n },\n {\n \"tag\": "Nordicity",\n \"popularity\": 5096\n },\n {\n \"tag\": "interaccuse",\n \"popularity\": 5092\n },\n {\n \"tag\": "acridinic",\n \"popularity\": 5087\n },\n {\n \"tag\": "scholion",\n \"popularity\": 5083\n },\n {\n \"tag\": "pseudoaconitine",\n \"popularity\": 5079\n },\n {\n \"tag\": "doctorial",\n \"popularity\": 5075\n },\n {\n \"tag\": "Etchimin",\n \"popularity\": 5071\n },\n {\n \"tag\": "oliviform",\n \"popularity\": 5067\n },\n {\n \"tag\": "Pele",\n \"popularity\": 5063\n },\n {\n \"tag\": "Chiromantis Progymnasium",\n \"popularity\": 5059\n },\n {\n \"tag\": "toxosis",\n \"popularity\": 5055\n },\n {\n \"tag\": "spadilla",\n \"popularity\": 5051\n },\n {\n \"tag\": "Actinopterygii",\n \"popularity\": 5047\n },\n {\n \"tag\": "untiring",\n \"popularity\": 5043\n },\n {\n \"tag\": "butyral",\n \"popularity\": 5039\n },\n {\n \"tag\": "Gymnoderinae",\n \"popularity\": 5035\n },\n {\n \"tag\": "testudo",\n \"popularity\": 5031\n },\n {\n \"tag\": "frigorify",\n \"popularity\": 5027\n },\n {\n \"tag\": "aliency",\n \"popularity\": 5023\n },\n {\n \"tag\": "jargon",\n \"popularity\": 5019\n },\n {\n \"tag\": "counterservice",\n \"popularity\": 5015\n },\n {\n \"tag\": "isostrychnine",\n \"popularity\": 5011\n },\n {\n \"tag\": "tellership",\n \"popularity\": 5007\n },\n {\n \"tag\": "miscegenetic",\n \"popularity\": 5003\n },\n {\n \"tag\": "sorcer",\n \"popularity\": 4999\n },\n {\n \"tag\": "tilewright",\n \"popularity\": 4995\n },\n {\n \"tag\": "cyanoplastid",\n \"popularity\": 4991\n },\n {\n \"tag\": "fluxionally",\n \"popularity\": 4987\n },\n {\n \"tag\": "proudhearted",\n \"popularity\": 4983\n },\n {\n \"tag\": "blithely",\n \"popularity\": 4979\n },\n {\n \"tag\": "jestproof",\n \"popularity\": 4975\n },\n {\n \"tag\": "jestwise",\n \"popularity\": 4971\n },\n {\n \"tag\": "nonassimilable",\n \"popularity\": 4967\n },\n {\n \"tag\": "compurgation",\n \"popularity\": 4964\n },\n {\n \"tag\": "unhate",\n \"popularity\": 4960\n },\n {\n \"tag\": "haplodonty",\n \"popularity\": 4956\n },\n {\n \"tag\": "cardholder",\n \"popularity\": 4952\n },\n {\n \"tag\": "rainlight megohmmeter overstout",\n \"popularity\": 4948\n },\n {\n \"tag\": "itchless",\n \"popularity\": 4944\n },\n {\n \"tag\": "begiggle",\n \"popularity\": 4940\n },\n {\n \"tag\": "chromatosphere",\n \"popularity\": 4936\n },\n {\n \"tag\": "typicality",\n \"popularity\": 4932\n },\n {\n \"tag\": "overgrown",\n \"popularity\": 4928\n },\n {\n \"tag\": "envolume",\n \"popularity\": 4925\n },\n {\n \"tag\": "pachycholia",\n \"popularity\": 4921\n },\n {\n \"tag\": "passageable",\n \"popularity\": 4917\n },\n {\n \"tag\": "pathopoiesis",\n \"popularity\": 4913\n },\n {\n \"tag\": "overbreak",\n \"popularity\": 4909\n },\n {\n \"tag\": "satyric",\n \"popularity\": 4905\n },\n {\n \"tag\": "unaudited",\n \"popularity\": 4901\n },\n {\n \"tag\": "whimble",\n \"popularity\": 4898\n },\n {\n \"tag\": "pressureless",\n \"popularity\": 4894\n },\n {\n \"tag\": "Selene",\n \"popularity\": 4890\n },\n {\n \"tag\": "slithery",\n \"popularity\": 4886\n },\n {\n \"tag\": "nondisfigurement",\n \"popularity\": 4882\n },\n {\n \"tag\": "overdelicious",\n \"popularity\": 4878\n },\n {\n \"tag\": "Perca",\n \"popularity\": 4875\n },\n {\n \"tag\": "Palladium",\n \"popularity\": 4871\n },\n {\n \"tag\": "insagacity",\n \"popularity\": 4867\n },\n {\n \"tag\": "peristoma",\n \"popularity\": 4863\n },\n {\n \"tag\": "uncreativeness",\n \"popularity\": 4859\n },\n {\n \"tag\": "incomparability surfboarding",\n \"popularity\": 4856\n },\n {\n \"tag\": "bacillar",\n \"popularity\": 4852\n },\n {\n \"tag\": "ulcerative",\n \"popularity\": 4848\n },\n {\n \"tag\": "stychomythia",\n \"popularity\": 4844\n },\n {\n \"tag\": "sesma somatics nonentry",\n \"popularity\": 4840\n },\n {\n \"tag\": "unsepulchred",\n \"popularity\": 4837\n },\n {\n \"tag\": "cephalanthium",\n \"popularity\": 4833\n },\n {\n \"tag\": "Asiaticization",\n \"popularity\": 4829\n },\n {\n \"tag\": "killeen",\n \"popularity\": 4825\n },\n {\n \"tag\": "Pseudococcus",\n \"popularity\": 4822\n },\n {\n \"tag\": "untractable",\n \"popularity\": 4818\n },\n {\n \"tag\": "apolegamic",\n \"popularity\": 4814\n },\n {\n \"tag\": "hyperpnea",\n \"popularity\": 4810\n },\n {\n \"tag\": "martyrolatry",\n \"popularity\": 4807\n },\n {\n \"tag\": "Sarmatic",\n \"popularity\": 4803\n },\n {\n \"tag\": "nonsurface",\n \"popularity\": 4799\n },\n {\n \"tag\": "adjoined",\n \"popularity\": 4796\n },\n {\n \"tag\": "vasiform",\n \"popularity\": 4792\n },\n {\n \"tag\": "tastelessness",\n \"popularity\": 4788\n },\n {\n \"tag\": "rumbo",\n \"popularity\": 4784\n },\n {\n \"tag\": "subdititious",\n \"popularity\": 4781\n },\n {\n \"tag\": "reparticipation",\n \"popularity\": 4777\n },\n {\n \"tag\": "Yorkshireism",\n \"popularity\": 4773\n },\n {\n \"tag\": "outcrow",\n \"popularity\": 4770\n },\n {\n \"tag\": "casserole",\n \"popularity\": 4766\n },\n {\n \"tag\": "semideltaic",\n \"popularity\": 4762\n },\n {\n \"tag\": "freemason",\n \"popularity\": 4759\n },\n {\n \"tag\": "catkin",\n \"popularity\": 4755\n },\n {\n \"tag\": "conscient",\n \"popularity\": 4751\n },\n {\n \"tag\": "reliably",\n \"popularity\": 4748\n },\n {\n \"tag\": "Telembi",\n \"popularity\": 4744\n },\n {\n \"tag\": "hide",\n \"popularity\": 4740\n },\n {\n \"tag\": "social",\n \"popularity\": 4737\n },\n {\n \"tag\": "ichneutic",\n \"popularity\": 4733\n },\n {\n \"tag\": "polypotome blouse pentagrammatic",\n \"popularity\": 4729\n },\n {\n \"tag\": "airdrome pesthole",\n \"popularity\": 4726\n },\n {\n \"tag\": "unportended",\n \"popularity\": 4722\n },\n {\n \"tag\": "sheerly",\n \"popularity\": 4719\n },\n {\n \"tag\": "acardiac",\n \"popularity\": 4715\n },\n {\n \"tag\": "fetor",\n \"popularity\": 4711\n },\n {\n \"tag\": "storax",\n \"popularity\": 4708\n },\n {\n \"tag\": "syndactylic",\n \"popularity\": 4704\n },\n {\n \"tag\": "otiatrics",\n \"popularity\": 4700\n },\n {\n \"tag\": "range",\n \"popularity\": 4697\n },\n {\n \"tag\": "branchway",\n \"popularity\": 4693\n },\n {\n \"tag\": "beatific",\n \"popularity\": 4690\n },\n {\n \"tag\": "Rugosa",\n \"popularity\": 4686\n },\n {\n \"tag\": "rafty",\n \"popularity\": 4682\n },\n {\n \"tag\": "gapy",\n \"popularity\": 4679\n },\n {\n \"tag\": "heterocercal",\n \"popularity\": 4675\n },\n {\n \"tag\": "actinopterygious",\n \"popularity\": 4672\n },\n {\n \"tag\": "glauconite",\n \"popularity\": 4668\n },\n {\n \"tag\": "limbless priest",\n \"popularity\": 4665\n },\n {\n \"tag\": "chrysene",\n \"popularity\": 4661\n },\n {\n \"tag\": "isentropic",\n \"popularity\": 4658\n },\n {\n \"tag\": "lairdess",\n \"popularity\": 4654\n },\n {\n \"tag\": "butterhead choliambic",\n \"popularity\": 4650\n },\n {\n \"tag\": "hexaseme",\n \"popularity\": 4647\n },\n {\n \"tag\": "treeify",\n \"popularity\": 4643\n },\n {\n \"tag\": "coronetted fructify",\n \"popularity\": 4640\n },\n {\n \"tag\": "admiralty",\n \"popularity\": 4636\n },\n {\n \"tag\": "Flosculariidae",\n \"popularity\": 4633\n },\n {\n \"tag\": "limaceous",\n \"popularity\": 4629\n },\n {\n \"tag\": "subterconscious",\n \"popularity\": 4626\n },\n {\n \"tag\": "stayless",\n \"popularity\": 4622\n },\n {\n \"tag\": "psha",\n \"popularity\": 4619\n },\n {\n \"tag\": "Mediterraneanize",\n \"popularity\": 4615\n },\n {\n \"tag\": "impenetrably",\n \"popularity\": 4612\n },\n {\n \"tag\": "Myrmeleonidae",\n \"popularity\": 4608\n },\n {\n \"tag\": "germander",\n \"popularity\": 4605\n },\n {\n \"tag\": "Buri",\n \"popularity\": 4601\n },\n {\n \"tag\": "papyrotamia",\n \"popularity\": 4598\n },\n {\n \"tag\": "Toxylon",\n \"popularity\": 4594\n },\n {\n \"tag\": "batatilla",\n \"popularity\": 4591\n },\n {\n \"tag\": "fabella assumer",\n \"popularity\": 4587\n },\n {\n \"tag\": "macromethod",\n \"popularity\": 4584\n },\n {\n \"tag\": "Blechnum",\n \"popularity\": 4580\n },\n {\n \"tag\": "pantography",\n \"popularity\": 4577\n },\n {\n \"tag\": "seminovel",\n \"popularity\": 4574\n },\n {\n \"tag\": "disembarrassment",\n \"popularity\": 4570\n },\n {\n \"tag\": "bushmaking",\n \"popularity\": 4567\n },\n {\n \"tag\": "neurosis",\n \"popularity\": 4563\n },\n {\n \"tag\": "Animalia",\n \"popularity\": 4560\n },\n {\n \"tag\": "Bernice",\n \"popularity\": 4556\n },\n {\n \"tag\": "wisen",\n \"popularity\": 4553\n },\n {\n \"tag\": "subhymenium",\n \"popularity\": 4549\n },\n {\n \"tag\": "esophagomycosis",\n \"popularity\": 4546\n },\n {\n \"tag\": "wireworks",\n \"popularity\": 4543\n },\n {\n \"tag\": "Sabellidae",\n \"popularity\": 4539\n },\n {\n \"tag\": "fustianish",\n \"popularity\": 4536\n },\n {\n \"tag\": "professively",\n \"popularity\": 4532\n },\n {\n \"tag\": "overcorruptly",\n \"popularity\": 4529\n },\n {\n \"tag\": "overcreep",\n \"popularity\": 4526\n },\n {\n \"tag\": "Castilloa",\n \"popularity\": 4522\n },\n {\n \"tag\": "forelady Georgie",\n \"popularity\": 4519\n },\n {\n \"tag\": "outsider",\n \"popularity\": 4515\n },\n {\n \"tag\": "Enukki",\n \"popularity\": 4512\n },\n {\n \"tag\": "gypsy",\n \"popularity\": 4509\n },\n {\n \"tag\": "Passamaquoddy",\n \"popularity\": 4505\n },\n {\n \"tag\": "reposit",\n \"popularity\": 4502\n },\n {\n \"tag\": "overtenderness",\n \"popularity\": 4499\n },\n {\n \"tag\": "keratome",\n \"popularity\": 4495\n },\n {\n \"tag\": "interclavicular hypermonosyllable Susanna",\n \"popularity\": 4492\n },\n {\n \"tag\": "mispropose",\n \"popularity\": 4489\n },\n {\n \"tag\": "Membranipora",\n \"popularity\": 4485\n },\n {\n \"tag\": "lampad",\n \"popularity\": 4482\n },\n {\n \"tag\": "header",\n \"popularity\": 4479\n },\n {\n \"tag\": "triseriate",\n \"popularity\": 4475\n },\n {\n \"tag\": "distrainment",\n \"popularity\": 4472\n },\n {\n \"tag\": "staphyloplastic",\n \"popularity\": 4469\n },\n {\n \"tag\": "outscour",\n \"popularity\": 4465\n },\n {\n \"tag\": "tallowmaking",\n \"popularity\": 4462\n },\n {\n \"tag\": "plugger",\n \"popularity\": 4459\n },\n {\n \"tag\": "fashionize",\n \"popularity\": 4455\n },\n {\n \"tag\": "puzzle",\n \"popularity\": 4452\n },\n {\n \"tag\": "imbrue",\n \"popularity\": 4449\n },\n {\n \"tag\": "osteoblast",\n \"popularity\": 4445\n },\n {\n \"tag\": "Hydrocores",\n \"popularity\": 4442\n },\n {\n \"tag\": "Lutra",\n \"popularity\": 4439\n },\n {\n \"tag\": "upridge scarfy",\n \"popularity\": 4435\n },\n {\n \"tag\": "ancon taffle",\n \"popularity\": 4432\n },\n {\n \"tag\": "impest",\n \"popularity\": 4429\n },\n {\n \"tag\": "uncollatedness",\n \"popularity\": 4426\n },\n {\n \"tag\": "hypersensitize",\n \"popularity\": 4422\n },\n {\n \"tag\": "autographically",\n \"popularity\": 4419\n },\n {\n \"tag\": "louther",\n \"popularity\": 4416\n },\n {\n \"tag\": "Ollie",\n \"popularity\": 4413\n },\n {\n \"tag\": "recompensate",\n \"popularity\": 4409\n },\n {\n \"tag\": "Shan",\n \"popularity\": 4406\n },\n {\n \"tag\": "brachycnemic",\n \"popularity\": 4403\n },\n {\n \"tag\": "Carinatae",\n \"popularity\": 4399\n },\n {\n \"tag\": "geotherm",\n \"popularity\": 4396\n },\n {\n \"tag\": "sawback",\n \"popularity\": 4393\n },\n {\n \"tag\": "Novatianist",\n \"popularity\": 4390\n },\n {\n \"tag\": "reapproach",\n \"popularity\": 4387\n },\n {\n \"tag\": "myelopoietic",\n \"popularity\": 4383\n },\n {\n \"tag\": "cyanin",\n \"popularity\": 4380\n },\n {\n \"tag\": "unsmutted",\n \"popularity\": 4377\n },\n {\n \"tag\": "nonpapist",\n \"popularity\": 4374\n },\n {\n \"tag\": "transbaikalian",\n \"popularity\": 4370\n },\n {\n \"tag\": "connately",\n \"popularity\": 4367\n },\n {\n \"tag\": "tenderize iterance",\n \"popularity\": 4364\n },\n {\n \"tag\": "hydrostatical",\n \"popularity\": 4361\n },\n {\n \"tag\": "unflag",\n \"popularity\": 4358\n },\n {\n \"tag\": "translate",\n \"popularity\": 4354\n },\n {\n \"tag\": "Scorzonera",\n \"popularity\": 4351\n },\n {\n \"tag\": "uncomforted",\n \"popularity\": 4348\n },\n {\n \"tag\": "risser varied",\n \"popularity\": 4345\n },\n {\n \"tag\": "plumbate",\n \"popularity\": 4342\n },\n {\n \"tag\": "Usneaceae",\n \"popularity\": 4338\n },\n {\n \"tag\": "fohat",\n \"popularity\": 4335\n },\n {\n \"tag\": "slagging",\n \"popularity\": 4332\n },\n {\n \"tag\": "superserious",\n \"popularity\": 4329\n },\n {\n \"tag\": "theocracy",\n \"popularity\": 4326\n },\n {\n \"tag\": "valonia",\n \"popularity\": 4323\n },\n {\n \"tag\": "Sapindales",\n \"popularity\": 4319\n },\n {\n \"tag\": "palaeozoologist",\n \"popularity\": 4316\n },\n {\n \"tag\": "yalb",\n \"popularity\": 4313\n },\n {\n \"tag\": "unviewed",\n \"popularity\": 4310\n },\n {\n \"tag\": "polyarteritis",\n \"popularity\": 4307\n },\n {\n \"tag\": "vectorial",\n \"popularity\": 4304\n },\n {\n \"tag\": "skimpingly",\n \"popularity\": 4301\n },\n {\n \"tag\": "athort",\n \"popularity\": 4297\n },\n {\n \"tag\": "tribofluorescence",\n \"popularity\": 4294\n },\n {\n \"tag\": "benzonitrol",\n \"popularity\": 4291\n },\n {\n \"tag\": "swiller subobtuse subjacency",\n \"popularity\": 4288\n },\n {\n \"tag\": "uncompassed",\n \"popularity\": 4285\n },\n {\n \"tag\": "cacochymia",\n \"popularity\": 4282\n },\n {\n \"tag\": "commensalist butadiene",\n \"popularity\": 4279\n },\n {\n \"tag\": "culpable",\n \"popularity\": 4276\n },\n {\n \"tag\": "contributive",\n \"popularity\": 4273\n },\n {\n \"tag\": "attemperately",\n \"popularity\": 4269\n },\n {\n \"tag\": "spelt",\n \"popularity\": 4266\n },\n {\n \"tag\": "exoneration",\n \"popularity\": 4263\n },\n {\n \"tag\": "antivivisectionist",\n \"popularity\": 4260\n },\n {\n \"tag\": "granitification",\n \"popularity\": 4257\n },\n {\n \"tag\": "palladize",\n \"popularity\": 4254\n },\n {\n \"tag\": "marksmanship",\n \"popularity\": 4251\n },\n {\n \"tag\": "bullydom",\n \"popularity\": 4248\n },\n {\n \"tag\": "spirality",\n \"popularity\": 4245\n },\n {\n \"tag\": "caliginous",\n \"popularity\": 4242\n },\n {\n \"tag\": "reportedly",\n \"popularity\": 4239\n },\n {\n \"tag\": "polyad",\n \"popularity\": 4236\n },\n {\n \"tag\": "arthroempyesis",\n \"popularity\": 4233\n },\n {\n \"tag\": "semibay facultatively",\n \"popularity\": 4229\n },\n {\n \"tag\": "metastatically",\n \"popularity\": 4226\n },\n {\n \"tag\": "prophetically",\n \"popularity\": 4223\n },\n {\n \"tag\": "Linguatula elapid",\n \"popularity\": 4220\n },\n {\n \"tag\": "pyknatom",\n \"popularity\": 4217\n },\n {\n \"tag\": "centimeter",\n \"popularity\": 4214\n },\n {\n \"tag\": "mensurate",\n \"popularity\": 4211\n },\n {\n \"tag\": "migraine",\n \"popularity\": 4208\n },\n {\n \"tag\": "pentagamist",\n \"popularity\": 4205\n },\n {\n \"tag\": "querken",\n \"popularity\": 4202\n },\n {\n \"tag\": "ambulance",\n \"popularity\": 4199\n },\n {\n \"tag\": "Stokavian",\n \"popularity\": 4196\n },\n {\n \"tag\": "malvasian",\n \"popularity\": 4193\n },\n {\n \"tag\": "uncouthsome",\n \"popularity\": 4190\n },\n {\n \"tag\": "readable",\n \"popularity\": 4187\n },\n {\n \"tag\": "enlodge",\n \"popularity\": 4184\n },\n {\n \"tag\": "plasterwise Appendiculariidae perspectograph",\n \"popularity\": 4181\n },\n {\n \"tag\": "inkweed",\n \"popularity\": 4178\n },\n {\n \"tag\": "streep",\n \"popularity\": 4175\n },\n {\n \"tag\": "diadelphian cultured",\n \"popularity\": 4172\n },\n {\n \"tag\": "hymenopterous",\n \"popularity\": 4169\n },\n {\n \"tag\": "unexorableness",\n \"popularity\": 4166\n },\n {\n \"tag\": "cascaron",\n \"popularity\": 4163\n },\n {\n \"tag\": "undaintiness",\n \"popularity\": 4160\n },\n {\n \"tag\": "Curtana",\n \"popularity\": 4157\n },\n {\n \"tag\": "scurvied",\n \"popularity\": 4154\n },\n {\n \"tag\": "molluscoidal",\n \"popularity\": 4151\n },\n {\n \"tag\": "yurt",\n \"popularity\": 4148\n },\n {\n \"tag\": "deciduitis",\n \"popularity\": 4145\n },\n {\n \"tag\": "creephole",\n \"popularity\": 4142\n },\n {\n \"tag\": "quatrefeuille",\n \"popularity\": 4139\n },\n {\n \"tag\": "bicapitate adenomatome",\n \"popularity\": 4136\n },\n {\n \"tag\": "damassin",\n \"popularity\": 4134\n },\n {\n \"tag\": "planching",\n \"popularity\": 4131\n },\n {\n \"tag\": "dashedly inferential",\n \"popularity\": 4128\n },\n {\n \"tag\": "lobe",\n \"popularity\": 4125\n },\n {\n \"tag\": "Hyrachyus",\n \"popularity\": 4122\n },\n {\n \"tag\": "knab",\n \"popularity\": 4119\n },\n {\n \"tag\": "discohexaster",\n \"popularity\": 4116\n },\n {\n \"tag\": "malign",\n \"popularity\": 4113\n },\n {\n \"tag\": "pedagoguism",\n \"popularity\": 4110\n },\n {\n \"tag\": "shrubbery",\n \"popularity\": 4107\n },\n {\n \"tag\": "undershrub",\n \"popularity\": 4104\n },\n {\n \"tag\": "bureaucrat",\n \"popularity\": 4101\n },\n {\n \"tag\": "pantaleon",\n \"popularity\": 4098\n },\n {\n \"tag\": "mesoventral",\n \"popularity\": 4096\n }]'; + +var log2 = Math.log(2); +var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); + +function makeTagCloud(tagInfo) +{ + var output = '
'; + + tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; }); + + for (var i = 0; i < tagInfo.length; i++) { + var tag = tagInfo[i].tag; + + var validates = true; + for (var j = 0; j < tag.length; j++) { + var ch = tag.charCodeAt(j); + if (ch < 0x20 || ch >= 0x7f) { + validates = false; + break; + } + } + + if (!validates) + continue; + + var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); + var popularity = tagInfo[i].popularity; + var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; + output += ' ' + tag + ' \n'; + } + + output += '
'; + output.replace(" ", " "); + + return output; +} + +var tagcloud = makeTagCloud(tagInfo); +tagInfo = null; + +// The result string embeds floating-point numbers, which can vary a bit on different platforms, +// so we truncate them a bit before comparing. +var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) +assertEq(tagcloud_norm.length, 295906) diff --git a/js/src/tests/js1_8_1/jit/jstests.list b/js/src/tests/js1_8_1/jit/jstests.list new file mode 100644 index 00000000000..d21cf7d0743 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/jstests.list @@ -0,0 +1,24 @@ +url-prefix ../../jsreftest.html?test=js1_8_1/jit/ +script math-jit-tests.js +skip script regress-451673.js # bogus perf test (bug 540512) +skip script regress-451974-01.js # bogus perf test (bug 540512) +skip script regress-451974-02.js # bogus perf test (bug 540512) +skip script regress-452498-01.js # bogus perf test (bug 540512) +script regress-458838.js +script regress-462459-01.js +script regress-462459-02.js +script regress-462459-03.js +script regress-462459-04.js +script regress-462459-05.js +script regress-462459-06.js +script regress-462459-07.js +script regress-462459-08.js +script regress-462459-09.js +script regress-462459-10.js +script regress-462459-11.js +script regress-462459-12.js +skip script regress-469927.js # bogus perf test (bug 540512) +skip script regress-470739.js # bogus perf test (bug 540512) +script regress-471635.js +script regress-489682.js +script testDeepBailFromNonNative.js diff --git a/js/src/tests/js1_8_1/jit/regress-451673.js b/js/src/tests/js1_8_1/jit/regress-451673.js new file mode 100644 index 00000000000..5c7202fe039 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451673.js @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451673; +var summary = 'TM: Tracing prime number generation'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function doTest(enablejit) + { + if (enablejit) + jit(true); + else + jit(false); + + var n = 1000000; + var start = new Date(); + var i=0; + var j=0; + var numprimes=0; + var limit=0; + numprimes = 1; // 2 is prime + var mceil = Math.floor; + var msqrt = Math.sqrt; + var isPrime = 1; + + for (i = 3; i<= n; i+=2) + { + isPrime=1; + limit = mceil(msqrt(i)+1) + 1; + + for (j = 3; j < limit; j+=2) + { + if (i % j == 0) + { + isPrime = 0; + break; + } + } + + if (isPrime) + { + numprimes ++; + } + } + + var end = new Date(); + + var timetaken = end - start; + timetaken = timetaken / 1000; + + if (enablejit) + jit(false); + + print((enablejit ? ' JIT' : 'Non-JIT') + ": Number of primes up to: " + n + " is " + numprimes + ", counted in " + timetaken + " secs."); + + return timetaken; + } + + var timenonjit = doTest(false); + var timejit = doTest(true); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-451974-01.js b/js/src/tests/js1_8_1/jit/regress-451974-01.js new file mode 100644 index 00000000000..59fc1415da3 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451974-01.js @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451974; +var summary = 'TM: loops with anon functions should not be slower with jit enabled'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var chars = '0123456789abcdef'; +var size = 10000; +var mult = 1000; +var densearray = []; +var lsize = size; + +while (lsize--) +{ + densearray.push(chars); +} + +function loop() +{ + var start = new Date(); + + for (var a = 0; a < mult; a++) + { + var f = (function(x){}); + for (var i = 0, len = densearray.length; i < len; i++) + { + f(densearray[i]); + } + } + + var stop = new Date(); + return stop - start; +} + +jit(false); +var timenonjit = loop(); +jit(true); +var timejit = loop(); +jit(false); + +print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + +expect = true; +actual = timejit < timenonjit/2; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-451974-02.js b/js/src/tests/js1_8_1/jit/regress-451974-02.js new file mode 100644 index 00000000000..f0de29d49bf --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-451974-02.js @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 451974; +var summary = 'TM: loops with anon functions should not be slower with jit enabled'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + var chars = '0123456789abcdef'; + var size = 10000; + var mult = 1000; + var densearray = []; + var lsize = size; + + while (lsize--) + { + densearray.push(chars); + } + + function loop() + { + var start = new Date(); + + for (var a = 0; a < mult; a++) + { + var f = (function(x){}); + for (var i = 0, len = densearray.length; i < len; i++) + { + f(densearray[i]); + } + } + + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = loop(); + jit(true); + var timejit = loop(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit/2; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-452498-01.js b/js/src/tests/js1_8_1/jit/regress-452498-01.js new file mode 100644 index 00000000000..c857e2087af --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-452498-01.js @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarsky + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 452498; +var summary = 'TM: upvar2: jit heavyweight functions'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function complex(aReal, aImag) { + this.r = aReal; + this.i = aImag; + this.square = function() { + return new complex(this.r * this.r - this.i * this.i, + 2 * this.r * this.i); + } + this.dist = function() { + return Math.sqrt(this.r * this.r + this.i * this.i); + } + this.add = function(aComplex) { + return new complex(this.r + aComplex.r, this.i + aComplex.i); + } +} + +function mandelbrotValueOO (aC, aIterMax) { + let Z = new complex(0.0, 0.0); + for (var iter = 0; iter < aIterMax; iter++) { + Z = Z.square().add(aC); + if (Z.r * Z.r + Z.i * Z.i > 256) { break; } + } + return iter; +} + +function f(trace) { + jit(trace); + var start = Date.now(); + const width = 60; + const height = 60; + const max_iters = 50; + var output = []; + for (let img_x = 0; img_x < width; img_x++) { + for (let img_y = 0; img_y < height; img_y++) { + let C = new complex(-2 + (img_x / width) * 3, + -1.5 + (img_y / height) * 3); + var res = mandelbrotValueOO(C, max_iters); + if (output.length > 0 && output[output.length -1][0] == res) { + output[output.length-1][1]++; + } else { + output.push([res, 1]); + } + } + } + jit(false); + const reference = "[[2, 6], [3, 17], [4, 6], [5, 1], [50, 1], [5, 1], [4, 6], [3, 17], [2, 10], [3, 17], [4, 6], [5, 1], [6, 1], [50, 1], [6, 1], [5, 1], [4, 6], [3, 17], [2, 8], [3, 17], [4, 6], [5, 2], [6, 1], [50, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 6], [3, 17], [4, 6], [5, 2], [6, 1], [7, 1], [50, 1], [7, 1], [6, 1], [5, 2], [4, 6], [3, 17], [2, 4], [3, 17], [4, 7], [5, 2], [6, 1], [8, 1], [50, 1], [8, 1], [6, 1], [5, 2], [4, 7], [3, 17], [2, 2], [3, 17], [4, 7], [5, 3], [6, 1], [9, 1], [50, 1], [9, 1], [6, 1], [5, 3], [4, 7], [3, 17], [2, 1], [3, 16], [4, 7], [5, 3], [6, 2], [8, 1], [50, 1], [8, 1], [6, 2], [5, 3], [4, 7], [3, 32], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 31], [4, 7], [5, 3], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 30], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [50, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 28], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [10, 1], [50, 1], [10, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 26], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [11, 1], [50, 1], [11, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 25], [4, 6], [5, 3], [6, 3], [7, 1], [8, 1], [18, 1], [13, 1], [15, 1], [50, 1], [15, 1], [13, 1], [18, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 6], [3, 24], [4, 7], [5, 2], [6, 2], [7, 3], [8, 1], [10, 1], [14, 1], [50, 3], [14, 1], [10, 1], [8, 1], [7, 3], [6, 2], [5, 2], [4, 7], [3, 23], [4, 6], [5, 3], [7, 1], [8, 1], [9, 1], [8, 2], [10, 1], [11, 1], [15, 1], [50, 3], [15, 1], [11, 1], [10, 1], [8, 2], [9, 1], [8, 1], [7, 1], [5, 3], [4, 6], [3, 22], [4, 7], [5, 2], [6, 1], [7, 1], [14, 1], [16, 1], [11, 1], [10, 1], [12, 1], [20, 1], [23, 1], [46, 1], [50, 1], [46, 1], [23, 1], [20, 1], [12, 1], [10, 1], [11, 1], [16, 1], [14, 1], [7, 1], [6, 1], [5, 2], [4, 7], [3, 20], [4, 7], [5, 3], [6, 1], [7, 1], [8, 1], [10, 1], [17, 1], [16, 1], [20, 1], [50, 7], [20, 1], [16, 1], [17, 1], [10, 1], [8, 1], [7, 1], [6, 1], [5, 3], [4, 7], [3, 19], [4, 7], [5, 3], [6, 2], [7, 1], [10, 1], [21, 1], [50, 11], [21, 1], [10, 1], [7, 1], [6, 2], [5, 3], [4, 7], [3, 18], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [9, 1], [13, 1], [25, 1], [50, 9], [25, 1], [13, 1], [9, 1], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 17], [4, 7], [5, 4], [6, 1], [7, 1], [8, 1], [14, 2], [50, 11], [14, 2], [8, 1], [7, 1], [6, 1], [5, 4], [4, 7], [3, 16], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [11, 1], [36, 1], [50, 11], [36, 1], [11, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 15], [4, 7], [5, 4], [6, 2], [7, 1], [8, 1], [9, 1], [14, 1], [50, 11], [14, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 4], [4, 7], [3, 14], [4, 7], [5, 4], [6, 3], [7, 1], [8, 1], [9, 1], [12, 1], [26, 1], [50, 9], [26, 1], [12, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 4], [4, 7], [3, 13], [4, 7], [5, 4], [6, 2], [7, 2], [8, 1], [9, 1], [10, 1], [15, 1], [50, 9], [15, 1], [10, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 4], [4, 7], [3, 12], [4, 7], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [10, 1], [12, 1], [16, 1], [50, 7], [16, 1], [12, 1], [10, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 7], [3, 11], [4, 6], [5, 4], [6, 3], [7, 1], [8, 2], [9, 1], [11, 1], [12, 1], [14, 1], [17, 1], [23, 1], [34, 1], [50, 3], [34, 1], [23, 1], [17, 1], [14, 1], [12, 1], [11, 1], [9, 1], [8, 2], [7, 1], [6, 3], [5, 4], [4, 6], [3, 10], [4, 7], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [22, 1], [12, 1], [50, 1], [25, 1], [50, 11], [25, 1], [50, 1], [12, 1], [22, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 7], [3, 9], [4, 6], [5, 4], [6, 1], [7, 1], [8, 2], [9, 1], [14, 1], [50, 1], [21, 1], [50, 15], [21, 1], [50, 1], [14, 1], [9, 1], [8, 2], [7, 1], [6, 1], [5, 4], [4, 6], [3, 8], [4, 7], [5, 3], [6, 2], [9, 1], [14, 1], [13, 1], [11, 1], [13, 1], [26, 1], [50, 17], [26, 1], [13, 1], [11, 1], [13, 1], [14, 1], [9, 1], [6, 2], [5, 3], [4, 7], [3, 7], [4, 6], [5, 4], [6, 1], [7, 1], [9, 1], [49, 1], [43, 1], [50, 23], [43, 1], [49, 1], [9, 1], [7, 1], [6, 1], [5, 4], [4, 6], [3, 7], [4, 5], [5, 4], [6, 2], [7, 1], [9, 1], [13, 1], [50, 25], [13, 1], [9, 1], [7, 1], [6, 2], [5, 4], [4, 5], [3, 6], [4, 6], [5, 3], [6, 2], [7, 2], [9, 1], [11, 1], [17, 1], [50, 23], [17, 1], [11, 1], [9, 1], [7, 2], [6, 2], [5, 3], [4, 6], [3, 5], [4, 5], [5, 3], [6, 3], [7, 1], [8, 1], [9, 1], [50, 1], [26, 1], [50, 23], [26, 1], [50, 1], [9, 1], [8, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 5], [4, 4], [5, 3], [6, 3], [7, 1], [8, 2], [10, 1], [21, 1], [50, 25], [21, 1], [10, 1], [8, 2], [7, 1], [6, 3], [5, 3], [4, 4], [3, 5], [4, 4], [5, 2], [6, 3], [7, 1], [12, 1], [9, 1], [10, 1], [11, 1], [50, 27], [11, 1], [10, 1], [9, 1], [12, 1], [7, 1], [6, 3], [5, 2], [4, 4], [3, 5], [4, 3], [5, 2], [6, 2], [7, 2], [9, 1], [42, 1], [15, 1], [23, 1], [14, 1], [50, 27], [14, 1], [23, 1], [15, 1], [42, 1], [9, 1], [7, 2], [6, 2], [5, 2], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [20, 1], [9, 1], [8, 1], [9, 1], [10, 1], [16, 1], [50, 33], [16, 1], [10, 1], [9, 1], [8, 1], [9, 1], [20, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 1], [6, 1], [9, 1], [13, 1], [12, 1], [11, 1], [38, 1], [25, 1], [50, 33], [25, 1], [38, 1], [11, 1], [12, 1], [13, 1], [9, 1], [6, 1], [5, 1], [4, 3], [3, 5], [4, 3], [5, 2], [6, 1], [7, 1], [10, 1], [24, 1], [25, 1], [50, 35], [25, 1], [24, 1], [10, 1], [7, 1], [6, 1], [5, 2], [4, 3], [3, 5], [4, 4], [5, 1], [6, 1], [7, 1], [11, 2], [13, 1], [19, 1], [50, 33], [19, 1], [13, 1], [11, 2], [7, 1], [6, 1], [5, 1], [4, 4], [3, 5], [4, 4], [5, 2], [6, 1], [50, 1], [8, 2], [17, 1], [19, 1], [35, 1], [14, 1], [24, 1], [50, 25], [24, 1], [14, 1], [35, 1], [19, 1], [17, 1], [8, 2], [50, 1], [6, 1], [5, 2], [4, 4], [3, 5], [4, 5], [5, 2], [6, 2], [7, 1], [8, 1], [9, 2], [11, 1], [38, 1], [50, 25], [38, 1], [11, 1], [9, 2], [8, 1], [7, 1], [6, 2], [5, 2], [4, 5], [3, 6], [4, 4], [5, 3], [6, 2], [7, 2], [8, 1], [9, 1], [15, 1], [50, 25], [15, 1], [9, 1], [8, 1], [7, 2], [6, 2], [5, 3], [4, 4], [3, 7], [4, 5], [5, 3], [6, 3], [7, 1], [9, 1], [42, 1], [21, 1], [50, 23], [21, 1], [42, 1], [9, 1], [7, 1], [6, 3], [5, 3], [4, 5], [3, 8], [4, 5], [5, 3], [6, 2], [7, 1], [8, 1], [9, 1], [13, 1], [50, 23], [13, 1], [9, 1], [8, 1], [7, 1], [6, 2], [5, 3], [4, 5], [3, 9], [4, 6], [5, 3], [6, 2], [7, 1], [9, 1], [14, 1], [50, 23], [14, 1], [9, 1], [7, 1], [6, 2], [5, 3], [4, 6], [3, 10], [4, 6], [5, 3], [6, 1], [7, 1], [9, 1], [16, 1], [50, 2], [35, 1], [50, 8], [13, 1], [50, 8], [35, 1], [50, 2], [16, 1], [9, 1], [7, 1], [6, 1], [5, 3], [4, 6], [3, 12], [4, 6], [5, 2], [6, 1], [19, 1], [16, 1], [17, 1], [25, 1], [21, 1], [13, 1], [18, 1], [50, 6], [11, 1], [9, 1], [11, 1], [50, 6], [18, 1], [13, 1], [21, 1], [25, 1], [17, 1], [16, 1], [19, 1], [6, 1], [5, 2], [4, 6], [3, 14], [4, 5], [5, 3], [6, 1], [8, 1], [16, 1], [10, 1], [8, 2], [11, 1], [50, 1], [16, 1], [15, 1], [32, 1], [29, 1], [9, 1], [8, 1], [7, 1], [8, 1], [9, 1], [29, 1], [32, 1], [15, 1], [16, 1], [50, 1], [11, 1], [8, 2], [10, 1], [16, 1], [8, 1], [6, 1], [5, 3], [4, 5], [3, 15], [4, 6], [5, 3], [6, 4], [7, 1], [20, 1], [19, 1], [9, 3], [7, 3], [6, 1], [7, 3], [9, 3], [19, 1], [20, 1], [7, 1], [6, 4], [5, 3], [4, 6], [3, 16], [4, 7], [5, 4], [6, 3], [7, 1], [6, 13], [7, 1], [6, 3], [5, 4], [4, 7], [3, 18], [4, 7], [5, 27], [4, 7], [3, 20], [4, 9], [5, 21], [4, 9], [3, 23], [4, 12], [5, 11], [4, 12], [3, 26], [4, 33], [3, 29], [4, 29], [3, 33], [4, 25], [3, 38], [4, 19], [3, 20], [2, 1], [3, 26], [4, 7], [3, 26], [2, 2], [3, 57], [2, 1]]"; + reportCompare(reference, output.toSource(), summary + ': correctness jit=' + trace); + return (Date.now() - start); +} + + +var timenonjit = f(false); +var timejit = f(true); + +expect = true; +actual = timejit < timenonjit; + +print('time nonjit: ' + timenonjit + ', time jit: ' + timejit); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/regress-458838.js b/js/src/tests/js1_8_1/jit/regress-458838.js new file mode 100644 index 00000000000..0cc6991eb78 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-458838.js @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarksy + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 458838; +var summary = 'TM: do not fall off trace when nested function accesses var of outer function'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + jit(true); + + function f() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); + } + + expect = 10; + actual = f(); + + var recorderStarted; + var recorderAborted; + var traceCompleted; + var skip = true; + + if (this.tracemonkey && !this.tracemonkey.profiler) + { + recorderStarted = this.tracemonkey.recorderStarted; + recorderAborted = this.tracemonkey.recorderAborted; + traceCompleted = this.tracemonkey.traceCompleted; + skip = false; + } + + jit(false); + + reportCompare(expect, actual, summary + ': return value 10'); + + if (!skip) + { + expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; + actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; + reportCompare(expect, actual, summary + ': trace'); + } + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-462459-01.js b/js/src/tests/js1_8_1/jit/regress-462459-01.js new file mode 100644 index 00000000000..7cfe2a90ba4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-01.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array()'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-02.js b/js/src/tests/js1_8_1/jit/regress-462459-02.js new file mode 100644 index 00000000000..14cc20198c4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-02.js @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-03.js b/js/src/tests/js1_8_1/jit/regress-462459-03.js new file mode 100644 index 00000000000..a1d3db47083 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-03.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1, 2)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1, 2); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-04.js b/js/src/tests/js1_8_1/jit/regress-462459-04.js new file mode 100644 index 00000000000..3bfe7278b1e --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-04.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace Array(1, 2, 3)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + Array(1, 2, 3); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-05.js b/js/src/tests/js1_8_1/jit/regress-462459-05.js new file mode 100644 index 00000000000..5513b078e44 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-05.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array()'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-06.js b/js/src/tests/js1_8_1/jit/regress-462459-06.js new file mode 100644 index 00000000000..aab4093ab5a --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-06.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-07.js b/js/src/tests/js1_8_1/jit/regress-462459-07.js new file mode 100644 index 00000000000..0a9632a723d --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-07.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1, 2)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1, 2); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-08.js b/js/src/tests/js1_8_1/jit/regress-462459-08.js new file mode 100644 index 00000000000..2c57b27fde4 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-08.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace new Array(1, 2, 3)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + new Array(1, 2, 3); + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-09.js b/js/src/tests/js1_8_1/jit/regress-462459-09.js new file mode 100644 index 00000000000..221fc19c429 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-09.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace []'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + []; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-10.js b/js/src/tests/js1_8_1/jit/regress-462459-10.js new file mode 100644 index 00000000000..4917d5cf31b --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-10.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-11.js b/js/src/tests/js1_8_1/jit/regress-462459-11.js new file mode 100644 index 00000000000..2f7cb1c5945 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-11.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1, 2]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1, 2]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-462459-12.js b/js/src/tests/js1_8_1/jit/regress-462459-12.js new file mode 100644 index 00000000000..524a7e4ae4c --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-462459-12.js @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 462459; +var summary = 'TM: trace [1, 2, 3]'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +if (!this.tracemonkey || this.tracemonkey.profiler) +{ + jit(false); + expect = actual = 'Test skipped due to lack of tracemonkey jitstats'; + reportCompare(expect, actual, summary); +} +else +{ + jit(true); + + expect = 'recorder started, recorder not aborted, trace completed'; + actual = ''; + + var recorderStartedStart = this.tracemonkey.recorderStarted; + var recorderAbortedStart = this.tracemonkey.recorderAborted; + var traceCompletedStart = this.tracemonkey.traceCompleted; + + + for (var i = 0; i < RUNLOOP; i++) + { + [1, 2, 3]; + } + + jit(false); + + var recorderStartedEnd = this.tracemonkey.recorderStarted; + var recorderAbortedEnd = this.tracemonkey.recorderAborted; + var traceCompletedEnd = this.tracemonkey.traceCompleted; + + if (recorderStartedEnd > recorderStartedStart) + { + actual = 'recorder started, '; + } + else + { + actual = 'recorder not started, '; + } + + if (recorderAbortedEnd > recorderAbortedStart) + { + actual += 'recorder aborted, '; + } + else + { + actual += 'recorder not aborted, '; + } + + if (traceCompletedEnd > traceCompletedStart) + { + actual += 'trace completed'; + } + else + { + actual += 'trace not completed'; + } + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/js1_8_1/jit/regress-469927.js b/js/src/tests/js1_8_1/jit/regress-469927.js new file mode 100644 index 00000000000..17b893674b1 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-469927.js @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469927; +var summary = 'TM: jit should not slow down short loop with let'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function letitbe() { + var start = new Date(); + for (let i = 0; i < 500000; ++i) { + for (let j = 0; j < 4; ++j) { } + } + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = letitbe(); + jit(true); + var timejit = letitbe(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-470739.js b/js/src/tests/js1_8_1/jit/regress-470739.js new file mode 100644 index 00000000000..b6b0e64e0f2 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-470739.js @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470739; +var summary = 'TM: never abort on =='; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + function loop() + { + var i; + var start = new Date(); + + for(i=0;i<500000;++i) { var r = (void 0) == null; } + + var stop = new Date(); + return stop - start; + } + + jit(false); + var timenonjit = loop(); + jit(true); + var timejit = loop(); + jit(false); + + print('time: nonjit = ' + timenonjit + ', jit = ' + timejit); + + expect = true; + actual = timejit < timenonjit; + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-471635.js b/js/src/tests/js1_8_1/jit/regress-471635.js new file mode 100644 index 00000000000..76078649204 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-471635.js @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Boris Zbarksy + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 471635; +var summary = 'TM: trace js shell print()'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + enterFunc ('test'); + printBugNumber(BUGNUMBER); + printStatus (summary); + + jit(true); + + (function(){ + for (var i = 1; i < 20; ++i) { + print("#"); + } + })(); + + var recorderStarted; + var recorderAborted; + var traceCompleted; + var skip = true; + + if (this.tracemonkey && !this.tracemonkey.profiler) + { + recorderStarted = this.tracemonkey.recorderStarted; + recorderAborted = this.tracemonkey.recorderAborted; + traceCompleted = this.tracemonkey.traceCompleted; + skip = false; + } + + jit(false); + + if (!skip) + { + expect = 'recorderStarted=1, recorderAborted=0, traceCompleted=1'; + actual = 'recorderStarted=' + recorderStarted + ', recorderAborted=' + recorderAborted + ', traceCompleted=' + traceCompleted; + } + else + { + expect = actual = 'Test skipped due to lack of tracemonkey jitstats object.'; + } + + reportCompare(expect, actual, summary); + + exitFunc ('test'); +} diff --git a/js/src/tests/js1_8_1/jit/regress-489682.js b/js/src/tests/js1_8_1/jit/regress-489682.js new file mode 100644 index 00000000000..b8b73ec1ca7 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/regress-489682.js @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is JavaScript Engine testing utilities. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Jesse Ruderman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 489682; +var summary = 'TM: wrong number with nested type-unstable loops'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +jit(true); + +var v = 0; + +for each (var a in [0, {}, {}, {}]) { + print(v); + v = v >>> 0; + for each (var b in [{}, {}, new String(''), 42, new String(''), {}, 42]) + { + } + } +print(v); + +jit(false); + +expect = '0'; +actual = v + ''; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/jit/shell.js b/js/src/tests/js1_8_1/jit/shell.js new file mode 100644 index 00000000000..63f283b96f8 --- /dev/null +++ b/js/src/tests/js1_8_1/jit/shell.js @@ -0,0 +1,4 @@ +// The loop count at which we trace +const RECORDLOOP = this.tracemonkey ? tracemonkey.HOTLOOP : 8; +// The loop count at which we run the trace +const RUNLOOP = RECORDLOOP + 1; From e8113edabedaddc4e1310467816ddb5ffe8da37b Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Tue, 2 Nov 2010 13:38:17 -0700 Subject: [PATCH 166/263] backing out a=bustage From b5b05337305a8b24b0e42a2dd6d3dfb3411f6b4d Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Thu, 21 Oct 2010 10:39:51 -0700 Subject: [PATCH 167/263] Bug 594909 - Intermittent failure in browser/base/content/test/tabview/browser_tabview_launch.js | Tab View is visible r=dietrich, a=test --- .../test/tabview/browser_tabview_launch.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/browser/base/content/test/tabview/browser_tabview_launch.js b/browser/base/content/test/tabview/browser_tabview_launch.js index 661ecf3be38..c8673e9f1e6 100644 --- a/browser/base/content/test/tabview/browser_tabview_launch.js +++ b/browser/base/content/test/tabview/browser_tabview_launch.js @@ -55,13 +55,28 @@ function test() { function onTabViewLoadedAndShown() { window.removeEventListener("tabviewshown", onTabViewLoadedAndShown, false); - ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); - tabViewShownCount++; + // Evidently sometimes isVisible (which is based on the selectedIndex of the + // tabview deck) isn't updated immediately when called from button.doCommand, + // so we add a little timeout here to get outside of the doCommand call. + // If the initial timeout isn't enough, we keep waiting in case it's taking + // longer than expected. + // See bug 594909. + let deck = document.getElementById("tab-view-deck"); + function waitForSwitch() { + if (deck.selectedIndex == 1) { + ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount); + tabViewShownCount++; + + // kick off the series + window.addEventListener("tabviewshown", onTabViewShown, false); + window.addEventListener("tabviewhidden", onTabViewHidden, false); + TabView.toggle(); + } else { + setTimeout(waitForSwitch, 10); + } + } - // kick off the series - window.addEventListener("tabviewshown", onTabViewShown, false); - window.addEventListener("tabviewhidden", onTabViewHidden, false); - TabView.toggle(); + setTimeout(waitForSwitch, 1); } // ---------- From e66e086b97b6e4ff7e7860ec95bbf8288cc18fff Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Tue, 2 Nov 2010 14:55:05 -0700 Subject: [PATCH 168/263] Bug 608911 - Invalid check in browser_bug562890.js. r=dtownsend, a=test fix --- .../extensions/test/browser/Makefile.in | 1 + .../extensions/test/browser/addon_prefs.xul | 1 + .../test/browser/browser_bug562890.js | 29 ++++++++++++------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/toolkit/mozapps/extensions/test/browser/Makefile.in b/toolkit/mozapps/extensions/test/browser/Makefile.in index cb629818ca8..42dbeb22d14 100644 --- a/toolkit/mozapps/extensions/test/browser/Makefile.in +++ b/toolkit/mozapps/extensions/test/browser/Makefile.in @@ -82,6 +82,7 @@ _TEST_FILES = \ $(NULL) _TEST_RESOURCES = \ + addon_prefs.xul \ browser_bug557956.rdf \ browser_bug557956_8_2.xpi \ browser_bug557956_9_2.xpi \ diff --git a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul index d058af2c5cd..85cfe6b2d4c 100644 --- a/toolkit/mozapps/extensions/test/browser/addon_prefs.xul +++ b/toolkit/mozapps/extensions/test/browser/addon_prefs.xul @@ -1,4 +1,5 @@ +