author | Kannan Vijayan <kvijayan@mozilla.com> |
Wed, 18 Jul 2012 15:14:16 -0400 | |
changeset 106562 | 787e00928fef52745d4cca6b567e54de463900f3 |
parent 106561 | bef02b378666624c29ef59b0790374b28a725d2b |
child 106563 | 02af560a8cc486670c985ebc497b9001f8b11375 |
push id | 23447 |
push user | danderson@mozilla.com |
push date | Tue, 11 Sep 2012 17:34:27 +0000 |
treeherder | mozilla-central@fdfaef738a00 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 775186 |
milestone | 16.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -196,16 +196,35 @@ CodeGenerator::visitTestVAndBranch(LTest bool CodeGenerator::visitInlineFunctionGuard(LInlineFunctionGuard *lir) { Register inputReg = ToRegister(lir->input()); masm.cmpPtr(inputReg, ImmGCPtr(lir->function())); emitBranch(Assembler::Equal, lir->functionBlock(), lir->fallbackBlock()); return true; } + +bool +CodeGenerator::visitPolyInlineDispatch(LPolyInlineDispatch *lir) +{ + MPolyInlineDispatch *mir = lir->mir(); + Register inputReg = ToRegister(lir->input()); + + for (size_t i = 0; i < mir->numCallees(); i++) { + JSFunction *func = mir->getFunctionConstant(i)->value().toObject().toFunction(); + LBlock *target = mir->getSuccessor(i)->lir(); + if (i < mir->numCallees() - 1) { + masm.branchPtr(Assembler::Equal, inputReg, ImmGCPtr(func), target->label()); + } else { + // Don't generate guard for final case + masm.jump(target->label()); + } + } + return true; +} bool CodeGenerator::visitIntToString(LIntToString *lir) { typedef JSFixedString *(*pf)(JSContext *, int); static const VMFunction IntToStringInfo = FunctionInfo<pf>(Int32ToString); pushArg(ToRegister(lir->input()));
--- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -88,16 +88,17 @@ class CodeGenerator : public CodeGenerat bool visitOsrEntry(LOsrEntry *lir); bool visitOsrScopeChain(LOsrScopeChain *lir); bool visitStackArg(LStackArg *lir); bool visitValueToInt32(LValueToInt32 *lir); bool visitValueToDouble(LValueToDouble *lir); bool visitInt32ToDouble(LInt32ToDouble *lir); bool visitTestVAndBranch(LTestVAndBranch *lir); bool visitInlineFunctionGuard(LInlineFunctionGuard *lir); + bool visitPolyInlineDispatch(LPolyInlineDispatch *lir); bool visitIntToString(LIntToString *lir); bool visitInteger(LInteger *lir); bool visitRegExp(LRegExp *lir); bool visitLambda(LLambda *lir); bool visitLambdaForSingleton(LLambdaForSingleton *lir); bool visitPointer(LPointer *lir); bool visitSlots(LSlots *lir); bool visitStoreSlotV(LStoreSlotV *store);
--- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -800,16 +800,36 @@ class LInlineFunctionGuard : public LIns JSFunction *function() const { return func_; } const LAllocation *input() { return getOperand(0); } }; +class LPolyInlineDispatch : public LInstructionHelper<0, 1, 0> +{ + // Accesses function/block table from MIR instruction. + public: + LIR_HEADER(PolyInlineDispatch); + + LPolyInlineDispatch(const LAllocation &in) { + setOperand(0, in); + } + + const LAllocation *input() { + return getOperand(0); + } + + MPolyInlineDispatch *mir() { + return mir_->toPolyInlineDispatch(); + } +}; + + // Compares two integral values of the same JS type, either integer or object. // For objects, both operands are in registers. class LCompare : public LInstructionHelper<1, 2, 0> { JSOp jsop_; public: LIR_HEADER(Compare);
--- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -77,16 +77,17 @@ _(ShiftOp) \ _(Return) \ _(Throw) \ _(Phi) \ _(TestIAndBranch) \ _(TestDAndBranch) \ _(TestVAndBranch) \ _(InlineFunctionGuard) \ + _(PolyInlineDispatch) \ _(Compare) \ _(CompareD) \ _(CompareS) \ _(CompareV) \ _(CompareAndBranch) \ _(CompareDAndBranch) \ _(CompareB) \ _(CompareBAndBranch) \
--- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -424,16 +424,23 @@ bool LIRGenerator::visitInlineFunctionGuard(MInlineFunctionGuard *ins) { LInlineFunctionGuard *lir = new LInlineFunctionGuard(useRegister(ins->input()), ins->function(), ins->functionBlock(), ins->fallbackBlock()); return add(lir); } +bool +LIRGenerator::visitPolyInlineDispatch(MPolyInlineDispatch *ins) +{ + LPolyInlineDispatch *lir = new LPolyInlineDispatch(useRegister(ins->input())); + return add(lir, ins); +} + static inline bool CanEmitCompareAtUses(MInstruction *ins) { if (!ins->canEmitAtUses()) return false; bool foundTest = false; for (MUseIterator iter(ins->usesBegin()); iter != ins->usesEnd(); iter++) {
--- a/js/src/ion/Lowering.h +++ b/js/src/ion/Lowering.h @@ -121,16 +121,17 @@ class LIRGenerator : public LIRGenerator bool visitPrepareCall(MPrepareCall *ins); bool visitPassArg(MPassArg *arg); bool visitCreateThis(MCreateThis *ins); bool visitReturnFromCtor(MReturnFromCtor *ins); bool visitCall(MCall *call); bool visitApplyArgs(MApplyArgs *apply); bool visitTest(MTest *test); bool visitInlineFunctionGuard(MInlineFunctionGuard *test); + bool visitPolyInlineDispatch(MPolyInlineDispatch *ins); bool visitCompare(MCompare *comp); bool visitTypeOf(MTypeOf *ins); bool visitToId(MToId *ins); bool visitBitNot(MBitNot *ins); bool visitBitAnd(MBitAnd *ins); bool visitBitOr(MBitOr *ins); bool visitBitXor(MBitXor *ins); bool visitLsh(MLsh *ins);
--- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -978,16 +978,98 @@ class MInlineFunctionGuard : public MAry return setSuccessor(1, fallback); } AliasSet getAliasSet() const { return AliasSet::None(); } }; +// Represents a polymorphic dispatch to one or more functions. +class MPolyInlineDispatch : public MControlInstruction, public SingleObjectPolicy +{ + // A table to map JSFunctions to the blocks that execute them. + struct Entry { + MConstant *funcConst; + MBasicBlock *block; + Entry(MConstant *funcConst, MBasicBlock *block) + : funcConst(funcConst), block(block) {} + }; + Vector<Entry, 4, IonAllocPolicy> dispatchTable_; + + MDefinition *operand_; + + MPolyInlineDispatch(MDefinition *ins) + : dispatchTable_(), operand_(NULL) + { + initOperand(0, ins); + } + + protected: + virtual void setOperand(size_t index, MDefinition *operand) { + JS_ASSERT(index == 0); + operand_ = operand; + } + + public: + INSTRUCTION_HEADER(PolyInlineDispatch); + + virtual MDefinition *getOperand(size_t index) const { + JS_ASSERT(index == 0); + return operand_; + } + + virtual size_t numOperands() const { return 1; } + virtual size_t numSuccessors() const { return dispatchTable_.length(); } + + virtual void replaceSuccessor(size_t i, MBasicBlock *successor) { + JS_ASSERT(i < dispatchTable_.length()); + dispatchTable_[i].block = successor; + } + + static MPolyInlineDispatch *New(MDefinition *ins) { + return new MPolyInlineDispatch(ins); + } + + size_t numCallees() const { + return dispatchTable_.length(); + } + + void addCallee(MConstant *funcConst, MBasicBlock *block) { + dispatchTable_.append(Entry(funcConst, block)); + } + + MConstant *getFunctionConstant(size_t i) const { + JS_ASSERT(i < numCallees()); + return dispatchTable_[i].funcConst; + } + + JSFunction *getFunction(size_t i) const { + return getFunctionConstant(i)->value().toObject().toFunction(); + } + + void setSuccessor(size_t i, MBasicBlock *successor) { + JS_ASSERT(i < numCallees()); + dispatchTable_[i].block = successor; + } + + MBasicBlock *getSuccessor(size_t i) const { + JS_ASSERT(i < numCallees()); + return dispatchTable_[i].block; + } + + MDefinition *input() const { + return getOperand(0); + } + + TypePolicy *typePolicy() { + return this; + } +}; + // Returns from this function to the previous caller. class MReturn : public MAryControlInstruction<1, 0>, public BoxInputsPolicy { MReturn(MDefinition *ins) { initOperand(0, ins);
--- a/js/src/ion/MOpcodes.h +++ b/js/src/ion/MOpcodes.h @@ -49,16 +49,17 @@ namespace ion { #define MIR_OPCODE_LIST(_) \ _(Constant) \ _(Parameter) \ _(Callee) \ _(TableSwitch) \ _(Goto) \ _(Test) \ _(InlineFunctionGuard) \ + _(PolyInlineDispatch) \ _(Compare) \ _(Phi) \ _(Beta) \ _(OsrValue) \ _(OsrScopeChain) \ _(ReturnFromCtor) \ _(CheckOverRecursed) \ _(RecompileCheck) \