Bug 915495 - Support float32 optimization in typed array SetElem ICs. (r=bbouvier)

This commit is contained in:
Shu-yu Guo 2013-09-13 22:45:42 -07:00
parent 0e29e13e23
commit 278f8c1f64
24 changed files with 301 additions and 105 deletions

View File

@ -0,0 +1,11 @@
function testFloat32SetElemIC(a) {
for (var i = 0; i < a.length; i++) {
var r = Math.fround(Math.random());
a[i] = r;
assertEq(a[i], r);
}
}
testFloat32SetElemIC(new Array(2048));
testFloat32SetElemIC(new Float64Array(2048));
testFloat32SetElemIC(new Float32Array(2048));

View File

@ -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 double or float.
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())

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
@ -504,6 +511,10 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
as_vcmp(ScratchFloatReg, input);
as_vmrs(pc);
ma_bic(Imm32(1), output, NoSetCond, Zero);
// We added 0.5 in place, but the input register might be used again,
// so undo it.
ma_vimm(0.5, ScratchFloatReg);
ma_vsub(input, ScratchFloatReg, input);
bind(&outOfRange);
}
#else
@ -546,6 +557,10 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
}
bind(&done);
// The input register might be used again, so subtract the 0.5 we added.
loadStaticDouble(&DoubleHalf, ScratchFloatReg);
subDouble(ScratchFloatReg, input);
#endif
}
@ -1374,9 +1389,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 +1408,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 +1442,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 +1512,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 (src.typedReg().fpu() != output)
moveDouble(src.typedReg().fpu(), output);
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");
@ -1722,6 +1760,8 @@ 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);

View File

@ -285,12 +285,16 @@ 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>
@ -427,12 +431,16 @@ 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) {
@ -995,12 +1003,73 @@ class MacroAssembler : public MacroAssemblerSpecific
void tracelogLog(TraceLogging::Type type);
#endif
#define FLOATING_POINT_OP_2(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)
{
FLOATING_POINT_OP_2(loadStatic, destType, dp, fp, dest);
}
void loadConstantFloatingPoint(double d, float f, FloatRegister dest, MIRType destType) {
FLOATING_POINT_OP_2(loadConstant, destType, d, f, dest);
}
void boolValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
FLOATING_POINT_OP_2(boolValueTo, destType, value, value, dest);
}
void int32ValueToFloatingPoint(ValueOperand value, FloatRegister dest, MIRType destType) {
FLOATING_POINT_OP_2(int32ValueTo, destType, value, value, dest);
}
void convertInt32ToFloatingPoint(Register src, FloatRegister dest, MIRType destType) {
FLOATING_POINT_OP_2(convertInt32To, destType, src, src, dest);
}
#undef FLOATING_POINT_OP_2
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,

View File

@ -6964,6 +6964,8 @@ class MSetElementCache
TypePolicy *typePolicy() {
return this;
}
bool canConsumeFloat32() const { return true; }
};
class MCallGetProperty

View File

@ -1264,15 +1264,19 @@ 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, reg);
//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;
}

View File

@ -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);

View File

@ -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.

View File

@ -9,9 +9,9 @@
#define LIR_CPU_OPCODE_LIST(_) \
_(Unbox) \
_(UnboxDouble) \
_(UnboxFloatingPoint) \
_(Box) \
_(BoxDouble) \
_(BoxFloatingPoint) \
_(DivI) \
_(SoftDivI) \
_(DivPowTwoI) \

View File

@ -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);
}

View File

@ -1457,6 +1457,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
ma_vstr(VFPRegister(ScratchFloatReg).singleOverlay(), base, index, 0, cond);
}
void moveFloat(FloatRegister src, FloatRegister dest) {
ma_vmov(VFPRegister(src).singleOverlay(), VFPRegister(dest).singleOverlay());
}
};
typedef MacroAssemblerARMCompat MacroAssemblerSpecific;

View File

@ -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()) {

View File

@ -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

View File

@ -84,10 +84,13 @@ CodeGeneratorX64::visitBox(LBox *box)
const LAllocation *in = box->getOperand(0);
const LDefinition *result = box->getDef(0);
if (box->type() != MIRType_Double)
masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
else
if (IsFloatingPointType(box->type())) {
if (box->type() == MIRType_Float32)
masm.convertFloatToDouble(ToFloatRegister(in), ToFloatRegister(in));
masm.movq(ToFloatRegister(in), ToRegister(result));
} else {
masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
}
return true;
}

View File

@ -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.

View File

@ -10,7 +10,7 @@
#define LIR_CPU_OPCODE_LIST(_) \
_(Box) \
_(Unbox) \
_(UnboxDouble) \
_(UnboxFloatingPoint) \
_(DivI) \
_(DivPowTwoI) \
_(DivSelfI) \

View File

@ -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));

View File

@ -118,12 +118,15 @@ 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, reg);
masm.boxDouble(reg, out);
return true;
}

View File

@ -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);

View File

@ -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.

View File

@ -9,9 +9,9 @@
#define LIR_CPU_OPCODE_LIST(_) \
_(Unbox) \
_(UnboxDouble) \
_(UnboxFloatingPoint) \
_(Box) \
_(BoxDouble) \
_(BoxFloatingPoint) \
_(DivI) \
_(DivPowTwoI) \
_(DivSelfI) \

View File

@ -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);
}