Bug 1526870 - Part 15: Use AutoCallVM for additional CacheIR emitters. r=jandem

Use a single implementation in CacheIRCompiler.cpp for CacheIR emitters which
can be updated to the changed AutoCallVM class.

Differential Revision: https://phabricator.services.mozilla.com/D49922

--HG--
extra : moz-landing-system : lando
This commit is contained in:
André Bargull 2019-10-31 13:23:43 +00:00
parent 9e6e95098a
commit 18c6d4b6e2
6 changed files with 287 additions and 598 deletions

View File

@ -2102,30 +2102,6 @@ uint8_t* ICCacheIR_Updated::stubDataStart() {
return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
}
bool BaselineCacheIRCompiler::emitCallStringConcatResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.push(rhs);
masm.push(lhs);
using Fn = JSString* (*)(JSContext*, HandleString, HandleString);
callVM<Fn, ConcatStrings<CanGC>>(masm);
masm.tagValue(JSVAL_TYPE_STRING, ReturnReg, output.valueReg());
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitCallStringObjectConcatResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
ValueOperand lhs = allocator.useValueRegister(masm, reader.valOperandId());
@ -2147,283 +2123,6 @@ bool BaselineCacheIRCompiler::emitCallStringObjectConcatResult() {
return true;
}
template <typename CallVM>
bool BaselineCacheIRCompiler::emitBigIntBinaryOperationShared(
const CallVM& emitCallVM) {
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.push(rhs);
masm.push(lhs);
emitCallVM();
masm.tagValue(JSVAL_TYPE_BIGINT, ReturnReg, output.valueReg());
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitBigIntAddResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntAdd>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntSubResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntSub>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntMulResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntMul>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntDivResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntDiv>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntModResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntMod>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntPowResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntPow>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntBitAndResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitAnd>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntBitOrResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitOr>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntBitXorResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitXor>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntLeftShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntLeftShift>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntRightShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntRightShift>(masm);
});
}
template <typename CallVM>
bool BaselineCacheIRCompiler::emitBigIntUnaryOperationShared(
const CallVM& emitCallVM) {
AutoOutputRegister output(*this);
Register val = allocator.useRegister(masm, reader.bigIntOperandId());
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.push(val);
emitCallVM();
masm.tagValue(JSVAL_TYPE_BIGINT, ReturnReg, output.valueReg());
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitBigIntNotResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntBitNot>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntNegationResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntNeg>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntIncResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntInc>(masm);
});
}
bool BaselineCacheIRCompiler::emitBigIntDecResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntDec>(masm);
});
}
bool BaselineCacheIRCompiler::emitCompareBigIntStringResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
JSOp op = reader.jsop();
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
if (op == JSOP_LE || op == JSOP_GT) {
masm.Push(lhs);
masm.Push(rhs);
} else {
masm.Push(rhs);
masm.Push(lhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
if (op == JSOP_EQ) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::Equal>>(masm);
} else if (op == JSOP_NE) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::NotEqual>>(
masm);
} else if (op == JSOP_LT) {
callVM<FnBigIntString, jit::BigIntStringCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_GT) {
callVM<FnStringBigInt, jit::StringBigIntCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_LE) {
callVM<FnStringBigInt,
jit::StringBigIntCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
} else {
MOZ_ASSERT(op == JSOP_GE);
callVM<FnBigIntString,
jit::BigIntStringCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
}
stubFrame.leave(masm);
masm.tagValue(JSVAL_TYPE_BOOLEAN, ReturnReg, output.valueReg());
return true;
}
bool BaselineCacheIRCompiler::emitCompareStringBigIntResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
JSOp op = reader.jsop();
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
// Also push the operands in reverse order for JSOP_EQ and JSOP_NE.
if (op == JSOP_LT || op == JSOP_GE) {
masm.Push(rhs);
masm.Push(lhs);
} else {
masm.Push(lhs);
masm.Push(rhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
if (op == JSOP_EQ) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::Equal>>(masm);
} else if (op == JSOP_NE) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::NotEqual>>(
masm);
} else if (op == JSOP_LT) {
callVM<FnStringBigInt, jit::StringBigIntCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_GT) {
callVM<FnBigIntString, jit::BigIntStringCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_LE) {
callVM<FnBigIntString,
jit::BigIntStringCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
} else {
MOZ_ASSERT(op == JSOP_GE);
callVM<FnStringBigInt,
jit::StringBigIntCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
}
stubFrame.leave(masm);
masm.tagValue(JSVAL_TYPE_BOOLEAN, ReturnReg, output.valueReg());
return true;
}
// The value of argc entering the call IC is not always the value of
// argc entering the callee. (For example, argc for a spread call IC
// is always 1, but argc for the callee is the length of the array.)

View File

@ -71,12 +71,6 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler {
MOZ_MUST_USE bool emitCallNativeGetterResultShared(T receiver,
const CallVM& emitCallVM);
template <typename CallVM>
MOZ_MUST_USE bool emitBigIntBinaryOperationShared(const CallVM& emitCallVM);
template <typename CallVM>
MOZ_MUST_USE bool emitBigIntUnaryOperationShared(const CallVM& emitCallVM);
public:
friend class AutoStubFrame;

View File

@ -2748,6 +2748,124 @@ bool CacheIRCompiler::emitDoubleDecResult() {
return emitDoubleIncDecResult(false);
}
template <typename Fn, Fn fn>
bool CacheIRCompiler::emitBigIntBinaryOperationShared() {
AutoCallVM callvm(masm, this, allocator);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
callvm.prepare();
masm.Push(rhs);
masm.Push(lhs);
callvm.call<Fn, fn>();
return true;
}
bool CacheIRCompiler::emitBigIntAddResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntAdd>();
}
bool CacheIRCompiler::emitBigIntSubResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntSub>();
}
bool CacheIRCompiler::emitBigIntMulResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntMul>();
}
bool CacheIRCompiler::emitBigIntDivResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntDiv>();
}
bool CacheIRCompiler::emitBigIntModResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntMod>();
}
bool CacheIRCompiler::emitBigIntPowResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntPow>();
}
bool CacheIRCompiler::emitBigIntBitAndResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntBitAnd>();
}
bool CacheIRCompiler::emitBigIntBitOrResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntBitOr>();
}
bool CacheIRCompiler::emitBigIntBitXorResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntBitXor>();
}
bool CacheIRCompiler::emitBigIntLeftShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntLeftShift>();
}
bool CacheIRCompiler::emitBigIntRightShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
return emitBigIntBinaryOperationShared<Fn, jit::BigIntRightShift>();
}
template <typename Fn, Fn fn>
bool CacheIRCompiler::emitBigIntUnaryOperationShared() {
AutoCallVM callvm(masm, this, allocator);
Register val = allocator.useRegister(masm, reader.bigIntOperandId());
callvm.prepare();
masm.Push(val);
callvm.call<Fn, fn>();
return true;
}
bool CacheIRCompiler::emitBigIntNotResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
return emitBigIntUnaryOperationShared<Fn, jit::BigIntBitNot>();
}
bool CacheIRCompiler::emitBigIntNegationResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
return emitBigIntUnaryOperationShared<Fn, jit::BigIntNeg>();
}
bool CacheIRCompiler::emitBigIntIncResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
return emitBigIntUnaryOperationShared<Fn, jit::BigIntInc>();
}
bool CacheIRCompiler::emitBigIntDecResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
return emitBigIntUnaryOperationShared<Fn, jit::BigIntDec>();
}
bool CacheIRCompiler::emitTruncateDoubleToUInt32() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
@ -4476,6 +4594,133 @@ bool CacheIRCompiler::emitCompareNumberBigIntResult() {
return true;
}
bool CacheIRCompiler::emitCompareBigIntStringResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
JSOp op = reader.jsop();
callvm.prepare();
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
if (op == JSOP_LE || op == JSOP_GT) {
masm.Push(lhs);
masm.Push(rhs);
} else {
masm.Push(rhs);
masm.Push(lhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
switch (op) {
case JSOP_EQ: {
constexpr auto Equal = EqualityKind::Equal;
callvm.call<FnBigIntString, BigIntStringEqual<Equal>>();
break;
}
case JSOP_NE: {
constexpr auto NotEqual = EqualityKind::NotEqual;
callvm.call<FnBigIntString, BigIntStringEqual<NotEqual>>();
break;
}
case JSOP_LT: {
constexpr auto LessThan = ComparisonKind::LessThan;
callvm.call<FnBigIntString, BigIntStringCompare<LessThan>>();
break;
}
case JSOP_GT: {
constexpr auto LessThan = ComparisonKind::LessThan;
callvm.call<FnStringBigInt, StringBigIntCompare<LessThan>>();
break;
}
case JSOP_LE: {
constexpr auto GreaterThanOrEqual = ComparisonKind::GreaterThanOrEqual;
callvm.call<FnStringBigInt, StringBigIntCompare<GreaterThanOrEqual>>();
break;
}
case JSOP_GE: {
constexpr auto GreaterThanOrEqual = ComparisonKind::GreaterThanOrEqual;
callvm.call<FnBigIntString, BigIntStringCompare<GreaterThanOrEqual>>();
break;
}
default:
MOZ_CRASH("unhandled op");
}
return true;
}
bool CacheIRCompiler::emitCompareStringBigIntResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
JSOp op = reader.jsop();
callvm.prepare();
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
// Also push the operands in reverse order for JSOP_EQ and JSOP_NE.
if (op == JSOP_LT || op == JSOP_GE) {
masm.Push(rhs);
masm.Push(lhs);
} else {
masm.Push(lhs);
masm.Push(rhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
switch (op) {
case JSOP_EQ: {
constexpr auto Equal = EqualityKind::Equal;
callvm.call<FnBigIntString, BigIntStringEqual<Equal>>();
break;
}
case JSOP_NE: {
constexpr auto NotEqual = EqualityKind::NotEqual;
callvm.call<FnBigIntString, BigIntStringEqual<NotEqual>>();
break;
}
case JSOP_LT: {
constexpr auto LessThan = ComparisonKind::LessThan;
callvm.call<FnStringBigInt, StringBigIntCompare<LessThan>>();
break;
}
case JSOP_GT: {
constexpr auto LessThan = ComparisonKind::LessThan;
callvm.call<FnBigIntString, BigIntStringCompare<LessThan>>();
break;
}
case JSOP_LE: {
constexpr auto GreaterThanOrEqual = ComparisonKind::GreaterThanOrEqual;
callvm.call<FnBigIntString, BigIntStringCompare<GreaterThanOrEqual>>();
break;
}
case JSOP_GE: {
constexpr auto GreaterThanOrEqual = ComparisonKind::GreaterThanOrEqual;
callvm.call<FnStringBigInt, StringBigIntCompare<GreaterThanOrEqual>>();
break;
}
default:
MOZ_CRASH("unhandled op");
}
return true;
}
bool CacheIRCompiler::emitCompareObjectUndefinedNullResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoOutputRegister output(*this);
@ -5190,6 +5435,24 @@ void js::jit::LoadTypedThingLength(MacroAssembler& masm,
}
}
bool CacheIRCompiler::emitCallStringConcatResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
callvm.prepare();
masm.Push(rhs);
masm.Push(lhs);
using Fn = JSString* (*)(JSContext*, HandleString, HandleString);
callvm.call<Fn, ConcatStrings<CanGC>>();
return true;
}
bool CacheIRCompiler::emitCallIsSuspendedGeneratorResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoOutputRegister output(*this);
@ -5242,8 +5505,6 @@ bool CacheIRCompiler::emitCallNativeGetElementResult() {
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
allocator.discardStack(masm);
callvm.prepare();
masm.Push(index);

View File

@ -100,6 +100,21 @@ class IonCacheIRCompiler;
_(DoubleIncResult) \
_(DoubleDecResult) \
_(DoubleNegationResult) \
_(BigIntAddResult) \
_(BigIntSubResult) \
_(BigIntMulResult) \
_(BigIntDivResult) \
_(BigIntModResult) \
_(BigIntPowResult) \
_(BigIntBitOrResult) \
_(BigIntBitXorResult) \
_(BigIntBitAndResult) \
_(BigIntLeftShiftResult) \
_(BigIntRightShiftResult) \
_(BigIntNegationResult) \
_(BigIntNotResult) \
_(BigIntIncResult) \
_(BigIntDecResult) \
_(TruncateDoubleToUInt32) \
_(LoadArgumentsObjectLengthResult) \
_(LoadFunctionLengthResult) \
@ -131,6 +146,8 @@ class IonCacheIRCompiler;
_(CompareInt32BigIntResult) \
_(CompareBigIntNumberResult) \
_(CompareNumberBigIntResult) \
_(CompareBigIntStringResult) \
_(CompareStringBigIntResult) \
_(CompareObjectUndefinedNullResult) \
_(ArrayJoinResult) \
_(StoreTypedElement) \
@ -145,6 +162,7 @@ class IonCacheIRCompiler;
_(CallInt32ToString) \
_(CallNumberToString) \
_(BooleanToString) \
_(CallStringConcatResult) \
_(CallIsSuspendedGeneratorResult) \
_(CallNativeGetElementResult) \
_(CallProxyHasPropResult) \
@ -906,6 +924,12 @@ class MOZ_RAII CacheIRCompiler {
JSOp op,
const AutoOutputRegister& output);
template <typename Fn, Fn fn>
MOZ_MUST_USE bool emitBigIntBinaryOperationShared();
template <typename Fn, Fn fn>
MOZ_MUST_USE bool emitBigIntUnaryOperationShared();
bool emitDoubleIncDecResult(bool isInc);
#define DEFINE_SHARED_OP(op) MOZ_MUST_USE bool emit##op();

View File

@ -2279,28 +2279,6 @@ void IonIC::attachCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
*attached = true;
}
bool IonCacheIRCompiler::emitCallStringConcatResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(rhs);
masm.Push(lhs);
using Fn = JSString* (*)(JSContext*, HandleString, HandleString);
callVM<Fn, ConcatStrings<CanGC>>(masm);
masm.tagValue(JSVAL_TYPE_STRING, ReturnReg, output.valueReg());
return true;
}
bool IonCacheIRCompiler::emitCallStringObjectConcatResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
@ -2322,267 +2300,6 @@ bool IonCacheIRCompiler::emitCallStringObjectConcatResult() {
return true;
}
template <typename CallVM>
bool IonCacheIRCompiler::emitBigIntBinaryOperationShared(
const CallVM& emitCallVM) {
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(rhs);
masm.Push(lhs);
emitCallVM();
masm.tagValue(JSVAL_TYPE_BIGINT, ReturnReg, output.valueReg());
return true;
}
bool IonCacheIRCompiler::emitBigIntAddResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntAdd>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntSubResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntSub>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntMulResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntMul>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntDivResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntDiv>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntModResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntMod>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntPowResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntPow>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntBitAndResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitAnd>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntBitOrResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitOr>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntBitXorResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntBitXor>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntLeftShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntLeftShift>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntRightShiftResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntBinaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt, HandleBigInt);
callVM<Fn, jit::BigIntRightShift>(masm);
});
}
template <typename CallVM>
bool IonCacheIRCompiler::emitBigIntUnaryOperationShared(
const CallVM& emitCallVM) {
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register val = allocator.useRegister(masm, reader.bigIntOperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(val);
emitCallVM();
masm.tagValue(JSVAL_TYPE_BIGINT, ReturnReg, output.valueReg());
return true;
}
bool IonCacheIRCompiler::emitBigIntNotResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntBitNot>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntNegationResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntNeg>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntIncResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntInc>(masm);
});
}
bool IonCacheIRCompiler::emitBigIntDecResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
return emitBigIntUnaryOperationShared([&]() {
using Fn = BigInt* (*)(JSContext*, HandleBigInt);
callVM<Fn, jit::BigIntDec>(masm);
});
}
bool IonCacheIRCompiler::emitCompareBigIntStringResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.bigIntOperandId());
Register rhs = allocator.useRegister(masm, reader.stringOperandId());
JSOp op = reader.jsop();
allocator.discardStack(masm);
prepareVMCall(masm, save);
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
if (op == JSOP_LE || op == JSOP_GT) {
masm.Push(lhs);
masm.Push(rhs);
} else {
masm.Push(rhs);
masm.Push(lhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
if (op == JSOP_EQ) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::Equal>>(masm);
} else if (op == JSOP_NE) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::NotEqual>>(
masm);
} else if (op == JSOP_LT) {
callVM<FnBigIntString, jit::BigIntStringCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_GT) {
callVM<FnStringBigInt, jit::StringBigIntCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_LE) {
callVM<FnStringBigInt,
jit::StringBigIntCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
} else {
MOZ_ASSERT(op == JSOP_GE);
callVM<FnBigIntString,
jit::BigIntStringCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
}
masm.storeCallBoolResult(output.typedReg().gpr());
return true;
}
bool IonCacheIRCompiler::emitCompareStringBigIntResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register lhs = allocator.useRegister(masm, reader.stringOperandId());
Register rhs = allocator.useRegister(masm, reader.bigIntOperandId());
JSOp op = reader.jsop();
allocator.discardStack(masm);
prepareVMCall(masm, save);
// Push the operands in reverse order for JSOP_LE and JSOP_GT:
// - |left <= right| is implemented as |right >= left|.
// - |left > right| is implemented as |right < left|.
// Also push the operands in reverse order for JSOP_EQ and JSOP_NE.
if (op == JSOP_LT || op == JSOP_GE) {
masm.Push(rhs);
masm.Push(lhs);
} else {
masm.Push(lhs);
masm.Push(rhs);
}
using FnBigIntString =
bool (*)(JSContext*, HandleBigInt, HandleString, bool*);
using FnStringBigInt =
bool (*)(JSContext*, HandleString, HandleBigInt, bool*);
if (op == JSOP_EQ) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::Equal>>(masm);
} else if (op == JSOP_NE) {
callVM<FnBigIntString, jit::BigIntStringEqual<EqualityKind::NotEqual>>(
masm);
} else if (op == JSOP_LT) {
callVM<FnStringBigInt, jit::StringBigIntCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_GT) {
callVM<FnBigIntString, jit::BigIntStringCompare<ComparisonKind::LessThan>>(
masm);
} else if (op == JSOP_LE) {
callVM<FnBigIntString,
jit::BigIntStringCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
} else {
MOZ_ASSERT(op == JSOP_GE);
callVM<FnStringBigInt,
jit::StringBigIntCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
}
masm.storeCallBoolResult(output.typedReg().gpr());
return true;
}
bool IonCacheIRCompiler::emitCallScriptedFunction() {
MOZ_CRASH("Call ICs not used in ion");
}

View File

@ -67,12 +67,6 @@ class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
TypedOrValueRegister receiver, const AutoOutputRegister& output,
AutoSaveLiveRegisters& save);
template <typename CallVM>
MOZ_MUST_USE bool emitBigIntBinaryOperationShared(const CallVM& emitCallVM);
template <typename CallVM>
MOZ_MUST_USE bool emitBigIntUnaryOperationShared(const CallVM& emitCallVM);
bool needsPostBarrier() const;
void pushStubCodePointer();