2 * Copyright (C) 2008, 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "LLIntThunks.h"
30 #include "JSCInlines.h"
31 #include "ProtoCallFrame.h"
32 #include "RegisterPreservationWrapperGenerator.h"
33 #include <wtf/PrintStream.h>
37 JITCode::JITCode(JITType jitType
)
46 const char* JITCode::typeName(JITType jitType
)
53 case InterpreterThunk
:
67 void JITCode::validateReferences(const TrackedReferences
&)
71 JSValue
JITCode::execute(VM
* vm
, ProtoCallFrame
* protoCallFrame
)
74 JSFunction
* function
= jsDynamicCast
<JSFunction
*>(protoCallFrame
->callee());
76 if (!function
|| !protoCallFrame
->needArityCheck()) {
77 ASSERT(!protoCallFrame
->needArityCheck());
78 entryAddress
= executableAddress();
80 entryAddress
= addressForCall(*vm
, function
->executable(), MustCheckArity
, RegisterPreservationNotRequired
).executableAddress();
81 JSValue result
= JSValue::decode(vmEntryToJavaScript(entryAddress
, vm
, protoCallFrame
));
82 return vm
->exception() ? jsNull() : result
;
85 DFG::CommonData
* JITCode::dfgCommon()
87 RELEASE_ASSERT_NOT_REACHED();
91 DFG::JITCode
* JITCode::dfg()
93 RELEASE_ASSERT_NOT_REACHED();
97 FTL::JITCode
* JITCode::ftl()
99 RELEASE_ASSERT_NOT_REACHED();
103 FTL::ForOSREntryJITCode
* JITCode::ftlForOSREntry()
105 RELEASE_ASSERT_NOT_REACHED();
109 JITCodeWithCodeRef::JITCodeWithCodeRef(JITType jitType
)
114 JITCodeWithCodeRef::JITCodeWithCodeRef(CodeRef ref
, JITType jitType
)
120 JITCodeWithCodeRef::~JITCodeWithCodeRef()
124 void* JITCodeWithCodeRef::executableAddressAtOffset(size_t offset
)
126 RELEASE_ASSERT(m_ref
);
127 return reinterpret_cast<char*>(m_ref
.code().executableAddress()) + offset
;
130 void* JITCodeWithCodeRef::dataAddressAtOffset(size_t offset
)
132 RELEASE_ASSERT(m_ref
);
133 ASSERT(offset
<= size()); // use <= instead of < because it is valid to ask for an address at the exclusive end of the code.
134 return reinterpret_cast<char*>(m_ref
.code().dataLocation()) + offset
;
137 unsigned JITCodeWithCodeRef::offsetOf(void* pointerIntoCode
)
139 RELEASE_ASSERT(m_ref
);
140 intptr_t result
= reinterpret_cast<intptr_t>(pointerIntoCode
) - reinterpret_cast<intptr_t>(m_ref
.code().executableAddress());
141 ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result
)) == result
);
142 return static_cast<unsigned>(result
);
145 size_t JITCodeWithCodeRef::size()
147 RELEASE_ASSERT(m_ref
);
151 bool JITCodeWithCodeRef::contains(void* address
)
153 RELEASE_ASSERT(m_ref
);
154 return m_ref
.executableMemory()->contains(address
);
157 DirectJITCode::DirectJITCode(JITType jitType
)
158 : JITCodeWithCodeRef(jitType
)
162 DirectJITCode::DirectJITCode(JITCode::CodeRef ref
, JITCode::CodePtr withArityCheck
, JITType jitType
)
163 : JITCodeWithCodeRef(ref
, jitType
)
164 , m_withArityCheck(withArityCheck
)
168 DirectJITCode::~DirectJITCode()
172 void DirectJITCode::initializeCodeRef(JITCode::CodeRef ref
, JITCode::CodePtr withArityCheck
)
174 RELEASE_ASSERT(!m_ref
);
176 m_withArityCheck
= withArityCheck
;
179 DirectJITCode::RegisterPreservationWrappers
* DirectJITCode::ensureWrappers()
182 m_wrappers
= std::make_unique
<RegisterPreservationWrappers
>();
183 return m_wrappers
.get();
186 JITCode::CodePtr
DirectJITCode::addressForCall(
187 VM
& vm
, ExecutableBase
* executable
, ArityCheckMode arity
,
188 RegisterPreservationMode registers
)
191 case ArityCheckNotRequired
:
193 case RegisterPreservationNotRequired
:
194 RELEASE_ASSERT(m_ref
);
196 case MustPreserveRegisters
: {
198 RegisterPreservationWrappers
* wrappers
= ensureWrappers();
199 if (!wrappers
->withoutArityCheck
)
200 wrappers
->withoutArityCheck
= generateRegisterPreservationWrapper(vm
, executable
, m_ref
.code());
201 return wrappers
->withoutArityCheck
.code();
204 UNUSED_PARAM(executable
);
205 RELEASE_ASSERT_NOT_REACHED();
210 case RegisterPreservationNotRequired
:
211 RELEASE_ASSERT(m_withArityCheck
);
212 return m_withArityCheck
;
213 case MustPreserveRegisters
: {
215 RegisterPreservationWrappers
* wrappers
= ensureWrappers();
216 if (!wrappers
->withArityCheck
)
217 wrappers
->withArityCheck
= generateRegisterPreservationWrapper(vm
, executable
, m_withArityCheck
);
218 return wrappers
->withArityCheck
.code();
220 RELEASE_ASSERT_NOT_REACHED();
224 RELEASE_ASSERT_NOT_REACHED();
228 NativeJITCode::NativeJITCode(JITType jitType
)
229 : JITCodeWithCodeRef(jitType
)
233 NativeJITCode::NativeJITCode(CodeRef ref
, JITType jitType
)
234 : JITCodeWithCodeRef(ref
, jitType
)
238 NativeJITCode::~NativeJITCode()
242 void NativeJITCode::initializeCodeRef(CodeRef ref
)
248 JITCode::CodePtr
NativeJITCode::addressForCall(
249 VM
&, ExecutableBase
*, ArityCheckMode
, RegisterPreservationMode
)
251 RELEASE_ASSERT(!!m_ref
);
259 void printInternal(PrintStream
& out
, JSC::JITCode::JITType type
)
261 out
.print(JSC::JITCode::typeName(type
));