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 2016 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_table_h
20 #define wasm_table_h
21 
22 #include "gc/Policy.h"
23 #include "wasm/WasmCode.h"
24 
25 namespace js {
26 namespace wasm {
27 
28 // A Table is an indexable array of opaque values. Tables are first-class
29 // stateful objects exposed to WebAssembly. asm.js also uses Tables to represent
30 // its homogeneous function-pointer tables.
31 //
32 // A table of FuncRef holds FunctionTableElems, which are (code*,tls*) pairs,
33 // where the tls must be traced.
34 //
35 // A table of AnyRef holds JSObject pointers, which must be traced.
36 
37 // TODO/AnyRef-boxing: With boxed immediates and strings, JSObject* is no longer
38 // the most appropriate representation for Cell::anyref.
39 STATIC_ASSERT_ANYREF_IS_JSOBJECT;
40 
41 using TableAnyRefVector = GCVector<HeapPtr<JSObject*>, 0, SystemAllocPolicy>;
42 
43 class Table : public ShareableBase<Table> {
44   using InstanceSet =
45       JS::WeakCache<GCHashSet<WeakHeapPtrWasmInstanceObject,
46                               MovableCellHasher<WeakHeapPtrWasmInstanceObject>,
47                               SystemAllocPolicy>>;
48   using UniqueFuncRefArray = UniquePtr<FunctionTableElem[], JS::FreePolicy>;
49 
50   WeakHeapPtrWasmTableObject maybeObject_;
51   InstanceSet observers_;
52   UniqueFuncRefArray functions_;  // either functions_ has data
53   TableAnyRefVector objects_;     //   or objects_, but not both
54   const RefType elemType_;
55   const bool isAsmJS_;
56   uint32_t length_;
57   const Maybe<uint32_t> maximum_;
58 
59   template <class>
60   friend struct js::MallocProvider;
61   Table(JSContext* cx, const TableDesc& desc, HandleWasmTableObject maybeObject,
62         UniqueFuncRefArray functions);
63   Table(JSContext* cx, const TableDesc& desc, HandleWasmTableObject maybeObject,
64         TableAnyRefVector&& objects);
65 
66   void tracePrivate(JSTracer* trc);
67   friend class js::WasmTableObject;
68 
69  public:
70   static RefPtr<Table> create(JSContext* cx, const TableDesc& desc,
71                               HandleWasmTableObject maybeObject);
72   void trace(JSTracer* trc);
73 
elemType()74   RefType elemType() const { return elemType_; }
repr()75   TableRepr repr() const { return elemType_.tableRepr(); }
76 
isAsmJS()77   bool isAsmJS() const {
78     MOZ_ASSERT(elemType_.isFunc());
79     return isAsmJS_;
80   }
isFunction()81   bool isFunction() const { return elemType().isFunc(); }
length()82   uint32_t length() const { return length_; }
maximum()83   Maybe<uint32_t> maximum() const { return maximum_; }
84 
85   // Only for function values.  Raw pointer to the table.
86   uint8_t* functionBase() const;
87 
88   // set/get/fillFuncRef is allowed only on table-of-funcref.
89   // get/fillAnyRef is allowed only on table-of-anyref.
90   // setNull is allowed on either.
91 
92   const FunctionTableElem& getFuncRef(uint32_t index) const;
93   bool getFuncRef(JSContext* cx, uint32_t index,
94                   MutableHandleFunction fun) const;
95   void setFuncRef(uint32_t index, void* code, const Instance* instance);
96   void fillFuncRef(uint32_t index, uint32_t fillCount, FuncRef ref,
97                    JSContext* cx);
98 
99   AnyRef getAnyRef(uint32_t index) const;
100   void fillAnyRef(uint32_t index, uint32_t fillCount, AnyRef ref);
101 
102   void setNull(uint32_t index);
103 
104   // Copy entry from |srcTable| at |srcIndex| to this table at |dstIndex|.  Used
105   // by table.copy.  May OOM if it needs to box up a function during an upcast.
106   bool copy(const Table& srcTable, uint32_t dstIndex, uint32_t srcIndex);
107 
108   // grow() returns (uint32_t)-1 if it could not grow.
109   uint32_t grow(uint32_t delta);
110   bool movingGrowable() const;
111   bool addMovingGrowObserver(JSContext* cx, WasmInstanceObject* instance);
112 
113   // about:memory reporting:
114 
115   size_t sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const;
116 
117   size_t gcMallocBytes() const;
118 };
119 
120 using SharedTable = RefPtr<Table>;
121 using SharedTableVector = Vector<SharedTable, 0, SystemAllocPolicy>;
122 
123 }  // namespace wasm
124 }  // namespace js
125 
126 #endif  // wasm_table_h
127