зеркало из https://github.com/mozilla/gecko-dev.git
Bug 915495 - Support float32 optimization in typed array SetElem ICs. (r=bbouvier)
This commit is contained in:
Родитель
8c051beff7
Коммит
bd9a5ad153
|
@ -0,0 +1,23 @@
|
|||
function testFloat32SetElemIC(a) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var r = Math.fround(Math.random());
|
||||
a[i] = r;
|
||||
assertEq(a[i], r);
|
||||
}
|
||||
}
|
||||
|
||||
function testCompoundClamping(a, b) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var r = Math.random();
|
||||
a[i] = b[i] = r;
|
||||
assertEq(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
testFloat32SetElemIC(new Array(2048));
|
||||
testFloat32SetElemIC(new Float64Array(2048));
|
||||
testFloat32SetElemIC(new Float32Array(2048));
|
||||
|
||||
testCompoundClamping(new Array(2048), new Array(2048));
|
||||
testCompoundClamping(new Uint8Array(2048), new Uint8Array(2048));
|
||||
testCompoundClamping(new Uint8ClampedArray(2048), new Uint8ClampedArray(2048));
|
|
@ -20,6 +20,7 @@
|
|||
#include "jit/ExecutionModeInlines.h"
|
||||
#include "jit/IonLinker.h"
|
||||
#include "jit/IonSpewer.h"
|
||||
#include "jit/Lowering.h"
|
||||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MoveEmitter.h"
|
||||
#include "jit/ParallelFunctions.h"
|
||||
|
@ -5754,55 +5755,58 @@ CodeGenerator::link()
|
|||
return true;
|
||||
}
|
||||
|
||||
// An out-of-line path to convert a boxed int32 to a double.
|
||||
class OutOfLineUnboxDouble : public OutOfLineCodeBase<CodeGenerator>
|
||||
// An out-of-line path to convert a boxed int32 to either a float or double.
|
||||
class OutOfLineUnboxFloatingPoint : public OutOfLineCodeBase<CodeGenerator>
|
||||
{
|
||||
LUnboxDouble *unboxDouble_;
|
||||
LUnboxFloatingPoint *unboxFloatingPoint_;
|
||||
|
||||
public:
|
||||
OutOfLineUnboxDouble(LUnboxDouble *unboxDouble)
|
||||
: unboxDouble_(unboxDouble)
|
||||
OutOfLineUnboxFloatingPoint(LUnboxFloatingPoint *unboxFloatingPoint)
|
||||
: unboxFloatingPoint_(unboxFloatingPoint)
|
||||
{ }
|
||||
|
||||
bool accept(CodeGenerator *codegen) {
|
||||
return codegen->visitOutOfLineUnboxDouble(this);
|
||||
return codegen->visitOutOfLineUnboxFloatingPoint(this);
|
||||
}
|
||||
|
||||
LUnboxDouble *unboxDouble() const {
|
||||
return unboxDouble_;
|
||||
LUnboxFloatingPoint *unboxFloatingPoint() const {
|
||||
return unboxFloatingPoint_;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
CodeGenerator::visitUnboxDouble(LUnboxDouble *lir)
|
||||
CodeGenerator::visitUnboxFloatingPoint(LUnboxFloatingPoint *lir)
|
||||
{
|
||||
const ValueOperand box = ToValue(lir, LUnboxDouble::Input);
|
||||
const ValueOperand box = ToValue(lir, LUnboxFloatingPoint::Input);
|
||||
const LDefinition *result = lir->output();
|
||||
|
||||
// Out-of-line path to convert int32 to double or bailout
|
||||
// if this instruction is fallible.
|
||||
OutOfLineUnboxDouble *ool = new OutOfLineUnboxDouble(lir);
|
||||
OutOfLineUnboxFloatingPoint *ool = new OutOfLineUnboxFloatingPoint(lir);
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
FloatRegister resultReg = ToFloatRegister(result);
|
||||
masm.branchTestDouble(Assembler::NotEqual, box, ool->entry());
|
||||
masm.unboxDouble(box, ToFloatRegister(result));
|
||||
masm.unboxDouble(box, resultReg);
|
||||
if (lir->type() == MIRType_Float32)
|
||||
masm.convertDoubleToFloat(resultReg, resultReg);
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool)
|
||||
CodeGenerator::visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool)
|
||||
{
|
||||
LUnboxDouble *ins = ool->unboxDouble();
|
||||
const ValueOperand value = ToValue(ins, LUnboxDouble::Input);
|
||||
LUnboxFloatingPoint *ins = ool->unboxFloatingPoint();
|
||||
const ValueOperand value = ToValue(ins, LUnboxFloatingPoint::Input);
|
||||
|
||||
if (ins->mir()->fallible()) {
|
||||
Assembler::Condition cond = masm.testInt32(Assembler::NotEqual, value);
|
||||
if (!bailoutIf(cond, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
masm.int32ValueToDouble(value, ToFloatRegister(ins->output()));
|
||||
masm.int32ValueToFloatingPoint(value, ToFloatRegister(ins->output()), ins->type());
|
||||
masm.jump(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
@ -6700,7 +6704,9 @@ template <typename T>
|
|||
static inline void
|
||||
StoreToTypedArray(MacroAssembler &masm, int arrayType, const LAllocation *value, const T &dest)
|
||||
{
|
||||
if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 || arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) {
|
||||
if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 ||
|
||||
arrayType == ScalarTypeRepresentation::TYPE_FLOAT64)
|
||||
{
|
||||
masm.storeToTypedFloatArray(arrayType, ToFloatRegister(value), dest);
|
||||
} else {
|
||||
if (value->isConstant())
|
||||
|
|
|
@ -30,7 +30,7 @@ class CheckOverRecursedFailure;
|
|||
class CheckOverRecursedFailurePar;
|
||||
class OutOfLineCheckInterruptPar;
|
||||
class OutOfLineInterruptCheckImplicit;
|
||||
class OutOfLineUnboxDouble;
|
||||
class OutOfLineUnboxFloatingPoint;
|
||||
class OutOfLineStoreElementHole;
|
||||
class OutOfLineTypeOfV;
|
||||
class OutOfLineLoadTypedArray;
|
||||
|
@ -272,8 +272,8 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitInterruptCheckImplicit(LInterruptCheckImplicit *ins);
|
||||
bool visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ins);
|
||||
|
||||
bool visitUnboxDouble(LUnboxDouble *lir);
|
||||
bool visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool);
|
||||
bool visitUnboxFloatingPoint(LUnboxFloatingPoint *lir);
|
||||
bool visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool);
|
||||
bool visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool);
|
||||
|
||||
bool visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool);
|
||||
|
|
|
@ -3402,9 +3402,11 @@ GenerateSetTypedArrayElement(JSContext *cx, MacroAssembler &masm, IonCache::Stub
|
|||
int width = TypedArrayObject::slotWidth(arrayType);
|
||||
BaseIndex target(elements, index, ScaleFromElemWidth(width));
|
||||
|
||||
if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32 ||
|
||||
arrayType == ScalarTypeRepresentation::TYPE_FLOAT64)
|
||||
{
|
||||
if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT32) {
|
||||
if (!masm.convertConstantOrRegisterToFloat(cx, value, tempFloat, &failures))
|
||||
return false;
|
||||
masm.storeToTypedFloatArray(arrayType, tempFloat, target);
|
||||
} else if (arrayType == ScalarTypeRepresentation::TYPE_FLOAT64) {
|
||||
if (!masm.convertConstantOrRegisterToDouble(cx, value, tempFloat, &failures))
|
||||
return false;
|
||||
masm.storeToTypedFloatArray(arrayType, tempFloat, target);
|
||||
|
|
|
@ -305,7 +305,8 @@ MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register &re
|
|||
|
||||
template<typename S, typename T>
|
||||
static void
|
||||
StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, const T &dest) {
|
||||
StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, const T &dest)
|
||||
{
|
||||
switch (arrayType) {
|
||||
case ScalarTypeRepresentation::TYPE_FLOAT32:
|
||||
if (LIRGenerator::allowFloat32Optimizations()) {
|
||||
|
@ -331,10 +332,16 @@ StoreToTypedFloatArray(MacroAssembler &masm, int arrayType, const S &value, cons
|
|||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, const BaseIndex &dest) {
|
||||
void
|
||||
MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value,
|
||||
const BaseIndex &dest)
|
||||
{
|
||||
StoreToTypedFloatArray(*this, arrayType, value, dest);
|
||||
}
|
||||
void MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value, const Address &dest) {
|
||||
void
|
||||
MacroAssembler::storeToTypedFloatArray(int arrayType, const FloatRegister &value,
|
||||
const Address &dest)
|
||||
{
|
||||
StoreToTypedFloatArray(*this, arrayType, value, dest);
|
||||
}
|
||||
|
||||
|
@ -1374,9 +1381,13 @@ MacroAssembler::convertInt32ValueToDouble(const Address &address, Register scrat
|
|||
|
||||
static const double DoubleZero = 0.0;
|
||||
static const double DoubleOne = 1.0;
|
||||
static const float FloatZero = 0.0;
|
||||
static const float FloatOne = 1.0;
|
||||
static const float FloatNaN = js_NaN;
|
||||
|
||||
void
|
||||
MacroAssembler::convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail)
|
||||
MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister output,
|
||||
Label *fail, MIRType outputType)
|
||||
{
|
||||
Register tag = splitTagForTest(value);
|
||||
|
||||
|
@ -1389,28 +1400,31 @@ MacroAssembler::convertValueToDouble(ValueOperand value, FloatRegister output, L
|
|||
branchTestUndefined(Assembler::NotEqual, tag, fail);
|
||||
|
||||
// fall-through: undefined
|
||||
loadStaticDouble(&js_NaN, output);
|
||||
loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType);
|
||||
jump(&done);
|
||||
|
||||
bind(&isNull);
|
||||
loadStaticDouble(&DoubleZero, output);
|
||||
loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType);
|
||||
jump(&done);
|
||||
|
||||
bind(&isBool);
|
||||
boolValueToDouble(value, output);
|
||||
boolValueToFloatingPoint(value, output, outputType);
|
||||
jump(&done);
|
||||
|
||||
bind(&isInt32);
|
||||
int32ValueToDouble(value, output);
|
||||
int32ValueToFloatingPoint(value, output, outputType);
|
||||
jump(&done);
|
||||
|
||||
bind(&isDouble);
|
||||
unboxDouble(value, output);
|
||||
if (outputType == MIRType_Float32)
|
||||
convertDoubleToFloat(output, output);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
bool
|
||||
MacroAssembler::convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail)
|
||||
MacroAssembler::convertValueToFloatingPoint(JSContext *cx, const Value &v, FloatRegister output,
|
||||
Label *fail, MIRType outputType)
|
||||
{
|
||||
if (v.isNumber() || v.isString()) {
|
||||
double d;
|
||||
|
@ -1420,28 +1434,28 @@ MacroAssembler::convertValueToDouble(JSContext *cx, const Value &v, FloatRegiste
|
|||
return false;
|
||||
|
||||
if (d == js_NaN)
|
||||
loadStaticDouble(&js_NaN, output);
|
||||
loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType);
|
||||
else
|
||||
loadConstantDouble(d, output);
|
||||
loadConstantFloatingPoint(d, static_cast<float>(d), output, outputType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (v.isBoolean()) {
|
||||
if (v.toBoolean())
|
||||
loadStaticDouble(&DoubleOne, output);
|
||||
loadStaticFloatingPoint(&DoubleOne, &FloatOne, output, outputType);
|
||||
else
|
||||
loadStaticDouble(&DoubleZero, output);
|
||||
loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (v.isNull()) {
|
||||
loadStaticDouble(&DoubleZero, output);
|
||||
loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (v.isUndefined()) {
|
||||
loadStaticDouble(&js_NaN, output);
|
||||
loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1490,43 +1504,59 @@ MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg,
|
|||
}
|
||||
|
||||
bool
|
||||
MacroAssembler::convertConstantOrRegisterToDouble(JSContext *cx, ConstantOrRegister src,
|
||||
FloatRegister output, Label *fail)
|
||||
MacroAssembler::convertConstantOrRegisterToFloatingPoint(JSContext *cx, ConstantOrRegister src,
|
||||
FloatRegister output, Label *fail,
|
||||
MIRType outputType)
|
||||
{
|
||||
if (src.constant())
|
||||
return convertValueToDouble(cx, src.value(), output, fail);
|
||||
return convertValueToFloatingPoint(cx, src.value(), output, fail, outputType);
|
||||
|
||||
convertTypedOrValueToDouble(src.reg(), output, fail);
|
||||
convertTypedOrValueToFloatingPoint(src.reg(), output, fail, outputType);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output,
|
||||
Label *fail)
|
||||
MacroAssembler::convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output,
|
||||
Label *fail, MIRType outputType)
|
||||
{
|
||||
JS_ASSERT(IsFloatingPointType(outputType));
|
||||
|
||||
if (src.hasValue()) {
|
||||
convertValueToDouble(src.valueReg(), output, fail);
|
||||
convertValueToFloatingPoint(src.valueReg(), output, fail, outputType);
|
||||
return;
|
||||
}
|
||||
|
||||
bool outputIsDouble = outputType == MIRType_Double;
|
||||
switch (src.type()) {
|
||||
case MIRType_Null:
|
||||
loadStaticDouble(&DoubleZero, output);
|
||||
loadStaticFloatingPoint(&DoubleZero, &FloatZero, output, outputType);
|
||||
break;
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
convertInt32ToDouble(src.typedReg().gpr(), output);
|
||||
convertInt32ToFloatingPoint(src.typedReg().gpr(), output, outputType);
|
||||
break;
|
||||
case MIRType_Float32:
|
||||
if (outputIsDouble) {
|
||||
convertFloatToDouble(src.typedReg().fpu(), output);
|
||||
} else {
|
||||
if (src.typedReg().fpu() != output)
|
||||
moveFloat(src.typedReg().fpu(), output);
|
||||
}
|
||||
break;
|
||||
case MIRType_Double:
|
||||
if (outputIsDouble) {
|
||||
if (src.typedReg().fpu() != output)
|
||||
moveDouble(src.typedReg().fpu(), output);
|
||||
} else {
|
||||
convertDoubleToFloat(src.typedReg().fpu(), output);
|
||||
}
|
||||
break;
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
jump(fail);
|
||||
break;
|
||||
case MIRType_Undefined:
|
||||
loadStaticDouble(&js_NaN, output);
|
||||
loadStaticFloatingPoint(&js_NaN, &FloatNaN, output, outputType);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Bad MIRType");
|
||||
|
@ -1534,8 +1564,9 @@ MacroAssembler::convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegis
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, Label *truncateFail,
|
||||
Label *fail, IntConversionBehavior behavior)
|
||||
MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp,
|
||||
Label *truncateFail, Label *fail,
|
||||
IntConversionBehavior behavior)
|
||||
{
|
||||
switch (behavior) {
|
||||
case IntConversion_Normal:
|
||||
|
@ -1546,7 +1577,9 @@ MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, Label *tr
|
|||
branchTruncateDouble(src, output, truncateFail ? truncateFail : fail);
|
||||
break;
|
||||
case IntConversion_ClampToUint8:
|
||||
clampDoubleToUint8(src, output);
|
||||
// Clamping clobbers the input register, so use a temp.
|
||||
moveDouble(src, temp);
|
||||
clampDoubleToUint8(temp, output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1613,7 +1646,7 @@ MacroAssembler::convertValueToInt(ValueOperand value, MDefinition *maybeInput,
|
|||
if (handleStrings)
|
||||
bind(handleStringRejoin);
|
||||
|
||||
convertDoubleToInt(temp, output, truncateDoubleSlow, fail, behavior);
|
||||
convertDoubleToInt(temp, output, temp, truncateDoubleSlow, fail, behavior);
|
||||
jump(&done);
|
||||
}
|
||||
|
||||
|
@ -1722,9 +1755,11 @@ MacroAssembler::convertTypedOrValueToInt(TypedOrValueRegister src, FloatRegister
|
|||
case MIRType_Int32:
|
||||
if (src.typedReg().gpr() != output)
|
||||
move32(src.typedReg().gpr(), output);
|
||||
if (src.type() == MIRType_Int32 && behavior == IntConversion_ClampToUint8)
|
||||
clampIntToUint8(output);
|
||||
break;
|
||||
case MIRType_Double:
|
||||
convertDoubleToInt(src.typedReg().fpu(), output, NULL, fail, behavior);
|
||||
convertDoubleToInt(src.typedReg().fpu(), output, temp, NULL, fail, behavior);
|
||||
break;
|
||||
case MIRType_String:
|
||||
case MIRType_Object:
|
||||
|
|
|
@ -285,13 +285,17 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
template <typename T>
|
||||
void storeTypedOrValue(TypedOrValueRegister src, const T &dest) {
|
||||
if (src.hasValue())
|
||||
if (src.hasValue()) {
|
||||
storeValue(src.valueReg(), dest);
|
||||
else if (src.type() == MIRType_Double)
|
||||
storeDouble(src.typedReg().fpu(), dest);
|
||||
else
|
||||
} else if (IsFloatingPointType(src.type())) {
|
||||
FloatRegister reg = src.typedReg().fpu();
|
||||
if (src.type() == MIRType_Float32)
|
||||
convertFloatToDouble(reg, reg);
|
||||
storeDouble(reg, dest);
|
||||
} else {
|
||||
storeValue(ValueTypeFromMIRType(src.type()), src.typedReg().gpr(), dest);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void storeConstantOrRegister(ConstantOrRegister src, const T &dest) {
|
||||
|
@ -427,13 +431,17 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
void Push(TypedOrValueRegister v) {
|
||||
if (v.hasValue())
|
||||
if (v.hasValue()) {
|
||||
Push(v.valueReg());
|
||||
else if (IsFloatingPointType(v.type()))
|
||||
Push(v.typedReg().fpu());
|
||||
else
|
||||
} else if (IsFloatingPointType(v.type())) {
|
||||
FloatRegister reg = v.typedReg().fpu();
|
||||
if (v.type() == MIRType_Float32)
|
||||
convertFloatToDouble(reg, reg);
|
||||
Push(reg);
|
||||
} else {
|
||||
Push(ValueTypeFromMIRType(v.type()), v.typedReg().gpr());
|
||||
}
|
||||
}
|
||||
|
||||
void Push(ConstantOrRegister v) {
|
||||
if (v.constant())
|
||||
|
@ -995,12 +1003,73 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void tracelogLog(TraceLogging::Type type);
|
||||
#endif
|
||||
|
||||
#define DISPATCH_FLOATING_POINT_OP(method, type, arg1d, arg1f, arg2) \
|
||||
JS_ASSERT(IsFloatingPointType(type)); \
|
||||
if (type == MIRType_Double) \
|
||||
method##Double(arg1d, arg2); \
|
||||
else \
|
||||
method##Float32(arg1f, arg2); \
|
||||
|
||||
void loadStaticFloatingPoint(const double *dp, const float *fp, FloatRegister dest,
|
||||
MIRType destType)
|
||||
{
|
||||
DISPATCH_FLOATING_POINT_OP(loadStatic, destType, dp, fp, dest);
|
||||
}
|
||||
void loadConstantFloatingPoint(double d, float f, FloatRegister dest, MIRType destType) {
|
||||
DISPATCH_FLOATING_POINT_OP(loadConstant, destType, d, f, dest);
|
||||
}
|
||||
void boolValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
|
||||
DISPATCH_FLOATING_POINT_OP(boolValueTo, destType, value, value, dest);
|
||||
}
|
||||
void int32ValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
|
||||
DISPATCH_FLOATING_POINT_OP(int32ValueTo, destType, value, value, dest);
|
||||
}
|
||||
void convertInt32ToFloatingPoint(Register src, FloatRegister dest, MIRType destType) {
|
||||
DISPATCH_FLOATING_POINT_OP(convertInt32To, destType, src, src, dest);
|
||||
}
|
||||
|
||||
#undef DISPATCH_FLOATING_POINT_OP
|
||||
|
||||
void convertValueToFloatingPoint(ValueOperand value, FloatRegister output, Label *fail,
|
||||
MIRType outputType);
|
||||
bool convertValueToFloatingPoint(JSContext *cx, const Value &v, FloatRegister output,
|
||||
Label *fail, MIRType outputType);
|
||||
bool convertConstantOrRegisterToFloatingPoint(JSContext *cx, ConstantOrRegister src,
|
||||
FloatRegister output, Label *fail,
|
||||
MIRType outputType);
|
||||
void convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output,
|
||||
Label *fail, MIRType outputType);
|
||||
|
||||
void convertInt32ValueToDouble(const Address &address, Register scratch, Label *done);
|
||||
void convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail);
|
||||
bool convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail);
|
||||
void convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail) {
|
||||
convertValueToFloatingPoint(value, output, fail, MIRType_Double);
|
||||
}
|
||||
bool convertValueToDouble(JSContext *cx, const Value &v, FloatRegister output, Label *fail) {
|
||||
return convertValueToFloatingPoint(cx, v, output, fail, MIRType_Double);
|
||||
}
|
||||
bool convertConstantOrRegisterToDouble(JSContext *cx, ConstantOrRegister src,
|
||||
FloatRegister output, Label *fail);
|
||||
void convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output, Label *fail);
|
||||
FloatRegister output, Label *fail)
|
||||
{
|
||||
return convertConstantOrRegisterToFloatingPoint(cx, src, output, fail, MIRType_Double);
|
||||
}
|
||||
void convertTypedOrValueToDouble(TypedOrValueRegister src, FloatRegister output, Label *fail) {
|
||||
convertTypedOrValueToFloatingPoint(src, output, fail, MIRType_Double);
|
||||
}
|
||||
|
||||
void convertValueToFloat(ValueOperand value, FloatRegister output, Label *fail) {
|
||||
convertValueToFloatingPoint(value, output, fail, MIRType_Float32);
|
||||
}
|
||||
bool convertValueToFloat(JSContext *cx, const Value &v, FloatRegister output, Label *fail) {
|
||||
return convertValueToFloatingPoint(cx, v, output, fail, MIRType_Float32);
|
||||
}
|
||||
bool convertConstantOrRegisterToFloat(JSContext *cx, ConstantOrRegister src,
|
||||
FloatRegister output, Label *fail)
|
||||
{
|
||||
return convertConstantOrRegisterToFloatingPoint(cx, src, output, fail, MIRType_Float32);
|
||||
}
|
||||
void convertTypedOrValueToFloat(TypedOrValueRegister src, FloatRegister output, Label *fail) {
|
||||
convertTypedOrValueToFloatingPoint(src, output, fail, MIRType_Float32);
|
||||
}
|
||||
|
||||
enum IntConversionBehavior {
|
||||
IntConversion_Normal,
|
||||
|
@ -1012,8 +1081,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
//
|
||||
// Functions for converting values to int.
|
||||
//
|
||||
void convertDoubleToInt(FloatRegister src, Register output, Label *truncateFail, Label *fail,
|
||||
IntConversionBehavior behavior);
|
||||
void convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp,
|
||||
Label *truncateFail, Label *fail, IntConversionBehavior behavior);
|
||||
|
||||
// Strings may be handled by providing labels to jump to when the behavior
|
||||
// is truncation or clamping. The subroutine, usually an OOL call, is
|
||||
|
|
|
@ -6964,6 +6964,8 @@ class MSetElementCache
|
|||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
bool canConsumeFloat32() const { return true; }
|
||||
};
|
||||
|
||||
class MCallGetProperty
|
||||
|
|
|
@ -1264,15 +1264,21 @@ CodeGeneratorARM::visitBox(LBox *box)
|
|||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorARM::visitBoxDouble(LBoxDouble *box)
|
||||
CodeGeneratorARM::visitBoxFloatingPoint(LBoxFloatingPoint *box)
|
||||
{
|
||||
const LDefinition *payload = box->getDef(PAYLOAD_INDEX);
|
||||
const LDefinition *type = box->getDef(TYPE_INDEX);
|
||||
const LAllocation *in = box->getOperand(0);
|
||||
|
||||
FloatRegister reg = ToFloatRegister(in);
|
||||
if (box->type() == MIRType_Float32) {
|
||||
masm.convertFloatToDouble(reg, ScratchFloatReg);
|
||||
reg = ScratchFloatReg;
|
||||
}
|
||||
|
||||
//masm.as_vxfer(ToRegister(payload), ToRegister(type),
|
||||
// VFPRegister(ToFloatRegister(in)), Assembler::FloatToCore);
|
||||
masm.ma_vxfer(VFPRegister(ToFloatRegister(in)), ToRegister(payload), ToRegister(type));
|
||||
masm.ma_vxfer(VFPRegister(reg), ToRegister(payload), ToRegister(type));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
|||
|
||||
public:
|
||||
bool visitBox(LBox *box);
|
||||
bool visitBoxDouble(LBoxDouble *box);
|
||||
bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
bool visitUnbox(LUnbox *unbox);
|
||||
bool visitValue(LValue *value);
|
||||
bool visitOsrValue(LOsrValue *value);
|
||||
|
|
|
@ -28,15 +28,23 @@ class LBox : public LInstructionHelper<2, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LBoxDouble : public LInstructionHelper<2, 1, 1>
|
||||
class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(BoxDouble);
|
||||
MIRType type_;
|
||||
|
||||
LBoxDouble(const LAllocation &in, const LDefinition &temp) {
|
||||
public:
|
||||
LIR_HEADER(BoxFloatingPoint);
|
||||
|
||||
LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type)
|
||||
: type_(type)
|
||||
{
|
||||
setOperand(0, in);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
MIRType type() const {
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
class LUnbox : public LInstructionHelper<1, 2, 0>
|
||||
|
@ -55,16 +63,26 @@ class LUnbox : public LInstructionHelper<1, 2, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LUnboxDouble : public LInstructionHelper<1, 2, 0>
|
||||
class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
|
||||
{
|
||||
MIRType type_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(UnboxDouble);
|
||||
LIR_HEADER(UnboxFloatingPoint);
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
LUnboxFloatingPoint(MIRType type)
|
||||
: type_(type)
|
||||
{ }
|
||||
|
||||
MUnbox *mir() const {
|
||||
return mir_->toUnbox();
|
||||
}
|
||||
|
||||
MIRType type() const {
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a 32-bit unsigned integer to a double.
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#define LIR_CPU_OPCODE_LIST(_) \
|
||||
_(Unbox) \
|
||||
_(UnboxDouble) \
|
||||
_(UnboxFloatingPoint) \
|
||||
_(Box) \
|
||||
_(BoxDouble) \
|
||||
_(BoxFloatingPoint) \
|
||||
_(DivI) \
|
||||
_(SoftDivI) \
|
||||
_(DivPowTwoI) \
|
||||
|
|
|
@ -82,8 +82,9 @@ LIRGeneratorARM::visitBox(MBox *box)
|
|||
MDefinition *inner = box->getOperand(0);
|
||||
|
||||
// If the box wrapped a double, it needs a new register.
|
||||
if (inner->type() == MIRType_Double)
|
||||
return defineBox(new LBoxDouble(useRegisterAtStart(inner), tempCopy(inner, 0)), box);
|
||||
if (IsFloatingPointType(inner->type()))
|
||||
return defineBox(new LBoxFloatingPoint(useRegisterAtStart(inner), tempCopy(inner, 0),
|
||||
inner->type()), box);
|
||||
|
||||
if (box->canEmitAtUses())
|
||||
return emitAtUses(box);
|
||||
|
@ -123,11 +124,11 @@ LIRGeneratorARM::visitUnbox(MUnbox *unbox)
|
|||
if (!ensureDefined(inner))
|
||||
return false;
|
||||
|
||||
if (unbox->type() == MIRType_Double) {
|
||||
LUnboxDouble *lir = new LUnboxDouble();
|
||||
if (IsFloatingPointType(unbox->type())) {
|
||||
LUnboxFloatingPoint *lir = new LUnboxFloatingPoint(unbox->type());
|
||||
if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
|
||||
return false;
|
||||
if (!useBox(lir, LUnboxDouble::Input, inner))
|
||||
if (!useBox(lir, LUnboxFloatingPoint::Input, inner))
|
||||
return false;
|
||||
return define(lir, unbox);
|
||||
}
|
||||
|
|
|
@ -784,6 +784,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
void loadStaticFloat32(const float *dp, const FloatRegister &dest) {
|
||||
MOZ_ASSUME_UNREACHABLE("NYI");
|
||||
}
|
||||
void loadConstantFloat32(const float dp, const FloatRegister &dest) {
|
||||
MOZ_ASSUME_UNREACHABLE("NYI");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void branchTestInt32(Condition cond, const T & t, Label *label) {
|
||||
|
@ -1457,6 +1460,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
ma_vstr(VFPRegister(ScratchFloatReg).singleOverlay(), base, index, 0, cond);
|
||||
|
||||
}
|
||||
void moveFloat(FloatRegister src, FloatRegister dest) {
|
||||
as_vmov(VFPRegister(src).singleOverlay(), VFPRegister(dest).singleOverlay());
|
||||
}
|
||||
};
|
||||
|
||||
typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
|
||||
|
|
|
@ -329,6 +329,10 @@ class AssemblerX86Shared
|
|||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||
}
|
||||
}
|
||||
void movss(const FloatRegister &src, const FloatRegister &dest) {
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.movss_rr(src.code(), dest.code());
|
||||
}
|
||||
void movss(const Operand &src, const FloatRegister &dest) {
|
||||
JS_ASSERT(HasSSE2());
|
||||
switch (src.kind()) {
|
||||
|
|
|
@ -392,6 +392,9 @@ class MacroAssemblerX86Shared : public Assembler
|
|||
void storeFloat(FloatRegister src, const BaseIndex &dest) {
|
||||
movss(src, Operand(dest));
|
||||
}
|
||||
void moveFloat(FloatRegister src, FloatRegister dest) {
|
||||
movss(src, dest);
|
||||
}
|
||||
|
||||
// Checks whether a double is representable as a 32-bit integer. If so, the
|
||||
// integer is written to the output register. Otherwise, a bailout is taken to
|
||||
|
|
|
@ -84,10 +84,16 @@ CodeGeneratorX64::visitBox(LBox *box)
|
|||
const LAllocation *in = box->getOperand(0);
|
||||
const LDefinition *result = box->getDef(0);
|
||||
|
||||
if (box->type() != MIRType_Double)
|
||||
if (IsFloatingPointType(box->type())) {
|
||||
FloatRegister reg = ToFloatRegister(in);
|
||||
if (box->type() == MIRType_Float32) {
|
||||
masm.convertFloatToDouble(reg, ScratchFloatReg);
|
||||
reg = ScratchFloatReg;
|
||||
}
|
||||
masm.movq(reg, ToRegister(result));
|
||||
} else {
|
||||
masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
|
||||
else
|
||||
masm.movq(ToFloatRegister(in), ToRegister(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,13 +54,20 @@ class LUnbox : public LUnboxBase {
|
|||
{ }
|
||||
};
|
||||
|
||||
class LUnboxDouble : public LUnboxBase {
|
||||
public:
|
||||
LIR_HEADER(UnboxDouble)
|
||||
class LUnboxFloatingPoint : public LUnboxBase {
|
||||
MIRType type_;
|
||||
|
||||
LUnboxDouble(const LAllocation &input)
|
||||
: LUnboxBase(input)
|
||||
public:
|
||||
LIR_HEADER(UnboxFloatingPoint)
|
||||
|
||||
LUnboxFloatingPoint(const LAllocation &input, MIRType type)
|
||||
: LUnboxBase(input),
|
||||
type_(type)
|
||||
{ }
|
||||
|
||||
MIRType type() const {
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a 32-bit unsigned integer to a double.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define LIR_CPU_OPCODE_LIST(_) \
|
||||
_(Box) \
|
||||
_(Unbox) \
|
||||
_(UnboxDouble) \
|
||||
_(UnboxFloatingPoint) \
|
||||
_(DivI) \
|
||||
_(DivPowTwoI) \
|
||||
_(DivSelfI) \
|
||||
|
|
|
@ -76,8 +76,8 @@ LIRGeneratorX64::visitUnbox(MUnbox *unbox)
|
|||
{
|
||||
MDefinition *box = unbox->getOperand(0);
|
||||
LUnboxBase *lir;
|
||||
if (unbox->type() == MIRType_Double)
|
||||
lir = new LUnboxDouble(useRegister(box));
|
||||
if (IsFloatingPointType(unbox->type()))
|
||||
lir = new LUnboxFloatingPoint(useRegister(box), unbox->type());
|
||||
else
|
||||
lir = new LUnbox(useRegister(box));
|
||||
|
||||
|
|
|
@ -118,12 +118,17 @@ CodeGeneratorX86::visitBox(LBox *box)
|
|||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86::visitBoxDouble(LBoxDouble *box)
|
||||
CodeGeneratorX86::visitBoxFloatingPoint(LBoxFloatingPoint *box)
|
||||
{
|
||||
const LAllocation *in = box->getOperand(0);
|
||||
const ValueOperand out = ToOutValue(box);
|
||||
|
||||
masm.boxDouble(ToFloatRegister(in), out);
|
||||
FloatRegister reg = ToFloatRegister(in);
|
||||
if (box->type() == MIRType_Float32) {
|
||||
masm.convertFloatToDouble(reg, ScratchFloatReg);
|
||||
reg = ScratchFloatReg;
|
||||
}
|
||||
masm.boxDouble(reg, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared
|
|||
|
||||
public:
|
||||
bool visitBox(LBox *box);
|
||||
bool visitBoxDouble(LBoxDouble *box);
|
||||
bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
bool visitUnbox(LUnbox *unbox);
|
||||
bool visitValue(LValue *value);
|
||||
bool visitOsrValue(LOsrValue *value);
|
||||
|
|
|
@ -28,15 +28,24 @@ class LBox : public LInstructionHelper<2, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LBoxDouble : public LInstructionHelper<2, 1, 1>
|
||||
class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(BoxDouble);
|
||||
MIRType type_;
|
||||
|
||||
LBoxDouble(const LAllocation &in, const LDefinition &temp) {
|
||||
public:
|
||||
LIR_HEADER(BoxFloatingPoint);
|
||||
|
||||
LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type)
|
||||
: type_(type)
|
||||
{
|
||||
JS_ASSERT(IsFloatingPointType(type));
|
||||
setOperand(0, in);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
MIRType type() const {
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
class LUnbox : public LInstructionHelper<1, 2, 0>
|
||||
|
@ -55,16 +64,26 @@ class LUnbox : public LInstructionHelper<1, 2, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LUnboxDouble : public LInstructionHelper<1, 2, 0>
|
||||
class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
|
||||
{
|
||||
MIRType type_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(UnboxDouble);
|
||||
LIR_HEADER(UnboxFloatingPoint);
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
LUnboxFloatingPoint(MIRType type)
|
||||
: type_(type)
|
||||
{ }
|
||||
|
||||
MUnbox *mir() const {
|
||||
return mir_->toUnbox();
|
||||
}
|
||||
|
||||
MIRType type() const {
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a 32-bit unsigned integer to a double.
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#define LIR_CPU_OPCODE_LIST(_) \
|
||||
_(Unbox) \
|
||||
_(UnboxDouble) \
|
||||
_(UnboxFloatingPoint) \
|
||||
_(Box) \
|
||||
_(BoxDouble) \
|
||||
_(BoxFloatingPoint) \
|
||||
_(DivI) \
|
||||
_(DivPowTwoI) \
|
||||
_(DivSelfI) \
|
||||
|
|
|
@ -59,8 +59,9 @@ LIRGeneratorX86::visitBox(MBox *box)
|
|||
MDefinition *inner = box->getOperand(0);
|
||||
|
||||
// If the box wrapped a double, it needs a new register.
|
||||
if (inner->type() == MIRType_Double)
|
||||
return defineBox(new LBoxDouble(useRegisterAtStart(inner), tempCopy(inner, 0)), box);
|
||||
if (IsFloatingPointType(inner->type()))
|
||||
return defineBox(new LBoxFloatingPoint(useRegisterAtStart(inner), tempCopy(inner, 0),
|
||||
inner->type()), box);
|
||||
|
||||
if (box->canEmitAtUses())
|
||||
return emitAtUses(box);
|
||||
|
@ -100,11 +101,11 @@ LIRGeneratorX86::visitUnbox(MUnbox *unbox)
|
|||
if (!ensureDefined(inner))
|
||||
return false;
|
||||
|
||||
if (unbox->type() == MIRType_Double) {
|
||||
LUnboxDouble *lir = new LUnboxDouble;
|
||||
if (IsFloatingPointType(unbox->type())) {
|
||||
LUnboxFloatingPoint *lir = new LUnboxFloatingPoint(unbox->type());
|
||||
if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
|
||||
return false;
|
||||
if (!useBox(lir, LUnboxDouble::Input, inner))
|
||||
if (!useBox(lir, LUnboxFloatingPoint::Input, inner))
|
||||
return false;
|
||||
return define(lir, unbox);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче