Bug 1112165 - Recover SimdBox. r=bbouvier

This commit is contained in:
Nicolas B. Pierron 2015-02-26 17:37:36 +01:00
parent af9750271d
commit d412a275e2
11 changed files with 194 additions and 33 deletions

View File

@ -495,7 +495,7 @@ js_InitSIMDClass(JSContext *cx, HandleObject obj)
template<typename V>
JSObject *
js::CreateSimd(JSContext *cx, typename V::Elem *data)
js::CreateSimd(JSContext *cx, const typename V::Elem *data)
{
typedef typename V::Elem Elem;
Rooted<TypeDescr*> typeDescr(cx, &V::GetTypeDescr(*cx->global()));
@ -510,9 +510,9 @@ js::CreateSimd(JSContext *cx, typename V::Elem *data)
return result;
}
template JSObject *js::CreateSimd<Float32x4>(JSContext *cx, Float32x4::Elem *data);
template JSObject *js::CreateSimd<Float64x2>(JSContext *cx, Float64x2::Elem *data);
template JSObject *js::CreateSimd<Int32x4>(JSContext *cx, Int32x4::Elem *data);
template JSObject *js::CreateSimd<Float32x4>(JSContext *cx, const Float32x4::Elem *data);
template JSObject *js::CreateSimd<Float64x2>(JSContext *cx, const Float64x2::Elem *data);
template JSObject *js::CreateSimd<Int32x4>(JSContext *cx, const Int32x4::Elem *data);
namespace js {
// Unary SIMD operators

View File

@ -323,7 +323,7 @@ struct Int32x4 {
};
template<typename V>
JSObject *CreateSimd(JSContext *cx, typename V::Elem *data);
JSObject *CreateSimd(JSContext *cx, const typename V::Elem *data);
template<typename V>
bool IsVectorObject(HandleValue v);

View File

@ -0,0 +1,40 @@
load(libdir + 'simd.js');
if (!this.hasOwnProperty("SIMD"))
quit();
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
// This function is used to cause an invalidation after having removed a branch
// after DCE. This is made to check if we correctly recover an array
// allocation.
var uceFault = function (i) {
if (i > 98)
uceFault = function (i) { return true; };
return false;
};
// Check that we can correctly recover a boxed value.
var uceFault_simdBox_i4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_i4'));
function simdBox_i4(i) {
var a = SIMD.int32x4(i, i, i, i);
if (uceFault_simdBox_i4(i) || uceFault_simdBox_i4(i)) {
assertEqX4(a, [i, i, i, i]);
}
return 0;
}
var uceFault_simdBox_f4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_f4'));
function simdBox_f4(i) {
var a = SIMD.float32x4(i, i + 0.1, i + 0.2, i + 0.3);
if (uceFault_simdBox_f4(i) || uceFault_simdBox_f4(i)) {
assertEqX4(a, [i, i + 0.1, i + 0.2, i + 0.3].map(Math.fround));
}
return 0;
}
for (var i = 0; i < 100; i++) {
simdBox_i4(i);
simdBox_f4(i);
}

View File

@ -2072,6 +2072,8 @@ IsResumableMIRType(MIRType type)
case MIRType_MagicOptimizedOut:
case MIRType_MagicUninitializedLexical:
case MIRType_Value:
case MIRType_Float32x4:
case MIRType_Int32x4:
return true;
case MIRType_MagicHole:
@ -2083,9 +2085,7 @@ IsResumableMIRType(MIRType type)
case MIRType_Pointer:
case MIRType_Shape:
case MIRType_ObjectGroup:
case MIRType_Float32x4:
case MIRType_Int32x4:
case MIRType_Doublex2:
case MIRType_Doublex2: // NYI, see also RSimdBox::recover
return false;
}
MOZ_CRASH("Unknown MIRType.");

View File

@ -382,6 +382,7 @@ struct MaybeReadFallback
class RResumePoint;
class RSimdBox;
// Reads frame information in snapshot-encoding order (that is, outermost frame
// to innermost frame).
@ -442,6 +443,10 @@ class SnapshotIterator
void writeAllocationValuePayload(const RValueAllocation &a, Value v);
void warnUnreadableAllocation();
private:
friend class RSimdBox;
const FloatRegisters::RegisterContent *floatAllocationPointer(const RValueAllocation &a) const;
public:
// Handle iterating over RValueAllocations of the snapshots.
inline RValueAllocation readAllocation() {

View File

@ -51,40 +51,46 @@ OffsetOfFrameSlot(int32_t slot)
return -slot;
}
static inline uint8_t *
AddressOfFrameSlot(JitFrameLayout *fp, int32_t slot)
{
return (uint8_t *) fp + OffsetOfFrameSlot(slot);
}
static inline uintptr_t
ReadFrameSlot(JitFrameLayout *fp, int32_t slot)
{
return *(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot));
return *(uintptr_t *) AddressOfFrameSlot(fp, slot);
}
static inline void
WriteFrameSlot(JitFrameLayout *fp, int32_t slot, uintptr_t value)
{
*(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot)) = value;
*(uintptr_t *) AddressOfFrameSlot(fp, slot) = value;
}
static inline double
ReadFrameDoubleSlot(JitFrameLayout *fp, int32_t slot)
{
return *(double *)((char *)fp + OffsetOfFrameSlot(slot));
return *(double *) AddressOfFrameSlot(fp, slot);
}
static inline float
ReadFrameFloat32Slot(JitFrameLayout *fp, int32_t slot)
{
return *(float *)((char *)fp + OffsetOfFrameSlot(slot));
return *(float *) AddressOfFrameSlot(fp, slot);
}
static inline int32_t
ReadFrameInt32Slot(JitFrameLayout *fp, int32_t slot)
{
return *(int32_t *)((char *)fp + OffsetOfFrameSlot(slot));
return *(int32_t *) AddressOfFrameSlot(fp, slot);
}
static inline bool
ReadFrameBooleanSlot(JitFrameLayout *fp, int32_t slot)
{
return *(bool *)((char *)fp + OffsetOfFrameSlot(slot));
return *(bool *) AddressOfFrameSlot(fp, slot);
}
JitFrameIterator::JitFrameIterator()
@ -1835,6 +1841,7 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc, ReadMethod rm)
double d;
float f;
} pun;
MOZ_ASSERT(alloc.fpuReg().isSingle());
pun.d = fromRegister(alloc.fpuReg());
// The register contains the encoding of a float32. We just read
// the bits without making any conversion.
@ -1929,6 +1936,21 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc, ReadMethod rm)
}
}
const FloatRegisters::RegisterContent *
SnapshotIterator::floatAllocationPointer(const RValueAllocation &alloc) const
{
switch (alloc.mode()) {
case RValueAllocation::FLOAT32_REG:
return machine_.address(alloc.fpuReg());
case RValueAllocation::FLOAT32_STACK:
return (FloatRegisters::RegisterContent *) AddressOfFrameSlot(fp_, alloc.stackOffset());
default:
MOZ_CRASH("Not a float allocation.");
}
}
Value
SnapshotIterator::maybeRead(const RValueAllocation &a, MaybeReadFallback &fallback)
{
@ -2485,8 +2507,10 @@ MachineState::FromBailout(RegisterDump::GPRArray &regs, RegisterDump::FPUArray &
}
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Single), &fpregs[i].s);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Double), &fpregs[i].d);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Single), &fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Double), &fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Int32x4), &fpregs[i]);
machine.setRegisterLocation(FloatRegister(i, FloatRegisters::Float32x4), &fpregs[i]);
}
#elif defined(JS_CODEGEN_NONE)
MOZ_CRASH();

View File

@ -3032,6 +3032,11 @@ class MSimdBox
AliasSet getAliasSet() const MOZ_OVERRIDE {
return AliasSet::None();
}
bool writeRecoverData(CompactBufferWriter &writer) const MOZ_OVERRIDE;
bool canRecoverOnBailout() const MOZ_OVERRIDE {
return true;
}
};
class MSimdUnbox

View File

@ -13,6 +13,7 @@
#include "jsstr.h"
#include "builtin/RegExp.h"
#include "builtin/SIMD.h"
#include "builtin/TypedObject.h"
#include "gc/Heap.h"
@ -1313,6 +1314,54 @@ RLambda::recover(JSContext *cx, SnapshotIterator &iter) const
return true;
}
bool
MSimdBox::writeRecoverData(CompactBufferWriter &writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_SimdBox));
SimdTypeDescr &simdTypeDescr = templateObject()->typeDescr().as<SimdTypeDescr>();
SimdTypeDescr::Type type = simdTypeDescr.type();
writer.writeByte(uint8_t(type));
return true;
}
RSimdBox::RSimdBox(CompactBufferReader &reader)
{
type_ = reader.readByte();
}
bool
RSimdBox::recover(JSContext *cx, SnapshotIterator &iter) const
{
JSObject *resultObject = nullptr;
RValueAllocation a = iter.readAllocation();
MOZ_ASSERT(iter.allocationReadable(a));
const FloatRegisters::RegisterContent *raw = iter.floatAllocationPointer(a);
switch (SimdTypeDescr::Type(type_)) {
case SimdTypeDescr::TYPE_INT32:
MOZ_ASSERT_IF(a.mode() == RValueAllocation::FLOAT32_REG,
a.fpuReg().isInt32x4());
resultObject = js::CreateSimd<Int32x4>(cx, (const Int32x4::Elem *) raw);
break;
case SimdTypeDescr::TYPE_FLOAT32:
MOZ_ASSERT_IF(a.mode() == RValueAllocation::FLOAT32_REG,
a.fpuReg().isFloat32x4());
resultObject = js::CreateSimd<Float32x4>(cx, (const Float32x4::Elem *) raw);
break;
case SimdTypeDescr::TYPE_FLOAT64:
MOZ_CRASH("NYI, RSimdBox of Float64x2");
break;
}
if (!resultObject)
return false;
RootedValue result(cx);
result.setObject(*resultObject);
iter.storeInstructionResult(result);
return true;
}
bool
MObjectState::writeRecoverData(CompactBufferWriter &writer) const
{

View File

@ -64,6 +64,7 @@ namespace jit {
_(NewDerivedTypedObject) \
_(CreateThisWithTemplate) \
_(Lambda) \
_(SimdBox) \
_(ObjectState) \
_(ArrayState)
@ -684,6 +685,21 @@ class RLambda MOZ_FINAL : public RInstruction
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RSimdBox MOZ_FINAL : public RInstruction
{
private:
uint8_t type_;
public:
RINSTRUCTION_HEADER_(SimdBox)
virtual uint32_t numOperands() const {
return 1;
}
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RObjectState MOZ_FINAL : public RInstruction
{
private:

View File

@ -122,6 +122,9 @@ class MachineState
void setRegisterLocation(FloatRegister reg, double *dp) {
fpregs_[reg.code()] = (FloatRegisters::RegisterContent *) dp;
}
void setRegisterLocation(FloatRegister reg, FloatRegisters::RegisterContent *rp) {
fpregs_[reg.code()] = rp;
}
bool has(Register reg) const {
return regs_[reg.code()] != nullptr;
@ -138,6 +141,9 @@ class MachineState
void write(Register reg, uintptr_t value) const {
regs_[reg.code()]->r = value;
}
const FloatRegisters::RegisterContent *address(FloatRegister reg) const {
return fpregs_[reg.code()];
}
};
} // namespace jit

View File

@ -381,30 +381,46 @@ CodeGeneratorShared::encodeAllocation(LSnapshot *snapshot, MDefinition *mir,
case MIRType_ObjectOrNull:
case MIRType_Boolean:
case MIRType_Double:
case MIRType_Float32:
{
LAllocation *payload = snapshot->payloadOfSlot(*allocIndex);
JSValueType valueType =
(type == MIRType_ObjectOrNull) ? JSVAL_TYPE_OBJECT : ValueTypeFromMIRType(type);
if (payload->isMemory()) {
if (type == MIRType_Float32)
alloc = RValueAllocation::Float32(ToStackIndex(payload));
else
alloc = RValueAllocation::Typed(valueType, ToStackIndex(payload));
} else if (payload->isGeneralReg()) {
alloc = RValueAllocation::Typed(valueType, ToRegister(payload));
} else if (payload->isFloatReg()) {
FloatRegister reg = ToFloatRegister(payload);
if (type == MIRType_Float32)
alloc = RValueAllocation::Float32(reg);
else
alloc = RValueAllocation::Double(reg);
} else {
if (payload->isConstant()) {
MConstant *constant = mir->toConstant();
uint32_t index;
masm.propagateOOM(graph.addConstantToPool(constant->value(), &index));
alloc = RValueAllocation::ConstantPool(index);
break;
}
JSValueType valueType =
(type == MIRType_ObjectOrNull) ? JSVAL_TYPE_OBJECT : ValueTypeFromMIRType(type);
MOZ_ASSERT(payload->isMemory() || payload->isRegister());
if (payload->isMemory())
alloc = RValueAllocation::Typed(valueType, ToStackIndex(payload));
else if (payload->isGeneralReg())
alloc = RValueAllocation::Typed(valueType, ToRegister(payload));
else if (payload->isFloatReg())
alloc = RValueAllocation::Double(ToFloatRegister(payload));
break;
}
case MIRType_Float32:
case MIRType_Int32x4:
case MIRType_Float32x4:
{
LAllocation *payload = snapshot->payloadOfSlot(*allocIndex);
if (payload->isConstant()) {
MConstant *constant = mir->toConstant();
uint32_t index;
masm.propagateOOM(graph.addConstantToPool(constant->value(), &index));
alloc = RValueAllocation::ConstantPool(index);
break;
}
MOZ_ASSERT(payload->isMemory() || payload->isFloatReg());
if (payload->isFloatReg())
alloc = RValueAllocation::Float32(ToFloatRegister(payload));
else
alloc = RValueAllocation::Float32(ToStackIndex(payload));
break;
}
case MIRType_MagicOptimizedArguments: