Bug 1115043: Ensure that range analysis takes size of element into account when removing bounds checks of AsmJS{Load/Store}Heap; r=luke

--HG--
extra : rebase_source : a7d3b262ca4ac87871da03a37cff99e355533098
This commit is contained in:
Benjamin Bouvier 2014-12-23 18:24:25 +01:00
parent db4a263c26
commit b898694f7d
5 changed files with 37 additions and 6 deletions

View File

@ -782,7 +782,7 @@ AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx
// ptr + data-type-byte-size > heapLength
// i.e. ptr >= heapLength + 1 - data-type-byte-size
// (Note that we need >= as this is what codegen uses.)
size_t scalarByteSize = 1 << TypedArrayShift(access.type());
size_t scalarByteSize = TypedArrayElemSize(access.type());
X86Assembler::setPointer(access.patchLengthAt(code_),
(void*)(heap->byteLength() + 1 - scalarByteSize));
}
@ -804,7 +804,7 @@ AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx
const jit::AsmJSHeapAccess &access = heapAccesses_[i];
if (access.hasLengthCheck()) {
// See comment above for x86 codegen.
size_t scalarByteSize = 1 << TypedArrayShift(access.type());
size_t scalarByteSize = TypedArrayElemSize(access.type());
X86Assembler::setInt32(access.patchLengthAt(code_), heapLength + 1 - scalarByteSize);
}
}

View File

@ -4360,7 +4360,7 @@ CheckArrayAccess(FunctionCompiler &f, ParseNode *viewName, ParseNode *indexExpr,
if (byteOffset > INT32_MAX)
return f.fail(indexExpr, "constant index out of range");
unsigned elementSize = 1 << TypedArrayShift(*viewType);
unsigned elementSize = TypedArrayElemSize(*viewType);
if (!f.m().tryRequireHeapLengthToBeAtLeast(byteOffset + elementSize)) {
return f.failf(indexExpr, "constant index outside heap size range declared by the "
"change-heap function (0x%x - 0x%x)",
@ -4375,7 +4375,7 @@ CheckArrayAccess(FunctionCompiler &f, ParseNode *viewName, ParseNode *indexExpr,
// Mask off the low bits to account for the clearing effect of a right shift
// followed by the left shift implicit in the array access. E.g., H32[i>>2]
// loses the low two bits.
int32_t mask = ~((uint32_t(1) << TypedArrayShift(*viewType)) - 1);
int32_t mask = ~(TypedArrayElemSize(*viewType) - 1);
MDefinition *pointerDef;
if (indexExpr->isKind(PNK_RSH)) {

View File

@ -1128,6 +1128,29 @@ assertEqX4(f32l(SIZE - 1), BatNaN);
assertEqX4(f32l(SIZE - 2), BatNaN);
assertEqX4(f32l(SIZE - 3), BatNaN);
var code = `
"use asm";
var f4 = glob.SIMD.float32x4;
var f4l = f4.load;
var u8 = new glob.Uint8Array(heap);
function g(x) {
x = x|0;
// set a constraint on the size of the heap
var ptr = 0;
ptr = u8[0xFFFF] | 0;
// give a precise range to x
x = (x>>0) > 5 ? 5 : x;
x = (x>>0) < 0 ? 0 : x;
// ptr value gets a precise range but the bounds check shouldn't get
// eliminated.
return f4(f4l(u8, 0xFFFA + x | 0));
}
return g;
`;
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', code), this, {}, new ArrayBuffer(0x10000))(0), BatNaN);
// Float32x4.store
function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); };

View File

@ -2206,15 +2206,17 @@ RangeAnalysis::analyze()
if (iter->isAsmJSLoadHeap()) {
MAsmJSLoadHeap *ins = iter->toAsmJSLoadHeap();
Range *range = ins->ptr()->range();
uint32_t elemSize = TypedArrayElemSize(ins->viewType());
if (range && range->hasInt32LowerBound() && range->lower() >= 0 &&
range->hasInt32UpperBound() && (uint32_t) range->upper() < minHeapLength) {
range->hasInt32UpperBound() && uint32_t(range->upper()) + elemSize < minHeapLength) {
ins->removeBoundsCheck();
}
} else if (iter->isAsmJSStoreHeap()) {
MAsmJSStoreHeap *ins = iter->toAsmJSStoreHeap();
Range *range = ins->ptr()->range();
uint32_t elemSize = TypedArrayElemSize(ins->viewType());
if (range && range->hasInt32LowerBound() && range->lower() >= 0 &&
range->hasInt32UpperBound() && (uint32_t) range->upper() < minHeapLength) {
range->hasInt32UpperBound() && uint32_t(range->upper()) + elemSize < minHeapLength) {
ins->removeBoundsCheck();
}
}

View File

@ -304,6 +304,12 @@ TypedArrayShift(Scalar::Type viewType)
MOZ_CRASH("Unexpected array type");
}
static inline unsigned
TypedArrayElemSize(Scalar::Type viewType)
{
return 1u << TypedArrayShift(viewType);
}
class DataViewObject : public NativeObject
{
private: