Bug 1434717: Part 5: Connect UnaryArith IC to IonMonkey r=tcampbell

--HG--
extra : rebase_source : e5d3bf65d98899e4cb101e210c51aa4b2a11071e
This commit is contained in:
Matthew Gaudet 2018-02-02 10:38:43 -05:00
parent bab333ec1a
commit d9eed90b0e
9 changed files with 181 additions and 24 deletions

View File

@ -1,7 +1,14 @@
function warmup(fun, input, output) {
for (var i = 0; i < 30; i++) {
var y = fun(input);
assertEq(y, output)
setJitCompilerOption('ion.forceinlineCaches', 1);
function warmup(fun, input_array, output_array) {
assertEq(output_array.length, input_array.length);
for (var index = 0; index < input_array.length; index++) {
input = input_array[index];
output = output_array[index];
for (var i = 0; i < 30; i++) {
var y = fun(input);
assertEq(y, output)
}
}
}
@ -11,13 +18,12 @@ var fun2 = (x) => { return -x; }
var fun3 = (x) => { return ~x; }
var fun4 = (x) => { return ~x; }
warmup(fun1, 1, -1);
warmup(fun1, 0, -0);
warmup(fun1, [1, 2], [-1, -2]);
warmup(fun2, [0], [-0]);
warmup(fun2, 3, -3);
warmup(fun2, 1.2, -1.2);
warmup(fun2, [3, 4], [-3, -4]);
warmup(fun1, [1.2, 1.4], [-1.2, -1.4]);
warmup(fun3, -1, 0);
warmup(fun4, 1.2, -2);
warmup(fun4, 3, -4)
warmup(fun3, [-1, 0], [0, -1]);
warmup(fun4, [-1.0, 0.0, 1.2, 3], [0, -1, -2, -4]);

View File

@ -175,12 +175,16 @@ typedef bool (*IonInICFn)(JSContext*, HandleScript, IonInIC*, HandleValue, Handl
static const VMFunction IonInICInfo =
FunctionInfo<IonInICFn>(IonInIC::update, "IonInIC::update");
typedef bool (*IonInstanceOfICFn)(JSContext*, HandleScript, IonInstanceOfIC*,
HandleValue lhs, HandleObject rhs, bool* res);
static const VMFunction IonInstanceOfInfo =
FunctionInfo<IonInstanceOfICFn>(IonInstanceOfIC::update, "IonInstanceOfIC::update");
typedef bool (*IonUnaryArithICFn)(JSContext* cx, HandleScript outerScript, IonUnaryArithIC* stub,
HandleValue val, MutableHandleValue res);
static const VMFunction IonUnaryArithICInfo =
FunctionInfo<IonUnaryArithICFn>(IonUnaryArithIC::update, "IonUnaryArithIC::update");
void
CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
{
@ -357,7 +361,22 @@ CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
masm.jump(ool->rejoin());
return;
}
case CacheKind::UnaryArith:
case CacheKind::UnaryArith: {
IonUnaryArithIC* unaryArithIC = ic->asUnaryArithIC();
saveLive(lir);
pushArg(unaryArithIC->input());
icInfo_[cacheInfoIndex].icOffsetForPush = pushArgWithPatch(ImmWord(-1));
pushArg(ImmGCPtr(gen->info().script()));
callVM(IonUnaryArithICInfo, lir);
StoreValueTo(unaryArithIC->output()).generate(this);
restoreLiveIgnore(lir, StoreValueTo(unaryArithIC->output()).clobbered());
masm.jump(ool->rejoin());
return;
}
case CacheKind::Call:
case CacheKind::Compare:
case CacheKind::TypeOf:
@ -2760,6 +2779,16 @@ CodeGenerator::visitBinarySharedStub(LBinarySharedStub* lir)
}
}
void
CodeGenerator::visitUnaryCache(LUnaryCache* lir)
{
LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
TypedOrValueRegister input = TypedOrValueRegister(ToValue(lir, LUnaryCache::Input));
ValueOperand output = ToOutValue(lir);
IonUnaryArithIC ic(liveRegs, input, output);
addIC(lir, allocateIC(ic));
}
void
CodeGenerator::visitNullarySharedStub(LNullarySharedStub* lir)

View File

@ -3271,6 +3271,10 @@ IonBuilder::jsop_bitnot()
return Ok();
}
MOZ_TRY(arithTrySharedStub(&emitted, JSOP_BITNOT, nullptr, input));
if (emitted)
return Ok();
// Not possible to optimize. Do a slow vm call.
MBitNot* ins = MBitNot::New(alloc(), input);
@ -3533,12 +3537,16 @@ IonBuilder::arithTrySharedStub(bool* emitted, JSOp op,
if (actualOp == JSOP_POS)
return Ok();
// JSOP_NEG and JSOP_BITNOT can't be handled here right now.
if (actualOp == JSOP_NEG || actualOp == JSOP_BITNOT)
return Ok();
MInstruction* stub = nullptr;
switch (actualOp) {
case JSOP_NEG:
case JSOP_BITNOT:
MOZ_ASSERT_IF(op == JSOP_MUL,
left->maybeConstantValue() && left->maybeConstantValue()->toInt32() == -1);
MOZ_ASSERT_IF(op != JSOP_MUL, !left);
stub = MUnaryCache::New(alloc(), right);
break;
case JSOP_ADD:
case JSOP_SUB:
case JSOP_MUL:

View File

@ -544,12 +544,24 @@ IonCacheIRCompiler::init()
AnyRegister(ic->rhs())));
break;
}
case CacheKind::UnaryArith: {
IonUnaryArithIC *ic = ic_->asUnaryArithIC();
ValueOperand output = ic->output();
available.add(output);
liveRegs_.emplace(ic->liveRegs());
outputUnchecked_.emplace(TypedOrValueRegister(output));
MOZ_ASSERT(numInputs == 1);
allocator.initInputLocation(0, ic->input());
break;
}
case CacheKind::Call:
case CacheKind::Compare:
case CacheKind::TypeOf:
case CacheKind::ToBool:
case CacheKind::GetIntrinsic:
case CacheKind::UnaryArith:
MOZ_CRASH("Unsupported IC");
}

View File

@ -56,12 +56,13 @@ IonIC::scratchRegisterForEntryJump()
return asGetIteratorIC()->temp1();
case CacheKind::InstanceOf:
return asInstanceOfIC()->output();
case CacheKind::UnaryArith:
return asUnaryArithIC()->output().scratchReg();
case CacheKind::Call:
case CacheKind::Compare:
case CacheKind::TypeOf:
case CacheKind::ToBool:
case CacheKind::GetIntrinsic:
case CacheKind::UnaryArith:
MOZ_CRASH("Unsupported IC");
}
@ -502,6 +503,48 @@ IonInstanceOfIC::update(JSContext* cx, HandleScript outerScript, IonInstanceOfIC
return HasInstance(cx, rhs, lhs, res);
}
/* static */ bool
IonUnaryArithIC::update(JSContext* cx, HandleScript outerScript, IonUnaryArithIC* ic,
HandleValue val, MutableHandleValue res)
{
IonScript* ionScript = outerScript->ionScript();
RootedScript script(cx, ic->script());
jsbytecode* pc = ic->pc();
JSOp op = JSOp(*pc);
switch (op) {
case JSOP_BITNOT: {
int32_t result;
if (!BitNot(cx, val, &result))
return false;
res.setInt32(result);
break;
}
case JSOP_NEG:
if (!NegOperation(cx, val, res))
return false;
break;
default:
MOZ_CRASH("Unexpected op");
}
if (ic->state().maybeTransition())
ic->discardStubs(cx->zone());
if (ic->state().canAttachStub()) {
bool attached = false;
UnaryArithIRGenerator gen(cx, script, pc, ic->state().mode(), op, val, res);
if (gen.tryAttachStub())
ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
if (!attached)
ic->state().trackNotAttached();
}
return true;
}
uint8_t*
IonICStub::stubDataStart()
{

View File

@ -65,6 +65,7 @@ class IonGetIteratorIC;
class IonHasOwnIC;
class IonInIC;
class IonInstanceOfIC;
class IonUnaryArithIC;
class IonIC
{
@ -172,6 +173,10 @@ class IonIC
MOZ_ASSERT(kind_ == CacheKind::InstanceOf);
return (IonInstanceOfIC*)this;
}
IonUnaryArithIC* asUnaryArithIC() {
MOZ_ASSERT(kind_ == CacheKind::UnaryArith);
return (IonUnaryArithIC*)this;
}
void updateBaseAddress(JitCode* code);
@ -475,6 +480,30 @@ class IonInstanceOfIC : public IonIC
HandleValue lhs, HandleObject rhs, bool* attached);
};
class IonUnaryArithIC : public IonIC
{
LiveRegisterSet liveRegs_;
TypedOrValueRegister input_;
ValueOperand output_;
public:
IonUnaryArithIC(LiveRegisterSet liveRegs, TypedOrValueRegister input, ValueOperand output)
: IonIC(CacheKind::UnaryArith),
liveRegs_(liveRegs),
input_(input),
output_(output)
{ }
LiveRegisterSet liveRegs() const { return liveRegs_; }
TypedOrValueRegister input() const { return input_; }
ValueOperand output() const { return output_; }
static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonUnaryArithIC* stub,
HandleValue val, MutableHandleValue res);
};
} // namespace jit
} // namespace js

View File

@ -2532,6 +2532,17 @@ LIRGenerator::visitBinarySharedStub(MBinarySharedStub* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitUnaryCache(MUnaryCache* ins)
{
MDefinition* input = ins->getOperand(0);
MOZ_ASSERT(ins->type() == MIRType::Value);
LUnaryCache* lir = new(alloc()) LUnaryCache(useBox(input));
defineBox(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitNullarySharedStub(MNullarySharedStub* ins)
{

View File

@ -8287,6 +8287,21 @@ class MBinarySharedStub
TRIVIAL_NEW_WRAPPERS
};
class MUnaryCache
: public MUnaryInstruction,
public BoxPolicy<0>::Data
{
explicit MUnaryCache(MDefinition* input)
: MUnaryInstruction(classOpcode, input)
{
setResultType(MIRType::Value);
}
public:
INSTRUCTION_HEADER(UnaryCache)
TRIVIAL_NEW_WRAPPERS
};
class MNullarySharedStub
: public MNullaryInstruction
{

View File

@ -5541,19 +5541,23 @@ class LBinarySharedStub : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIEC
static const size_t RhsInput = BOX_PIECES;
};
class LUnarySharedStub : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
class LUnaryCache : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
{
public:
LIR_HEADER(UnarySharedStub)
LIR_HEADER(UnaryCache)
explicit LUnarySharedStub(const LBoxAllocation& input)
: LCallInstructionHelper(classOpcode)
explicit LUnaryCache(const LBoxAllocation& input)
: LInstructionHelper(classOpcode)
{
setBoxOperand(Input, input);
}
const MUnarySharedStub* mir() const {
return mir_->toUnarySharedStub();
const MUnaryCache* mir() const {
return mir_->toUnaryCache();
}
const LAllocation* input() {
return getOperand(Input);
}
static const size_t Input = 0;