Bug 709490 - Part 3: Transfer OffscreenCanvas from mainthread to workers. r=baku, r=sfink

Thanks Jon Morton [:jmorton] (jonanin@gmail.com) for polishing patches.

--HG--
extra : rebase_source : 5cbf8b9f53b7d1978c6371dbdb3771f80b94a171
This commit is contained in:
Morris Tseng 2015-10-12 11:21:03 +08:00
Родитель d5147a9b2a
Коммит 6c0c249c5a
4 изменённых файлов: 80 добавлений и 8 удалений

Просмотреть файл

@ -21,6 +21,8 @@
#include "mozilla/dom/StructuredClone.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/MessagePortBinding.h"
#include "mozilla/dom/OffscreenCanvas.h"
#include "mozilla/dom/OffscreenCanvasBinding.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/SubtleCryptoBinding.h"
@ -1014,6 +1016,25 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
return true;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread);
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
nsRefPtr<OffscreenCanvas> canvas = OffscreenCanvas::CreateFromCloneData(data);
delete data;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, canvas, &value)) {
JS_ClearPendingException(aCx);
return false;
}
aReturnObject.set(&value.toObject());
return true;
}
return false;
}
@ -1045,6 +1066,24 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
return true;
}
if (mSupportedContext == SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread) {
OffscreenCanvas* canvas = nullptr;
rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(canvas);
*aExtraData = 0;
*aTag = SCTAG_DOM_CANVAS;
*aOwnership = JS::SCTAG_TMO_CUSTOM;
*aContent = canvas->ToCloneData();
MOZ_ASSERT(*aContent);
canvas->SetNeutered();
return true;
}
}
}
return false;
@ -1062,6 +1101,17 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
MOZ_ASSERT(!aContent);
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
return;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mSupportedContext == SameProcessSameThread ||
mSupportedContext == SameProcessDifferentThread);
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
delete data;
return;
}
}

Просмотреть файл

@ -48,6 +48,9 @@ enum StructuredCloneTags {
SCTAG_DOM_FORMDATA,
// This tag is for OffscreenCanvas.
SCTAG_DOM_CANVAS,
SCTAG_DOM_MAX
};

Просмотреть файл

@ -195,17 +195,20 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
// Copy some memory. It will be automatically freed by the destructor.
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
// Adopt some memory. It will be automatically freed by the destructor.
// data must have been allocated by the JS engine (e.g., extracted via
// JSAutoStructuredCloneBuffer::steal).
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
// Release the buffer and transfer ownership to the caller. The caller is
// responsible for calling JS_ClearStructuredClone or feeding the memory
// back to JSAutoStructuredCloneBuffer::adopt.
void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr);
void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr,
const JSStructuredCloneCallbacks** callbacks=nullptr, void** closure=nullptr);
// Abandon ownership of any transferable objects stored in the buffer,
// without freeing the buffer itself. Useful when copying the data out into

Просмотреть файл

@ -2049,7 +2049,7 @@ JS_StructuredClone(JSContext* cx, HandleValue value, MutableHandleValue vp,
JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
{
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_);
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
}
JSAutoStructuredCloneBuffer&
@ -2058,7 +2058,7 @@ JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
MOZ_ASSERT(&other != this);
clear();
ownTransferables_ = other.ownTransferables_;
other.steal(&data_, &nbytes_, &version_);
other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
return *this;
}
@ -2083,7 +2083,9 @@ JSAutoStructuredCloneBuffer::clear(const JSStructuredCloneCallbacks* optionalCal
}
bool
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version,
const JSStructuredCloneCallbacks* callbacks,
void* closure)
{
// transferable objects cannot be copied
if (StructuredCloneHasTransferObjects(data_, nbytes_))
@ -2099,31 +2101,45 @@ JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32
data_ = newData;
nbytes_ = nbytes;
version_ = version;
callbacks_ = callbacks;
closure_ = closure;
ownTransferables_ = NoTransferables;
return true;
}
void
JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version)
JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version,
const JSStructuredCloneCallbacks* callbacks,
void* closure)
{
clear();
data_ = data;
nbytes_ = nbytes;
version_ = version;
callbacks_ = callbacks;
closure_ = closure;
ownTransferables_ = OwnsTransferablesIfAny;
}
void
JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp)
JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp,
const JSStructuredCloneCallbacks** callbacks,
void** closure)
{
*datap = data_;
*nbytesp = nbytes_;
if (versionp)
*versionp = version_;
if (callbacks)
*callbacks = callbacks_;
if (closure)
*closure = closure_;
data_ = nullptr;
nbytes_ = 0;
version_ = 0;
callbacks_ = 0;
closure_ = 0;
ownTransferables_ = NoTransferables;
}