blob: 60e561902d4c18f81ee2f37cc5be7d654667deef [file] [log] [blame]
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +00001/*
jfbastien@apple.com802693a2018-01-12 23:47:58 +00002 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +00003 *
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#pragma once
27
28#if ENABLE(WEBASSEMBLY)
29
30#include "WasmFormat.h"
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +000031#include "WasmGlobal.h"
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000032#include "WasmMemory.h"
33#include "WasmModule.h"
34#include "WasmTable.h"
justin_michaud@apple.comc0e5bf22019-05-25 00:51:21 +000035#include "WriteBarrier.h"
36#include <wtf/BitVector.h>
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000037#include <wtf/RefPtr.h>
38#include <wtf/ThreadSafeRefCounted.h>
39
keith_miller@apple.com8e7bd482019-10-01 16:38:26 +000040namespace JSC {
41
tzagallo@apple.combf01be22019-10-31 22:32:52 +000042class LLIntOffsetsExtractor;
keith_miller@apple.com8e7bd482019-10-01 16:38:26 +000043class JSWebAssemblyInstance;
44
45namespace Wasm {
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000046
jfbastien@apple.com89177d32017-10-26 15:33:55 +000047struct Context;
justin_michaud@apple.comb0b1a532019-06-17 18:44:18 +000048class Instance;
49
cdumez@apple.com72332a62018-06-08 03:56:04 +000050class Instance : public ThreadSafeRefCounted<Instance>, public CanMakeWeakPtr<Instance> {
tzagallo@apple.combf01be22019-10-31 22:32:52 +000051 friend LLIntOffsetsExtractor;
52
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000053public:
sbarati@apple.comd8688072017-11-14 09:05:33 +000054 using StoreTopCallFrameCallback = WTF::Function<void(void*)>;
justin_michaud@apple.comb0b1a532019-06-17 18:44:18 +000055 using FunctionWrapperMap = HashMap<uint32_t, WriteBarrier<Unknown>, IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>>;
sbarati@apple.comd8688072017-11-14 09:05:33 +000056
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +000057 static Ref<Instance> create(Context*, Ref<Module>&&, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&&);
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000058
jfbastien@apple.com89177d32017-10-26 15:33:55 +000059 void finalizeCreation(void* owner, Ref<CodeBlock>&& codeBlock)
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000060 {
jfbastien@apple.com89177d32017-10-26 15:33:55 +000061 m_owner = owner;
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000062 m_codeBlock = WTFMove(codeBlock);
63 }
64
65 JS_EXPORT_PRIVATE ~Instance();
66
jfbastien@apple.com89177d32017-10-26 15:33:55 +000067 template<typename T> T* owner() const { return reinterpret_cast<T*>(m_owner); }
68 static ptrdiff_t offsetOfOwner() { return OBJECT_OFFSETOF(Instance, m_owner); }
69
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000070 size_t extraMemoryAllocated() const;
71
jfbastien@apple.com89177d32017-10-26 15:33:55 +000072 Wasm::Context* context() const { return m_context; }
73
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000074 Module& module() { return m_module.get(); }
75 CodeBlock* codeBlock() { return m_codeBlock.get(); }
76 Memory* memory() { return m_memory.get(); }
justin_michaud@apple.com6cae9352019-06-18 22:01:02 +000077 Table* table(unsigned);
78 void setTable(unsigned, Ref<Table>&&);
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +000079
commit-queue@webkit.orgf79caa42019-06-12 18:40:56 +000080 void* cachedMemory() const { return m_cachedMemory.getMayBeNull(cachedMemorySize()); }
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +000081 size_t cachedMemorySize() const { return m_cachedMemorySize; }
82
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +000083 void setMemory(Ref<Memory>&& memory)
84 {
85 m_memory = WTFMove(memory);
86 m_memory.get()->registerInstance(this);
87 updateCachedMemory();
88 }
89 void updateCachedMemory()
90 {
91 if (m_memory != nullptr) {
commit-queue@webkit.orgf79caa42019-06-12 18:40:56 +000092 m_cachedMemory = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>(memory()->memory(), memory()->size());
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +000093 m_cachedMemorySize = memory()->size();
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +000094 }
95 }
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +000096
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +000097 int32_t loadI32Global(unsigned i) const
98 {
99 Global::Value* slot = m_globals.get() + i;
100 if (m_globalsToBinding.get(i)) {
101 slot = slot->m_pointer;
102 if (!slot)
103 return 0;
104 }
105 return slot->m_primitive;
106 }
107 int64_t loadI64Global(unsigned i) const
108 {
109 Global::Value* slot = m_globals.get() + i;
110 if (m_globalsToBinding.get(i)) {
111 slot = slot->m_pointer;
112 if (!slot)
113 return 0;
114 }
115 return slot->m_primitive;
116 }
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000117 float loadF32Global(unsigned i) const { return bitwise_cast<float>(loadI32Global(i)); }
118 double loadF64Global(unsigned i) const { return bitwise_cast<double>(loadI64Global(i)); }
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000119 void setGlobal(unsigned i, int64_t bits)
120 {
121 Global::Value* slot = m_globals.get() + i;
122 if (m_globalsToBinding.get(i)) {
123 slot = slot->m_pointer;
124 if (!slot)
125 return;
126 }
127 slot->m_primitive = bits;
128 }
justin_michaud@apple.comc0e5bf22019-05-25 00:51:21 +0000129 void setGlobal(unsigned, JSValue);
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000130 void linkGlobal(unsigned, Ref<Global>&&);
justin_michaud@apple.comc0e5bf22019-05-25 00:51:21 +0000131 const BitVector& globalsToMark() { return m_globalsToMark; }
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000132 const BitVector& globalsToBinding() { return m_globalsToBinding; }
justin_michaud@apple.comb0b1a532019-06-17 18:44:18 +0000133 JSValue getFunctionWrapper(unsigned) const;
134 typename FunctionWrapperMap::ValuesConstIteratorRange functionWrappers() const { return m_functionWrappers.values(); }
135 void setFunctionWrapper(unsigned, JSValue);
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000136
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000137 Wasm::Global* getGlobalBinding(unsigned i)
138 {
139 ASSERT(m_globalsToBinding.get(i));
140 Wasm::Global::Value* pointer = m_globals.get()[i].m_pointer;
141 if (!pointer)
142 return nullptr;
143 return &Wasm::Global::fromBinding(*pointer);
144 }
145
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000146 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Instance, m_memory); }
147 static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(Instance, m_globals); }
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +0000148 static ptrdiff_t offsetOfCachedMemory() { return OBJECT_OFFSETOF(Instance, m_cachedMemory); }
149 static ptrdiff_t offsetOfCachedMemorySize() { return OBJECT_OFFSETOF(Instance, m_cachedMemorySize); }
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +0000150 static ptrdiff_t offsetOfPointerToTopEntryFrame() { return OBJECT_OFFSETOF(Instance, m_pointerToTopEntryFrame); }
keith_miller@apple.com7683fac2017-10-24 03:20:31 +0000151
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +0000152 static ptrdiff_t offsetOfPointerToActualStackLimit() { return OBJECT_OFFSETOF(Instance, m_pointerToActualStackLimit); }
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000153 static ptrdiff_t offsetOfCachedStackLimit() { return OBJECT_OFFSETOF(Instance, m_cachedStackLimit); }
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +0000154 void* cachedStackLimit() const
155 {
156 ASSERT(*m_pointerToActualStackLimit == m_cachedStackLimit);
157 return m_cachedStackLimit;
158 }
159 void setCachedStackLimit(void* limit)
160 {
161 ASSERT(*m_pointerToActualStackLimit == limit || bitwise_cast<void*>(std::numeric_limits<uintptr_t>::max()) == limit);
162 m_cachedStackLimit = limit;
163 }
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000164
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000165 // Tail accessors.
justin_michaud@apple.com6cae9352019-06-18 22:01:02 +0000166 static constexpr size_t offsetOfTail() { return WTF::roundUpToMultipleOf<sizeof(uint64_t)>(sizeof(Instance)); }
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000167 struct ImportFunctionInfo {
168 // Target instance and entrypoint are only set for wasm->wasm calls, and are otherwise nullptr. The embedder-specific logic occurs through import function.
169 Instance* targetInstance { nullptr };
mark.lam@apple.com52fa2cc2018-03-30 05:04:44 +0000170 WasmToWasmImportableFunction::LoadLocation wasmEntrypointLoadLocation { nullptr };
mark.lam@apple.comde0dba72018-04-18 03:31:09 +0000171 MacroAssemblerCodePtr<WasmEntryPtrTag> wasmToEmbedderStub;
mark.lam@apple.com7725e2a2019-02-27 05:43:34 +0000172 void* importFunction { nullptr }; // In a JS embedding, this is a WriteBarrier<JSObject>.
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000173 };
174 unsigned numImportFunctions() const { return m_numImportFunctions; }
175 ImportFunctionInfo* importFunctionInfo(size_t importFunctionNum)
176 {
177 RELEASE_ASSERT(importFunctionNum < m_numImportFunctions);
178 return &bitwise_cast<ImportFunctionInfo*>(bitwise_cast<char*>(this) + offsetOfTail())[importFunctionNum];
179 }
180 static size_t offsetOfTargetInstance(size_t importFunctionNum) { return offsetOfTail() + importFunctionNum * sizeof(ImportFunctionInfo) + OBJECT_OFFSETOF(ImportFunctionInfo, targetInstance); }
mark.lam@apple.com52fa2cc2018-03-30 05:04:44 +0000181 static size_t offsetOfWasmEntrypointLoadLocation(size_t importFunctionNum) { return offsetOfTail() + importFunctionNum * sizeof(ImportFunctionInfo) + OBJECT_OFFSETOF(ImportFunctionInfo, wasmEntrypointLoadLocation); }
182 static size_t offsetOfWasmToEmbedderStub(size_t importFunctionNum) { return offsetOfTail() + importFunctionNum * sizeof(ImportFunctionInfo) + OBJECT_OFFSETOF(ImportFunctionInfo, wasmToEmbedderStub); }
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000183 static size_t offsetOfImportFunction(size_t importFunctionNum) { return offsetOfTail() + importFunctionNum * sizeof(ImportFunctionInfo) + OBJECT_OFFSETOF(ImportFunctionInfo, importFunction); }
184 template<typename T> T* importFunction(unsigned importFunctionNum) { return reinterpret_cast<T*>(&importFunctionInfo(importFunctionNum)->importFunction); }
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000185
justin_michaud@apple.com6cae9352019-06-18 22:01:02 +0000186 static_assert(sizeof(ImportFunctionInfo) == WTF::roundUpToMultipleOf<sizeof(uint64_t)>(sizeof(ImportFunctionInfo)), "We rely on this for the alignment to be correct");
187 static constexpr size_t offsetOfTablePtr(unsigned numImportFunctions, unsigned i) { return offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions + sizeof(Table*) * i; }
188
sbarati@apple.comd8688072017-11-14 09:05:33 +0000189 void storeTopCallFrame(void* callFrame)
190 {
191 m_storeTopCallFrame(callFrame);
192 }
193
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000194private:
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +0000195 Instance(Context*, Ref<Module>&&, EntryFrame**, void**, StoreTopCallFrameCallback&&);
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000196
justin_michaud@apple.com6cae9352019-06-18 22:01:02 +0000197 static size_t allocationSize(Checked<size_t> numImportFunctions, Checked<size_t> numTables)
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000198 {
justin_michaud@apple.com6cae9352019-06-18 22:01:02 +0000199 return (offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions + sizeof(Table*) * numTables).unsafeGet();
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000200 }
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000201 void* m_owner { nullptr }; // In a JS embedding, this is a JSWebAssemblyInstance*.
202 Context* m_context { nullptr };
commit-queue@webkit.orgf79caa42019-06-12 18:40:56 +0000203 CagedPtr<Gigacage::Primitive, void, tagCagedPtr> m_cachedMemory;
gskachkov@gmail.com0ac47572018-02-23 23:16:59 +0000204 size_t m_cachedMemorySize { 0 };
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000205 Ref<Module> m_module;
206 RefPtr<CodeBlock> m_codeBlock;
207 RefPtr<Memory> m_memory;
justin_michaud@apple.comc0e5bf22019-05-25 00:51:21 +0000208
ysuzuki@apple.com4642e112020-01-03 02:36:43 +0000209 MallocPtr<Global::Value, VMMalloc> m_globals;
justin_michaud@apple.comb0b1a532019-06-17 18:44:18 +0000210 FunctionWrapperMap m_functionWrappers;
justin_michaud@apple.comc0e5bf22019-05-25 00:51:21 +0000211 BitVector m_globalsToMark;
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000212 BitVector m_globalsToBinding;
jfbastien@apple.comc4b8a5f2017-12-01 21:58:36 +0000213 EntryFrame** m_pointerToTopEntryFrame { nullptr };
214 void** m_pointerToActualStackLimit { nullptr };
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000215 void* m_cachedStackLimit { bitwise_cast<void*>(std::numeric_limits<uintptr_t>::max()) };
sbarati@apple.comd8688072017-11-14 09:05:33 +0000216 StoreTopCallFrameCallback m_storeTopCallFrame;
jfbastien@apple.com89177d32017-10-26 15:33:55 +0000217 unsigned m_numImportFunctions { 0 };
ysuzuki@apple.com7d52c092019-12-04 01:36:56 +0000218 HashMap<uint32_t, Ref<Global>, IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_linkedGlobals;
jfbastien@apple.comd9f999e2017-10-20 02:23:29 +0000219};
220
221} } // namespace JSC::Wasm
222
223#endif // ENABLE(WEBASSEMBLY)