mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
5536f71c38
@ -1,29 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fun1 = (x) => { return -x; }
|
||||
var fun2 = (x) => { return -x; }
|
||||
|
||||
var fun3 = (x) => { return ~x; }
|
||||
var fun4 = (x) => { return ~x; }
|
||||
|
||||
warmup(fun1, [1, 2], [-1, -2]);
|
||||
warmup(fun2, [0], [-0]);
|
||||
|
||||
warmup(fun2, [3, 4], [-3, -4]);
|
||||
warmup(fun1, [1.2, 1.4], [-1.2, -1.4]);
|
||||
|
||||
warmup(fun3, [-1, 0], [0, -1]);
|
||||
warmup(fun4, [-1.0, 0.0, 1.2, 3], [0, -1, -2, -4]);
|
||||
|
@ -2105,7 +2105,6 @@ 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;
|
||||
|
@ -1930,7 +1930,7 @@ BaselineCompiler::emitUnaryArith()
|
||||
frame.popRegsAndSync(1);
|
||||
|
||||
// Call IC
|
||||
ICUnaryArith_Fallback::Compiler stubCompiler(cx);
|
||||
ICUnaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
|
||||
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
|
||||
return false;
|
||||
|
||||
|
@ -4533,89 +4533,5 @@ ICRest_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return tailCallVM(DoRestFallbackInfo, 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*> debug_stub(ICStubEngine::Baseline, frame, stub);
|
||||
|
||||
RootedScript script(cx, frame->script());
|
||||
jsbytecode* pc = stub->icEntry()->pc(script);
|
||||
JSOp op = JSOp(*pc);
|
||||
FallbackICSpew(cx, stub, "UnaryArith(%s)", 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, val, res))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (debug_stub.invalid())
|
||||
return true;
|
||||
|
||||
if (res.isDouble())
|
||||
stub->setSawDoubleResult();
|
||||
|
||||
if (stub->state().maybeTransition())
|
||||
stub->discardStubs(cx);
|
||||
|
||||
if (stub->state().canAttachStub()) {
|
||||
UnaryArithIRGenerator gen(cx, script, pc, stub->state().mode(),
|
||||
op, val, res);
|
||||
if (gen.tryAttachStub()) {
|
||||
bool attached = false;
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Regular,
|
||||
ICStubEngine::Baseline, script, stub, &attached);
|
||||
if (newStub) {
|
||||
JitSpew(JitSpew_BaselineIC, " Attached (shared) CacheIR stub for %s", CodeName[op]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DoUnaryArithFallbackFn)(JSContext*, BaselineFrame*, ICUnaryArith_Fallback*,
|
||||
HandleValue, MutableHandleValue);
|
||||
static const VMFunction DoUnaryArithFallbackInfo =
|
||||
FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, "DoUnaryArithFallback", TailCall,
|
||||
PopValues(1));
|
||||
|
||||
bool
|
||||
ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
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);
|
||||
pushStubPayload(masm, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoUnaryArithFallbackInfo, masm);
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -1459,44 +1459,6 @@ class ICRetSub_Resume : 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:
|
||||
bool sawDoubleResult() {
|
||||
return extra_;
|
||||
}
|
||||
void setSawDoubleResult() {
|
||||
extra_ = 1;
|
||||
}
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback, Engine::Baseline)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICUnaryArith_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
inline bool
|
||||
IsCacheableDOMProxy(JSObject* obj)
|
||||
{
|
||||
|
@ -34,8 +34,6 @@ namespace jit {
|
||||
\
|
||||
_(ToNumber_Fallback) \
|
||||
\
|
||||
_(UnaryArith_Fallback) \
|
||||
\
|
||||
_(Call_Fallback) \
|
||||
_(Call_Scripted) \
|
||||
_(Call_AnyScripted) \
|
||||
|
@ -334,9 +334,11 @@ BaselineInspector::expectedResultType(jsbytecode* pc)
|
||||
return MIRType::Double;
|
||||
return MIRType::Int32;
|
||||
case ICStub::BinaryArith_BooleanWithInt32:
|
||||
case ICStub::UnaryArith_Int32:
|
||||
case ICStub::BinaryArith_DoubleWithInt32:
|
||||
return MIRType::Int32;
|
||||
case ICStub::BinaryArith_Double:
|
||||
case ICStub::UnaryArith_Double:
|
||||
return MIRType::Double;
|
||||
case ICStub::BinaryArith_StringConcat:
|
||||
case ICStub::BinaryArith_StringObjectConcat:
|
||||
|
@ -4683,86 +4683,4 @@ GetIntrinsicIRGenerator::tryAttachStub()
|
||||
writer.returnFromIC();
|
||||
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;
|
||||
if (tryAttachNumber())
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
UnaryArithIRGenerator::tryAttachNumber()
|
||||
{
|
||||
if (!val_.isNumber() || !res_.isNumber() || !cx_->runtime()->jitSupportsFloatingPoint)
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
writer.guardType(valId, JSVAL_TYPE_DOUBLE);
|
||||
Int32OperandId truncatedId;
|
||||
switch (op_) {
|
||||
case JSOP_BITNOT:
|
||||
truncatedId = writer.truncateDoubleToUInt32(valId);
|
||||
writer.int32NotResult(truncatedId);
|
||||
trackAttached("UnaryArith.DoubleNot");
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
writer.doubleNegationResult(valId);
|
||||
trackAttached("UnaryArith.DoubleNeg");
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected OP");
|
||||
}
|
||||
|
||||
writer.returnFromIC();
|
||||
return true;
|
||||
}
|
@ -153,8 +153,7 @@ class TypedOperandId : public OperandId
|
||||
_(GetIterator) \
|
||||
_(Compare) \
|
||||
_(ToBool) \
|
||||
_(Call) \
|
||||
_(UnaryArith)
|
||||
_(Call)
|
||||
|
||||
enum class CacheKind : uint8_t
|
||||
{
|
||||
@ -172,7 +171,6 @@ extern const char* CacheKindNames[];
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsNumber) \
|
||||
_(GuardIsInt32) \
|
||||
_(GuardIsInt32Index) \
|
||||
_(GuardType) \
|
||||
_(GuardShape) \
|
||||
@ -209,8 +207,6 @@ extern const char* CacheKindNames[];
|
||||
_(LoadEnclosingEnvironment) \
|
||||
_(LoadWrapperTarget) \
|
||||
\
|
||||
_(TruncateDoubleToUInt32) \
|
||||
\
|
||||
_(MegamorphicLoadSlotResult) \
|
||||
_(MegamorphicLoadSlotByValueResult) \
|
||||
_(MegamorphicStoreSlot) \
|
||||
@ -276,9 +272,6 @@ extern const char* CacheKindNames[];
|
||||
_(LoadStringResult) \
|
||||
_(LoadInstanceOfObjectResult) \
|
||||
_(LoadTypeOfObjectResult) \
|
||||
_(Int32NotResult) \
|
||||
_(Int32NegationResult) \
|
||||
_(DoubleNegationResult) \
|
||||
_(LoadInt32TruthyResult) \
|
||||
_(LoadDoubleTruthyResult) \
|
||||
_(LoadStringTruthyResult) \
|
||||
@ -530,12 +523,6 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
||||
writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
|
||||
return SymbolOperandId(val.id());
|
||||
}
|
||||
Int32OperandId guardIsInt32(ValOperandId val) {
|
||||
Int32OperandId res(nextOperandId_++);
|
||||
writeOpWithOperandId(CacheOp::GuardIsInt32, val);
|
||||
writeOperandId(res);
|
||||
return res;
|
||||
}
|
||||
Int32OperandId guardIsInt32Index(ValOperandId val) {
|
||||
Int32OperandId res(nextOperandId_++);
|
||||
writeOpWithOperandId(CacheOp::GuardIsInt32Index, val);
|
||||
@ -728,13 +715,6 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
||||
return res;
|
||||
}
|
||||
|
||||
Int32OperandId truncateDoubleToUInt32(ValOperandId val) {
|
||||
Int32OperandId res(nextOperandId_++);
|
||||
writeOpWithOperandId(CacheOp::TruncateDoubleToUInt32, val);
|
||||
writeOperandId(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
ValOperandId loadDOMExpandoValue(ObjOperandId obj) {
|
||||
ValOperandId res(nextOperandId_++);
|
||||
writeOpWithOperandId(CacheOp::LoadDOMExpandoValue, obj);
|
||||
@ -919,15 +899,6 @@ 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 doubleNegationResult(ValOperandId val) {
|
||||
writeOpWithOperandId(CacheOp::DoubleNegationResult, val);
|
||||
}
|
||||
void loadBooleanResult(bool val) {
|
||||
writeOp(CacheOp::LoadBooleanResult);
|
||||
buffer_.writeByte(uint32_t(val));
|
||||
@ -1682,24 +1653,6 @@ class MOZ_RAII GetIntrinsicIRGenerator : public IRGenerator
|
||||
bool tryAttachStub();
|
||||
};
|
||||
|
||||
class MOZ_RAII UnaryArithIRGenerator : public IRGenerator
|
||||
{
|
||||
JSOp op_;
|
||||
HandleValue val_;
|
||||
HandleValue res_;
|
||||
|
||||
bool tryAttachInt32();
|
||||
bool tryAttachNumber();
|
||||
|
||||
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
|
||||
|
||||
|
@ -18,7 +18,6 @@ using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::BitwiseCast;
|
||||
|
||||
ValueOperand
|
||||
CacheRegisterAllocator::useValueRegister(MacroAssembler& masm, ValOperandId op)
|
||||
@ -1312,29 +1311,6 @@ CacheIRCompiler::emitGuardIsSymbol()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsInt32()
|
||||
{
|
||||
ValOperandId inputId = reader.valOperandId();
|
||||
Register output = allocator.defineRegister(masm, reader.int32OperandId());
|
||||
|
||||
if (allocator.knownType(inputId) == JSVAL_TYPE_INT32) {
|
||||
Register input = allocator.useRegister(masm, Int32OperandId(inputId.id()));
|
||||
masm.move32(input, output);
|
||||
return true;
|
||||
}
|
||||
ValueOperand input = allocator.useValueRegister(masm, inputId);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
Label notInt32, done;
|
||||
masm.branchTestInt32(Assembler::NotEqual, input, failure->label());
|
||||
masm.unboxInt32(input, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsInt32Index()
|
||||
{
|
||||
@ -1803,92 +1779,6 @@ 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, both 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::emitDoubleNegationResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
// If we're compiling a Baseline IC, FloatReg0 is always available.
|
||||
Label failurePopReg, done;
|
||||
if (mode_ != Mode::Baseline)
|
||||
masm.push(FloatReg0);
|
||||
|
||||
masm.ensureDouble(val, FloatReg0, (mode_ != Mode::Baseline) ? &failurePopReg : failure->label());
|
||||
masm.negateDouble(FloatReg0);
|
||||
masm.boxDouble(FloatReg0, output.valueReg(), FloatReg0);
|
||||
|
||||
if (mode_ != Mode::Baseline) {
|
||||
masm.pop(FloatReg0);
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&failurePopReg);
|
||||
masm.pop(FloatReg0);
|
||||
masm.jump(failure->label());
|
||||
}
|
||||
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitTruncateDoubleToUInt32()
|
||||
{
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
Register res = allocator.defineRegister(masm, reader.int32OperandId());
|
||||
|
||||
Label doneTruncate, truncateABICall;
|
||||
if (mode_ != Mode::Baseline)
|
||||
masm.push(FloatReg0);
|
||||
|
||||
masm.unboxDouble(val, FloatReg0);
|
||||
masm.branchTruncateDoubleMaybeModUint32(FloatReg0, res, &truncateABICall);
|
||||
masm.jump(&doneTruncate);
|
||||
|
||||
masm.bind(&truncateABICall);
|
||||
masm.setupUnalignedABICall(res);
|
||||
masm.passABIArg(FloatReg0, MoveOp::DOUBLE);
|
||||
masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32),
|
||||
MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther);
|
||||
masm.storeCallInt32Result(res);
|
||||
|
||||
masm.bind(&doneTruncate);
|
||||
if (mode_ != Mode::Baseline)
|
||||
masm.pop(FloatReg0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitLoadArgumentsObjectLengthResult()
|
||||
{
|
||||
|
@ -21,7 +21,6 @@ namespace jit {
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsNumber) \
|
||||
_(GuardIsInt32) \
|
||||
_(GuardIsInt32Index) \
|
||||
_(GuardType) \
|
||||
_(GuardClass) \
|
||||
@ -45,10 +44,6 @@ namespace jit {
|
||||
_(LoadUndefinedResult) \
|
||||
_(LoadBooleanResult) \
|
||||
_(LoadInt32ArrayLengthResult) \
|
||||
_(Int32NegationResult) \
|
||||
_(Int32NotResult) \
|
||||
_(DoubleNegationResult) \
|
||||
_(TruncateDoubleToUInt32) \
|
||||
_(LoadArgumentsObjectLengthResult) \
|
||||
_(LoadFunctionLengthResult) \
|
||||
_(LoadStringLengthResult) \
|
||||
|
@ -175,16 +175,12 @@ 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)
|
||||
{
|
||||
@ -361,22 +357,6 @@ CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
|
||||
masm.jump(ool->rejoin());
|
||||
return;
|
||||
}
|
||||
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:
|
||||
@ -2757,14 +2737,22 @@ CodeGenerator::visitBinarySharedStub(LBinarySharedStub* lir)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitUnaryCache(LUnaryCache* lir)
|
||||
CodeGenerator::visitUnarySharedStub(LUnarySharedStub* lir)
|
||||
{
|
||||
LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
|
||||
TypedOrValueRegister input = TypedOrValueRegister(ToValue(lir, LUnaryCache::Input));
|
||||
ValueOperand output = GetValueOutput(lir);
|
||||
|
||||
IonUnaryArithIC ic(liveRegs, input, output);
|
||||
addIC(lir, allocateIC(ic));
|
||||
JSOp jsop = JSOp(*lir->mir()->resumePoint()->pc());
|
||||
switch (jsop) {
|
||||
case JSOP_BITNOT:
|
||||
case JSOP_NEG:
|
||||
emitSharedStub(ICStub::Kind::UnaryArith_Fallback, lir);
|
||||
break;
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_LENGTH:
|
||||
emitSharedStub(ICStub::Kind::GetProp_Fallback, lir);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unsupported jsop in shared stubs.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -9957,6 +9945,11 @@ CodeGenerator::linkSharedStubs(JSContext* cx)
|
||||
stub = stubCompiler.getStub(&stubSpace_);
|
||||
break;
|
||||
}
|
||||
case ICStub::Kind::UnaryArith_Fallback: {
|
||||
ICUnaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonSharedIC);
|
||||
stub = stubCompiler.getStub(&stubSpace_);
|
||||
break;
|
||||
}
|
||||
case ICStub::Kind::Compare_Fallback: {
|
||||
ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::IonSharedIC);
|
||||
stub = stubCompiler.getStub(&stubSpace_);
|
||||
|
@ -136,7 +136,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
||||
void visitStringReplace(LStringReplace* lir);
|
||||
void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
|
||||
void visitBinarySharedStub(LBinarySharedStub* lir);
|
||||
void visitUnaryCache(LUnaryCache* lir);
|
||||
void visitUnarySharedStub(LUnarySharedStub* lir);
|
||||
void visitNullarySharedStub(LNullarySharedStub* lir);
|
||||
void visitClassConstructor(LClassConstructor* lir);
|
||||
void visitLambda(LLambda* lir);
|
||||
|
@ -3546,6 +3546,11 @@ IonBuilder::arithTrySharedStub(bool* emitted, JSOp op,
|
||||
if (actualOp == JSOP_POS)
|
||||
return Ok();
|
||||
|
||||
// FIXME: The JSOP_BITNOT path doesn't track optimizations yet.
|
||||
if (actualOp != JSOP_BITNOT) {
|
||||
trackOptimizationAttempt(TrackedStrategy::BinaryArith_SharedCache);
|
||||
trackOptimizationSuccess();
|
||||
}
|
||||
|
||||
MInstruction* stub = nullptr;
|
||||
switch (actualOp) {
|
||||
@ -3554,7 +3559,8 @@ IonBuilder::arithTrySharedStub(bool* emitted, JSOp op,
|
||||
MOZ_ASSERT_IF(op == JSOP_MUL,
|
||||
left->maybeConstantValue() && left->maybeConstantValue()->toInt32() == -1);
|
||||
MOZ_ASSERT_IF(op != JSOP_MUL, !left);
|
||||
stub = MUnaryCache::New(alloc(), right);
|
||||
|
||||
stub = MUnarySharedStub::New(alloc(), right);
|
||||
break;
|
||||
case JSOP_ADD:
|
||||
case JSOP_SUB:
|
||||
|
@ -542,19 +542,6 @@ 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:
|
||||
|
@ -60,8 +60,6 @@ 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:
|
||||
@ -507,48 +505,6 @@ 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()
|
||||
{
|
||||
|
@ -65,7 +65,6 @@ class IonGetIteratorIC;
|
||||
class IonHasOwnIC;
|
||||
class IonInIC;
|
||||
class IonInstanceOfIC;
|
||||
class IonUnaryArithIC;
|
||||
|
||||
class IonIC
|
||||
{
|
||||
@ -173,10 +172,6 @@ class IonIC
|
||||
MOZ_ASSERT(kind_ == CacheKind::InstanceOf);
|
||||
return (IonInstanceOfIC*)this;
|
||||
}
|
||||
IonUnaryArithIC* asUnaryArithIC() {
|
||||
MOZ_ASSERT(kind_ == CacheKind::UnaryArith);
|
||||
return (IonUnaryArithIC*)this;
|
||||
}
|
||||
|
||||
void updateBaseAddress(JitCode* code, MacroAssembler& masm);
|
||||
|
||||
@ -480,30 +475,6 @@ 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
|
||||
|
||||
|
@ -2531,13 +2531,13 @@ LIRGenerator::visitBinarySharedStub(MBinarySharedStub* ins)
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitUnaryCache(MUnaryCache* ins)
|
||||
LIRGenerator::visitUnarySharedStub(MUnarySharedStub* ins)
|
||||
{
|
||||
MDefinition* input = ins->getOperand(0);
|
||||
MOZ_ASSERT(ins->type() == MIRType::Value);
|
||||
|
||||
LUnaryCache* lir = new(alloc()) LUnaryCache(useBox(input));
|
||||
defineBox(lir, ins);
|
||||
LUnarySharedStub* lir = new(alloc()) LUnarySharedStub(useBoxFixedAtStart(input, R0));
|
||||
defineSharedStubReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitGetFirstDollarIndex(MGetFirstDollarIndex* ins) override;
|
||||
void visitStringReplace(MStringReplace* ins) override;
|
||||
void visitBinarySharedStub(MBinarySharedStub* ins) override;
|
||||
void visitUnaryCache(MUnaryCache* ins) override;
|
||||
void visitUnarySharedStub(MUnarySharedStub* ins) override;
|
||||
void visitNullarySharedStub(MNullarySharedStub* ins) override;
|
||||
void visitClassConstructor(MClassConstructor* ins) override;
|
||||
void visitLambda(MLambda* ins) override;
|
||||
|
@ -8231,18 +8231,18 @@ class MBinarySharedStub
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
};
|
||||
|
||||
class MUnaryCache
|
||||
class MUnarySharedStub
|
||||
: public MUnaryInstruction,
|
||||
public BoxPolicy<0>::Data
|
||||
{
|
||||
explicit MUnaryCache(MDefinition* input)
|
||||
explicit MUnarySharedStub(MDefinition* input)
|
||||
: MUnaryInstruction(classOpcode, input)
|
||||
{
|
||||
setResultType(MIRType::Value);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(UnaryCache)
|
||||
INSTRUCTION_HEADER(UnarySharedStub)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ namespace jit {
|
||||
_(OsrArgumentsObject) \
|
||||
_(ReturnFromCtor) \
|
||||
_(BinarySharedStub) \
|
||||
_(UnaryCache) \
|
||||
_(UnarySharedStub) \
|
||||
_(NullarySharedStub) \
|
||||
_(CheckOverRecursed) \
|
||||
_(DefVar) \
|
||||
|
@ -1233,6 +1233,144 @@ ICBinaryArith_DoubleWithInt32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// UnaryArith_Fallback
|
||||
//
|
||||
|
||||
static bool
|
||||
DoUnaryArithFallback(JSContext* cx, void* payload, ICUnaryArith_Fallback* stub_,
|
||||
HandleValue val, MutableHandleValue res)
|
||||
{
|
||||
SharedStubInfo info(cx, payload, stub_->icEntry());
|
||||
ICStubCompiler::Engine engine = info.engine();
|
||||
|
||||
// This fallback stub may trigger debug mode toggling.
|
||||
DebugModeOSRVolatileStub<ICUnaryArith_Fallback*> stub(engine, info.maybeFrame(), stub_);
|
||||
|
||||
jsbytecode* pc = info.pc();
|
||||
JSOp op = JSOp(*pc);
|
||||
FallbackICSpew(cx, stub, "UnaryArith(%s)", 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, 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", CodeName[op]);
|
||||
ICUnaryArith_Int32::Compiler compiler(cx, op, engine);
|
||||
ICStub* int32Stub = compiler.getStub(compiler.getStubSpace(info.outerScript(cx)));
|
||||
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", 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, engine);
|
||||
ICStub* doubleStub = compiler.getStub(compiler.getStubSpace(info.outerScript(cx)));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DoUnaryArithFallbackFn)(JSContext*, void*, ICUnaryArith_Fallback*,
|
||||
HandleValue, MutableHandleValue);
|
||||
static const VMFunction DoUnaryArithFallbackInfo =
|
||||
FunctionInfo<DoUnaryArithFallbackFn>(DoUnaryArithFallback, "DoUnaryArithFallback", TailCall,
|
||||
PopValues(1));
|
||||
|
||||
bool
|
||||
ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
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);
|
||||
pushStubPayload(masm, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoUnaryArithFallbackInfo, masm);
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
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, FloatReg0);
|
||||
} else {
|
||||
// Truncate the double to an int32.
|
||||
Register scratchReg = R1.scratchReg();
|
||||
|
||||
Label doneTruncate;
|
||||
Label truncateABICall;
|
||||
masm.branchTruncateDoubleMaybeModUint32(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),
|
||||
MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther);
|
||||
masm.storeCallInt32Result(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;
|
||||
}
|
||||
|
||||
//
|
||||
// Compare_Fallback
|
||||
//
|
||||
|
@ -1914,6 +1914,94 @@ 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:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx, Engine engine)
|
||||
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback, engine)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
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:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, JSOp op, Engine engine)
|
||||
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, engine)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
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:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, JSOp op, Engine engine)
|
||||
: ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, engine)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICUnaryArith_Double>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Compare
|
||||
// JSOP_LT
|
||||
// JSOP_LE
|
||||
|
@ -20,6 +20,10 @@ namespace jit {
|
||||
_(BinaryArith_BooleanWithInt32) \
|
||||
_(BinaryArith_DoubleWithInt32) \
|
||||
\
|
||||
_(UnaryArith_Fallback) \
|
||||
_(UnaryArith_Int32) \
|
||||
_(UnaryArith_Double) \
|
||||
\
|
||||
_(Compare_Fallback) \
|
||||
_(Compare_Int32) \
|
||||
_(Compare_Double) \
|
||||
|
@ -186,5 +186,33 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.ma_mvn(R0.payloadReg(), R0.payloadReg());
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
|
||||
|
||||
// Compile -x as 0 - x.
|
||||
masm.as_rsb(R0.payloadReg(), R0.payloadReg(), Imm8(0));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -185,5 +185,36 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.Mvn(ARMRegister(R1.valueReg(), 32), ARMRegister(R0.valueReg(), 32));
|
||||
masm.movePayload(R1.valueReg(), R0.valueReg());
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
|
||||
|
||||
// Compile -x as 0 - x.
|
||||
masm.Sub(ARMRegister(R1.valueReg(), 32), wzr, ARMRegister(R0.valueReg(), 32));
|
||||
masm.movePayload(R1.valueReg(), R0.valueReg());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -143,5 +143,34 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.not32(R0.payloadReg());
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(INT32_MAX), &failure);
|
||||
|
||||
masm.neg32(R0.payloadReg());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
return false;
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -154,5 +154,37 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.not32(R0.valueReg());
|
||||
masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, ExtractTemp0, Imm32(INT32_MAX), &failure);
|
||||
|
||||
masm.neg32(ExtractTemp0);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, ExtractTemp0, R0);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
return false;
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -45,3 +45,4 @@ BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& iter, Invalidati
|
||||
bool ICCompare_Int32::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
|
||||
bool ICCompare_Double::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
|
||||
bool ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
|
||||
bool ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
|
||||
|
@ -5114,21 +5114,17 @@ class LBinarySharedStub : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIEC
|
||||
static const size_t RhsInput = BOX_PIECES;
|
||||
};
|
||||
|
||||
class LUnaryCache : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
|
||||
class LUnarySharedStub : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(UnaryCache)
|
||||
LIR_HEADER(UnarySharedStub)
|
||||
|
||||
explicit LUnaryCache(const LBoxAllocation& input) {
|
||||
explicit LUnarySharedStub(const LBoxAllocation& input) {
|
||||
setBoxOperand(Input, input);
|
||||
}
|
||||
|
||||
const MUnaryCache* mir() const {
|
||||
return mir_->toUnaryCache();
|
||||
}
|
||||
|
||||
const LAllocation* input() {
|
||||
return getOperand(Input);
|
||||
const MUnarySharedStub* mir() const {
|
||||
return mir_->toUnarySharedStub();
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
@ -244,7 +244,7 @@
|
||||
_(StringReplace) \
|
||||
_(Substr) \
|
||||
_(BinarySharedStub) \
|
||||
_(UnaryCache) \
|
||||
_(UnarySharedStub) \
|
||||
_(NullarySharedStub) \
|
||||
_(ClassConstructor) \
|
||||
_(Lambda) \
|
||||
|
@ -210,7 +210,7 @@ LIRGeneratorShared::defineSharedStubReturn(LInstruction* lir, MDefinition* mir)
|
||||
{
|
||||
lir->setMir(mir);
|
||||
|
||||
MOZ_ASSERT(lir->isBinarySharedStub() || lir->isNullarySharedStub());
|
||||
MOZ_ASSERT(lir->isBinarySharedStub() || lir->isUnarySharedStub() || lir->isNullarySharedStub());
|
||||
MOZ_ASSERT(mir->type() == MIRType::Value);
|
||||
|
||||
uint32_t vreg = getVirtualRegister();
|
||||
|
@ -202,5 +202,33 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.notl(R0.valueReg());
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
|
||||
masm.negl(R0.valueReg());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -212,5 +212,31 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.notl(R0.payloadReg());
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
|
||||
masm.negl(R0.payloadReg());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -5231,15 +5231,21 @@ AddCanvasBackgroundColor(const nsDisplayList& aList, nsIFrame* aCanvasFrame,
|
||||
nscolor aColor, bool aCSSBackgroundColor)
|
||||
{
|
||||
for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
|
||||
const DisplayItemType type = i->GetType();
|
||||
|
||||
if (i->Frame() == aCanvasFrame &&
|
||||
i->GetType() == DisplayItemType::TYPE_CANVAS_BACKGROUND_COLOR) {
|
||||
type == DisplayItemType::TYPE_CANVAS_BACKGROUND_COLOR) {
|
||||
nsDisplayCanvasBackgroundColor* bg = static_cast<nsDisplayCanvasBackgroundColor*>(i);
|
||||
bg->SetExtraBackgroundColor(aColor);
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool isBlendContainer =
|
||||
type == DisplayItemType::TYPE_BLEND_CONTAINER ||
|
||||
type == DisplayItemType::TYPE_TABLE_BLEND_CONTAINER;
|
||||
|
||||
nsDisplayList* sublist = i->GetSameCoordinateSystemChildren();
|
||||
if (sublist &&
|
||||
!(i->GetType() == DisplayItemType::TYPE_BLEND_CONTAINER && !aCSSBackgroundColor) &&
|
||||
if (sublist && !(isBlendContainer && !aCSSBackgroundColor) &&
|
||||
AddCanvasBackgroundColor(*sublist, aCanvasFrame, aColor, aCSSBackgroundColor))
|
||||
return true;
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BLEND_CONTAINER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BLEND_MODE, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BLEND_MODE, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BORDER, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER, TYPE_RENDERS_NO_IMAGES)
|
||||
@ -59,12 +61,14 @@ DECLARE_DISPLAY_ITEM_TYPE(FILTER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_CHAR_CLIP, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_WRAPPER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_IMAGE, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_THEMED_BACKGROUND_IMAGE, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_FIXED_POSITION, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TEXT, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW, TYPE_RENDERS_NO_IMAGES)
|
||||
|
@ -1572,8 +1572,8 @@ nsDisplayListBuilder::Allocate(size_t aSize, DisplayItemType aType)
|
||||
size_t roundedUpSize = RoundUpPow2(aSize);
|
||||
uint_fast8_t type = FloorLog2Size(roundedUpSize);
|
||||
|
||||
MOZ_ASSERT(gDisplayItemSizes[static_cast<uint32_t>(aType)] == type ||
|
||||
gDisplayItemSizes[static_cast<uint32_t>(aType)] == 0);
|
||||
MOZ_RELEASE_ASSERT(gDisplayItemSizes[static_cast<uint32_t>(aType)] == type ||
|
||||
gDisplayItemSizes[static_cast<uint32_t>(aType)] == 0);
|
||||
gDisplayItemSizes[static_cast<uint32_t>(aType)] = type;
|
||||
return mPool.AllocateByCustomID(type, roundedUpSize);
|
||||
}
|
||||
@ -6368,7 +6368,9 @@ RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
LayerState state = i->GetLayerState(aBuilder, aManager, aParameters);
|
||||
if (state == LAYER_ACTIVE && i->GetType() == DisplayItemType::TYPE_BLEND_MODE) {
|
||||
if (state == LAYER_ACTIVE &&
|
||||
(i->GetType() == DisplayItemType::TYPE_BLEND_MODE ||
|
||||
i->GetType() == DisplayItemType::TYPE_TABLE_BLEND_MODE)) {
|
||||
// nsDisplayBlendMode always returns LAYER_ACTIVE to ensure that the
|
||||
// blending operation happens in the intermediate surface of its parent
|
||||
// display item (usually an nsDisplayBlendContainer). But this does not
|
||||
|
@ -4136,7 +4136,7 @@ public:
|
||||
|
||||
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
|
||||
|
||||
NS_DISPLAY_DECL_NAME("TableThemedBackground", TYPE_TABLE_BACKGROUND_IMAGE)
|
||||
NS_DISPLAY_DECL_NAME("TableThemedBackground", TYPE_TABLE_THEMED_BACKGROUND_IMAGE)
|
||||
protected:
|
||||
virtual nsIFrame* StyleFrame() const override { return mAncestorFrame; }
|
||||
nsIFrame* mAncestorFrame;
|
||||
@ -5259,7 +5259,7 @@ public:
|
||||
nsDisplayItem::GetPerFrameKey();
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
|
||||
NS_DISPLAY_DECL_NAME("TableBlendMode", TYPE_TABLE_BLEND_MODE)
|
||||
|
||||
protected:
|
||||
nsIFrame* mAncestorFrame;
|
||||
@ -5354,7 +5354,7 @@ public:
|
||||
nsDisplayItem::GetPerFrameKey();
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
|
||||
NS_DISPLAY_DECL_NAME("TableBlendContainer", TYPE_TABLE_BLEND_CONTAINER)
|
||||
|
||||
protected:
|
||||
nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
@ -6680,7 +6680,8 @@ public:
|
||||
|
||||
static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
|
||||
DisplayItemType t = aItem->GetType();
|
||||
return (t == DisplayItemType::TYPE_TEXT)
|
||||
return (t == DisplayItemType::TYPE_TEXT ||
|
||||
t == DisplayItemType::TYPE_SVG_CHAR_CLIP)
|
||||
? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
|
||||
}
|
||||
|
||||
|
@ -2733,7 +2733,7 @@ public:
|
||||
aRun.GetClipEdges(mVisIStartEdge, mVisIEndEdge);
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("SVGText", TYPE_TEXT)
|
||||
NS_DISPLAY_DECL_NAME("SVGCharClip", TYPE_SVG_CHAR_CLIP)
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -249,6 +249,9 @@ void
|
||||
nsHttpConnection::Start0RTTSpdy(uint8_t spdyVersion)
|
||||
{
|
||||
LOG(("nsHttpConnection::Start0RTTSpdy [this=%p]", this));
|
||||
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
mDid0RTTSpdy = true;
|
||||
mUsingSpdyVersion = spdyVersion;
|
||||
mSpdySession = ASpdySession::NewSpdySession(spdyVersion, mSocketTransport,
|
||||
@ -277,6 +280,7 @@ nsHttpConnection::StartSpdy(uint8_t spdyVersion)
|
||||
{
|
||||
LOG(("nsHttpConnection::StartSpdy [this=%p, mDid0RTTSpdy=%d]\n", this, mDid0RTTSpdy));
|
||||
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT(!mSpdySession || mDid0RTTSpdy);
|
||||
|
||||
mUsingSpdyVersion = spdyVersion;
|
||||
@ -2444,6 +2448,7 @@ nsAHttpTransaction *
|
||||
nsHttpConnection::CloseConnectionFastOpenTakesTooLongOrError(bool aCloseSocketTransport)
|
||||
{
|
||||
MOZ_ASSERT(!mCurrentBytesRead);
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
mFastOpenStatus = TFO_FAILED;
|
||||
RefPtr<nsAHttpTransaction> trans;
|
||||
|
@ -4703,10 +4703,15 @@ void
|
||||
nsHttpConnectionMgr::
|
||||
nsHalfOpenSocket::SetFastOpenStatus(uint8_t tfoStatus)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT(mFastOpenInProgress);
|
||||
|
||||
mFastOpenStatus = tfoStatus;
|
||||
mConnectionNegotiatingFastOpen->SetFastOpenStatus(tfoStatus);
|
||||
mConnectionNegotiatingFastOpen->Transaction()->SetFastOpenStatus(tfoStatus);
|
||||
if (mConnectionNegotiatingFastOpen->Transaction()) {
|
||||
// The transaction could already be canceled in the meantime, hence nullified.
|
||||
mConnectionNegotiatingFastOpen->Transaction()->SetFastOpenStatus(tfoStatus);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
x
Reference in New Issue
Block a user