1/*
2 * Copyright (C) 2019 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 "BytecodeConventions.h"
31#include "InstructionStream.h"
32#include "MacroAssemblerCodeRef.h"
33#include "WasmLLIntTierUpCounter.h"
34#include <wtf/HashMap.h>
35#include <wtf/Vector.h>
36
37namespace JSC {
38
39class JITCode;
40class LLIntOffsetsExtractor;
41
42template<typename Traits>
43class BytecodeGeneratorBase;
44
45namespace Wasm {
46
47class Signature;
48struct GeneratorTraits;
49enum Type : int8_t;
50
51// FIXME: Consider merging this with LLIntCallee
52// https://bugs.webkit.org/show_bug.cgi?id=203691
53class FunctionCodeBlock {
54 WTF_MAKE_FAST_ALLOCATED;
55 WTF_MAKE_NONCOPYABLE(FunctionCodeBlock);
56
57 friend BytecodeGeneratorBase<GeneratorTraits>;
58 friend LLIntOffsetsExtractor;
59 friend class LLIntGenerator;
60
61public:
62 FunctionCodeBlock(uint32_t functionIndex)
63 : m_functionIndex(functionIndex)
64 {
65 }
66
67 uint32_t functionIndex() const { return m_functionIndex; }
68 int numVars() const { return m_numVars; }
69 int numCalleeLocals() const { return m_numCalleeLocals; }
70 uint32_t numArguments() const { return m_numArguments; }
71 const Vector<Type>& constantTypes() const { return m_constantTypes; }
72 const Vector<uint64_t>& constants() const { return m_constants; }
73 const InstructionStream& instructions() const { return *m_instructions; }
74
75 ALWAYS_INLINE uint64_t getConstant(int index) const { return m_constants[index - FirstConstantRegisterIndex]; }
76 ALWAYS_INLINE Type getConstantType(int index) const
77 {
78 ASSERT(Options::dumpGeneratedWasmBytecodes());
79 return m_constantTypes[index - FirstConstantRegisterIndex];
80 }
81
82 void setInstructions(std::unique_ptr<InstructionStream>);
83 void addJumpTarget(InstructionStream::Offset jumpTarget) { m_jumpTargets.append(jumpTarget); }
84 InstructionStream::Offset numberOfJumpTargets() { return m_jumpTargets.size(); }
85 InstructionStream::Offset lastJumpTarget() { return m_jumpTargets.last(); }
86
87 void addOutOfLineJumpTarget(InstructionStream::Offset, int target);
88 const Instruction* outOfLineJumpTarget(const Instruction*);
89 InstructionStream::Offset outOfLineJumpOffset(InstructionStream::Offset);
90 InstructionStream::Offset outOfLineJumpOffset(const InstructionStream::Ref& instruction)
91 {
92 return outOfLineJumpOffset(instruction.offset());
93 }
94
95 inline InstructionStream::Offset bytecodeOffset(const Instruction* returnAddress)
96 {
97 const auto* instructionsBegin = m_instructions->at(0).ptr();
98 const auto* instructionsEnd = reinterpret_cast<const Instruction*>(reinterpret_cast<uintptr_t>(instructionsBegin) + m_instructions->size());
99 RELEASE_ASSERT(returnAddress >= instructionsBegin && returnAddress < instructionsEnd);
100 return returnAddress - instructionsBegin;
101 }
102
103 LLIntTierUpCounter& tierUpCounter() { return m_tierUpCounter; }
104
105 unsigned addSignature(const Signature&);
106 const Signature& signature(unsigned index) const;
107
108 using JumpTable = Vector<InstructionStream::Offset>;
109 JumpTable& addJumpTable(size_t numberOfEntries);
110 const JumpTable& jumpTable(unsigned tableIndex) const;
111 unsigned numberOfJumpTables() const;
112
113private:
114 using OutOfLineJumpTargets = HashMap<InstructionStream::Offset, int>;
115
116 uint32_t m_functionIndex;
117
118 // Used for the number of WebAssembly locals, as in https://webassembly.github.io/spec/core/syntax/modules.html#syntax-local
119 int m_numVars { 0 };
120 // Number of VirtualRegister. The naming is unfortunate, but has to match UnlinkedCodeBlock
121 int m_numCalleeLocals { 0 };
122 uint32_t m_numArguments { 0 };
123 Vector<Type> m_constantTypes;
124 Vector<uint64_t> m_constants;
125 std::unique_ptr<InstructionStream> m_instructions;
126 const void* m_instructionsRawPointer { nullptr };
127 Vector<InstructionStream::Offset> m_jumpTargets;
128 Vector<const Signature*> m_signatures;
129 OutOfLineJumpTargets m_outOfLineJumpTargets;
130 LLIntTierUpCounter m_tierUpCounter;
131 Vector<JumpTable> m_jumpTables;
132};
133
134} } // namespace JSC::Wasm
135
136#endif // ENABLE(WEBASSEMBLY)
137