Bug 899903 - OdinMonkey: merge AsmJSBoundsCheckVector with HeapAccessVector (r=mjrosenb)

--HG--
extra : rebase_source : 85be8040e2bdde27bc68679eb6927dec9ca828ed
This commit is contained in:
Luke Wagner 2013-07-31 03:19:58 -05:00
parent 0fc4510b29
commit eeb85f3043
8 changed files with 58 additions and 125 deletions

View File

@ -1436,13 +1436,8 @@ class MOZ_STACK_CLASS ModuleCompiler
}
bool collectAccesses(MIRGenerator &gen) {
#ifdef JS_CPU_ARM
if (!module_->addBoundsChecks(gen.asmBoundsChecks()))
return false;
#else
if (!module_->addHeapAccesses(gen.heapAccesses()))
return false;
#endif
if (!globalAccesses_.appendAll(gen.globalAccesses()))
return false;
return true;
@ -1589,26 +1584,21 @@ class MOZ_STACK_CLASS ModuleCompiler
data[j] = code + masm_.actualOffset(table.elem(j).code()->offset());
}
// Global accesses in function bodies
// Fix up heap/global accesses now that compilation has finished
#ifdef JS_CPU_ARM
JS_ASSERT(globalAccesses_.length() == 0);
// The AsmJSHeapAccess offsets need to be updated to reflect the
// "actualOffset" (an ARM distinction).
module_->convertBoundsChecksToActualOffset(masm_);
for (unsigned i = 0; i < module_->numHeapAccesses(); i++) {
AsmJSHeapAccess &access = module_->heapAccess(i);
access.setOffset(masm_.actualOffset(access.offset()));
}
JS_ASSERT(globalAccesses_.length() == 0);
#else
for (unsigned i = 0; i < globalAccesses_.length(); i++) {
AsmJSGlobalAccess access = globalAccesses_[i];
masm_.patchAsmJSGlobalAccess(access.offset, code, codeBytes, access.globalDataOffset);
}
#endif
// The AsmJSHeapAccess offsets need to be updated to reflect the
// "actualOffset" (an ARM distinction).
for (unsigned i = 0; i < module_->numHeapAccesses(); i++) {
AsmJSHeapAccess &access = module_->heapAccess(i);
access.updateOffset(masm_.actualOffset(access.offset()));
}
*module = module_.forget();

View File

@ -220,22 +220,7 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
#if defined(JS_CPU_X86)
void *heapOffset = (void*)heap->dataPointer();
void *heapLength = (void*)heap->byteLength();
uint8_t *code = module.functionCode();
for (unsigned i = 0; i < module.numHeapAccesses(); i++) {
const AsmJSHeapAccess &access = module.heapAccess(i);
JSC::X86Assembler::setPointer(access.patchLengthAt(code), heapLength);
JSC::X86Assembler::setPointer(access.patchOffsetAt(code), heapOffset);
}
#elif defined(JS_CPU_ARM)
// Now the length of the array is know, patch all of the bounds check sites
// with the new length.
ion::IonContext ic(cx, NULL);
module.patchBoundsChecks(heap->byteLength());
#endif
module.patchHeapAccesses(heap, cx);
}
AutoObjectVector ffis(cx);

View File

@ -72,6 +72,26 @@ js::NewAsmJSModuleObject(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *module)
return obj;
}
void
AsmJSModule::patchHeapAccesses(ArrayBufferObject *heap, JSContext *cx)
{
JS_ASSERT(IsPowerOfTwo(heap->byteLength()));
#if defined(JS_CPU_X86)
void *heapOffset = (void*)heap->dataPointer();
void *heapLength = (void*)heap->byteLength();
for (unsigned i = 0; i < heapAccesses_.length(); i++) {
JSC::X86Assembler::setPointer(heapAccesses_[i].patchLengthAt(code_), heapLength);
JSC::X86Assembler::setPointer(heapAccesses_[i].patchOffsetAt(code_), heapOffset);
}
#elif defined(JS_CPU_ARM)
ion::IonContext ic(cx, NULL);
ion::AutoFlushCache afc("patchBoundsCheck");
uint32_t bits = mozilla::CeilingLog2(heap->byteLength());
for (unsigned i = 0; i < heapAccesses_.length(); i++)
ion::Assembler::updateBoundsCheck(bits, (ion::Instruction*)(heapAccesses_[i].offset() + code_));
#endif
}
AsmJSModule::~AsmJSModule()
{
if (code_) {

View File

@ -360,9 +360,6 @@ class AsmJSModule
typedef Vector<Global, 0, SystemAllocPolicy> GlobalVector;
typedef Vector<Exit, 0, SystemAllocPolicy> ExitVector;
typedef Vector<ion::AsmJSHeapAccess, 0, SystemAllocPolicy> HeapAccessVector;
#if defined(JS_CPU_ARM)
typedef Vector<ion::AsmJSBoundsCheck, 0, SystemAllocPolicy> BoundsCheckVector;
#endif
typedef Vector<ion::IonScriptCounts *, 0, SystemAllocPolicy> FunctionCountsVector;
#if defined(MOZ_VTUNE) or defined(JS_ION_PERF)
typedef Vector<ProfiledFunction, 0, SystemAllocPolicy> ProfiledFunctionVector;
@ -372,9 +369,6 @@ class AsmJSModule
ExitVector exits_;
ExportedFunctionVector exports_;
HeapAccessVector heapAccesses_;
#if defined(JS_CPU_ARM)
BoundsCheckVector boundsChecks_;
#endif
#if defined(MOZ_VTUNE)
ProfiledFunctionVector profiledFunctions_;
#endif
@ -676,33 +670,7 @@ class AsmJSModule
const ion::AsmJSHeapAccess &heapAccess(unsigned i) const {
return heapAccesses_[i];
}
#if defined(JS_CPU_ARM)
bool addBoundsChecks(const ion::AsmJSBoundsCheckVector &checks) {
return boundsChecks_.appendAll(checks);
}
void convertBoundsChecksToActualOffset(ion::MacroAssembler &masm) {
for (unsigned i = 0; i < boundsChecks_.length(); i++)
boundsChecks_[i].setOffset(masm.actualOffset(boundsChecks_[i].offset()));
}
void patchBoundsChecks(unsigned heapSize) {
if (heapSize == 0)
return;
ion::AutoFlushCache afc("patchBoundsCheck");
uint32_t bits = mozilla::CeilingLog2(heapSize);
for (unsigned i = 0; i < boundsChecks_.length(); i++)
ion::Assembler::updateBoundsCheck(bits, (ion::Instruction*)(boundsChecks_[i].offset() + code_));
}
unsigned numBoundsChecks() const {
return boundsChecks_.length();
}
const ion::AsmJSBoundsCheck &boundsCheck(unsigned i) const {
return boundsChecks_[i];
}
#endif
void patchHeapAccesses(ArrayBufferObject *heap, JSContext *cx);
void takeOwnership(JSC::ExecutablePool *pool, uint8_t *code, size_t codeBytes, size_t totalBytes) {
JS_ASSERT(uintptr_t(code) % AsmJSPageSize == 0);

View File

@ -115,21 +115,12 @@ class MIRGenerator
JS_ASSERT(compilingAsmJS());
return performsAsmJSCall_;
}
#ifndef JS_CPU_ARM
bool noteHeapAccess(AsmJSHeapAccess heapAccess) {
return asmJSHeapAccesses_.append(heapAccess);
}
const Vector<AsmJSHeapAccess, 0, IonAllocPolicy> &heapAccesses() const {
return asmJSHeapAccesses_;
}
#else
bool noteBoundsCheck(uint32_t offsetBefore) {
return asmJSBoundsChecks_.append(AsmJSBoundsCheck(offsetBefore));
}
const Vector<AsmJSBoundsCheck, 0, IonAllocPolicy> &asmBoundsChecks() const {
return asmJSBoundsChecks_;
}
#endif
bool noteGlobalAccess(unsigned offset, unsigned globalDataOffset) {
return asmJSGlobalAccesses_.append(AsmJSGlobalAccess(offset, globalDataOffset));
}
@ -151,11 +142,7 @@ class MIRGenerator
uint32_t maxAsmJSStackArgBytes_;
bool performsAsmJSCall_;
#ifdef JS_CPU_ARM
AsmJSBoundsCheckVector asmJSBoundsChecks_;
#else
AsmJSHeapAccessVector asmJSHeapAccesses_;
#endif
AsmJSGlobalAccessVector asmJSGlobalAccesses_;
#if defined(JS_ION_PERF)

View File

@ -785,77 +785,60 @@ class ABIArg
class AsmJSHeapAccess
{
uint32_t offset_;
uint8_t opLength_;
#if defined(JS_CPU_X86)
uint8_t cmpDelta_;
uint8_t cmpDelta_; // the number of bytes from the cmp to the load/store instruction
#endif
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
uint8_t opLength_; // the length of the load/store instruction
uint8_t isFloat32Load_;
ion::AnyRegister::Code loadedReg_ : 8;
#endif
JS_STATIC_ASSERT(ion::AnyRegister::Total < UINT8_MAX);
public:
#if defined(JS_CPU_X86)
AsmJSHeapAccess(uint32_t cmp, uint32_t offset, uint32_t after, ArrayBufferView::ViewType vt,
AnyRegister loadedReg)
: offset_(offset),
opLength_(after - offset),
cmpDelta_(offset - cmp),
isFloat32Load_(vt == ArrayBufferView::TYPE_FLOAT32),
loadedReg_(loadedReg.code())
{}
AsmJSHeapAccess(uint32_t cmp, uint32_t offset, uint8_t after)
: offset_(offset),
opLength_(after - offset),
cmpDelta_(offset - cmp),
isFloat32Load_(false),
loadedReg_(UINT8_MAX)
{}
#else
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
AsmJSHeapAccess(uint32_t offset, uint32_t after, ArrayBufferView::ViewType vt,
AnyRegister loadedReg)
AnyRegister loadedReg, uint32_t cmp = UINT32_MAX)
: offset_(offset),
# if defined(JS_CPU_X86)
cmpDelta_(offset - cmp),
# endif
opLength_(after - offset),
isFloat32Load_(vt == ArrayBufferView::TYPE_FLOAT32),
loadedReg_(loadedReg.code())
{}
AsmJSHeapAccess(uint32_t offset, uint8_t after)
AsmJSHeapAccess(uint32_t offset, uint8_t after, uint32_t cmp = UINT32_MAX)
: offset_(offset),
# if defined(JS_CPU_X86)
cmpDelta_(offset - cmp),
# endif
opLength_(after - offset),
isFloat32Load_(false),
loadedReg_(UINT8_MAX)
{}
#elif defined(JS_CPU_ARM)
explicit AsmJSHeapAccess(uint32_t offset)
: offset_(offset)
{}
#endif
uint32_t offset() const { return offset_; }
unsigned opLength() const { return opLength_; }
bool isLoad() const { return loadedReg_ != UINT8_MAX; }
bool isFloat32Load() const { return isFloat32Load_; }
ion::AnyRegister loadedReg() const { return ion::AnyRegister::FromCode(loadedReg_); }
void setOffset(uint32_t offset) { offset_ = offset; }
#if defined(JS_CPU_X86)
void *patchLengthAt(uint8_t *code) const { return code + (offset_ - cmpDelta_); }
void *patchOffsetAt(uint8_t *code) const { return code + (offset_ + opLength_); }
#endif
void updateOffset(uint32_t offset) { offset_ = offset; }
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
unsigned opLength() const { return opLength_; }
bool isLoad() const { return loadedReg_ != UINT8_MAX; }
bool isFloat32Load() const { return isFloat32Load_; }
ion::AnyRegister loadedReg() const { return ion::AnyRegister::FromCode(loadedReg_); }
#endif
};
typedef Vector<AsmJSHeapAccess, 0, IonAllocPolicy> AsmJSHeapAccessVector;
#ifdef JS_CPU_ARM
struct AsmJSBoundsCheck
{
unsigned offset_;
AsmJSBoundsCheck(unsigned offset)
: offset_(offset)
{}
void setOffset(uint32_t offset) { offset_ = offset; }
unsigned offset() {return offset_;}
};
typedef Vector<AsmJSBoundsCheck, 0, IonAllocPolicy> AsmJSBoundsCheckVector;
#endif
} // namespace ion
} // namespace js

View File

@ -1808,7 +1808,7 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
ToRegister(ins->output()), Offset, Assembler::Zero);
masm.ma_mov(Imm32(0), ToRegister(ins->output()), NoSetCond, Assembler::NonZero);
}
return gen->noteBoundsCheck(bo.getOffset());
return gen->noteHeapAccess(AsmJSHeapAccess(bo.getOffset()));
}
bool
@ -1846,7 +1846,7 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
masm.ma_dataTransferN(IsStore, size, isSigned, HeapReg, index,
ToRegister(ins->value()), Offset, Assembler::Zero);
}
return gen->noteBoundsCheck(bo.getOffset());
return gen->noteHeapAccess(AsmJSHeapAccess(bo.getOffset()));
}
bool

View File

@ -496,13 +496,13 @@ CodeGeneratorX86::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
uint32_t after = masm.size();
masm.cvtss2sd(dest, dest);
masm.bind(ool->rejoin());
return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after, vt, AnyRegister(dest)));
return gen->noteHeapAccess(AsmJSHeapAccess(before, after, vt, AnyRegister(dest), cmp.offset()));
}
uint32_t before = masm.size();
loadViewTypeElement(vt, srcAddr, out);
uint32_t after = masm.size();
masm.bind(ool->rejoin());
return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after, vt, ToAnyRegister(out)));
return gen->noteHeapAccess(AsmJSHeapAccess(before, after, vt, ToAnyRegister(out), cmp.offset()));
}
bool
@ -583,13 +583,13 @@ CodeGeneratorX86::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
masm.movssWithPatch(ScratchFloatReg, dstAddr);
uint32_t after = masm.size();
masm.bind(&rejoin);
return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after));
return gen->noteHeapAccess(AsmJSHeapAccess(before, after, cmp.offset()));
}
uint32_t before = masm.size();
storeViewTypeElement(vt, value, dstAddr);
uint32_t after = masm.size();
masm.bind(&rejoin);
return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after));
return gen->noteHeapAccess(AsmJSHeapAccess(before, after, cmp.offset()));
}
bool