Bug 1175976: IonMonkey - Part1: Move unaryArith from baseline to shared stub, r=jandem

This commit is contained in:
Hannes Verschore 2015-08-21 10:14:21 +02:00
Родитель f2b116c0d6
Коммит a6e8869a63
4 изменённых файлов: 224 добавлений и 225 удалений

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

@ -1861,143 +1861,6 @@ ICToNumber_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return tailCallVM(DoToNumberFallbackInfo, masm);
}
//
// UnaryArith_Fallback
//
static bool
DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame, ICUnaryArith_Fallback* stub_,
HandleValue val, MutableHandleValue res)
{
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICUnaryArith_Fallback*> stub(frame, stub_);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
JSOp op = JSOp(*pc);
FallbackICSpew(cx, stub, "UnaryArith(%s)", js_CodeName[op]);
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, script, pc, val, res))
return false;
break;
default:
MOZ_CRASH("Unexpected op");
}
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
if (res.isDouble())
stub->setSawDoubleResult();
if (stub->numOptimizedStubs() >= ICUnaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
// TODO: Discard/replace stubs.
return true;
}
if (val.isInt32() && res.isInt32()) {
JitSpew(JitSpew_BaselineIC, " Generating %s(Int32 => Int32) stub", js_CodeName[op]);
ICUnaryArith_Int32::Compiler compiler(cx, op);
ICStub* int32Stub = compiler.getStub(compiler.getStubSpace(script));
if (!int32Stub)
return false;
stub->addNewStub(int32Stub);
return true;
}
if (val.isNumber() && res.isNumber() && cx->runtime()->jitSupportsFloatingPoint) {
JitSpew(JitSpew_BaselineIC, " Generating %s(Number => Number) stub", js_CodeName[op]);
// Unlink int32 stubs, the double stub handles both cases and TI specializes for both.
stub->unlinkStubsWithKind(cx, ICStub::UnaryArith_Int32);
ICUnaryArith_Double::Compiler compiler(cx, op);
ICStub* doubleStub = compiler.getStub(compiler.getStubSpace(script));
if (!doubleStub)
return false;
stub->addNewStub(doubleStub);
return true;
}
return true;
}
typedef bool (*DoUnaryArithFallbackFn)(JSContext*, BaselineFrame*, ICUnaryArith_Fallback*,
HandleValue, MutableHandleValue);
static const VMFunction DoUnaryArithFallbackInfo =
FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, TailCall, PopValues(1));
bool
ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
EmitRestoreTailCallReg(masm);
// Ensure stack is fully synced for the expression decompiler.
masm.pushValue(R0);
// Push arguments.
masm.pushValue(R0);
masm.push(ICStubReg);
pushFramePtr(masm, R0.scratchReg());
return tailCallVM(DoUnaryArithFallbackInfo, masm);
}
bool
ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
masm.ensureDouble(R0, FloatReg0, &failure);
MOZ_ASSERT(op == JSOP_NEG || op == JSOP_BITNOT);
if (op == JSOP_NEG) {
masm.negateDouble(FloatReg0);
masm.boxDouble(FloatReg0, R0);
} else {
// Truncate the double to an int32.
Register scratchReg = R1.scratchReg();
Label doneTruncate;
Label truncateABICall;
masm.branchTruncateDouble(FloatReg0, scratchReg, &truncateABICall);
masm.jump(&doneTruncate);
masm.bind(&truncateABICall);
masm.setupUnalignedABICall(scratchReg);
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32));
masm.storeCallResult(scratchReg);
masm.bind(&doneTruncate);
masm.not32(scratchReg);
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
}
EmitReturnFromIC(masm);
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// GetElem_Fallback
//

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

@ -1104,94 +1104,6 @@ class ICToNumber_Fallback : public ICFallbackStub
};
};
// UnaryArith
// JSOP_BITNOT
// JSOP_NEG
class ICUnaryArith_Fallback : public ICFallbackStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Fallback(JitCode* stubCode)
: ICFallbackStub(UnaryArith_Fallback, stubCode)
{
extra_ = 0;
}
public:
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
bool sawDoubleResult() {
return extra_;
}
void setSawDoubleResult() {
extra_ = 1;
}
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Fallback>(space, getStubCode());
}
};
};
class ICUnaryArith_Int32 : public ICStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Int32(JitCode* stubCode)
: ICStub(UnaryArith_Int32, stubCode)
{}
public:
class Compiler : public ICMultiStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
Compiler(JSContext* cx, JSOp op)
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Int32>(space, getStubCode());
}
};
};
class ICUnaryArith_Double : public ICStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Double(JitCode* stubCode)
: ICStub(UnaryArith_Double, stubCode)
{}
public:
class Compiler : public ICMultiStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
Compiler(JSContext* cx, JSOp op)
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Double>(space, getStubCode());
}
};
};
// GetElem
// JSOP_GETELEM

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

@ -1427,7 +1427,142 @@ ICBinaryArith_DoubleWithInt32::Compiler::generateStubCode(MacroAssembler& masm)
return true;
}
//
// UnaryArith_Fallback
//
static bool
DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame, ICUnaryArith_Fallback* stub_,
HandleValue val, MutableHandleValue res)
{
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICUnaryArith_Fallback*> stub(frame, stub_);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
JSOp op = JSOp(*pc);
FallbackICSpew(cx, stub, "UnaryArith(%s)", js_CodeName[op]);
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, script, pc, val, res))
return false;
break;
default:
MOZ_CRASH("Unexpected op");
}
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
if (res.isDouble())
stub->setSawDoubleResult();
if (stub->numOptimizedStubs() >= ICUnaryArith_Fallback::MAX_OPTIMIZED_STUBS) {
// TODO: Discard/replace stubs.
return true;
}
if (val.isInt32() && res.isInt32()) {
JitSpew(JitSpew_BaselineIC, " Generating %s(Int32 => Int32) stub", js_CodeName[op]);
ICUnaryArith_Int32::Compiler compiler(cx, op);
ICStub* int32Stub = compiler.getStub(compiler.getStubSpace(script));
if (!int32Stub)
return false;
stub->addNewStub(int32Stub);
return true;
}
if (val.isNumber() && res.isNumber() && cx->runtime()->jitSupportsFloatingPoint) {
JitSpew(JitSpew_BaselineIC, " Generating %s(Number => Number) stub", js_CodeName[op]);
// Unlink int32 stubs, the double stub handles both cases and TI specializes for both.
stub->unlinkStubsWithKind(cx, ICStub::UnaryArith_Int32);
ICUnaryArith_Double::Compiler compiler(cx, op);
ICStub* doubleStub = compiler.getStub(compiler.getStubSpace(script));
if (!doubleStub)
return false;
stub->addNewStub(doubleStub);
return true;
}
return true;
}
typedef bool (*DoUnaryArithFallbackFn)(JSContext*, BaselineFrame*, ICUnaryArith_Fallback*,
HandleValue, MutableHandleValue);
static const VMFunction DoUnaryArithFallbackInfo =
FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, TailCall, PopValues(1));
bool
ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
EmitRestoreTailCallReg(masm);
// Ensure stack is fully synced for the expression decompiler.
masm.pushValue(R0);
// Push arguments.
masm.pushValue(R0);
masm.push(ICStubReg);
pushFramePtr(masm, R0.scratchReg());
return tailCallVM(DoUnaryArithFallbackInfo, masm);
}
bool
ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
masm.ensureDouble(R0, FloatReg0, &failure);
MOZ_ASSERT(op == JSOP_NEG || op == JSOP_BITNOT);
if (op == JSOP_NEG) {
masm.negateDouble(FloatReg0);
masm.boxDouble(FloatReg0, R0);
} else {
// Truncate the double to an int32.
Register scratchReg = R1.scratchReg();
Label doneTruncate;
Label truncateABICall;
masm.branchTruncateDouble(FloatReg0, scratchReg, &truncateABICall);
masm.jump(&doneTruncate);
masm.bind(&truncateABICall);
masm.setupUnalignedABICall(scratchReg);
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32));
masm.storeCallResult(scratchReg);
masm.bind(&doneTruncate);
masm.not32(scratchReg);
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
}
EmitReturnFromIC(masm);
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
} // namespace jit
} // namespace js

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

@ -1389,6 +1389,95 @@ class ICBinaryArith_DoubleWithInt32 : public ICStub
};
};
// UnaryArith
// JSOP_BITNOT
// JSOP_NEG
class ICUnaryArith_Fallback : public ICFallbackStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Fallback(JitCode* stubCode)
: ICFallbackStub(UnaryArith_Fallback, stubCode)
{
extra_ = 0;
}
public:
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
bool sawDoubleResult() {
return extra_;
}
void setSawDoubleResult() {
extra_ = 1;
}
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Fallback>(space, getStubCode());
}
};
};
class ICUnaryArith_Int32 : public ICStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Int32(JitCode* stubCode)
: ICStub(UnaryArith_Int32, stubCode)
{}
public:
class Compiler : public ICMultiStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
Compiler(JSContext* cx, JSOp op)
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Int32>(space, getStubCode());
}
};
};
class ICUnaryArith_Double : public ICStub
{
friend class ICStubSpace;
explicit ICUnaryArith_Double(JitCode* stubCode)
: ICStub(UnaryArith_Double, stubCode)
{}
public:
class Compiler : public ICMultiStubCompiler {
protected:
bool generateStubCode(MacroAssembler& masm);
public:
Compiler(JSContext* cx, JSOp op)
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, Engine::Baseline)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICUnaryArith_Double>(space, getStubCode());
}
};
};
} // namespace jit
} // namespace js