Implement LBitNotV (bug 725000, r=sstangl).

This commit is contained in:
David Anderson 2012-02-09 15:28:15 -08:00
parent 12446370fb
commit 3cf56bb5ef
18 changed files with 76 additions and 28 deletions

View File

@ -45,6 +45,7 @@
#include "MIRGenerator.h"
#include "shared/CodeGenerator-shared-inl.h"
#include "jsnum.h"
#include "jsinterpinlines.h"
using namespace js;
using namespace js::ion;
@ -1751,6 +1752,16 @@ CodeGenerator::visitThrow(LThrow *lir)
return callVM(ThrowInfo, lir);
}
bool
CodeGenerator::visitBitNotV(LBitNotV *lir)
{
typedef bool (*pf)(JSContext *, const Value &, int *p);
static const VMFunction info = FunctionInfo<pf>(BitNot);
pushArg(ToValue(lir, LBitNotV::Input));
return callVM(info, lir);
}
bool
CodeGenerator::visitLoadElementV(LLoadElementV *load)
{

View File

@ -132,6 +132,7 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitCallIteratorMore(LCallIteratorMore *lir);
bool visitCallIteratorEnd(LCallIteratorEnd *lir);
bool visitCallSetProperty(LCallSetProperty *ins);
bool visitBitNotV(LBitNotV *lir);
bool visitCheckOverRecursed(LCheckOverRecursed *lir);
bool visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);

View File

@ -2015,6 +2015,8 @@ IonBuilder::jsop_bitnot()
ins->infer(oracle->unaryOp(script, pc));
current->push(ins);
if (ins->isEffectful() && !resumeAfter(ins))
return false;
return true;
}
bool

View File

@ -615,10 +615,20 @@ class LCompareDAndBranch : public LInstructionHelper<0, 2, 0>
// Bitwise not operation, takes a 32-bit integer as input and returning
// a 32-bit integer result as an output.
class LBitNot : public LInstructionHelper<1, 1, 0>
class LBitNotI : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(BitNot);
LIR_HEADER(BitNotI);
};
// Call a stub to perform a binary operation.
class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
{
public:
LIR_HEADER(BitNotV);
BOX_OUTPUT_ACCESSORS();
static const size_t Input = 0;
};
// Binary bitwise operation, taking two 32-bit integers as inputs and returning

View File

@ -61,7 +61,8 @@
_(CallGeneric) \
_(CallNative) \
_(StackArg) \
_(BitNot) \
_(BitNotI) \
_(BitNotV) \
_(BitOp) \
_(ShiftOp) \
_(Return) \

View File

@ -354,9 +354,15 @@ LIRGenerator::visitBitNot(MBitNot *ins)
{
MDefinition *input = ins->getOperand(0);
JS_ASSERT(input->type() == MIRType_Int32);
if (input->type() == MIRType_Int32)
return lowerForALU(new LBitNotI(), ins, input);
return lowerForALU(new LBitNot(), ins, input);
LBitNotV *lir = new LBitNotV;
if (!useBox(lir, LBitNotV::Input, input))
return false;
if (!defineVMReturn(lir, ins))
return false;
return assignSafepoint(lir, ins);
}
bool

View File

@ -1540,7 +1540,7 @@ class MBitNot
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const {
if (specialization_ >= MIRType_Object)
if (specialization_ == MIRType_None)
return AliasSet::Store(AliasSet::Any);
return AliasSet::None();
}

View File

@ -49,7 +49,7 @@ namespace ion {
enum DataType {
Type_Void,
Type_Bool,
Type_JSBool,
Type_Int32,
Type_Object,
Type_Value
};
@ -189,7 +189,7 @@ template <> struct TypeToArgProperties<const Value &> {
template <class> struct OutParamToDataType { static const DataType result = Type_Void; };
template <> struct OutParamToDataType<Value *> { static const DataType result = Type_Value; };
template <> struct OutParamToDataType<JSBool *> { static const DataType result = Type_JSBool; };
template <> struct OutParamToDataType<int *> { static const DataType result = Type_Int32; };
#define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1)
#define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2)
@ -245,8 +245,8 @@ struct FunctionInfo<R (*)(JSContext *)> : public VMFunction {
return 0;
}
FunctionInfo(pf fun)
: VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(),
argumentProperties(), outParam(), returnType())
: VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(),
argumentProperties(), outParam(), returnType())
{ }
};

View File

@ -514,7 +514,7 @@ CodeGeneratorARM::visitDivI(LDivI *ins)
}
bool
CodeGeneratorARM::visitBitNot(LBitNot *ins)
CodeGeneratorARM::visitBitNotI(LBitNotI *ins)
{
const LAllocation *input = ins->getOperand(0);
const LDefinition *dest = ins->getDef(0);

View File

@ -102,7 +102,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
virtual bool visitAbsD(LAbsD *ins);
virtual bool visitAddI(LAddI *ins);
virtual bool visitSubI(LSubI *ins);
virtual bool visitBitNot(LBitNot *ins);
virtual bool visitBitNotI(LBitNotI *ins);
virtual bool visitBitOp(LBitOp *ins);
virtual bool visitMulI(LMulI *ins);

View File

@ -587,9 +587,9 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.ma_mov(sp, outReg);
break;
case Type_JSBool:
case Type_Int32:
outReg = regs.takeAny();
masm.reserveStack(sizeof(JSBool));
masm.reserveStack(sizeof(int));
masm.ma_mov(sp, outReg);
break;
@ -657,9 +657,9 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.freeStack(sizeof(Value));
break;
case Type_JSBool:
case Type_Int32:
masm.load32(Address(sp, 0), ReturnReg);
masm.freeStack(sizeof(JSBool));
masm.freeStack(sizeof(int32));
break;
default:

View File

@ -636,7 +636,7 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
}
bool
CodeGeneratorX86Shared::visitBitNot(LBitNot *ins)
CodeGeneratorX86Shared::visitBitNotI(LBitNotI *ins)
{
const LAllocation *input = ins->getOperand(0);
JS_ASSERT(!input->isConstant());

View File

@ -122,7 +122,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
virtual bool visitMulI(LMulI *ins);
virtual bool visitDivI(LDivI *ins);
virtual bool visitModI(LModI *ins);
virtual bool visitBitNot(LBitNot *ins);
virtual bool visitBitNotI(LBitNotI *ins);
virtual bool visitBitOp(LBitOp *ins);
virtual bool visitShiftOp(LShiftOp *ins);
virtual bool visitMoveGroup(LMoveGroup *group);

View File

@ -513,9 +513,9 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.movq(esp, outReg);
break;
case Type_JSBool:
case Type_Int32:
outReg = regs.takeAny();
masm.reserveStack(sizeof(JSBool));
masm.reserveStack(sizeof(int));
masm.movq(esp, outReg);
break;
@ -592,10 +592,9 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.freeStack(sizeof(Value));
break;
case Type_JSBool:
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
case Type_Int32:
masm.load32(Address(esp, 0), ReturnReg);
masm.freeStack(sizeof(JSBool));
masm.freeStack(sizeof(int));
break;
default:

View File

@ -531,9 +531,9 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.movl(esp, outReg);
break;
case Type_JSBool:
case Type_Int32:
outReg = regs.takeAny();
masm.reserveStack(sizeof(JSBool));
masm.reserveStack(sizeof(int32));
masm.movl(esp, outReg);
break;
@ -598,7 +598,7 @@ IonCompartment::generateVMWrapper(JSContext *cx, const VMFunction &f)
masm.freeStack(sizeof(Value));
break;
case Type_JSBool:
case Type_Int32:
masm.load32(Address(esp, 0), ReturnReg);
masm.freeStack(sizeof(JSBool));
break;

View File

@ -0,0 +1,9 @@
function f(s) {
var q;
for (var i = 0; i < 10000; i++)
q = ~s;
return q;
}
var obj = { valueOf: function () { return 3; } }
assertEq(f(obj), -4);

View File

@ -2461,9 +2461,8 @@ END_CASE(JSOP_NOT)
BEGIN_CASE(JSOP_BITNOT)
{
int32_t i;
if (!ToInt32(cx, regs.sp[-1], &i))
if (!BitNot(cx, regs.sp[-1], &i))
goto error;
i = ~i;
regs.sp[-1].setInt32(i);
}
END_CASE(JSOP_BITNOT)

View File

@ -817,6 +817,16 @@ GreaterThanOrEqualOperation(JSContext *cx, const Value &lhs, const Value &rhs, b
RELATIONAL_OP(>=);
}
static JS_ALWAYS_INLINE bool
BitNot(JSContext *cx, const Value &in, int *out)
{
int i;
if (!ToInt32(cx, in, &i))
return false;
*out = ~i;
return true;
}
#undef RELATIONAL_OP
} /* namespace js */