Bug 1434717: Part 2: Implement CacheIR IC for unary arithmetic operators r=tcampbell

This provides a CacheIR implementation of the IC for JSOP_BITNOT and JSOP_NEG.
However this commit does not connect the IC, as that requires more work to the
shared IC system.

--HG--
extra : rebase_source : 200a76e6a664e5d6513c8165eed55e3ac6e1a737
This commit is contained in:
Matthew Gaudet 2018-01-31 16:02:25 -05:00
Родитель d608db43e3
Коммит 2c9c7f027e
9 изменённых файлов: 137 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,23 @@
function warmup(fun, input, output) {
for (var i = 0; i < 30; i++) {
var y = fun(input);
assertEq(y, output)
}
}
var fun1 = (x) => { return -x; }
var fun2 = (x) => { return -x; }
var fun3 = (x) => { return ~x; }
var fun4 = (x) => { return ~x; }
warmup(fun1, 1, -1);
warmup(fun1, 0, -0);
warmup(fun2, 3, -3);
warmup(fun2, 1.2, -1.2);
warmup(fun3, -1, 0);
warmup(fun4, 1.2, -2);
warmup(fun4, 3, -4)

Просмотреть файл

@ -2135,6 +2135,7 @@ BaselineCacheIRCompiler::init(CacheKind kind)
case CacheKind::TypeOf:
case CacheKind::GetIterator:
case CacheKind::ToBool:
case CacheKind::UnaryArith:
MOZ_ASSERT(numInputs == 1);
allocator.initInputLocation(0, R0);
break;

Просмотреть файл

@ -4839,3 +4839,56 @@ GetIntrinsicIRGenerator::tryAttachStub()
trackAttached("GetIntrinsic");
return true;
}
UnaryArithIRGenerator::UnaryArithIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode,
JSOp op, HandleValue val, HandleValue res)
: IRGenerator(cx, script, pc, CacheKind::UnaryArith, mode),
op_(op),
val_(val),
res_(res)
{ }
void
UnaryArithIRGenerator::trackAttached(const char* name)
{
#ifdef JS_CACHEIR_SPEW
if (const CacheIRSpewer::Guard& sp = CacheIRSpewer::Guard(*this, name)) {
sp.valueProperty("val", val_);
}
#endif
}
bool
UnaryArithIRGenerator::tryAttachStub()
{
if (tryAttachInt32())
return true;
trackAttached(IRGenerator::NotAttached);
return false;
}
bool
UnaryArithIRGenerator::tryAttachInt32()
{
if (!val_.isInt32() || !res_.isInt32())
return false;
ValOperandId valId(writer.setInputOperandId(0));
Int32OperandId intId = writer.guardIsInt32(valId);
switch (op_) {
case JSOP_BITNOT:
writer.int32NotResult(intId);
trackAttached("UnaryArith.Int32Not");
break;
case JSOP_NEG:
writer.int32NegationResult(intId);
trackAttached("UnaryArith.Int32Neg");
break;
default:
MOZ_CRASH("Unexected OP");
}
writer.returnFromIC();
return true;
}

Просмотреть файл

@ -163,7 +163,8 @@ class TypedOperandId : public OperandId
_(GetIterator) \
_(Compare) \
_(ToBool) \
_(Call)
_(Call) \
_(UnaryArith)
enum class CacheKind : uint8_t
{
@ -285,6 +286,8 @@ extern const char* CacheKindNames[];
_(LoadStringResult) \
_(LoadInstanceOfObjectResult) \
_(LoadTypeOfObjectResult) \
_(Int32NotResult) \
_(Int32NegationResult) \
_(LoadInt32TruthyResult) \
_(LoadDoubleTruthyResult) \
_(LoadStringTruthyResult) \
@ -963,6 +966,12 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
buffer_.writeByte(uint32_t(hasOwn));
}
void int32NotResult(Int32OperandId id) {
writeOpWithOperandId(CacheOp::Int32NotResult, id);
}
void int32NegationResult(Int32OperandId id) {
writeOpWithOperandId(CacheOp::Int32NegationResult, id);
}
void loadBooleanResult(bool val) {
writeOp(CacheOp::LoadBooleanResult);
buffer_.writeByte(uint32_t(val));
@ -1719,6 +1728,23 @@ class MOZ_RAII GetIntrinsicIRGenerator : public IRGenerator
bool tryAttachStub();
};
class MOZ_RAII UnaryArithIRGenerator : public IRGenerator
{
JSOp op_;
HandleValue val_;
HandleValue res_;
bool tryAttachInt32();
void trackAttached(const char* name);
public:
UnaryArithIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
JSOp op, HandleValue val, HandleValue res);
bool tryAttachStub();
};
} // namespace jit
} // namespace js

Просмотреть файл

@ -1817,6 +1817,34 @@ CacheIRCompiler::emitLoadInt32ArrayLengthResult()
return true;
}
bool
CacheIRCompiler::emitInt32NegationResult()
{
AutoOutputRegister output(*this);
Register val = allocator.useRegister(masm, reader.int32OperandId());
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Guard against 0 and MIN_INT by checking if low 31-bits are all zero.
// Both of these result in a double.
masm.branchTest32(Assembler::Zero, val, Imm32(0x7fffffff), failure->label());
masm.neg32(val);
masm.tagValue(JSVAL_TYPE_INT32, val, output.valueReg());
return true;
}
bool
CacheIRCompiler::emitInt32NotResult()
{
AutoOutputRegister output(*this);
Register val = allocator.useRegister(masm, reader.int32OperandId());
masm.not32(val);
masm.tagValue(JSVAL_TYPE_INT32, val, output.valueReg());
return true;
}
bool
CacheIRCompiler::emitLoadArgumentsObjectLengthResult()
{

Просмотреть файл

@ -49,6 +49,8 @@ namespace jit {
_(LoadUndefinedResult) \
_(LoadBooleanResult) \
_(LoadInt32ArrayLengthResult) \
_(Int32NegationResult) \
_(Int32NotResult) \
_(LoadArgumentsObjectLengthResult) \
_(LoadFunctionLengthResult) \
_(LoadStringLengthResult) \

Просмотреть файл

@ -357,6 +357,7 @@ CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
masm.jump(ool->rejoin());
return;
}
case CacheKind::UnaryArith:
case CacheKind::Call:
case CacheKind::Compare:
case CacheKind::TypeOf:

Просмотреть файл

@ -549,6 +549,7 @@ IonCacheIRCompiler::init()
case CacheKind::TypeOf:
case CacheKind::ToBool:
case CacheKind::GetIntrinsic:
case CacheKind::UnaryArith:
MOZ_CRASH("Unsupported IC");
}

Просмотреть файл

@ -61,6 +61,7 @@ IonIC::scratchRegisterForEntryJump()
case CacheKind::TypeOf:
case CacheKind::ToBool:
case CacheKind::GetIntrinsic:
case CacheKind::UnaryArith:
MOZ_CRASH("Unsupported IC");
}