예제 #1
0
JS_DetachArrayBuffer(JSContext* cx, HandleObject obj,
                     DetachDataDisposition changeData)
{
    if (!obj->is<ArrayBufferObject>()) {
        JS_ReportError(cx, "ArrayBuffer object required");
        return false;
    }

    Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());

    if (changeData == ChangeData && buffer->hasStealableContents()) {
        ArrayBufferObject::BufferContents newContents =
            AllocateArrayBufferContents(cx, buffer->byteLength());
        if (!newContents)
            return false;
        if (!ArrayBufferObject::detach(cx, buffer, newContents)) {
            js_free(newContents.data());
            return false;
        }
    } else {
        if (!ArrayBufferObject::detach(cx, buffer, buffer->contents()))
            return false;
    }

    return true;
}
예제 #2
0
static void
NoteViewBufferWasDetached(ArrayBufferViewObject* view,
                          ArrayBufferObject::BufferContents newContents,
                          JSContext* cx)
{
    view->notifyBufferDetached(newContents.data());

    // Notify compiled jit code that the base pointer has moved.
    MarkObjectStateChange(cx, view);
}
예제 #3
0
static bool
TransferAsmJSMappedBuffer(JSContext* cx, const CallArgs& args,
                          Handle<ArrayBufferObject*> oldBuffer, size_t newByteLength)
{
    size_t oldByteLength = oldBuffer->byteLength();
    MOZ_ASSERT(oldByteLength % AsmJSPageSize == 0);
    MOZ_ASSERT(newByteLength % AsmJSPageSize == 0);

    ArrayBufferObject::BufferContents stolen =
        ArrayBufferObject::stealContents(cx, oldBuffer, /* hasStealableContents = */ true);
    if (!stolen)
        return false;

    MOZ_ASSERT(stolen.kind() == ArrayBufferObject::ASMJS_MAPPED);
    uint8_t* data = stolen.data();

    if (newByteLength > oldByteLength) {
        void* diffStart = data + oldByteLength;
        size_t diffLength = newByteLength - oldByteLength;
#  ifdef XP_WIN
        if (!VirtualAlloc(diffStart, diffLength, MEM_COMMIT, PAGE_READWRITE)) {
            ReleaseAsmJSMappedData(data);
            ReportOutOfMemory(cx);
            return false;
        }
#  else
        // To avoid memset, use MAP_FIXED to clobber the newly-accessible pages
        // with zero pages.
        int flags = MAP_FIXED | MAP_PRIVATE | MAP_ANON;
        if (mmap(diffStart, diffLength, PROT_READ | PROT_WRITE, flags, -1, 0) == MAP_FAILED) {
            ReleaseAsmJSMappedData(data);
            ReportOutOfMemory(cx);
            return false;
        }
#  endif
        MemProfiler::SampleNative(diffStart, diffLength);
    } else if (newByteLength < oldByteLength) {
        void* diffStart = data + newByteLength;
        size_t diffLength = oldByteLength - newByteLength;
#  ifdef XP_WIN
        if (!VirtualFree(diffStart, diffLength, MEM_DECOMMIT)) {
            ReleaseAsmJSMappedData(data);
            ReportOutOfMemory(cx);
            return false;
        }
#  else
        if (madvise(diffStart, diffLength, MADV_DONTNEED) ||
            mprotect(diffStart, diffLength, PROT_NONE))
        {
            ReleaseAsmJSMappedData(data);
            ReportOutOfMemory(cx);
            return false;
        }
#  endif
    }

    ArrayBufferObject::BufferContents newContents =
        ArrayBufferObject::BufferContents::create<ArrayBufferObject::ASMJS_MAPPED>(data);

    RootedObject newBuffer(cx, ArrayBufferObject::create(cx, newByteLength, newContents));
    if (!newBuffer) {
        ReleaseAsmJSMappedData(data);
        return false;
    }

    args.rval().setObject(*newBuffer);
    return true;
}