diff options
Diffstat (limited to 'js/src/vm/StencilObject.cpp')
-rw-r--r-- | js/src/vm/StencilObject.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/js/src/vm/StencilObject.cpp b/js/src/vm/StencilObject.cpp new file mode 100644 index 0000000000..da8a144e81 --- /dev/null +++ b/js/src/vm/StencilObject.cpp @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "vm/StencilObject.h" + +#include "mozilla/Assertions.h" // MOZ_ASSERT +#include "mozilla/PodOperations.h" // mozilla::PodCopy + +#include <stddef.h> // size_t +#include <stdint.h> // uint8_t, INT32_MAX + +#include "jsapi.h" // JS_NewObject +#include "js/Class.h" // JSClassOps, JSClass, JSCLASS_* +#include "js/ErrorReport.h" // JS_ReportErrorASCII +#include "js/experimental/JSStencil.h" // JS::Stencil, JS::StencilAddRef, JS::StencilRelease +#include "js/RootingAPI.h" // JS::Rooted +#include "js/Utility.h" // js_free +#include "vm/JSContext.h" // JSContext +#include "vm/JSObject.h" // JSObject + +using namespace js; + +/*static */ const JSClassOps StencilObject::classOps_ = { + nullptr, // addProperty + nullptr, // delProperty + nullptr, // enumerate + nullptr, // newEnumerate + nullptr, // resolve + nullptr, // mayResolve + StencilObject::finalize, // finalize + nullptr, // call + nullptr, // construct + nullptr, // trace +}; + +/*static */ const JSClass StencilObject::class_ = { + "StencilObject", + JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots) | + JSCLASS_BACKGROUND_FINALIZE, + &StencilObject::classOps_}; + +bool StencilObject::hasStencil() const { + // The stencil may not be present yet if we GC during initialization. + return !getReservedSlot(StencilSlot).isUndefined(); +} + +JS::Stencil* StencilObject::stencil() const { + void* ptr = getReservedSlot(StencilSlot).toPrivate(); + MOZ_ASSERT(ptr); + return static_cast<JS::Stencil*>(ptr); +} + +/* static */ StencilObject* StencilObject::create(JSContext* cx, + RefPtr<JS::Stencil> stencil) { + JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_)); + if (!obj) { + return nullptr; + } + + obj->as<StencilObject>().setReservedSlot( + StencilSlot, PrivateValue(stencil.forget().take())); + + return &obj->as<StencilObject>(); +} + +/* static */ void StencilObject::finalize(JS::GCContext* gcx, JSObject* obj) { + if (obj->as<StencilObject>().hasStencil()) { + JS::StencilRelease(obj->as<StencilObject>().stencil()); + } +} + +/*static */ const JSClassOps StencilXDRBufferObject::classOps_ = { + nullptr, // addProperty + nullptr, // delProperty + nullptr, // enumerate + nullptr, // newEnumerate + nullptr, // resolve + nullptr, // mayResolve + StencilXDRBufferObject::finalize, // finalize + nullptr, // call + nullptr, // construct + nullptr, // trace +}; + +/*static */ const JSClass StencilXDRBufferObject::class_ = { + "StencilXDRBufferObject", + JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots) | + JSCLASS_BACKGROUND_FINALIZE, + &StencilXDRBufferObject::classOps_}; + +bool StencilXDRBufferObject::hasBuffer() const { + // The stencil may not be present yet if we GC during initialization. + return !getReservedSlot(BufferSlot).isUndefined(); +} + +const uint8_t* StencilXDRBufferObject::buffer() const { + void* ptr = getReservedSlot(BufferSlot).toPrivate(); + MOZ_ASSERT(ptr); + return static_cast<const uint8_t*>(ptr); +} + +uint8_t* StencilXDRBufferObject::writableBuffer() { + void* ptr = getReservedSlot(BufferSlot).toPrivate(); + MOZ_ASSERT(ptr); + return static_cast<uint8_t*>(ptr); +} + +size_t StencilXDRBufferObject::bufferLength() const { + return getReservedSlot(LengthSlot).toInt32(); +} + +/* static */ StencilXDRBufferObject* StencilXDRBufferObject::create( + JSContext* cx, uint8_t* buffer, size_t length) { + if (length >= INT32_MAX) { + JS_ReportErrorASCII(cx, "XDR buffer is too long"); + return nullptr; + } + + JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_)); + if (!obj) { + return nullptr; + } + + auto ownedBuffer = cx->make_pod_array<uint8_t>(length); + if (!ownedBuffer) { + return nullptr; + } + + mozilla::PodCopy(ownedBuffer.get(), buffer, length); + + obj->as<StencilXDRBufferObject>().setReservedSlot( + BufferSlot, PrivateValue(ownedBuffer.release())); + obj->as<StencilXDRBufferObject>().setReservedSlot(LengthSlot, + Int32Value(length)); + + return &obj->as<StencilXDRBufferObject>(); +} + +/* static */ void StencilXDRBufferObject::finalize(JS::GCContext* gcx, + JSObject* obj) { + if (obj->as<StencilXDRBufferObject>().hasBuffer()) { + js_free(obj->as<StencilXDRBufferObject>().writableBuffer()); + } +} |