Back out 0498e3bb74bd:9011919fcf00 (bug 799818) for build bustage

on a CLOSED TREE
This commit is contained in:
Phil Ringnalda 2012-10-19 14:55:53 -07:00
parent 8d06dfced3
commit 85edab9556
22 changed files with 144 additions and 282 deletions

View File

@ -361,49 +361,6 @@ 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)
{

View File

@ -45,8 +45,6 @@ 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);

View File

@ -4418,8 +4418,7 @@ TestSingletonProperty(JSContext *cx, HandleObject obj, HandleId id, bool *isKnow
static inline bool
TestSingletonPropertyTypes(JSContext *cx, types::StackTypeSet *types,
HandleObject globalObj, HandleId id,
bool *isKnownConstant, bool *testObject,
bool *testString)
bool *isKnownConstant, bool *testObject)
{
// As for TestSingletonProperty, but the input is any value in a type set
// rather than a specific object. If testObject is set then the constant
@ -4427,7 +4426,6 @@ TestSingletonPropertyTypes(JSContext *cx, types::StackTypeSet *types,
*isKnownConstant = false;
*testObject = false;
*testString = false;
if (!types || types->unknownObject())
return true;
@ -4457,15 +4455,6 @@ TestSingletonPropertyTypes(JSContext *cx, types::StackTypeSet *types,
case JSVAL_TYPE_OBJECT:
case JSVAL_TYPE_UNKNOWN: {
if (types->hasType(types::Type::StringType())) {
// Do not optimize if the object is either a String or an Object.
if (types->maybeObject())
return true;
key = JSProto_String;
*testString = true;
break;
}
// For property accesses which may be on many objects, we just need to
// find a prototype common to all the objects; if that prototype
// has the singleton property, the access will not be on a missing property.
@ -5065,9 +5054,6 @@ IonBuilder::jsop_getelem_string()
MStringLength *length = MStringLength::New(str);
current->add(length);
// This will cause an invalidation of this script once the 'undefined' type
// is monitored by the interpreter.
JS_ASSERT(oracle->propertyRead(script_, pc)->getKnownTypeTag() == JSVAL_TYPE_STRING);
id = addBoundsCheck(id, length);
MCharCodeAt *charCode = MCharCodeAt::New(str, id);
@ -5895,9 +5881,8 @@ IonBuilder::getPropTryConstant(bool *emitted, HandleId id, types::StackTypeSet *
RootedObject global(cx, &script_->global());
bool isConstant, testObject, testString;
if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id,
&isConstant, &testObject, &testString))
bool isConstant, testObject;
if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id, &isConstant, &testObject))
return false;
if (!isConstant)
@ -5906,11 +5891,8 @@ IonBuilder::getPropTryConstant(bool *emitted, HandleId id, types::StackTypeSet *
MDefinition *obj = current->pop();
// Property access is a known constant -- safe to emit.
JS_ASSERT(!testString || !testObject);
if (testObject)
current->add(MGuardObject::New(obj));
else if (testString)
current->add(MGuardString::New(obj));
MConstant *known = MConstant::New(ObjectValue(*singleton));
if (singleton->isFunction()) {

View File

@ -20,7 +20,6 @@
_(Parameter) \
_(Callee) \
_(TableSwitch) \
_(TableSwitchV) \
_(Goto) \
_(NewArray) \
_(NewObject) \

View File

@ -67,44 +67,6 @@ 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)
{
@ -1718,15 +1680,6 @@ LIRGenerator::visitGuardObject(MGuardObject *ins)
return redefine(ins, ins->input());
}
bool
LIRGenerator::visitGuardString(MGuardString *ins)
{
// The type policy does all the work, so at this point the input
// is guaranteed to be a string.
JS_ASSERT(ins->input()->type() == MIRType_String);
return redefine(ins, ins->input());
}
bool
LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
{

View File

@ -77,7 +77,6 @@ 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);
@ -165,7 +164,6 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitBindNameCache(MBindNameCache *ins);
bool visitGuardClass(MGuardClass *ins);
bool visitGuardObject(MGuardObject *ins);
bool visitGuardString(MGuardString *ins);
bool visitCallGetProperty(MCallGetProperty *ins);
bool visitDeleteProperty(MDeleteProperty *ins);
bool visitGetNameCache(MGetNameCache *ins);

View File

@ -695,7 +695,8 @@ class MControlInstruction : public MInstruction
};
class MTableSwitch
: public MControlInstruction
: public MControlInstruction,
public TableSwitchPolicy
{
// The successors of the tableswitch
// - First successor = the default case
@ -799,6 +800,10 @@ class MTableSwitch
size_t numOperands() const {
return 1;
}
TypePolicy *typePolicy() {
return this;
}
};
template <size_t Arity, size_t Successors>
@ -1501,37 +1506,6 @@ class MGuardObject : public MUnaryInstruction, public SingleObjectPolicy
}
};
class MGuardString
: public MUnaryInstruction,
public StringPolicy
{
MGuardString(MDefinition *ins)
: MUnaryInstruction(ins)
{
setGuard();
setMovable();
setResultType(MIRType_String);
}
public:
INSTRUCTION_HEADER(GuardString);
static MGuardString *New(MDefinition *ins) {
return new MGuardString(ins);
}
MDefinition *input() const {
return getOperand(0);
}
TypePolicy *typePolicy() {
return this;
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
};
// Caller-side allocation of |this| for |new|:
// Given a prototype operand, construct |this| for JSOP_NEW.
// For native constructors, returns MagicValue(JS_IS_CONSTRUCTING).

View File

@ -63,7 +63,6 @@ namespace ion {
_(Box) \
_(Unbox) \
_(GuardObject) \
_(GuardString) \
_(ToDouble) \
_(ToInt32) \
_(TruncateToInt32) \

View File

@ -357,11 +357,8 @@ TypeInferenceOracle::elementReadIsString(JSScript *script, jsbytecode *pc)
if (id->getKnownTypeTag() != JSVAL_TYPE_INT32)
return false;
// This function is used for jsop_getelem_string which should return
// undefined if this is out-side the string bounds. Currently we just
// fallback to a CallGetElement.
StackTypeSet *pushed = script->analysis()->pushedTypes(pc, 0);
if (pushed->getKnownTypeTag() != JSVAL_TYPE_STRING)
types::TypeSet *pushed = script->analysis()->pushedTypes(pc, 0);
if (!pushed->hasType(types::Type::StringType()))
return false;
return true;

View File

@ -222,6 +222,28 @@ 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)
{

View File

@ -75,6 +75,12 @@ class BitwisePolicy : public BoxInputsPolicy
}
};
class TableSwitchPolicy : public BoxInputsPolicy
{
public:
bool adjustInputs(MInstruction *def);
};
class ComparePolicy : public BoxInputsPolicy
{
protected:

View File

@ -26,20 +26,20 @@ using namespace js::ion;
class DeferredJumpTable : public DeferredData
{
MTableSwitch *mswitch;
LTableSwitch *lswitch;
BufferOffset off;
MacroAssembler *masm;
public:
DeferredJumpTable(MTableSwitch *mswitch, BufferOffset off_, MacroAssembler *masm_)
: mswitch(mswitch), off(off_), masm(masm_)
DeferredJumpTable(LTableSwitch *lswitch, BufferOffset off_, MacroAssembler *masm_)
: lswitch(lswitch), off(off_), masm(masm_)
{ }
void copy(IonCode *code, uint8 *ignore__) const {
void **jumpData = (void **)(((char*)code->raw()) + masm->actualOffset(off).getOffset());
int numCases = mswitch->numCases();
int numCases = lswitch->mir()->numCases();
// For every case write the pointer to the start in the table
for (int j = 0; j < numCases; j++) {
LBlock *caseblock = mswitch->getCase(numCases - 1 - j)->lir();
LBlock *caseblock = lswitch->mir()->getCase(numCases - 1 - j)->lir();
Label *caseheader = caseblock->label();
uint32 offset = caseheader->offset();
@ -841,8 +841,7 @@ CodeGeneratorARM::visitMoveGroup(LMoveGroup *group)
}
bool
CodeGeneratorARM::emitTableSwitchDispatch(MTableSwitch *mir, const Register &index,
const Register &base)
CodeGeneratorARM::visitTableSwitch(LTableSwitch *ins)
{
// the code generated by this is utter hax.
// the end result looks something like:
@ -870,16 +869,29 @@ CodeGeneratorARM::emitTableSwitchDispatch(MTableSwitch *mir, const Register &ind
// 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.
Label *defaultcase = mir->getDefault()->lir()->label();
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();
}
int32 cases = mir->numCases();
Register tempReg = ToRegister(temp);
// Lower value with low value
masm.ma_sub(index, Imm32(mir->low()), index, SetCond);
masm.ma_rsb(index, Imm32(cases - 1), index, SetCond, Assembler::Unsigned);
masm.ma_sub(tempReg, Imm32(mir->low()), tempReg, SetCond);
masm.ma_rsb(tempReg, Imm32(cases - 1), tempReg, SetCond, Assembler::Unsigned);
AutoForbidPools afp(&masm);
masm.ma_ldr(DTRAddr(pc, DtrRegImmShift(index, LSL, 2)), pc, Offset, Assembler::Unsigned);
masm.ma_ldr(DTRAddr(pc, DtrRegImmShift(tempReg, LSL, 2)), pc, Offset, Assembler::Unsigned);
masm.ma_b(defaultcase);
DeferredJumpTable *d = new DeferredJumpTable(mir, masm.nextOffset(), &masm);
DeferredJumpTable *d = new DeferredJumpTable(ins, masm.nextOffset(), &masm);
masm.as_jumpPool(cases);
if (!masm.addDeferredData(d, 0))

View File

@ -64,8 +64,6 @@ 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);
@ -101,6 +99,7 @@ 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.

View File

@ -200,41 +200,6 @@ 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.

View File

@ -281,17 +281,34 @@ LIRGeneratorARM::visitPowHalf(MPowHalf *ins)
return defineReuseInput(lir, ins, 0);
}
LTableSwitch *
LIRGeneratorARM::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
MTableSwitch *tableswitch)
bool
LIRGeneratorARM::visitTableSwitch(MTableSwitch *tableswitch)
{
return new LTableSwitch(in, inputCopy, tableswitch);
}
MDefinition *opd = tableswitch->getOperand(0);
LTableSwitchV *
LIRGeneratorARM::newLTableSwitchV(MTableSwitch *tableswitch)
{
return new LTableSwitchV(temp(), tempFloat(), 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));
}
bool

View File

@ -48,10 +48,7 @@ class LIRGeneratorARM : public LIRGeneratorShared
bool lowerModI(MMod *mod);
bool lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs);
bool visitPowHalf(MPowHalf *ins);
LTableSwitch *newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
MTableSwitch *ins);
LTableSwitchV *newLTableSwitchV(MTableSwitch *ins);
bool visitTableSwitch(MTableSwitch *tableswitch);
public:
bool visitConstant(MConstant *ins);

View File

@ -41,12 +41,6 @@ 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)
{

View File

@ -22,19 +22,19 @@ namespace ion {
class DeferredJumpTable : public DeferredData
{
MTableSwitch *mswitch;
LTableSwitch *lswitch;
public:
DeferredJumpTable(MTableSwitch *mswitch)
: mswitch(mswitch)
DeferredJumpTable(LTableSwitch *lswitch)
: lswitch(lswitch)
{ }
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 < mswitch->numCases(); j++) {
LBlock *caseblock = mswitch->getCase(j)->lir();
for (size_t j = 0; j < lswitch->mir()->numCases(); j++) {
LBlock *caseblock = lswitch->mir()->getCase(j)->lir();
Label *caseheader = caseblock->label();
uint32 offset = caseheader->offset();
@ -933,28 +933,40 @@ CodeGeneratorX86Shared::visitMoveGroup(LMoveGroup *group)
}
bool
CodeGeneratorX86Shared::emitTableSwitchDispatch(MTableSwitch *mir, const Register &index,
const Register &base)
CodeGeneratorX86Shared::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();
}
// Lower value with low value
if (mir->low() != 0)
masm.subl(Imm32(mir->low()), index);
masm.subl(Imm32(mir->low()), ToRegister(temp));
// Jump to default case if input is out of range
int32 cases = mir->numCases();
masm.cmpl(index, Imm32(cases));
masm.cmpl(ToRegister(temp), Imm32(cases));
masm.j(AssemblerX86Shared::AboveOrEqual, defaultcase);
// Create a JumpTable that during linking will get written.
DeferredJumpTable *d = new DeferredJumpTable(mir);
DeferredJumpTable *d = new DeferredJumpTable(ins);
if (!masm.addDeferredData(d, (1 << ScalePointer) * cases))
return false;
// Compute the position where a pointer to the right case stands.
masm.mov(d->label(), base);
Operand pointer = Operand(base, index, ScalePointer);
const LAllocation *base = ins->tempPointer();
masm.mov(d->label(), ToRegister(base));
Operand pointer = Operand(ToRegister(base), ToRegister(temp), ScalePointer);
// Jump to the right case
masm.jmp(pointer);

View File

@ -80,8 +80,6 @@ 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);
@ -113,6 +111,7 @@ 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);

View File

@ -117,38 +117,6 @@ 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>
{

View File

@ -12,17 +12,34 @@
using namespace js;
using namespace js::ion;
LTableSwitch *
LIRGeneratorX86Shared::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
MTableSwitch *tableswitch)
bool
LIRGeneratorX86Shared::visitTableSwitch(MTableSwitch *tableswitch)
{
return new LTableSwitch(in, inputCopy, temp(), tableswitch);
}
MDefinition *opd = tableswitch->getOperand(0);
LTableSwitchV *
LIRGeneratorX86Shared::newLTableSwitchV(MTableSwitch *tableswitch)
{
return new LTableSwitchV(temp(), tempFloat(), 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));
}
bool

View File

@ -20,10 +20,7 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared
: LIRGeneratorShared(gen, graph, lirGraph)
{}
LTableSwitch *newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
MTableSwitch *ins);
LTableSwitchV *newLTableSwitchV(MTableSwitch *ins);
bool visitTableSwitch(MTableSwitch *tableswitch);
bool visitRecompileCheck(MRecompileCheck *ins);
bool visitInterruptCheck(MInterruptCheck *ins);
bool visitGuardShape(MGuardShape *ins);