mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
Bug 1112165 - Recover SimdBox. r=bbouvier
This commit is contained in:
parent
af9750271d
commit
d412a275e2
@ -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
|
||||
|
@ -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);
|
||||
|
40
js/src/jit-test/tests/SIMD/recover.js
Normal file
40
js/src/jit-test/tests/SIMD/recover.js
Normal 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);
|
||||
}
|
@ -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.");
|
||||
|
@ -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() {
|
||||
|
@ -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 ®s, 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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user