2 * Copyright (C) 2011-2013, 2015 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.
26 #ifndef CommonSlowPaths_h
27 #define CommonSlowPaths_h
29 #include "CodeBlock.h"
30 #include "CodeSpecializationKind.h"
31 #include "ExceptionHelpers.h"
32 #include "JSStackInlines.h"
33 #include "StackAlignment.h"
36 #include <wtf/StdLibExtras.h>
40 // The purpose of this namespace is to include slow paths that are shared
41 // between the interpreter and baseline JIT. They are written to be agnostic
42 // with respect to the slow-path calling convention, but they do rely on the
43 // JS code being executed more-or-less directly from bytecode (so the call
44 // frame layout is unmodified, making it potentially awkward to use these
45 // from any optimizing JIT, like the DFG).
47 namespace CommonSlowPaths
{
49 struct ArityCheckData
{
50 unsigned paddedStackSpace
;
55 ALWAYS_INLINE
int arityCheckFor(ExecState
* exec
, JSStack
* stack
, CodeSpecializationKind kind
)
57 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
58 ASSERT(!callee
->isHostFunction());
59 CodeBlock
* newCodeBlock
= callee
->jsExecutable()->codeBlockFor(kind
);
60 int argumentCountIncludingThis
= exec
->argumentCountIncludingThis();
62 ASSERT(argumentCountIncludingThis
< newCodeBlock
->numParameters());
63 int missingArgumentCount
= newCodeBlock
->numParameters() - argumentCountIncludingThis
;
64 int neededStackSpace
= missingArgumentCount
+ 1; // Allow space to save the original return PC.
65 int paddedStackSpace
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), neededStackSpace
);
67 if (!stack
->ensureCapacityFor(exec
->registers() - paddedStackSpace
))
69 return paddedStackSpace
/ stackAlignmentRegisters();
72 inline bool opIn(ExecState
* exec
, JSValue propName
, JSValue baseVal
)
74 if (!baseVal
.isObject()) {
75 exec
->vm().throwException(exec
, createInvalidInParameterError(exec
, baseVal
));
79 JSObject
* baseObj
= asObject(baseVal
);
82 if (propName
.getUInt32(i
))
83 return baseObj
->hasProperty(exec
, i
);
85 auto property
= propName
.toPropertyKey(exec
);
86 if (exec
->vm().exception())
88 return baseObj
->hasProperty(exec
, property
);
91 inline void tryCachePutToScopeGlobal(
92 ExecState
* exec
, CodeBlock
* codeBlock
, Instruction
* pc
, JSObject
* scope
,
93 ResolveModeAndType modeAndType
, PutPropertySlot
& slot
)
95 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
97 if (modeAndType
.type() != GlobalProperty
&& modeAndType
.type() != GlobalPropertyWithVarInjectionChecks
)
100 if (!slot
.isCacheablePut()
101 || slot
.base() != scope
102 || !scope
->structure()->propertyAccessesAreCacheable())
105 if (slot
.type() == PutPropertySlot::NewProperty
) {
106 // Don't cache if we've done a transition. We want to detect the first replace so that we
107 // can invalidate the watchpoint.
111 scope
->structure()->didCachePropertyReplacement(exec
->vm(), slot
.cachedOffset());
113 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
114 pc
[5].u
.structure
.set(exec
->vm(), codeBlock
->ownerExecutable(), scope
->structure());
115 pc
[6].u
.operand
= slot
.cachedOffset();
118 } // namespace CommonSlowPaths
124 // According to C++ rules, a type used for the return signature of function with C linkage (i.e.
125 // 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
126 // warnings, or worse, a change in the ABI used to return these types.
127 struct SlowPathReturnType
{
132 inline SlowPathReturnType
encodeResult(void* a
, void* b
)
134 SlowPathReturnType result
;
140 inline void decodeResult(SlowPathReturnType result
, void*& a
, void*& b
)
146 #else // USE(JSVALUE32_64)
147 typedef int64_t SlowPathReturnType
;
155 } SlowPathReturnTypeEncoding
;
157 inline SlowPathReturnType
encodeResult(void* a
, void* b
)
159 SlowPathReturnTypeEncoding u
;
165 inline void decodeResult(SlowPathReturnType result
, void*& a
, void*& b
)
167 SlowPathReturnTypeEncoding u
;
172 #endif // USE(JSVALUE32_64)
176 #define SLOW_PATH_DECL(name) \
177 extern "C" SlowPathReturnType SLOW_PATH name(ExecState* exec, Instruction* pc)
179 #define SLOW_PATH_HIDDEN_DECL(name) \
180 SLOW_PATH_DECL(name) WTF_INTERNAL
182 SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck
);
183 SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck
);
184 SLOW_PATH_HIDDEN_DECL(slow_path_create_direct_arguments
);
185 SLOW_PATH_HIDDEN_DECL(slow_path_create_scoped_arguments
);
186 SLOW_PATH_HIDDEN_DECL(slow_path_create_out_of_band_arguments
);
187 SLOW_PATH_HIDDEN_DECL(slow_path_create_this
);
188 SLOW_PATH_HIDDEN_DECL(slow_path_enter
);
189 SLOW_PATH_HIDDEN_DECL(slow_path_get_callee
);
190 SLOW_PATH_HIDDEN_DECL(slow_path_to_this
);
191 SLOW_PATH_HIDDEN_DECL(slow_path_throw_tdz_error
);
192 SLOW_PATH_HIDDEN_DECL(slow_path_not
);
193 SLOW_PATH_HIDDEN_DECL(slow_path_eq
);
194 SLOW_PATH_HIDDEN_DECL(slow_path_neq
);
195 SLOW_PATH_HIDDEN_DECL(slow_path_stricteq
);
196 SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq
);
197 SLOW_PATH_HIDDEN_DECL(slow_path_less
);
198 SLOW_PATH_HIDDEN_DECL(slow_path_lesseq
);
199 SLOW_PATH_HIDDEN_DECL(slow_path_greater
);
200 SLOW_PATH_HIDDEN_DECL(slow_path_greatereq
);
201 SLOW_PATH_HIDDEN_DECL(slow_path_inc
);
202 SLOW_PATH_HIDDEN_DECL(slow_path_dec
);
203 SLOW_PATH_HIDDEN_DECL(slow_path_to_number
);
204 SLOW_PATH_HIDDEN_DECL(slow_path_to_string
);
205 SLOW_PATH_HIDDEN_DECL(slow_path_negate
);
206 SLOW_PATH_HIDDEN_DECL(slow_path_add
);
207 SLOW_PATH_HIDDEN_DECL(slow_path_mul
);
208 SLOW_PATH_HIDDEN_DECL(slow_path_sub
);
209 SLOW_PATH_HIDDEN_DECL(slow_path_div
);
210 SLOW_PATH_HIDDEN_DECL(slow_path_mod
);
211 SLOW_PATH_HIDDEN_DECL(slow_path_lshift
);
212 SLOW_PATH_HIDDEN_DECL(slow_path_rshift
);
213 SLOW_PATH_HIDDEN_DECL(slow_path_urshift
);
214 SLOW_PATH_HIDDEN_DECL(slow_path_unsigned
);
215 SLOW_PATH_HIDDEN_DECL(slow_path_bitand
);
216 SLOW_PATH_HIDDEN_DECL(slow_path_bitor
);
217 SLOW_PATH_HIDDEN_DECL(slow_path_bitxor
);
218 SLOW_PATH_HIDDEN_DECL(slow_path_typeof
);
219 SLOW_PATH_HIDDEN_DECL(slow_path_is_object
);
220 SLOW_PATH_HIDDEN_DECL(slow_path_is_object_or_null
);
221 SLOW_PATH_HIDDEN_DECL(slow_path_is_function
);
222 SLOW_PATH_HIDDEN_DECL(slow_path_in
);
223 SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val
);
224 SLOW_PATH_HIDDEN_DECL(slow_path_strcat
);
225 SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive
);
226 SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length
);
227 SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property
);
228 SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property
);
229 SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property
);
230 SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname
);
231 SLOW_PATH_HIDDEN_DECL(slow_path_get_property_enumerator
);
232 SLOW_PATH_HIDDEN_DECL(slow_path_next_structure_enumerator_pname
);
233 SLOW_PATH_HIDDEN_DECL(slow_path_next_generic_enumerator_pname
);
234 SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string
);
235 SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log
);
239 #endif // CommonSlowPaths_h