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_opcodeMapWide[numOpcodeIDs];
47
48class Data {
49
50public:
51 static void performAssertions(VM&);
52
53private:
54 static uint8_t s_exceptionInstructions[maxOpcodeLength + 1];
55
56 friend void initialize();
57
58 friend Instruction* exceptionInstructions();
59 friend Opcode* opcodeMap();
60 friend Opcode* opcodeMapWide();
61 friend Opcode getOpcode(OpcodeID);
62 friend Opcode getOpcodeWide(OpcodeID);
63 template<PtrTag tag> friend MacroAssemblerCodePtr<tag> getCodePtr(OpcodeID);
64 template<PtrTag tag> friend MacroAssemblerCodePtr<tag> getWideCodePtr(OpcodeID);
65 template<PtrTag tag> friend MacroAssemblerCodeRef<tag> getCodeRef(OpcodeID);
66};
67
68void initialize();
69
70inline Instruction* exceptionInstructions()
71{
72 return reinterpret_cast<Instruction*>(Data::s_exceptionInstructions);
73}
74
75inline Opcode* opcodeMap()
76{
77 return g_opcodeMap;
78}
79
80inline Opcode* opcodeMapWide()
81{
82 return g_opcodeMapWide;
83}
84
85inline Opcode getOpcode(OpcodeID id)
86{
87#if ENABLE(COMPUTED_GOTO_OPCODES)
88 return g_opcodeMap[id];
89#else
90 return static_cast<Opcode>(id);
91#endif
92}
93
94inline Opcode getOpcodeWide(OpcodeID id)
95{
96#if ENABLE(COMPUTED_GOTO_OPCODES)
97 return g_opcodeMapWide[id];
98#else
99 UNUSED_PARAM(id);
100 RELEASE_ASSERT_NOT_REACHED();
101#endif
102}
103
104template<PtrTag tag>
105ALWAYS_INLINE MacroAssemblerCodePtr<tag> getCodePtr(OpcodeID opcodeID)
106{
107 void* address = reinterpret_cast<void*>(getOpcode(opcodeID));
108 address = retagCodePtr<BytecodePtrTag, tag>(address);
109 return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address);
110}
111
112template<PtrTag tag>
113ALWAYS_INLINE MacroAssemblerCodePtr<tag> getWideCodePtr(OpcodeID opcodeID)
114{
115 void* address = reinterpret_cast<void*>(getOpcodeWide(opcodeID));
116 address = retagCodePtr<BytecodePtrTag, tag>(address);
117 return MacroAssemblerCodePtr<tag>::createFromExecutableAddress(address);
118}
119
120template<PtrTag tag>
121ALWAYS_INLINE MacroAssemblerCodeRef<tag> getCodeRef(OpcodeID opcodeID)
122{
123 return MacroAssemblerCodeRef<tag>::createSelfManagedCodeRef(getCodePtr<tag>(opcodeID));
124}
125
126#if ENABLE(JIT)
127template<PtrTag tag>
128ALWAYS_INLINE LLIntCode getCodeFunctionPtr(OpcodeID opcodeID)
129{
130 ASSERT(opcodeID >= NUMBER_OF_BYTECODE_IDS);
131#if COMPILER(MSVC)
132 return reinterpret_cast<LLIntCode>(getCodePtr<tag>(opcodeID).executableAddress());
133#else
134 return reinterpret_cast<LLIntCode>(getCodePtr<tag>(opcodeID).template executableAddress());
135#endif
136}
137
138#else
139ALWAYS_INLINE void* getCodePtr(OpcodeID id)
140{
141 return reinterpret_cast<void*>(getOpcode(id));
142}
143
144ALWAYS_INLINE void* getWideCodePtr(OpcodeID id)
145{
146 return reinterpret_cast<void*>(getOpcodeWide(id));
147}
148#endif
149
150ALWAYS_INLINE void* getCodePtr(JSC::EncodedJSValue glueHelper())
151{
152 return bitwise_cast<void*>(glueHelper);
153}
154
155} } // namespace JSC::LLInt
156