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 "mozilla/Assertions.h"  // MOZ_ASSERT
8 
9 #include <stdint.h>  // uint8_t, uint32_t
10 
11 #include "jstypes.h"  // JS_PUBLIC_API
12 
13 #include "js/ArrayBufferMaybeShared.h"
14 #include "vm/ArrayBufferObject.h"  // js::ArrayBufferObject
15 #include "vm/JSObject.h"           // JSObject
16 #include "vm/SharedArrayObject.h"  // js::SharedArrayBufferObject
17 #include "vm/SharedMem.h"          // SharedMem
18 
19 using namespace js;
20 
IsArrayBufferObjectMaybeShared(JSObject * obj)21 JS_PUBLIC_API bool JS::IsArrayBufferObjectMaybeShared(JSObject* obj) {
22   return obj->canUnwrapAs<ArrayBufferObjectMaybeShared>();
23 }
24 
UnwrapArrayBufferMaybeShared(JSObject * obj)25 JS_PUBLIC_API JSObject* JS::UnwrapArrayBufferMaybeShared(JSObject* obj) {
26   return obj->maybeUnwrapIf<ArrayBufferObjectMaybeShared>();
27 }
28 
GetArrayBufferMaybeSharedLengthAndData(JSObject * obj,size_t * length,bool * isSharedMemory,uint8_t ** data)29 JS_PUBLIC_API void JS::GetArrayBufferMaybeSharedLengthAndData(
30     JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data) {
31   MOZ_ASSERT(obj->is<ArrayBufferObjectMaybeShared>());
32 
33   if (obj->is<SharedArrayBufferObject>()) {
34     auto* buffer = &obj->as<SharedArrayBufferObject>();
35     *length = buffer->byteLength();
36     *data = buffer->dataPointerShared().unwrap();
37     *isSharedMemory = true;
38   } else {
39     auto* buffer = &obj->as<ArrayBufferObject>();
40     *length = buffer->byteLength();
41     *data = buffer->dataPointer();
42     *isSharedMemory = false;
43   }
44 }
45 
GetArrayBufferMaybeSharedData(JSObject * obj,bool * isSharedMemory,const JS::AutoRequireNoGC &)46 JS_PUBLIC_API uint8_t* JS::GetArrayBufferMaybeSharedData(
47     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&) {
48   MOZ_ASSERT(obj->maybeUnwrapIf<ArrayBufferObjectMaybeShared>());
49 
50   if (ArrayBufferObject* aobj = obj->maybeUnwrapIf<ArrayBufferObject>()) {
51     *isSharedMemory = false;
52     return aobj->dataPointer();
53   } else if (SharedArrayBufferObject* saobj =
54                  obj->maybeUnwrapIf<SharedArrayBufferObject>()) {
55     *isSharedMemory = true;
56     return saobj->dataPointerShared().unwrap();
57   }
58 
59   return nullptr;
60 }
61 
IsLargeArrayBufferMaybeShared(JSObject * obj)62 JS_PUBLIC_API bool JS::IsLargeArrayBufferMaybeShared(JSObject* obj) {
63 #ifdef JS_64BIT
64   obj = UnwrapArrayBufferMaybeShared(obj);
65   MOZ_ASSERT(obj);
66   size_t len = obj->is<ArrayBufferObject>()
67                    ? obj->as<ArrayBufferObject>().byteLength()
68                    : obj->as<SharedArrayBufferObject>().byteLength();
69   return len > ArrayBufferObject::MaxByteLengthForSmallBuffer;
70 #else
71   // Large ArrayBuffers are not supported on 32-bit.
72   MOZ_ASSERT(ArrayBufferObject::maxBufferByteLength() ==
73              ArrayBufferObject::MaxByteLengthForSmallBuffer);
74   return false;
75 #endif
76 }
77