Get rid of HeapRootVisitor and make SlotVisitor less painful to use
[WebKit-https.git] / Source / JavaScriptCore / wasm / js / JSWebAssemblyTable.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSWebAssemblyTable.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "JSCInlines.h"
32 #include "WasmFormat.h"
33
34 namespace JSC {
35
36 const ClassInfo JSWebAssemblyTable::s_info = { "WebAssembly.Table", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyTable) };
37
38 JSWebAssemblyTable* JSWebAssemblyTable::create(ExecState* exec, VM& vm, Structure* structure, uint32_t initial, std::optional<uint32_t> maximum)
39 {
40     auto throwScope = DECLARE_THROW_SCOPE(vm);
41     if (!isValidSize(initial)) {
42         throwException(exec, throwScope, createOutOfMemoryError(exec));
43         return nullptr;
44     }
45
46     auto* instance = new (NotNull, allocateCell<JSWebAssemblyTable>(vm.heap)) JSWebAssemblyTable(vm, structure, initial, maximum);
47     instance->finishCreation(vm);
48     return instance;
49 }
50
51 Structure* JSWebAssemblyTable::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
52 {
53     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
54 }
55
56 JSWebAssemblyTable::JSWebAssemblyTable(VM& vm, Structure* structure, uint32_t initial, std::optional<uint32_t> maximum)
57     : Base(vm, structure)
58 {
59     m_size = initial;
60     ASSERT(isValidSize(m_size));
61     m_maximum = maximum;
62     ASSERT(!m_maximum || *m_maximum >= m_size);
63
64     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
65     // But for now, we're not doing that.
66     m_functions = MallocPtr<Wasm::CallableFunction>::malloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(m_size));
67     m_jsFunctions = MallocPtr<WriteBarrier<WebAssemblyFunction>>::malloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(m_size));
68     for (uint32_t i = 0; i < m_size; ++i) {
69         new (&m_functions.get()[i]) Wasm::CallableFunction();
70         ASSERT(!m_functions.get()[i].signature); // We rely on this in compiled code.
71         new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
72     }
73 }
74
75 void JSWebAssemblyTable::finishCreation(VM& vm)
76 {
77     Base::finishCreation(vm);
78     ASSERT(inherits(info()));
79 }
80
81 void JSWebAssemblyTable::destroy(JSCell* cell)
82 {
83     static_cast<JSWebAssemblyTable*>(cell)->JSWebAssemblyTable::~JSWebAssemblyTable();
84 }
85
86 void JSWebAssemblyTable::visitChildren(JSCell* cell, SlotVisitor& visitor)
87 {
88     JSWebAssemblyTable* thisObject = jsCast<JSWebAssemblyTable*>(cell);
89     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
90
91     Base::visitChildren(thisObject, visitor);
92
93     for (unsigned i = 0; i < thisObject->m_size; ++i)
94         visitor.append(thisObject->m_jsFunctions.get()[i]);
95 }
96
97 bool JSWebAssemblyTable::grow(uint32_t newSize)
98 {
99     if (newSize < m_size)
100         return false;
101     if (newSize == m_size)
102         return true;
103     if (maximum() && newSize > *maximum())
104         return false;
105     if (!isValidSize(newSize))
106         return false;
107
108     m_functions.realloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(newSize));
109     m_jsFunctions.realloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(newSize));
110
111     for (uint32_t i = m_size; i < newSize; ++i) {
112         new (&m_functions.get()[i]) Wasm::CallableFunction();
113         new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
114     }
115     m_size = newSize;
116     return true;
117 }
118
119 void JSWebAssemblyTable::clearFunction(uint32_t index)
120 {
121     RELEASE_ASSERT(index < m_size);
122     m_jsFunctions.get()[index] = WriteBarrier<WebAssemblyFunction>();
123     m_functions.get()[index] = Wasm::CallableFunction();
124     ASSERT(!m_functions.get()[index].signature); // We rely on this in compiled code.
125 }
126
127 void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyFunction* function)
128 {
129     RELEASE_ASSERT(index < m_size);
130     m_jsFunctions.get()[index].set(vm, this, function);
131     m_functions.get()[index] = Wasm::CallableFunction(function->signature(), function->wasmEntrypoint());
132 }
133
134 } // namespace JSC
135
136 #endif // ENABLE(WEBASSEMBLY)