From 147904b2978fe946f7a1fa97d126cabdcc5e9e51 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Fri, 19 Oct 2012 14:30:38 -0700 Subject: [PATCH] Bug 799818 part 2 - Handle unknown double as input of a table switch. r=djvj,h4writer --- js/src/ion/CodeGenerator.cpp | 43 +++++++++++++++++++ js/src/ion/CodeGenerator.h | 2 + js/src/ion/LOpcodes.h | 1 + js/src/ion/Lowering.cpp | 38 ++++++++++++++++ js/src/ion/Lowering.h | 1 + js/src/ion/MIR.h | 7 +-- js/src/ion/TypePolicy.cpp | 22 ---------- js/src/ion/TypePolicy.h | 6 --- js/src/ion/arm/CodeGenerator-arm.cpp | 36 ++++++---------- js/src/ion/arm/CodeGenerator-arm.h | 3 +- js/src/ion/arm/LIR-arm.h | 35 +++++++++++++++ js/src/ion/arm/Lowering-arm.cpp | 35 ++++----------- js/src/ion/arm/Lowering-arm.h | 5 ++- js/src/ion/shared/CodeGenerator-shared-inl.h | 6 +++ .../ion/shared/CodeGenerator-x86-shared.cpp | 38 ++++++---------- js/src/ion/shared/CodeGenerator-x86-shared.h | 3 +- js/src/ion/shared/LIR-x86-shared.h | 32 ++++++++++++++ js/src/ion/shared/Lowering-x86-shared.cpp | 35 ++++----------- js/src/ion/shared/Lowering-x86-shared.h | 5 ++- 19 files changed, 214 insertions(+), 139 deletions(-) diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index a1b5614c34d..2b1602615ae 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -361,6 +361,49 @@ CodeGenerator::visitGoto(LGoto *lir) return true; } +bool +CodeGenerator::visitTableSwitch(LTableSwitch *ins) +{ + MTableSwitch *mir = ins->mir(); + Label *defaultcase = mir->getDefault()->lir()->label(); + const LAllocation *temp; + + if (ins->index()->isDouble()) { + temp = ins->tempInt(); + + // The input is a double, so try and convert it to an integer. + // If it does not fit in an integer, take the default case. + emitDoubleToInt32(ToFloatRegister(ins->index()), ToRegister(temp), defaultcase, false); + } else { + temp = ins->index(); + } + + return emitTableSwitchDispatch(mir, ToRegister(temp), ToRegisterOrInvalid(ins->tempPointer())); +} + +bool +CodeGenerator::visitTableSwitchV(LTableSwitchV *ins) +{ + MTableSwitch *mir = ins->mir(); + Label *defaultcase = mir->getDefault()->lir()->label(); + + Register index = ToRegister(ins->tempInt()); + ValueOperand value = ToValue(ins, LTableSwitchV::Index); + Register tag = masm.extractTag(value, index); + masm.branchTestNumber(Assembler::NotEqual, tag, defaultcase); + + Label isInt; + masm.branchTestInt32(Assembler::Equal, tag, &isInt); + { + FloatRegister floatIndex = ToFloatRegister(ins->tempFloat()); + masm.unboxDouble(value, floatIndex); + emitDoubleToInt32(floatIndex, index, defaultcase, false); + } + masm.bind(&isInt); + + return emitTableSwitchDispatch(mir, index, ToRegisterOrInvalid(ins->tempPointer())); +} + bool CodeGenerator::visitParameter(LParameter *lir) { diff --git a/js/src/ion/CodeGenerator.h b/js/src/ion/CodeGenerator.h index f023a6b221d..f6d37db4f3b 100644 --- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -45,6 +45,8 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitNop(LNop *lir); bool visitOsiPoint(LOsiPoint *lir); bool visitGoto(LGoto *lir); + bool visitTableSwitch(LTableSwitch *ins); + bool visitTableSwitchV(LTableSwitchV *ins); bool visitParameter(LParameter *lir); bool visitCallee(LCallee *lir); bool visitStart(LStart *lir); diff --git a/js/src/ion/LOpcodes.h b/js/src/ion/LOpcodes.h index 562bf54a033..7b4348ccc67 100644 --- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -20,6 +20,7 @@ _(Parameter) \ _(Callee) \ _(TableSwitch) \ + _(TableSwitchV) \ _(Goto) \ _(NewArray) \ _(NewObject) \ diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp index ccd7bbab83c..a90659c422f 100644 --- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -67,6 +67,44 @@ LIRGenerator::visitGoto(MGoto *ins) return add(new LGoto(ins->target())); } +bool +LIRGenerator::visitTableSwitch(MTableSwitch *tableswitch) +{ + MDefinition *opd = tableswitch->getOperand(0); + + // There should be at least 1 successor. The default case! + JS_ASSERT(tableswitch->numSuccessors() > 0); + + // If there are no cases, the default case is always taken. + if (tableswitch->numSuccessors() == 1) + return add(new LGoto(tableswitch->getDefault())); + + // If we don't know the type. + if (opd->type() == MIRType_Value) { + LTableSwitchV *lir = newLTableSwitchV(tableswitch); + if (!useBox(lir, LTableSwitchV::InputValue, opd)) + return false; + return add(lir); + } + + // Case indices are numeric, so other types will always go to the default case. + if (opd->type() != MIRType_Int32 && opd->type() != MIRType_Double) + return add(new LGoto(tableswitch->getDefault())); + + // Return an LTableSwitch, capable of handling either an integer or + // floating-point index. + LAllocation index; + LDefinition tempInt; + if (opd->type() == MIRType_Int32) { + index = useRegisterAtStart(opd); + tempInt = tempCopy(opd, 0); + } else { + index = useRegister(opd); + tempInt = temp(LDefinition::GENERAL); + } + return add(newLTableSwitch(index, tempInt, tableswitch)); +} + bool LIRGenerator::visitCheckOverRecursed(MCheckOverRecursed *ins) { diff --git a/js/src/ion/Lowering.h b/js/src/ion/Lowering.h index 224e2b5e0a3..31966994114 100644 --- a/js/src/ion/Lowering.h +++ b/js/src/ion/Lowering.h @@ -77,6 +77,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitParameter(MParameter *param); bool visitCallee(MCallee *callee); bool visitGoto(MGoto *ins); + bool visitTableSwitch(MTableSwitch *tableswitch); bool visitNewSlots(MNewSlots *ins); bool visitNewArray(MNewArray *ins); bool visitNewObject(MNewObject *ins); diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 6b5dc019d8f..8eda5a6a8da 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -695,8 +695,7 @@ class MControlInstruction : public MInstruction }; class MTableSwitch - : public MControlInstruction, - public TableSwitchPolicy + : public MControlInstruction { // The successors of the tableswitch // - First successor = the default case @@ -800,10 +799,6 @@ class MTableSwitch size_t numOperands() const { return 1; } - - TypePolicy *typePolicy() { - return this; - } }; template diff --git a/js/src/ion/TypePolicy.cpp b/js/src/ion/TypePolicy.cpp index 72ac421589e..9da2a4db01c 100644 --- a/js/src/ion/TypePolicy.cpp +++ b/js/src/ion/TypePolicy.cpp @@ -222,28 +222,6 @@ BitwisePolicy::adjustInputs(MInstruction *ins) return true; } -bool -TableSwitchPolicy::adjustInputs(MInstruction *ins) -{ - MDefinition *in = ins->getOperand(0); - MInstruction *replace; - - // Tableswitch can consume all types, except: - // - Value: unbox to int32 - switch (in->type()) { - case MIRType_Value: - replace = MUnbox::New(in, MIRType_Int32, MUnbox::Fallible); - break; - default: - return true; - } - - ins->block()->insertBefore(ins, replace); - ins->replaceOperand(0, replace); - - return true; -} - bool PowPolicy::adjustInputs(MInstruction *ins) { diff --git a/js/src/ion/TypePolicy.h b/js/src/ion/TypePolicy.h index 63695f5bf78..52e66b00947 100644 --- a/js/src/ion/TypePolicy.h +++ b/js/src/ion/TypePolicy.h @@ -75,12 +75,6 @@ class BitwisePolicy : public BoxInputsPolicy } }; -class TableSwitchPolicy : public BoxInputsPolicy -{ - public: - bool adjustInputs(MInstruction *def); -}; - class ComparePolicy : public BoxInputsPolicy { protected: diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index ab613932083..839ad7e02b0 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -26,20 +26,20 @@ using namespace js::ion; class DeferredJumpTable : public DeferredData { - LTableSwitch *lswitch; + MTableSwitch *mswitch; BufferOffset off; MacroAssembler *masm; public: - DeferredJumpTable(LTableSwitch *lswitch, BufferOffset off_, MacroAssembler *masm_) - : lswitch(lswitch), off(off_), masm(masm_) + DeferredJumpTable(MTableSwitch *mswitch, BufferOffset off_, MacroAssembler *masm_) + : mswitch(mswitch), off(off_), masm(masm_) { } void copy(IonCode *code, uint8 *ignore__) const { void **jumpData = (void **)(((char*)code->raw()) + masm->actualOffset(off).getOffset()); - int numCases = lswitch->mir()->numCases(); + int numCases = mswitch->numCases(); // For every case write the pointer to the start in the table for (int j = 0; j < numCases; j++) { - LBlock *caseblock = lswitch->mir()->getCase(numCases - 1 - j)->lir(); + LBlock *caseblock = mswitch->getCase(numCases - 1 - j)->lir(); Label *caseheader = caseblock->label(); uint32 offset = caseheader->offset(); @@ -841,7 +841,8 @@ CodeGeneratorARM::visitMoveGroup(LMoveGroup *group) } bool -CodeGeneratorARM::visitTableSwitch(LTableSwitch *ins) +CodeGeneratorARM::emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, + const Register &base) { // the code generated by this is utter hax. // the end result looks something like: @@ -869,29 +870,16 @@ CodeGeneratorARM::visitTableSwitch(LTableSwitch *ins) // unhandled case is the default case (both out of range high and out of range low) // I then insert a branch to default case into the extra slot, which ensures // we don't attempt to execute the address table. - MTableSwitch *mir = ins->mir(); - Label *defaultcase = mir->getDefault()->lir()->label(); - const LAllocation *temp; - - if (ins->index()->isDouble()) { - temp = ins->tempInt(); - - // The input is a double, so try and convert it to an integer. - // If it does not fit in an integer, take the default case. - emitDoubleToInt32(ToFloatRegister(ins->index()), ToRegister(temp), defaultcase, false); - } else { - temp = ins->index(); - } + Label *defaultcase = mir->getDefault()->lir()->label(); int32 cases = mir->numCases(); - Register tempReg = ToRegister(temp); // Lower value with low value - masm.ma_sub(tempReg, Imm32(mir->low()), tempReg, SetCond); - masm.ma_rsb(tempReg, Imm32(cases - 1), tempReg, SetCond, Assembler::Unsigned); + masm.ma_sub(index, Imm32(mir->low()), index, SetCond); + masm.ma_rsb(index, Imm32(cases - 1), index, SetCond, Assembler::Unsigned); AutoForbidPools afp(&masm); - masm.ma_ldr(DTRAddr(pc, DtrRegImmShift(tempReg, LSL, 2)), pc, Offset, Assembler::Unsigned); + masm.ma_ldr(DTRAddr(pc, DtrRegImmShift(index, LSL, 2)), pc, Offset, Assembler::Unsigned); masm.ma_b(defaultcase); - DeferredJumpTable *d = new DeferredJumpTable(ins, masm.nextOffset(), &masm); + DeferredJumpTable *d = new DeferredJumpTable(mir, masm.nextOffset(), &masm); masm.as_jumpPool(cases); if (!masm.addDeferredData(d, 0)) diff --git a/js/src/ion/arm/CodeGenerator-arm.h b/js/src/ion/arm/CodeGenerator-arm.h index 46fef8635c4..a040b7ba968 100644 --- a/js/src/ion/arm/CodeGenerator-arm.h +++ b/js/src/ion/arm/CodeGenerator-arm.h @@ -64,6 +64,8 @@ class CodeGeneratorARM : public CodeGeneratorShared // true, and the false block if |cond| is false. void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse); + bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); + public: // Instruction visitors. virtual bool visitMinMaxD(LMinMaxD *ins); @@ -99,7 +101,6 @@ class CodeGeneratorARM : public CodeGeneratorShared virtual bool visitMathD(LMathD *math); virtual bool visitFloor(LFloor *lir); virtual bool visitRound(LRound *lir); - virtual bool visitTableSwitch(LTableSwitch *ins); virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); // Out of line visitors. diff --git a/js/src/ion/arm/LIR-arm.h b/js/src/ion/arm/LIR-arm.h index 768d372af5f..56262e85398 100644 --- a/js/src/ion/arm/LIR-arm.h +++ b/js/src/ion/arm/LIR-arm.h @@ -200,6 +200,41 @@ class LTableSwitch : public LInstructionHelper<0, 1, 1> const LAllocation *tempInt() { return getTemp(0)->output(); } + // This is added to share the same CodeGenerator prefixes. + const LAllocation *tempPointer() { + return NULL; + } +}; + +// Takes a tableswitch with an integer to decide +class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2> +{ + public: + LIR_HEADER(TableSwitchV); + + LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, + MTableSwitch *ins) + { + setTemp(0, inputCopy); + setTemp(1, floatCopy); + setMir(ins); + } + + MTableSwitch *mir() const { + return mir_->toTableSwitch(); + } + + static const size_t InputValue = 0; + + const LAllocation *tempInt() { + return getTemp(0)->output(); + } + const LAllocation *tempFloat() { + return getTemp(1)->output(); + } + const LAllocation *tempPointer() { + return NULL; + } }; // Guard against an object's shape. diff --git a/js/src/ion/arm/Lowering-arm.cpp b/js/src/ion/arm/Lowering-arm.cpp index 25d0ab08210..835b57efb9c 100644 --- a/js/src/ion/arm/Lowering-arm.cpp +++ b/js/src/ion/arm/Lowering-arm.cpp @@ -281,34 +281,17 @@ LIRGeneratorARM::visitPowHalf(MPowHalf *ins) return defineReuseInput(lir, ins, 0); } -bool -LIRGeneratorARM::visitTableSwitch(MTableSwitch *tableswitch) +LTableSwitch * +LIRGeneratorARM::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy, + MTableSwitch *tableswitch) { - MDefinition *opd = tableswitch->getOperand(0); + return new LTableSwitch(in, inputCopy, tableswitch); +} - // There should be at least 1 successor. The default case! - JS_ASSERT(tableswitch->numSuccessors() > 0); - - // If there are no cases, the default case is always taken. - if (tableswitch->numSuccessors() == 1) - return add(new LGoto(tableswitch->getDefault())); - - // Case indices are numeric, so other types will always go to the default case. - if (opd->type() != MIRType_Int32 && opd->type() != MIRType_Double) - return add(new LGoto(tableswitch->getDefault())); - - // Return an LTableSwitch, capable of handling either an integer or - // floating-point index. - LAllocation index; - LDefinition tempInt; - if (opd->type() == MIRType_Int32) { - index = useRegisterAtStart(opd); - tempInt = tempCopy(opd, 0); - } else { - index = useRegister(opd); - tempInt = temp(LDefinition::GENERAL); - } - return add(new LTableSwitch(index, tempInt, tableswitch)); +LTableSwitchV * +LIRGeneratorARM::newLTableSwitchV(MTableSwitch *tableswitch) +{ + return new LTableSwitchV(temp(), tempFloat(), tableswitch); } bool diff --git a/js/src/ion/arm/Lowering-arm.h b/js/src/ion/arm/Lowering-arm.h index 12c1b1babe4..6b0e3c49366 100644 --- a/js/src/ion/arm/Lowering-arm.h +++ b/js/src/ion/arm/Lowering-arm.h @@ -48,7 +48,10 @@ class LIRGeneratorARM : public LIRGeneratorShared bool lowerModI(MMod *mod); bool lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs); bool visitPowHalf(MPowHalf *ins); - bool visitTableSwitch(MTableSwitch *tableswitch); + + LTableSwitch *newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy, + MTableSwitch *ins); + LTableSwitchV *newLTableSwitchV(MTableSwitch *ins); public: bool visitConstant(MConstant *ins); diff --git a/js/src/ion/shared/CodeGenerator-shared-inl.h b/js/src/ion/shared/CodeGenerator-shared-inl.h index 211969ce94a..bc33be471fd 100644 --- a/js/src/ion/shared/CodeGenerator-shared-inl.h +++ b/js/src/ion/shared/CodeGenerator-shared-inl.h @@ -41,6 +41,12 @@ ToRegister(const LDefinition *def) return ToRegister(*def->output()); } +static inline Register +ToRegisterOrInvalid(const LAllocation *a) +{ + return a ? ToRegister(*a) : InvalidReg; +} + static inline FloatRegister ToFloatRegister(const LAllocation &a) { diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index e612d3eb304..3c370dc5d78 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -22,19 +22,19 @@ namespace ion { class DeferredJumpTable : public DeferredData { - LTableSwitch *lswitch; + MTableSwitch *mswitch; public: - DeferredJumpTable(LTableSwitch *lswitch) - : lswitch(lswitch) + DeferredJumpTable(MTableSwitch *mswitch) + : mswitch(mswitch) { } - + void copy(IonCode *code, uint8 *buffer) const { void **jumpData = (void **)buffer; // For every case write the pointer to the start in the table - for (size_t j = 0; j < lswitch->mir()->numCases(); j++) { - LBlock *caseblock = lswitch->mir()->getCase(j)->lir(); + for (size_t j = 0; j < mswitch->numCases(); j++) { + LBlock *caseblock = mswitch->getCase(j)->lir(); Label *caseheader = caseblock->label(); uint32 offset = caseheader->offset(); @@ -933,40 +933,28 @@ CodeGeneratorX86Shared::visitMoveGroup(LMoveGroup *group) } bool -CodeGeneratorX86Shared::visitTableSwitch(LTableSwitch *ins) +CodeGeneratorX86Shared::emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, + const Register &base) { - MTableSwitch *mir = ins->mir(); Label *defaultcase = mir->getDefault()->lir()->label(); - const LAllocation *temp; - - if (ins->index()->isDouble()) { - temp = ins->tempInt(); - - // The input is a double, so try and convert it to an integer. - // If it does not fit in an integer, take the default case. - emitDoubleToInt32(ToFloatRegister(ins->index()), ToRegister(temp), defaultcase, false); - } else { - temp = ins->index(); - } // Lower value with low value if (mir->low() != 0) - masm.subl(Imm32(mir->low()), ToRegister(temp)); + masm.subl(Imm32(mir->low()), index); // Jump to default case if input is out of range int32 cases = mir->numCases(); - masm.cmpl(ToRegister(temp), Imm32(cases)); + masm.cmpl(index, Imm32(cases)); masm.j(AssemblerX86Shared::AboveOrEqual, defaultcase); // Create a JumpTable that during linking will get written. - DeferredJumpTable *d = new DeferredJumpTable(ins); + DeferredJumpTable *d = new DeferredJumpTable(mir); if (!masm.addDeferredData(d, (1 << ScalePointer) * cases)) return false; // Compute the position where a pointer to the right case stands. - const LAllocation *base = ins->tempPointer(); - masm.mov(d->label(), ToRegister(base)); - Operand pointer = Operand(ToRegister(base), ToRegister(temp), ScalePointer); + masm.mov(d->label(), base); + Operand pointer = Operand(base, index, ScalePointer); // Jump to the right case masm.jmp(pointer); diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h index afcfc85e950..61d99a24723 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.h +++ b/js/src/ion/shared/CodeGenerator-x86-shared.h @@ -80,6 +80,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared NaNCond ifNaN = NaN_Unexpected); void emitBranch(Assembler::DoubleCondition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse); + bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); + public: CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph &graph); @@ -111,7 +113,6 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared virtual bool visitMathD(LMathD *math); virtual bool visitFloor(LFloor *lir); virtual bool visitRound(LRound *lir); - virtual bool visitTableSwitch(LTableSwitch *ins); virtual bool visitGuardShape(LGuardShape *guard); virtual bool visitGuardClass(LGuardClass *guard); virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); diff --git a/js/src/ion/shared/LIR-x86-shared.h b/js/src/ion/shared/LIR-x86-shared.h index 8350c3196ef..12221b749d7 100644 --- a/js/src/ion/shared/LIR-x86-shared.h +++ b/js/src/ion/shared/LIR-x86-shared.h @@ -117,6 +117,38 @@ class LTableSwitch : public LInstructionHelper<0, 1, 2> } }; +// Takes a tableswitch with a value to decide +class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3> +{ + public: + LIR_HEADER(TableSwitchV); + + LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, + const LDefinition &jumpTablePointer, MTableSwitch *ins) + { + setTemp(0, inputCopy); + setTemp(1, floatCopy); + setTemp(2, jumpTablePointer); + setMir(ins); + } + + MTableSwitch *mir() const { + return mir_->toTableSwitch(); + } + + static const size_t InputValue = 0; + + const LAllocation *tempInt() { + return getTemp(0)->output(); + } + const LAllocation *tempFloat() { + return getTemp(1)->output(); + } + const LAllocation *tempPointer() { + return getTemp(2)->output(); + } +}; + // Guard against an object's shape. class LGuardShape : public LInstructionHelper<0, 1, 0> { diff --git a/js/src/ion/shared/Lowering-x86-shared.cpp b/js/src/ion/shared/Lowering-x86-shared.cpp index 077a3fd46d4..df173eb21e3 100644 --- a/js/src/ion/shared/Lowering-x86-shared.cpp +++ b/js/src/ion/shared/Lowering-x86-shared.cpp @@ -12,34 +12,17 @@ using namespace js; using namespace js::ion; -bool -LIRGeneratorX86Shared::visitTableSwitch(MTableSwitch *tableswitch) +LTableSwitch * +LIRGeneratorX86Shared::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy, + MTableSwitch *tableswitch) { - MDefinition *opd = tableswitch->getOperand(0); + return new LTableSwitch(in, inputCopy, temp(), tableswitch); +} - // There should be at least 1 successor. The default case! - JS_ASSERT(tableswitch->numSuccessors() > 0); - - // If there are no cases, the default case is always taken. - if (tableswitch->numSuccessors() == 1) - return add(new LGoto(tableswitch->getDefault())); - - // Case indices are numeric, so other types will always go to the default case. - if (opd->type() != MIRType_Int32 && opd->type() != MIRType_Double) - return add(new LGoto(tableswitch->getDefault())); - - // Return an LTableSwitch, capable of handling either an integer or - // floating-point index. - LAllocation index; - LDefinition tempInt; - if (opd->type() == MIRType_Int32) { - index = useRegisterAtStart(opd); - tempInt = tempCopy(opd, 0); - } else { - index = useRegister(opd); - tempInt = temp(LDefinition::GENERAL); - } - return add(new LTableSwitch(index, tempInt, temp(LDefinition::GENERAL), tableswitch)); +LTableSwitchV * +LIRGeneratorX86Shared::newLTableSwitchV(MTableSwitch *tableswitch) +{ + return new LTableSwitchV(temp(), tempFloat(), temp(), tableswitch); } bool diff --git a/js/src/ion/shared/Lowering-x86-shared.h b/js/src/ion/shared/Lowering-x86-shared.h index 7c75c52317a..fd23a05f368 100644 --- a/js/src/ion/shared/Lowering-x86-shared.h +++ b/js/src/ion/shared/Lowering-x86-shared.h @@ -20,7 +20,10 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared : LIRGeneratorShared(gen, graph, lirGraph) {} - bool visitTableSwitch(MTableSwitch *tableswitch); + LTableSwitch *newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy, + MTableSwitch *ins); + LTableSwitchV *newLTableSwitchV(MTableSwitch *ins); + bool visitRecompileCheck(MRecompileCheck *ins); bool visitInterruptCheck(MInterruptCheck *ins); bool visitGuardShape(MGuardShape *ins);