1/*
2 * Copyright (C) 2011-2018 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#include "JSCJSValue.h"
29#include "MacroAssemblerCodeRef.h"
30#include "Opcode.h"
31
32namespace JSC {
33
34class VM;
35struct Instruction;
36
37#if ENABLE(C_LOOP)
38typedef OpcodeID LLIntCode;
39#else
40typedef void (*LLIntCode)();
41#endif
42
43namespace LLInt {
44
45extern "C" JS_EXPORT_PRIVATE Opcode g_opcodeMap[numOpcodeIDs];
46extern "C" JS_EXPORT_PRIVATE Opcode g_opcodeMapWide16[numOpcodeIDs];
47extern "C" JS_EXPORT_PRIVATE Opcode g_opcodeMapWide32[numOpcodeIDs];
48
49class Data {
50
51public:
52 static void performAssertions(VM&);
53
54private:
55 static uint8_t s_exceptionInstructions[maxOpcodeLength + 1];
56
57 friend void initialize();
58
59 friend Instruction* exceptionInstructions();
60 friend Opcode* opcodeMap();
61 friend Opcode* opcodeMapWide16();
62 friend Opcode* opcodeMapWide32();
63 friend Opcode getOpcode(OpcodeID);
64 friend Opcode getOpcodeWide16(OpcodeID);
65 friend Opcode getOpcodeWide32(OpcodeID);
66 template<PtrTag tag> friend MacroAssemblerCodePtr<tag> getCodePtr(OpcodeID);
67 template<PtrTag tag> friend MacroAssemblerCodePtr<tag> getWide16CodePtr(OpcodeID);
68 template<PtrTag tag> friend MacroAssemblerCodePtr<tag> getWide32CodePtr(OpcodeID);
69 template<PtrTag tag> friend MacroAssemblerCodeRef<tag> getCodeRef(OpcodeID);
70};
71
72void initialize();
73
74inline Instruction* exceptionInstructions()
75{
76 return reinterpret_cast<Instruction*>(Data::s_exceptionInstructions);
77}
78
79inline Opcode* opcodeMap()
80{
81 return g_opcodeMap;
82}
83
84inline Opcode* opcodeMapWide16()
85{
86 return g_opcodeMapWide16;
87}
88
89inline Opcode* opcodeMapWide32()
90{
91 return g_opcodeMapWide32;
92}
93
94inline Opcode getOpcode(OpcodeID id)
95{
96#if ENABLE(COMPUTED_GOTO_OPCODES)
97 return g_opcodeMap[id];
98#else
99 return static_cast<Opcode>(id);
100#endif
101}
102
103inline Opcode getOpcodeWide16(OpcodeID id)
104{
105#if ENABLE(COMPUTED_GOTO_OPCODES)
106 return g_opcodeMapWide16[id];
107#else
108 UNUSED_PARAM(id);
109 RELEASE_ASSERT_NOT_REACHED();
110#endif
111}
112
113inline Opcode getOpcodeWide32(OpcodeID id)
114{
115#if ENABLE(COMPUTED_GOTO_OPCODES)
116 return g_opcodeMapWide32[id];
117#else
118 UNUSED_PARAM(id);
119 RELEASE_ASSERT_NOT_REACHED();
120#endif
121}
122
123template<PtrTag tag>
124ALWAYS_INLINE MacroAssemblerCodePtr<tag> getCodePtr(OpcodeID opcodeID)
125{
126 void* address = reinterpret_cast<void*>(getOpcode(opcodeID));
127 address = retagCodePtr<BytecodePtrTag, tag>(address);
128 return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address);
129}
130
131template<PtrTag tag>
132ALWAYS_INLINE MacroAssemblerCodePtr<tag> getWide16CodePtr(OpcodeID opcodeID)
133{
134 void* address = reinterpret_cast<void*>(getOpcodeWide16(opcodeID));
135 address = retagCodePtr<BytecodePtrTag, tag>(address);
136 return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address);
137}
138
139template<PtrTag tag>
140ALWAYS_INLINE MacroAssemblerCodePtr<tag> getWide32CodePtr(OpcodeID opcodeID)
141{
142 void* address = reinterpret_cast<void*>(getOpcodeWide32(opcodeID));
143 address = retagCodePtr<BytecodePtrTag, tag>(address);
144 return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address);
145}
146
147template<PtrTag tag>
148ALWAYS_INLINE MacroAssemblerCodeRef<tag> getCodeRef(OpcodeID opcodeID)
149{
150 return MacroAssemblerCodeRef<tag>::createSelfManagedCodeRef(getCodePtr<tag>(opcodeID));
151}
152
153#if ENABLE(JIT)
154template<PtrTag tag>
155ALWAYS_INLINE LLIntCode getCodeFunctionPtr(OpcodeID opcodeID)
156{
157 ASSERT(opcodeID >= NUMBER_OF_BYTECODE_IDS);
158#if COMPILER(MSVC)
159 return reinterpret_cast<LLIntCode>(getCodePtr<tag>(opcodeID).executableAddress());
160#else
161 return reinterpret_cast<LLIntCode>(getCodePtr<tag>(opcodeID).template executableAddress());
162#endif
163}
164
165#else
166ALWAYS_INLINE void* getCodePtr(OpcodeID id)
167{
168 return reinterpret_cast<void*>(getOpcode(id));
169}
170
171ALWAYS_INLINE void* getWide16CodePtr(OpcodeID id)
172{
173 return reinterpret_cast<void*>(getOpcodeWide16(id));
174}
175
176ALWAYS_INLINE void* getWide32CodePtr(OpcodeID id)
177{
178 return reinterpret_cast<void*>(getOpcodeWide32(id));
179}
180#endif
181
182ALWAYS_INLINE void* getCodePtr(JSC::EncodedJSValue glueHelper())
183{
184 return bitwise_cast<void*>(glueHelper);
185}
186
187} } // namespace JSC::LLInt
188