StencilObject.cpp (4950B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "vm/StencilObject.h" 8 9 #include "mozilla/Assertions.h" // MOZ_ASSERT 10 #include "mozilla/PodOperations.h" // mozilla::PodCopy 11 12 #include <stddef.h> // size_t 13 #include <stdint.h> // uint8_t, INT32_MAX 14 15 #include "jsapi.h" // JS_NewObject 16 #include "js/Class.h" // JSClassOps, JSClass, JSCLASS_* 17 #include "js/ErrorReport.h" // JS_ReportErrorASCII 18 #include "js/experimental/JSStencil.h" // JS::Stencil, JS::StencilAddRef, JS::StencilRelease 19 #include "js/Utility.h" // js_free 20 #include "vm/JSContext.h" // JSContext 21 #include "vm/JSObject.h" // JSObject 22 23 #include "vm/JSObject-inl.h" // NewBuiltinClassInstance 24 25 using namespace js; 26 27 /*static */ const JSClassOps StencilObject::classOps_ = { 28 nullptr, // addProperty 29 nullptr, // delProperty 30 nullptr, // enumerate 31 nullptr, // newEnumerate 32 nullptr, // resolve 33 nullptr, // mayResolve 34 StencilObject::finalize, // finalize 35 nullptr, // call 36 nullptr, // construct 37 nullptr, // trace 38 }; 39 40 /*static */ const JSClass StencilObject::class_ = { 41 "StencilObject", 42 JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots) | 43 JSCLASS_BACKGROUND_FINALIZE, 44 &StencilObject::classOps_, 45 }; 46 47 bool StencilObject::hasStencil() const { 48 // The stencil may not be present yet if we GC during initialization. 49 return !getReservedSlot(StencilSlot).isUndefined(); 50 } 51 52 JS::Stencil* StencilObject::stencil() const { 53 void* ptr = getReservedSlot(StencilSlot).toPrivate(); 54 MOZ_ASSERT(ptr); 55 return static_cast<JS::Stencil*>(ptr); 56 } 57 58 /* static */ StencilObject* StencilObject::create(JSContext* cx, 59 RefPtr<JS::Stencil> stencil) { 60 auto* obj = NewBuiltinClassInstance<StencilObject>(cx); 61 if (!obj) { 62 return nullptr; 63 } 64 65 obj->setReservedSlot(StencilSlot, PrivateValue(stencil.forget().take())); 66 67 return obj; 68 } 69 70 /* static */ void StencilObject::finalize(JS::GCContext* gcx, JSObject* obj) { 71 if (obj->as<StencilObject>().hasStencil()) { 72 JS::StencilRelease(obj->as<StencilObject>().stencil()); 73 } 74 } 75 76 /*static */ const JSClassOps StencilXDRBufferObject::classOps_ = { 77 nullptr, // addProperty 78 nullptr, // delProperty 79 nullptr, // enumerate 80 nullptr, // newEnumerate 81 nullptr, // resolve 82 nullptr, // mayResolve 83 StencilXDRBufferObject::finalize, // finalize 84 nullptr, // call 85 nullptr, // construct 86 nullptr, // trace 87 }; 88 89 /*static */ const JSClass StencilXDRBufferObject::class_ = { 90 "StencilXDRBufferObject", 91 JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots) | 92 JSCLASS_BACKGROUND_FINALIZE, 93 &StencilXDRBufferObject::classOps_, 94 }; 95 96 bool StencilXDRBufferObject::hasBuffer() const { 97 // The stencil may not be present yet if we GC during initialization. 98 return !getReservedSlot(BufferSlot).isUndefined(); 99 } 100 101 const uint8_t* StencilXDRBufferObject::buffer() const { 102 void* ptr = getReservedSlot(BufferSlot).toPrivate(); 103 MOZ_ASSERT(ptr); 104 return static_cast<const uint8_t*>(ptr); 105 } 106 107 uint8_t* StencilXDRBufferObject::writableBuffer() { 108 void* ptr = getReservedSlot(BufferSlot).toPrivate(); 109 MOZ_ASSERT(ptr); 110 return static_cast<uint8_t*>(ptr); 111 } 112 113 size_t StencilXDRBufferObject::bufferLength() const { 114 return getReservedSlot(LengthSlot).toInt32(); 115 } 116 117 /* static */ StencilXDRBufferObject* StencilXDRBufferObject::create( 118 JSContext* cx, uint8_t* buffer, size_t length) { 119 if (length >= INT32_MAX) { 120 JS_ReportErrorASCII(cx, "XDR buffer is too long"); 121 return nullptr; 122 } 123 124 auto* obj = NewBuiltinClassInstance<StencilXDRBufferObject>(cx); 125 if (!obj) { 126 return nullptr; 127 } 128 129 auto ownedBuffer = cx->make_pod_array<uint8_t>(length); 130 if (!ownedBuffer) { 131 return nullptr; 132 } 133 134 mozilla::PodCopy(ownedBuffer.get(), buffer, length); 135 136 obj->setReservedSlot(BufferSlot, PrivateValue(ownedBuffer.release())); 137 obj->setReservedSlot(LengthSlot, Int32Value(length)); 138 139 return obj; 140 } 141 142 /* static */ void StencilXDRBufferObject::finalize(JS::GCContext* gcx, 143 JSObject* obj) { 144 if (obj->as<StencilXDRBufferObject>().hasBuffer()) { 145 js_free(obj->as<StencilXDRBufferObject>().writableBuffer()); 146 } 147 }