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

This commit is contained in:
Morris Tseng 2015-09-29 11:51:24 +01:00
parent 6c5f27cc66
commit d0af7852c8
4 changed files with 80 additions and 8 deletions

View File

@ -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"
@ -1062,6 +1064,25 @@ StructuredCloneHelper::ReadTransferCallback(JSContext* aCx,
return true;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mContext == SameProcessSameThread ||
mContext == 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;
}
@ -1093,6 +1114,24 @@ StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
return true;
}
if (mContext == SameProcessSameThread ||
mContext == 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;
@ -1110,6 +1149,17 @@ StructuredCloneHelper::FreeTransferCallback(uint32_t aTag,
MOZ_ASSERT(!aContent);
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
return;
}
if (aTag == SCTAG_DOM_CANVAS) {
MOZ_ASSERT(mContext == SameProcessSameThread ||
mContext == SameProcessDifferentThread);
MOZ_ASSERT(aContent);
OffscreenCanvasCloneData* data =
static_cast<OffscreenCanvasCloneData*>(aContent);
delete data;
return;
}
}

View File

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

View File

@ -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

View File

@ -2054,7 +2054,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&
@ -2063,7 +2063,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;
}
@ -2088,7 +2088,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_))
@ -2104,31 +2106,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;
}