1/*
2 * Copyright (C) 2016-2017 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#pragma once
27
28#if ENABLE(WEBASSEMBLY)
29
30#include "B3Compilation.h"
31#include "RegisterAtOffsetList.h"
32#include "WasmCompilationMode.h"
33#include "WasmFormat.h"
34#include "WasmFunctionCodeBlock.h"
35#include "WasmIndexOrName.h"
36#include "WasmTierUpCount.h"
37#include <wtf/ThreadSafeRefCounted.h>
38
39namespace JSC {
40
41class LLIntOffsetsExtractor;
42
43namespace Wasm {
44
45class OMGForOSREntryCallee;
46
47class Callee : public ThreadSafeRefCounted<Callee> {
48 WTF_MAKE_FAST_ALLOCATED;
49
50public:
51 JS_EXPORT_PRIVATE virtual ~Callee();
52
53 IndexOrName indexOrName() const { return m_indexOrName; }
54 CompilationMode compilationMode() const { return m_compilationMode; }
55
56 virtual MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint() const = 0;
57 virtual RegisterAtOffsetList* calleeSaveRegisters() = 0;
58 virtual std::tuple<void*, void*> range() const = 0;
59
60 virtual void setOSREntryCallee(Ref<OMGForOSREntryCallee>&&)
61 {
62 RELEASE_ASSERT_NOT_REACHED();
63 }
64
65 void dump(PrintStream&) const;
66
67protected:
68 JS_EXPORT_PRIVATE Callee(Wasm::CompilationMode);
69 JS_EXPORT_PRIVATE Callee(Wasm::CompilationMode, size_t, std::pair<const Name*, RefPtr<NameSection>>&&);
70
71private:
72 CompilationMode m_compilationMode;
73 IndexOrName m_indexOrName;
74};
75
76class JITCallee : public Callee {
77public:
78 MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint() const override { return m_entrypoint.compilation->code().retagged<WasmEntryPtrTag>(); }
79 RegisterAtOffsetList* calleeSaveRegisters() override { return &m_entrypoint.calleeSaveRegisters; }
80 Vector<UnlinkedWasmToWasmCall>& wasmToWasmCallsites() { return m_wasmToWasmCallsites; }
81
82protected:
83 JS_EXPORT_PRIVATE JITCallee(Wasm::CompilationMode, Wasm::Entrypoint&&);
84 JS_EXPORT_PRIVATE JITCallee(Wasm::CompilationMode, Wasm::Entrypoint&&, size_t, std::pair<const Name*, RefPtr<NameSection>>&&, Vector<UnlinkedWasmToWasmCall>&&);
85
86 std::tuple<void*, void*> range() const override
87 {
88 void* start = m_entrypoint.compilation->codeRef().executableMemory()->start().untaggedPtr();
89 void* end = m_entrypoint.compilation->codeRef().executableMemory()->end().untaggedPtr();
90 return { start, end };
91 }
92
93private:
94 Vector<UnlinkedWasmToWasmCall> m_wasmToWasmCallsites;
95 Wasm::Entrypoint m_entrypoint;
96};
97
98class OMGCallee final : public JITCallee {
99public:
100 static Ref<OMGCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
101 {
102 return adoptRef(*new OMGCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls)));
103 }
104
105private:
106 OMGCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
107 : JITCallee(Wasm::CompilationMode::OMGMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
108 {
109 }
110};
111
112class OMGForOSREntryCallee final : public JITCallee {
113public:
114 static Ref<OMGForOSREntryCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
115 {
116 return adoptRef(*new OMGForOSREntryCallee(WTFMove(entrypoint), index, WTFMove(name), osrEntryScratchBufferSize, loopIndex, WTFMove(unlinkedCalls)));
117 }
118
119 unsigned osrEntryScratchBufferSize() const { return m_osrEntryScratchBufferSize; }
120 uint32_t loopIndex() const { return m_loopIndex; }
121
122private:
123 OMGForOSREntryCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, unsigned osrEntryScratchBufferSize, uint32_t loopIndex, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
124 : JITCallee(Wasm::CompilationMode::OMGForOSREntryMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
125 , m_osrEntryScratchBufferSize(osrEntryScratchBufferSize)
126 , m_loopIndex(loopIndex)
127 {
128 }
129
130 unsigned m_osrEntryScratchBufferSize;
131 uint32_t m_loopIndex;
132};
133
134class EmbedderEntrypointCallee final : public JITCallee {
135public:
136 static Ref<EmbedderEntrypointCallee> create(Wasm::Entrypoint&& entrypoint)
137 {
138 return adoptRef(*new EmbedderEntrypointCallee(WTFMove(entrypoint)));
139 }
140
141private:
142 EmbedderEntrypointCallee(Wasm::Entrypoint&& entrypoint)
143 : JITCallee(Wasm::CompilationMode::EmbedderEntrypointMode, WTFMove(entrypoint))
144 {
145 }
146};
147
148class BBQCallee final : public JITCallee {
149public:
150 static Ref<BBQCallee> create(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
151 {
152 return adoptRef(*new BBQCallee(WTFMove(entrypoint), index, WTFMove(name), WTFMove(tierUpCount), WTFMove(unlinkedCalls)));
153 }
154
155 OMGForOSREntryCallee* osrEntryCallee() { return m_osrEntryCallee.get(); }
156 void setOSREntryCallee(Ref<OMGForOSREntryCallee>&& osrEntryCallee) override
157 {
158 m_osrEntryCallee = WTFMove(osrEntryCallee);
159 }
160
161 bool didStartCompilingOSREntryCallee() const { return m_didStartCompilingOSREntryCallee; }
162 void setDidStartCompilingOSREntryCallee(bool value) { m_didStartCompilingOSREntryCallee = value; }
163
164 OMGCallee* replacement() { return m_replacement.get(); }
165 void setReplacement(Ref<OMGCallee>&& replacement)
166 {
167 m_replacement = WTFMove(replacement);
168 }
169
170 TierUpCount* tierUpCount() { return m_tierUpCount.get(); }
171
172private:
173 BBQCallee(Wasm::Entrypoint&& entrypoint, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name, std::unique_ptr<TierUpCount>&& tierUpCount, Vector<UnlinkedWasmToWasmCall>&& unlinkedCalls)
174 : JITCallee(Wasm::CompilationMode::BBQMode, WTFMove(entrypoint), index, WTFMove(name), WTFMove(unlinkedCalls))
175 , m_tierUpCount(WTFMove(tierUpCount))
176 {
177 }
178
179 RefPtr<OMGForOSREntryCallee> m_osrEntryCallee;
180 RefPtr<OMGCallee> m_replacement;
181 std::unique_ptr<TierUpCount> m_tierUpCount;
182 bool m_didStartCompilingOSREntryCallee { false };
183};
184
185class LLIntCallee final : public Callee {
186 friend LLIntOffsetsExtractor;
187
188public:
189 static Ref<LLIntCallee> create(std::unique_ptr<FunctionCodeBlock> codeBlock, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name)
190 {
191 return adoptRef(*new LLIntCallee(WTFMove(codeBlock), index, WTFMove(name)));
192 }
193
194 JS_EXPORT_PRIVATE void setEntrypoint(MacroAssemblerCodePtr<WasmEntryPtrTag>);
195 JS_EXPORT_PRIVATE MacroAssemblerCodePtr<WasmEntryPtrTag> entrypoint() const override;
196 JS_EXPORT_PRIVATE RegisterAtOffsetList* calleeSaveRegisters() override;
197 JS_EXPORT_PRIVATE std::tuple<void*, void*> range() const override;
198
199 JITCallee* replacement() { return m_replacement.get(); }
200 void setReplacement(Ref<JITCallee>&& replacement)
201 {
202 m_replacement = WTFMove(replacement);
203 }
204
205 OMGForOSREntryCallee* osrEntryCallee() { return m_osrEntryCallee.get(); }
206 void setOSREntryCallee(Ref<OMGForOSREntryCallee>&& osrEntryCallee) override
207 {
208 m_osrEntryCallee = WTFMove(osrEntryCallee);
209 }
210
211 LLIntTierUpCounter& tierUpCounter() { return m_codeBlock->tierUpCounter(); }
212
213private:
214 LLIntCallee(std::unique_ptr<FunctionCodeBlock> codeBlock, size_t index, std::pair<const Name*, RefPtr<NameSection>>&& name)
215 : Callee(Wasm::CompilationMode::LLIntMode, index, WTFMove(name))
216 , m_codeBlock(WTFMove(codeBlock))
217 {
218 }
219
220 RefPtr<JITCallee> m_replacement;
221 RefPtr<OMGForOSREntryCallee> m_osrEntryCallee;
222 std::unique_ptr<FunctionCodeBlock> m_codeBlock;
223 MacroAssemblerCodePtr<WasmEntryPtrTag> m_entrypoint;
224};
225
226} } // namespace JSC::Wasm
227
228#endif // ENABLE(WEBASSEMBLY)
229