mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 899903 - OdinMonkey: merge AsmJSBoundsCheckVector with HeapAccessVector (r=mjrosenb)
--HG-- extra : rebase_source : 85be8040e2bdde27bc68679eb6927dec9ca828ed
This commit is contained in:
parent
7ee2ac4c30
commit
1251adf127
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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_) {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user