From eeb85f3043e872da34ecdbaf6cba673ccc53089d Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 31 Jul 2013 03:19:58 -0500 Subject: [PATCH] Bug 899903 - OdinMonkey: merge AsmJSBoundsCheckVector with HeapAccessVector (r=mjrosenb) --HG-- extra : rebase_source : 85be8040e2bdde27bc68679eb6927dec9ca828ed --- js/src/ion/AsmJS.cpp | 22 +++------- js/src/ion/AsmJSLink.cpp | 17 +------- js/src/ion/AsmJSModule.cpp | 20 +++++++++ js/src/ion/AsmJSModule.h | 34 +-------------- js/src/ion/MIRGenerator.h | 13 ------ js/src/ion/RegisterSets.h | 65 ++++++++++------------------ js/src/ion/arm/CodeGenerator-arm.cpp | 4 +- js/src/ion/x86/CodeGenerator-x86.cpp | 8 ++-- 8 files changed, 58 insertions(+), 125 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 90aeb03471d..3f987cb7641 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -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(); diff --git a/js/src/ion/AsmJSLink.cpp b/js/src/ion/AsmJSLink.cpp index e0de2367dfb..609193cd771 100644 --- a/js/src/ion/AsmJSLink.cpp +++ b/js/src/ion/AsmJSLink.cpp @@ -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); diff --git a/js/src/ion/AsmJSModule.cpp b/js/src/ion/AsmJSModule.cpp index 6dfe283eaba..0a2b2a543f4 100644 --- a/js/src/ion/AsmJSModule.cpp +++ b/js/src/ion/AsmJSModule.cpp @@ -72,6 +72,26 @@ js::NewAsmJSModuleObject(JSContext *cx, ScopedJSDeletePtr *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_) { diff --git a/js/src/ion/AsmJSModule.h b/js/src/ion/AsmJSModule.h index 273326dbd08..ae8d6222cb1 100644 --- a/js/src/ion/AsmJSModule.h +++ b/js/src/ion/AsmJSModule.h @@ -360,9 +360,6 @@ class AsmJSModule typedef Vector GlobalVector; typedef Vector ExitVector; typedef Vector HeapAccessVector; -#if defined(JS_CPU_ARM) - typedef Vector BoundsCheckVector; -#endif typedef Vector FunctionCountsVector; #if defined(MOZ_VTUNE) or defined(JS_ION_PERF) typedef Vector 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); diff --git a/js/src/ion/MIRGenerator.h b/js/src/ion/MIRGenerator.h index 5e2c2ced2ab..134f244c86e 100644 --- a/js/src/ion/MIRGenerator.h +++ b/js/src/ion/MIRGenerator.h @@ -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 &heapAccesses() const { return asmJSHeapAccesses_; } -#else - bool noteBoundsCheck(uint32_t offsetBefore) { - return asmJSBoundsChecks_.append(AsmJSBoundsCheck(offsetBefore)); - } - const Vector &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) diff --git a/js/src/ion/RegisterSets.h b/js/src/ion/RegisterSets.h index 4bf9e667c41..ee0441e8f40 100644 --- a/js/src/ion/RegisterSets.h +++ b/js/src/ion/RegisterSets.h @@ -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 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 AsmJSBoundsCheckVector; -#endif - } // namespace ion } // namespace js diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index f6ba87dc4f3..82ab59965d0 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -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 diff --git a/js/src/ion/x86/CodeGenerator-x86.cpp b/js/src/ion/x86/CodeGenerator-x86.cpp index e848792cd4a..9609c9264de 100644 --- a/js/src/ion/x86/CodeGenerator-x86.cpp +++ b/js/src/ion/x86/CodeGenerator-x86.cpp @@ -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