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  *
4  * Copyright 2021 Mozilla Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef wasm_shareable_h
20 #define wasm_shareable_h
21 
22 #include "mozilla/RefPtr.h"
23 #include "js/RefCounted.h"
24 #include "wasm/WasmTypeDecls.h"
25 
26 namespace js {
27 namespace wasm {
28 
29 using mozilla::MallocSizeOf;
30 
31 // This reusable base class factors out the logic for a resource that is shared
32 // by multiple instances/modules but should only be counted once when computing
33 // about:memory stats.
34 
35 template <class T>
36 struct ShareableBase : AtomicRefCounted<T> {
37   using SeenSet = HashSet<const T*, DefaultHasher<const T*>, SystemAllocPolicy>;
38 
sizeOfIncludingThisIfNotSeenShareableBase39   size_t sizeOfIncludingThisIfNotSeen(MallocSizeOf mallocSizeOf,
40                                       SeenSet* seen) const {
41     const T* self = static_cast<const T*>(this);
42     typename SeenSet::AddPtr p = seen->lookupForAdd(self);
43     if (p) {
44       return 0;
45     }
46     bool ok = seen->add(p, self);
47     (void)ok;  // oh well
48     return mallocSizeOf(self) + self->sizeOfExcludingThis(mallocSizeOf);
49   }
50 };
51 
52 // ShareableBytes is a reference-counted Vector of bytes.
53 
54 struct ShareableBytes : ShareableBase<ShareableBytes> {
55   // Vector is 'final', so instead make Vector a member and add boilerplate.
56   Bytes bytes;
57 
58   ShareableBytes() = default;
ShareableBytesShareableBytes59   explicit ShareableBytes(Bytes&& bytes) : bytes(std::move(bytes)) {}
sizeOfExcludingThisShareableBytes60   size_t sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const {
61     return bytes.sizeOfExcludingThis(mallocSizeOf);
62   }
beginShareableBytes63   const uint8_t* begin() const { return bytes.begin(); }
endShareableBytes64   const uint8_t* end() const { return bytes.end(); }
lengthShareableBytes65   size_t length() const { return bytes.length(); }
appendShareableBytes66   bool append(const uint8_t* start, size_t len) {
67     return bytes.append(start, len);
68   }
69 };
70 
71 using MutableBytes = RefPtr<ShareableBytes>;
72 using SharedBytes = RefPtr<const ShareableBytes>;
73 
74 }  // namespace wasm
75 }  // namespace js
76 
77 #endif  // wasm_shareable_h
78