Bug 1125236 - SpiderMonkey: Verify that asm.js heap loads and stores can be correctly disassembled r=jandem

This commit is contained in:
Dan Gohman 2015-01-30 16:32:26 -08:00
parent 9057901f95
commit c097b35626
9 changed files with 97 additions and 0 deletions

View File

@ -244,6 +244,16 @@ MOZ_COLD uint8_t *DisassembleHeapAccess(uint8_t *ptr, HeapAccess *access);
#ifdef DEBUG
void DumpHeapAccess(const HeapAccess &access);
inline void
VerifyHeapAccess(uint8_t *begin, uint8_t *end, const HeapAccess &expected)
{
HeapAccess disassembled;
uint8_t *e = DisassembleHeapAccess(begin, &disassembled);
MOZ_ASSERT(e == end);
MOZ_ASSERT(disassembled == expected);
}
#endif
} // namespace Disassembler

View File

@ -1799,6 +1799,12 @@ class Assembler : public AssemblerShared
bool bailed() {
return m_buffer.bail();
}
void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
const Disassembler::HeapAccess &heapAccess)
{
// Implement this if we implement a disassembler.
}
}; // Assembler
// An Instruction is a structure for both encoding and decoding any and all ARM

View File

@ -1086,6 +1086,12 @@ class Assembler : public AssemblerShared
bool bailed() {
return m_buffer.bail();
}
void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
const Disassembler::HeapAccess &heapAccess)
{
// Implement this if we implement a disassembler.
}
}; // Assembler
// sll zero, zero, 0

View File

@ -30,6 +30,10 @@
namespace js {
namespace jit {
namespace Disassembler {
class HeapAccess;
};
static const uint32_t Simd128DataSize = 4 * sizeof(int32_t);
static_assert(Simd128DataSize == 4 * sizeof(int32_t), "SIMD data should be able to contain int32x4");
static_assert(Simd128DataSize == 4 * sizeof(float), "SIMD data should be able to contain float32x4");

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gc/Marking.h"
#include "jit/Disassembler.h"
#include "jit/JitCompartment.h"
#if defined(JS_CODEGEN_X86)
# include "jit/x86/MacroAssembler-x86.h"
@ -139,6 +140,15 @@ AssemblerX86Shared::InvertCondition(Condition cond)
}
}
void
AssemblerX86Shared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
const Disassembler::HeapAccess &heapAccess)
{
#ifdef DEBUG
Disassembler::VerifyHeapAccess(masm.data() + begin, masm.data() + end, heapAccess);
#endif
}
CPUInfo::SSEVersion CPUInfo::maxSSEVersion = UnknownSSE;
CPUInfo::SSEVersion CPUInfo::maxEnabledSSEVersion = UnknownSSE;
bool CPUInfo::avxPresent = false;

View File

@ -2594,6 +2594,9 @@ class AssemblerX86Shared : public AssemblerShared
*ptr == 0xE8); // CALL
*ptr = enabled ? 0xE8 : 0x3D;
}
MOZ_COLD void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
const Disassembler::HeapAccess &heapAccess);
};
} // namespace jit

View File

@ -8,6 +8,7 @@
#define jit_shared_CodeGenerator_shared_inl_h
#include "jit/shared/CodeGenerator-shared.h"
#include "jit/Disassembler.h"
namespace js {
namespace jit {
@ -183,6 +184,57 @@ CodeGeneratorShared::restoreLiveVolatile(LInstruction *ins)
masm.PopRegsInMask(regs);
}
void
CodeGeneratorShared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end, bool isLoad,
Scalar::Type type, const Operand &mem,
LAllocation alloc)
{
#ifdef DEBUG
using namespace Disassembler;
OtherOperand op;
Disassembler::HeapAccess::Kind kind = isLoad ? HeapAccess::Load : HeapAccess::Store;
switch (type) {
case Scalar::Int8:
case Scalar::Int16:
if (kind == HeapAccess::Load)
kind = HeapAccess::LoadSext32;
// FALL THROUGH
case Scalar::Uint8:
case Scalar::Uint16:
case Scalar::Int32:
case Scalar::Uint32:
if (!alloc.isConstant()) {
op = OtherOperand(ToRegister(alloc).code());
} else {
int32_t i = ToInt32(&alloc);
// Sign-extend the immediate value out to 32 bits. We do this even
// for unsigned element types so that we match what the disassembly
// code does, as it doesn't know about signedness of stores.
unsigned shift = 32 - TypedArrayElemSize(type) * 8;
i = i << shift >> shift;
op = OtherOperand(i);
}
break;
case Scalar::Float32:
case Scalar::Float64:
case Scalar::Float32x4:
case Scalar::Int32x4:
op = OtherOperand(ToFloatRegister(alloc).code());
break;
case Scalar::Uint8Clamped:
case Scalar::MaxTypedArrayViewType:
MOZ_CRASH("Unexpected array type");
}
masm.verifyHeapAccessDisassembly(begin, end,
HeapAccess(kind, TypedArrayElemSize(type),
ComplexAddress(mem), op));
#endif
}
} // ion
} // js

View File

@ -545,6 +545,10 @@ class CodeGeneratorShared : public LElementVisitor
emitTracelogScriptStop();
#endif
}
inline void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end, bool isLoad,
Scalar::Type type, const Operand &mem,
LAllocation alloc);
};
// An out-of-line path is generated at the end of the function.

View File

@ -300,6 +300,7 @@ CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
MOZ_CRASH("unexpected array type");
}
uint32_t after = masm.size();
verifyHeapAccessDisassembly(before, after, /*isLoad=*/true, vt, srcAddr, *out->output());
if (ool)
masm.bind(ool->rejoin());
memoryBarrier(ins->mir()->barrierAfter());
@ -366,6 +367,7 @@ CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
}
}
uint32_t after = masm.size();
verifyHeapAccessDisassembly(before, after, /*isLoad=*/false, vt, dstAddr, *ins->value());
if (rejoin.used())
masm.bind(&rejoin);
memoryBarrier(ins->mir()->barrierAfter());