js/src/vm/ArrayBufferObject.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     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/. */
     7 #ifndef vm_ArrayBufferObject_h
     8 #define vm_ArrayBufferObject_h
    10 #include "jsobj.h"
    12 #include "builtin/TypedObjectConstants.h"
    13 #include "vm/Runtime.h"
    15 typedef struct JSProperty JSProperty;
    17 namespace js {
    19 class ArrayBufferViewObject;
    21 // The inheritance hierarchy for the various classes relating to typed arrays
    22 // is as follows.
    23 //
    24 // - JSObject
    25 //   - ArrayBufferObject
    26 //     - SharedArrayBufferObject
    27 //   - ArrayBufferViewObject
    28 //     - DataViewObject
    29 //     - TypedArrayObject (declared in vm/TypedArrayObject.h)
    30 //       - TypedArrayObjectTemplate
    31 //         - Int8ArrayObject
    32 //         - Uint8ArrayObject
    33 //         - ...
    34 //     - TypedObject (declared in builtin/TypedObject.h)
    35 //
    36 // Note that |TypedArrayObjectTemplate| is just an implementation
    37 // detail that makes implementing its various subclasses easier.
    39 typedef Vector<ArrayBufferObject *, 0, SystemAllocPolicy> ArrayBufferVector;
    41 /*
    42  * ArrayBufferObject
    43  *
    44  * This class holds the underlying raw buffer that the various
    45  * ArrayBufferViewObject subclasses (DataViewObject and the TypedArrays)
    46  * access. It can be created explicitly and passed to an ArrayBufferViewObject
    47  * subclass, or can be created implicitly by constructing a TypedArrayObject
    48  * with a size.
    49  */
    50 class ArrayBufferObject : public JSObject
    51 {
    52     static bool byteLengthGetterImpl(JSContext *cx, CallArgs args);
    53     static bool fun_slice_impl(JSContext *cx, CallArgs args);
    55   public:
    56     static const uint8_t DATA_SLOT = 0;
    57     static const uint8_t BYTE_LENGTH_SLOT = 1;
    58     static const uint8_t VIEW_LIST_SLOT = 2;
    59     static const uint8_t FLAGS_SLOT = 3;
    61     static const uint8_t RESERVED_SLOTS = 4;
    63     static const size_t ARRAY_BUFFER_ALIGNMENT = 8;
    65     static const Class class_;
    67     static const Class protoClass;
    68     static const JSFunctionSpec jsfuncs[];
    69     static const JSFunctionSpec jsstaticfuncs[];
    71     static bool byteLengthGetter(JSContext *cx, unsigned argc, Value *vp);
    73     static bool fun_slice(JSContext *cx, unsigned argc, Value *vp);
    75     static bool fun_isView(JSContext *cx, unsigned argc, Value *vp);
    77     static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
    79     static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, void *contents = nullptr,
    80                                      NewObjectKind newKind = GenericObject, bool mapped = false);
    82     static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
    83                                  uint32_t begin, uint32_t end);
    85     static bool createDataViewForThisImpl(JSContext *cx, CallArgs args);
    86     static bool createDataViewForThis(JSContext *cx, unsigned argc, Value *vp);
    88     template<typename T>
    89     static bool createTypedArrayFromBufferImpl(JSContext *cx, CallArgs args);
    91     template<typename T>
    92     static bool createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Value *vp);
    94     static void obj_trace(JSTracer *trc, JSObject *obj);
    96     static void sweep(JSCompartment *rt);
    98     static void resetArrayBufferList(JSCompartment *rt);
    99     static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
   100     static void restoreArrayBufferLists(ArrayBufferVector &vector);
   102     static void *stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer);
   104     bool hasStealableContents() const {
   105         // Inline elements strictly adhere to the corresponding buffer.
   106         if (!ownsData())
   107             return false;
   109         // asm.js buffer contents are transferred by copying, just like inline
   110         // elements.
   111         if (isAsmJSArrayBuffer())
   112             return false;
   114         // Neutered contents aren't transferrable because we want a neutered
   115         // array's contents to be backed by zeroed memory equal in length to
   116         // the original buffer contents.  Transferring these contents would
   117         // allocate new ones based on the current byteLength, which is 0 for a
   118         // neutered array -- not the original byteLength.
   119         return !isNeutered();
   120     }
   122     static void addSizeOfExcludingThis(JSObject *obj, mozilla::MallocSizeOf mallocSizeOf,
   123                                        JS::ObjectsExtraSizes *sizes);
   125     void addView(ArrayBufferViewObject *view);
   127     void setNewOwnedData(FreeOp* fop, void *newData);
   128     void changeContents(JSContext *cx, void *newData);
   130     /*
   131      * Ensure data is not stored inline in the object. Used when handing back a
   132      * GC-safe pointer.
   133      */
   134     static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
   136     bool canNeuter(JSContext *cx);
   138     /* Neuter this buffer and all its views. */
   139     static void neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer, void *newData);
   141     uint8_t *dataPointer() const;
   142     size_t byteLength() const;
   144     void releaseData(FreeOp *fop);
   146     /*
   147      * Check if the arrayBuffer contains any data. This will return false for
   148      * ArrayBuffer.prototype and neutered ArrayBuffers.
   149      */
   150     bool hasData() const {
   151         return getClass() == &class_;
   152     }
   154     bool isAsmJSArrayBuffer() const { return flags() & ASMJS_BUFFER; }
   155     bool isSharedArrayBuffer() const { return flags() & SHARED_BUFFER; }
   156     bool isMappedArrayBuffer() const { return flags() & MAPPED_BUFFER; }
   157     bool isNeutered() const { return flags() & NEUTERED_BUFFER; }
   159     static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
   160     static bool canNeuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer);
   162     static void finalize(FreeOp *fop, JSObject *obj);
   164     static void *createMappedContents(int fd, size_t offset, size_t length);
   166     static size_t flagsOffset() {
   167         return getFixedSlotOffset(FLAGS_SLOT);
   168     }
   170     static uint32_t neuteredFlag() { return NEUTERED_BUFFER; }
   172   protected:
   173     enum OwnsState {
   174         DoesntOwnData = 0,
   175         OwnsData = 1,
   176     };
   178     void setDataPointer(void *data, OwnsState ownsState);
   179     void setByteLength(size_t length);
   181     ArrayBufferViewObject *viewList() const;
   182     void setViewList(ArrayBufferViewObject *viewsHead);
   183     void setViewListNoBarrier(ArrayBufferViewObject *viewsHead);
   185     enum ArrayBufferFlags {
   186         // In the gcLiveArrayBuffers list.
   187         IN_LIVE_LIST       =  0x1,
   189         // The dataPointer() is owned by this buffer and should be released
   190         // when no longer in use. Releasing the pointer may be done by either
   191         // freeing or unmapping it, and how to do this is determined by the
   192         // buffer's other flags.
   193         OWNS_DATA          =  0x2,
   195         ASMJS_BUFFER       =  0x4,
   196         SHARED_BUFFER      =  0x8,
   197         MAPPED_BUFFER      = 0x10,
   198         NEUTERED_BUFFER    = 0x20
   199     };
   201     uint32_t flags() const;
   202     void setFlags(uint32_t flags);
   204     bool inLiveList() const { return flags() & IN_LIVE_LIST; }
   205     void setInLiveList(bool value) {
   206         setFlags(value ? (flags() | IN_LIVE_LIST) : (flags() & ~IN_LIVE_LIST));
   207     }
   209     bool ownsData() const { return flags() & OWNS_DATA; }
   210     void setOwnsData(OwnsState owns) {
   211         setFlags(owns ? (flags() | OWNS_DATA) : (flags() & ~OWNS_DATA));
   212     }
   214     void setIsAsmJSArrayBuffer() { setFlags(flags() | ASMJS_BUFFER); }
   215     void setIsSharedArrayBuffer() { setFlags(flags() | SHARED_BUFFER); }
   216     void setIsMappedArrayBuffer() { setFlags(flags() | MAPPED_BUFFER); }
   217     void setIsNeutered() { setFlags(flags() | NEUTERED_BUFFER); }
   219     void initialize(size_t byteLength, void *data, OwnsState ownsState) {
   220         setByteLength(byteLength);
   221         setFlags(0);
   222         setViewListNoBarrier(nullptr);
   223         setDataPointer(data, ownsState);
   224     }
   226     void releaseAsmJSArray(FreeOp *fop);
   227     void releaseMappedArray();
   228 };
   230 /*
   231  * ArrayBufferViewObject
   232  *
   233  * Common definitions shared by all ArrayBufferViews.
   234  */
   236 class ArrayBufferViewObject : public JSObject
   237 {
   238   protected:
   239     /* Offset of view in underlying ArrayBufferObject */
   240     static const size_t BYTEOFFSET_SLOT  = JS_TYPEDOBJ_SLOT_BYTEOFFSET;
   242     /* Byte length of view */
   243     static const size_t BYTELENGTH_SLOT  = JS_TYPEDOBJ_SLOT_BYTELENGTH;
   245     /* Underlying ArrayBufferObject */
   246     static const size_t BUFFER_SLOT      = JS_TYPEDOBJ_SLOT_OWNER;
   248     /* ArrayBufferObjects point to a linked list of views, chained through this slot */
   249     static const size_t NEXT_VIEW_SLOT   = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
   251   public:
   252     static ArrayBufferObject *bufferObject(JSContext *cx, Handle<ArrayBufferViewObject *> obj);
   254     ArrayBufferViewObject *nextView() const {
   255         return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
   256     }
   258     inline void setNextView(ArrayBufferViewObject *view);
   260     void neuter(void *newData);
   262     static void trace(JSTracer *trc, JSObject *obj);
   264     uint8_t *dataPointer() {
   265         return static_cast<uint8_t *>(getPrivate());
   266     }
   267 };
   269 bool
   270 ToClampedIndex(JSContext *cx, HandleValue v, uint32_t length, uint32_t *out);
   272 inline void
   273 PostBarrierTypedArrayObject(JSObject *obj)
   274 {
   275 #ifdef JSGC_GENERATIONAL
   276     JS_ASSERT(obj);
   277     JSRuntime *rt = obj->runtimeFromMainThread();
   278     if (!rt->isHeapBusy() && !IsInsideNursery(rt, obj))
   279         rt->gcStoreBuffer.putWholeCell(obj);
   280 #endif
   281 }
   283 inline void
   284 InitArrayBufferViewDataPointer(ArrayBufferViewObject *obj, ArrayBufferObject *buffer, size_t byteOffset)
   285 {
   286     /*
   287      * N.B. The base of the array's data is stored in the object's
   288      * private data rather than a slot to avoid alignment restrictions
   289      * on private Values.
   290      */
   291     MOZ_ASSERT(buffer->dataPointer() != nullptr);
   292     obj->initPrivate(buffer->dataPointer() + byteOffset);
   294     PostBarrierTypedArrayObject(obj);
   295 }
   297 /*
   298  * Tests for either ArrayBufferObject or SharedArrayBufferObject.
   299  * For specific class testing, use e.g., obj->is<ArrayBufferObject>().
   300  */
   301 bool IsArrayBuffer(HandleValue v);
   302 bool IsArrayBuffer(HandleObject obj);
   303 bool IsArrayBuffer(JSObject *obj);
   304 ArrayBufferObject &AsArrayBuffer(HandleObject obj);
   305 ArrayBufferObject &AsArrayBuffer(JSObject *obj);
   307 inline void
   308 ArrayBufferViewObject::setNextView(ArrayBufferViewObject *view)
   309 {
   310     setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(view));
   311     PostBarrierTypedArrayObject(this);
   312 }
   314 extern uint32_t JS_FASTCALL
   315 ClampDoubleToUint8(const double x);
   317 struct uint8_clamped {
   318     uint8_t val;
   320     uint8_clamped() { }
   321     uint8_clamped(const uint8_clamped& other) : val(other.val) { }
   323     // invoke our assignment helpers for constructor conversion
   324     uint8_clamped(uint8_t x)    { *this = x; }
   325     uint8_clamped(uint16_t x)   { *this = x; }
   326     uint8_clamped(uint32_t x)   { *this = x; }
   327     uint8_clamped(int8_t x)     { *this = x; }
   328     uint8_clamped(int16_t x)    { *this = x; }
   329     uint8_clamped(int32_t x)    { *this = x; }
   330     uint8_clamped(double x)     { *this = x; }
   332     uint8_clamped& operator=(const uint8_clamped& x) {
   333         val = x.val;
   334         return *this;
   335     }
   337     uint8_clamped& operator=(uint8_t x) {
   338         val = x;
   339         return *this;
   340     }
   342     uint8_clamped& operator=(uint16_t x) {
   343         val = (x > 255) ? 255 : uint8_t(x);
   344         return *this;
   345     }
   347     uint8_clamped& operator=(uint32_t x) {
   348         val = (x > 255) ? 255 : uint8_t(x);
   349         return *this;
   350     }
   352     uint8_clamped& operator=(int8_t x) {
   353         val = (x >= 0) ? uint8_t(x) : 0;
   354         return *this;
   355     }
   357     uint8_clamped& operator=(int16_t x) {
   358         val = (x >= 0)
   359               ? ((x < 255)
   360                  ? uint8_t(x)
   361                  : 255)
   362               : 0;
   363         return *this;
   364     }
   366     uint8_clamped& operator=(int32_t x) {
   367         val = (x >= 0)
   368               ? ((x < 255)
   369                  ? uint8_t(x)
   370                  : 255)
   371               : 0;
   372         return *this;
   373     }
   375     uint8_clamped& operator=(const double x) {
   376         val = uint8_t(ClampDoubleToUint8(x));
   377         return *this;
   378     }
   380     operator uint8_t() const {
   381         return val;
   382     }
   384     void staticAsserts() {
   385         static_assert(sizeof(uint8_clamped) == 1,
   386                       "uint8_clamped must be layout-compatible with uint8_t");
   387     }
   388 };
   390 /* Note that we can't use std::numeric_limits here due to uint8_clamped. */
   391 template<typename T> inline const bool TypeIsFloatingPoint() { return false; }
   392 template<> inline const bool TypeIsFloatingPoint<float>() { return true; }
   393 template<> inline const bool TypeIsFloatingPoint<double>() { return true; }
   395 template<typename T> inline const bool TypeIsUnsigned() { return false; }
   396 template<> inline const bool TypeIsUnsigned<uint8_t>() { return true; }
   397 template<> inline const bool TypeIsUnsigned<uint16_t>() { return true; }
   398 template<> inline const bool TypeIsUnsigned<uint32_t>() { return true; }
   400 } // namespace js
   402 #endif // vm_ArrayBufferObject_h

mercurial