mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Support pre-SSE2 CPUs in JaegerMonkey (bug 696291, r=bhackett).
--HG-- extra : rebase_source : f1f6a1e60b05974533ff39292a0a278fc69fbb0f
This commit is contained in:
parent
8636172c79
commit
5365dca1bc
@ -1678,13 +1678,7 @@ void
|
||||
JSContext::updateJITEnabled()
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
methodJitEnabled = (runOptions & JSOPTION_METHODJIT) &&
|
||||
!IsJITBrokenHere()
|
||||
# if defined JS_CPU_X86 || defined JS_CPU_X64
|
||||
&& JSC::MacroAssemblerX86Common::getSSEState() >=
|
||||
JSC::MacroAssemblerX86Common::HasSSE2
|
||||
# endif
|
||||
;
|
||||
methodJitEnabled = (runOptions & JSOPTION_METHODJIT) && !IsJITBrokenHere();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,9 @@
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/Retcon.h"
|
||||
#ifdef JS_METHODJIT
|
||||
# include "assembler/assembler/MacroAssembler.h"
|
||||
#endif
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsgcinlines.h"
|
||||
@ -1961,8 +1964,13 @@ TypeCompartment::init(JSContext *cx)
|
||||
{
|
||||
PodZero(this);
|
||||
|
||||
if (cx && cx->getRunOptions() & JSOPTION_TYPE_INFERENCE)
|
||||
inferenceEnabled = true;
|
||||
if (cx && cx->getRunOptions() & JSOPTION_TYPE_INFERENCE) {
|
||||
#ifdef JS_METHODJIT
|
||||
JSC::MacroAssembler masm;
|
||||
if (masm.supportsFloatingPoint())
|
||||
#endif
|
||||
inferenceEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
TypeObject *
|
||||
|
@ -638,6 +638,7 @@ private:
|
||||
bool jsop_tableswitch(jsbytecode *pc);
|
||||
|
||||
/* Fast arithmetic. */
|
||||
bool jsop_binary_slow(JSOp op, VoidStub stub, JSValueType type, FrameEntry *lhs, FrameEntry *rhs);
|
||||
bool jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::TypeSet *typeSet);
|
||||
void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub,
|
||||
JSValueType type, bool cannotOverflow, bool ignoreOverflow);
|
||||
|
@ -175,6 +175,21 @@ mjit::Compiler::maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
mjit::Compiler::jsop_binary_slow(JSOp op, VoidStub stub, JSValueType type,
|
||||
FrameEntry *lhs, FrameEntry *rhs)
|
||||
{
|
||||
bool isStringResult = (op == JSOP_ADD) &&
|
||||
(lhs->isType(JSVAL_TYPE_STRING) || rhs->isType(JSVAL_TYPE_STRING));
|
||||
JS_ASSERT_IF(isStringResult && type != JSVAL_TYPE_UNKNOWN, type == JSVAL_TYPE_STRING);
|
||||
|
||||
prepareStubCall(Uses(2));
|
||||
INLINE_STUBCALL(stub, REJOIN_BINARY);
|
||||
frame.popn(2);
|
||||
frame.pushSynced(isStringResult ? JSVAL_TYPE_STRING : type);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
mjit::Compiler::jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::TypeSet *typeSet)
|
||||
{
|
||||
@ -205,16 +220,7 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::Typ
|
||||
(lhs->isTypeKnown() && (lhs->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET)) ||
|
||||
(rhs->isTypeKnown() && (rhs->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET)))
|
||||
{
|
||||
bool isStringResult = (op == JSOP_ADD) &&
|
||||
(lhs->isType(JSVAL_TYPE_STRING) ||
|
||||
rhs->isType(JSVAL_TYPE_STRING));
|
||||
JS_ASSERT_IF(isStringResult && type != JSVAL_TYPE_UNKNOWN, type == JSVAL_TYPE_STRING);
|
||||
|
||||
prepareStubCall(Uses(2));
|
||||
INLINE_STUBCALL(stub, REJOIN_BINARY);
|
||||
frame.popn(2);
|
||||
frame.pushSynced(isStringResult ? JSVAL_TYPE_STRING : type);
|
||||
return true;
|
||||
return jsop_binary_slow(op, stub, type, lhs, rhs);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -238,6 +244,9 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::Typ
|
||||
bool canDoIntMath = op != JSOP_DIV && type != JSVAL_TYPE_DOUBLE &&
|
||||
!(rhs->isType(JSVAL_TYPE_DOUBLE) || lhs->isType(JSVAL_TYPE_DOUBLE));
|
||||
|
||||
if (!masm.supportsFloatingPoint() && (!canDoIntMath || frame.haveSameBacking(lhs, rhs)))
|
||||
return jsop_binary_slow(op, stub, type, lhs, rhs);
|
||||
|
||||
if (canDoIntMath)
|
||||
jsop_binary_full(lhs, rhs, op, stub, type, cannotOverflow, ignoreOverflow);
|
||||
else
|
||||
@ -572,7 +581,7 @@ mjit::Compiler::jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op,
|
||||
|
||||
/* Perform the double addition. */
|
||||
MaybeJump doublePathDone;
|
||||
if (!rhs->isTypeKnown() || lhsUnknownDone.isSet()) {
|
||||
if (masm.supportsFloatingPoint() && (!rhs->isTypeKnown() || !lhs->isTypeKnown())) {
|
||||
/* If the LHS type was not known, link its path here. */
|
||||
if (lhsUnknownDone.isSet())
|
||||
lhsUnknownDone.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
@ -790,7 +799,9 @@ mjit::Compiler::jsop_neg()
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
JSValueType type = knownPushedType(0);
|
||||
|
||||
if (fe->isTypeKnown() && fe->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET) {
|
||||
if ((fe->isTypeKnown() && fe->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET) ||
|
||||
!masm.supportsFloatingPoint())
|
||||
{
|
||||
prepareStubCall(Uses(1));
|
||||
INLINE_STUBCALL(stubs::Neg, REJOIN_FALLTHROUGH);
|
||||
frame.pop();
|
||||
@ -802,7 +813,8 @@ mjit::Compiler::jsop_neg()
|
||||
|
||||
/* Handle negation of a known double, or of a known integer which has previously overflowed. */
|
||||
if (fe->isType(JSVAL_TYPE_DOUBLE) ||
|
||||
(fe->isType(JSVAL_TYPE_INT32) && type == JSVAL_TYPE_DOUBLE)) {
|
||||
(fe->isType(JSVAL_TYPE_INT32) && type == JSVAL_TYPE_DOUBLE))
|
||||
{
|
||||
FPRegisterID fpreg;
|
||||
if (fe->isType(JSVAL_TYPE_DOUBLE)) {
|
||||
fpreg = frame.tempFPRegForData(fe);
|
||||
@ -1309,6 +1321,11 @@ mjit::Compiler::emitLeftDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState:
|
||||
Jump lhsNotInt32 = masm.testInt32(Assembler::NotEqual, regs.lhsType.reg());
|
||||
stubcc.linkExitDirect(lhsNotInt32, stubcc.masm.label());
|
||||
|
||||
if (!masm.supportsFloatingPoint()) {
|
||||
lhsNotDouble = stubcc.masm.jump();
|
||||
return;
|
||||
}
|
||||
|
||||
/* OOL path for LHS as a double - first test LHS is double. */
|
||||
lhsNotDouble = stubcc.masm.testDouble(Assembler::NotEqual, regs.lhsType.reg());
|
||||
|
||||
@ -1354,6 +1371,11 @@ mjit::Compiler::emitRightDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState
|
||||
Jump notInt32 = masm.testInt32(Assembler::NotEqual, regs.rhsType.reg());
|
||||
stubcc.linkExitDirect(notInt32, stubcc.masm.label());
|
||||
|
||||
if (!masm.supportsFloatingPoint()) {
|
||||
rhsNotNumber2 = stubcc.masm.jump();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now test if RHS is a double. */
|
||||
rhsNotNumber2 = stubcc.masm.testDouble(Assembler::NotEqual, regs.rhsType.reg());
|
||||
|
||||
@ -1571,7 +1593,7 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target,
|
||||
|
||||
/* Both double paths will join here. */
|
||||
bool hasDoublePath = false;
|
||||
if (!rhs->isTypeKnown() || lhsUnknownDone.isSet())
|
||||
if (masm.supportsFloatingPoint() && (!rhs->isTypeKnown() || !lhs->isTypeKnown()))
|
||||
hasDoublePath = true;
|
||||
|
||||
/* Integer path - figure out the immutable side. */
|
||||
@ -1612,26 +1634,26 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target,
|
||||
frame.sync(stubcc.masm, Uses(frame.frameSlots()));
|
||||
doubleTest = stubcc.masm.branchDouble(dblCond, regs.lhsFP, regs.rhsFP);
|
||||
doubleFall = stubcc.masm.jump();
|
||||
|
||||
/* Link all incoming slow paths to here. */
|
||||
if (lhsNotDouble.isSet()) {
|
||||
lhsNotDouble.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
if (rhsNotNumber.isSet())
|
||||
rhsNotNumber.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
}
|
||||
if (rhsNotNumber2.isSet())
|
||||
rhsNotNumber2.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
/*
|
||||
* For fusions, spill the tracker state. xmm* remain intact. Note
|
||||
* that frame.sync() must be used directly, to avoid syncExit()'s
|
||||
* jumping logic.
|
||||
*/
|
||||
frame.sync(stubcc.masm, Uses(frame.frameSlots()));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stub, REJOIN_BRANCH);
|
||||
}
|
||||
|
||||
/* Link all incoming slow paths to here. */
|
||||
if (lhsNotDouble.isSet()) {
|
||||
lhsNotDouble.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
if (rhsNotNumber.isSet())
|
||||
rhsNotNumber.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
}
|
||||
if (rhsNotNumber2.isSet())
|
||||
rhsNotNumber2.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
/*
|
||||
* For fusions, spill the tracker state. xmm* remain intact. Note
|
||||
* that frame.sync() must be used directly, to avoid syncExit()'s
|
||||
* jumping logic.
|
||||
*/
|
||||
frame.sync(stubcc.masm, Uses(frame.frameSlots()));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stub, REJOIN_BRANCH);
|
||||
|
||||
/* Forget the world, preserving data. */
|
||||
frame.pinReg(cmpReg);
|
||||
if (reg.isSet())
|
||||
@ -1701,22 +1723,22 @@ mjit::Compiler::jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target,
|
||||
stubcc.masm.move(Imm32(1), regs.result);
|
||||
skip.linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
doubleDone = stubcc.masm.jump();
|
||||
|
||||
/* Link all incoming slow paths to here. */
|
||||
if (lhsNotDouble.isSet()) {
|
||||
lhsNotDouble.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
if (rhsNotNumber.isSet())
|
||||
rhsNotNumber.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
}
|
||||
if (rhsNotNumber2.isSet())
|
||||
rhsNotNumber2.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
/* Emit the slow path - note full frame syncage. */
|
||||
frame.sync(stubcc.masm, Uses(2));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stub, REJOIN_FALLTHROUGH);
|
||||
}
|
||||
|
||||
/* Link all incoming slow paths to here. */
|
||||
if (lhsNotDouble.isSet()) {
|
||||
lhsNotDouble.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
if (rhsNotNumber.isSet())
|
||||
rhsNotNumber.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
}
|
||||
if (rhsNotNumber2.isSet())
|
||||
rhsNotNumber2.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
/* Emit the slow path - note full frame syncage. */
|
||||
frame.sync(stubcc.masm, Uses(2));
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stub, REJOIN_FALLTHROUGH);
|
||||
|
||||
/* Get an integer comparison condition. */
|
||||
Assembler::Condition i32Cond = GetCompareCondition(cmpOp, fused);
|
||||
|
||||
|
@ -101,28 +101,42 @@ mjit::Compiler::ensureInteger(FrameEntry *fe, Uses uses)
|
||||
frame.freeReg(fptemp);
|
||||
frame.learnType(fe, JSVAL_TYPE_INT32, data);
|
||||
} else if (!fe->isType(JSVAL_TYPE_INT32)) {
|
||||
FPRegisterID fptemp = frame.allocFPReg();
|
||||
RegisterID typeReg = frame.tempRegForType(fe);
|
||||
frame.pinReg(typeReg);
|
||||
RegisterID dataReg = frame.copyDataIntoReg(fe);
|
||||
frame.unpinReg(typeReg);
|
||||
if (masm.supportsFloatingPoint()) {
|
||||
FPRegisterID fptemp = frame.allocFPReg();
|
||||
RegisterID typeReg = frame.tempRegForType(fe);
|
||||
frame.pinReg(typeReg);
|
||||
RegisterID dataReg = frame.copyDataIntoReg(fe);
|
||||
frame.unpinReg(typeReg);
|
||||
|
||||
Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg);
|
||||
Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg);
|
||||
|
||||
Label syncPath = stubcc.syncExitAndJump(uses);
|
||||
stubcc.linkExitDirect(intGuard, stubcc.masm.label());
|
||||
Label syncPath = stubcc.syncExitAndJump(uses);
|
||||
stubcc.linkExitDirect(intGuard, stubcc.masm.label());
|
||||
|
||||
/* Try an OOL path to truncate doubles representing int32s. */
|
||||
Jump doubleGuard = stubcc.masm.testDouble(Assembler::NotEqual, typeReg);
|
||||
doubleGuard.linkTo(syncPath, &stubcc.masm);
|
||||
/* Try an OOL path to truncate doubles representing int32s. */
|
||||
Jump doubleGuard = stubcc.masm.testDouble(Assembler::NotEqual, typeReg);
|
||||
doubleGuard.linkTo(syncPath, &stubcc.masm);
|
||||
|
||||
frame.loadDouble(fe, fptemp, stubcc.masm);
|
||||
Jump truncateGuard = stubcc.masm.branchTruncateDoubleToInt32(fptemp, dataReg);
|
||||
truncateGuard.linkTo(syncPath, &stubcc.masm);
|
||||
stubcc.crossJump(stubcc.masm.jump(), masm.label());
|
||||
frame.loadDouble(fe, fptemp, stubcc.masm);
|
||||
Jump truncateGuard = stubcc.masm.branchTruncateDoubleToInt32(fptemp, dataReg);
|
||||
truncateGuard.linkTo(syncPath, &stubcc.masm);
|
||||
stubcc.crossJump(stubcc.masm.jump(), masm.label());
|
||||
|
||||
frame.freeReg(fptemp);
|
||||
frame.learnType(fe, JSVAL_TYPE_INT32, dataReg);
|
||||
frame.freeReg(fptemp);
|
||||
frame.learnType(fe, JSVAL_TYPE_INT32, dataReg);
|
||||
} else {
|
||||
RegisterID typeReg = frame.tempRegForType(fe);
|
||||
frame.pinReg(typeReg);
|
||||
RegisterID dataReg = frame.copyDataIntoReg(fe);
|
||||
frame.unpinReg(typeReg);
|
||||
|
||||
Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg);
|
||||
|
||||
Label syncPath = stubcc.syncExitAndJump(uses);
|
||||
stubcc.linkExitDirect(intGuard, syncPath);
|
||||
|
||||
frame.learnType(fe, JSVAL_TYPE_INT32, dataReg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,6 +576,8 @@ mjit::Compiler::jsop_relational(JSOp op, BoolStub stub,
|
||||
} else if (lhs->isType(JSVAL_TYPE_STRING) || rhs->isType(JSVAL_TYPE_STRING)) {
|
||||
return emitStubCmpOp(stub, target, fused);
|
||||
} else if (lhs->isType(JSVAL_TYPE_DOUBLE) || rhs->isType(JSVAL_TYPE_DOUBLE)) {
|
||||
if (!masm.supportsFloatingPoint())
|
||||
return emitStubCmpOp(stub, target, fused);
|
||||
return jsop_relational_double(op, stub, target, fused);
|
||||
} else if (cx->typeInferenceEnabled() &&
|
||||
lhs->isType(JSVAL_TYPE_INT32) && rhs->isType(JSVAL_TYPE_INT32)) {
|
||||
|
@ -1530,10 +1530,12 @@ FrameState::merge(Assembler &masm, Changes changes) const
|
||||
* do not require stub paths to always generate a double when needed.
|
||||
* :FIXME: we check this on OOL stub calls, but not inline stub calls.
|
||||
*/
|
||||
for (unsigned i = 0; i < changes.nchanges; i++) {
|
||||
FrameEntry *fe = a->sp - 1 - i;
|
||||
if (fe->isTracked() && fe->isType(JSVAL_TYPE_DOUBLE))
|
||||
masm.ensureInMemoryDouble(addressOf(fe));
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
for (unsigned i = 0; i < changes.nchanges; i++) {
|
||||
FrameEntry *fe = a->sp - 1 - i;
|
||||
if (fe->isTracked() && fe->isType(JSVAL_TYPE_DOUBLE))
|
||||
masm.ensureInMemoryDouble(addressOf(fe));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mask = Registers::AvailAnyRegs & ~freeRegs.freeMask;
|
||||
|
@ -2537,6 +2537,14 @@ GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid i
|
||||
: Int32Key::FromRegister(idRemat.dataReg());
|
||||
|
||||
JSObject *tarray = js::TypedArray::getTypedArray(obj);
|
||||
if (!masm.supportsFloatingPoint() &&
|
||||
(TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 ||
|
||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64 ||
|
||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT32))
|
||||
{
|
||||
return disable(cx, "fpu not supported");
|
||||
}
|
||||
|
||||
MaybeRegisterID tempReg;
|
||||
masm.loadFromTypedArray(TypedArray::getType(tarray), objReg, key, typeReg, objReg, tempReg);
|
||||
|
||||
@ -2829,6 +2837,13 @@ SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32_t key)
|
||||
masm.loadPtr(Address(objReg, TypedArray::dataOffset()), objReg);
|
||||
|
||||
JSObject *tarray = js::TypedArray::getTypedArray(obj);
|
||||
if (!masm.supportsFloatingPoint() &&
|
||||
(TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 ||
|
||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64))
|
||||
{
|
||||
return disable(cx, "fpu not supported");
|
||||
}
|
||||
|
||||
int shift = js::TypedArray::slotWidth(obj);
|
||||
if (hasConstantKey) {
|
||||
Address addr(objReg, keyValue * shift);
|
||||
|
Loading…
Reference in New Issue
Block a user