static bool LinkModuleToHeap(JSContext* cx, AsmJSModule& module, Handle<ArrayBufferObjectMaybeShared*> heap) { uint32_t heapLength = heap->byteLength(); if (!IsValidAsmJSHeapLength(heapLength)) { ScopedJSFreePtr<char> msg( JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next " "valid length is 0x%x", heapLength, RoundUpToNextValidAsmJSHeapLength(heapLength))); return LinkFail(cx, msg.get()); } // This check is sufficient without considering the size of the loaded datum because heap // loads and stores start on an aligned boundary and the heap byteLength has larger alignment. MOZ_ASSERT((module.minHeapLength() - 1) <= INT32_MAX); if (heapLength < module.minHeapLength()) { ScopedJSFreePtr<char> msg( JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (the size implied " "by const heap accesses and/or change-heap minimum-length requirements).", heapLength, module.minHeapLength())); return LinkFail(cx, msg.get()); } if (heapLength > module.maxHeapLength()) { ScopedJSFreePtr<char> msg( JS_smprintf("ArrayBuffer byteLength 0x%x is greater than maximum length of 0x%x", heapLength, module.maxHeapLength())); return LinkFail(cx, msg.get()); } // If we've generated the code with signal handlers in mind (for bounds // checks on x64 and for interrupt callback requesting on all platforms), // we need to be able to use signals at runtime. In particular, a module // can have been created using signals and cached, and executed without // signals activated. if (module.usesSignalHandlersForInterrupt() && !cx->canUseSignalHandlers()) return LinkFail(cx, "Code generated with signal handlers but signals are deactivated"); if (heap->is<ArrayBufferObject>()) { Rooted<ArrayBufferObject*> abheap(cx, &heap->as<ArrayBufferObject>()); if (!ArrayBufferObject::prepareForAsmJS(cx, abheap, module.usesSignalHandlersForOOB())) return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use"); } module.initHeap(heap, cx); return true; }
static bool ChangeHeap(JSContext *cx, AsmJSModule &module, CallArgs args) { HandleValue bufferArg = args.get(0); if (!IsArrayBuffer(bufferArg)) { ReportIncompatible(cx, args); return false; } Rooted<ArrayBufferObject*> newBuffer(cx, &bufferArg.toObject().as<ArrayBufferObject>()); uint32_t heapLength = newBuffer->byteLength(); if (heapLength & module.heapLengthMask() || heapLength < module.minHeapLength() || heapLength > module.maxHeapLength()) { args.rval().set(BooleanValue(false)); return true; } if (!module.hasArrayView()) { args.rval().set(BooleanValue(true)); return true; } MOZ_ASSERT(IsValidAsmJSHeapLength(heapLength)); MOZ_ASSERT(!IsDeprecatedAsmJSHeapLength(heapLength)); if (!ArrayBufferObject::prepareForAsmJS(cx, newBuffer, module.usesSignalHandlersForOOB())) return false; args.rval().set(BooleanValue(module.changeHeap(newBuffer, cx))); return true; }