]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 | 1 | /* |
ed1e77d3 | 2 | * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved. |
6fe7ccc8 A |
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 | #ifndef CommonSlowPaths_h | |
27 | #define CommonSlowPaths_h | |
28 | ||
29 | #include "CodeBlock.h" | |
30 | #include "CodeSpecializationKind.h" | |
31 | #include "ExceptionHelpers.h" | |
81345200 | 32 | #include "JSStackInlines.h" |
81345200 | 33 | #include "StackAlignment.h" |
ed1e77d3 | 34 | #include "Symbol.h" |
81345200 A |
35 | #include "VM.h" |
36 | #include <wtf/StdLibExtras.h> | |
6fe7ccc8 A |
37 | |
38 | namespace JSC { | |
39 | ||
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). | |
46 | ||
47 | namespace CommonSlowPaths { | |
48 | ||
81345200 A |
49 | struct ArityCheckData { |
50 | unsigned paddedStackSpace; | |
51 | void* thunkToCall; | |
52 | void* returnPC; | |
53 | }; | |
54 | ||
55 | ALWAYS_INLINE int arityCheckFor(ExecState* exec, JSStack* stack, CodeSpecializationKind kind) | |
6fe7ccc8 A |
56 | { |
57 | JSFunction* callee = jsCast<JSFunction*>(exec->callee()); | |
58 | ASSERT(!callee->isHostFunction()); | |
81345200 | 59 | CodeBlock* newCodeBlock = callee->jsExecutable()->codeBlockFor(kind); |
6fe7ccc8 | 60 | int argumentCountIncludingThis = exec->argumentCountIncludingThis(); |
81345200 | 61 | |
6fe7ccc8 | 62 | ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters()); |
81345200 A |
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); | |
6fe7ccc8 | 66 | |
81345200 A |
67 | if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace)) |
68 | return -1; | |
69 | return paddedStackSpace / stackAlignmentRegisters(); | |
6fe7ccc8 A |
70 | } |
71 | ||
6fe7ccc8 A |
72 | inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) |
73 | { | |
74 | if (!baseVal.isObject()) { | |
ed1e77d3 | 75 | exec->vm().throwException(exec, createInvalidInParameterError(exec, baseVal)); |
6fe7ccc8 A |
76 | return false; |
77 | } | |
78 | ||
79 | JSObject* baseObj = asObject(baseVal); | |
80 | ||
81 | uint32_t i; | |
82 | if (propName.getUInt32(i)) | |
83 | return baseObj->hasProperty(exec, i); | |
84 | ||
ed1e77d3 | 85 | auto property = propName.toPropertyKey(exec); |
81345200 | 86 | if (exec->vm().exception()) |
6fe7ccc8 A |
87 | return false; |
88 | return baseObj->hasProperty(exec, property); | |
89 | } | |
90 | ||
ed1e77d3 A |
91 | inline void tryCachePutToScopeGlobal( |
92 | ExecState* exec, CodeBlock* codeBlock, Instruction* pc, JSObject* scope, | |
93 | ResolveModeAndType modeAndType, PutPropertySlot& slot) | |
94 | { | |
95 | // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. | |
96 | ||
97 | if (modeAndType.type() != GlobalProperty && modeAndType.type() != GlobalPropertyWithVarInjectionChecks) | |
98 | return; | |
99 | ||
100 | if (!slot.isCacheablePut() | |
101 | || slot.base() != scope | |
102 | || !scope->structure()->propertyAccessesAreCacheable()) | |
103 | return; | |
104 | ||
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. | |
108 | return; | |
109 | } | |
110 | ||
111 | scope->structure()->didCachePropertyReplacement(exec->vm(), slot.cachedOffset()); | |
112 | ||
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(); | |
116 | } | |
117 | ||
81345200 A |
118 | } // namespace CommonSlowPaths |
119 | ||
120 | class ExecState; | |
121 | struct Instruction; | |
122 | ||
123 | #if USE(JSVALUE64) | |
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 { | |
128 | void* a; | |
129 | void* b; | |
130 | }; | |
131 | ||
132 | inline SlowPathReturnType encodeResult(void* a, void* b) | |
133 | { | |
134 | SlowPathReturnType result; | |
135 | result.a = a; | |
136 | result.b = b; | |
137 | return result; | |
138 | } | |
139 | ||
140 | inline void decodeResult(SlowPathReturnType result, void*& a, void*& b) | |
141 | { | |
142 | a = result.a; | |
143 | b = result.b; | |
144 | } | |
145 | ||
146 | #else // USE(JSVALUE32_64) | |
147 | typedef int64_t SlowPathReturnType; | |
148 | ||
149 | typedef union { | |
150 | struct { | |
151 | void* a; | |
152 | void* b; | |
153 | } pair; | |
154 | int64_t i; | |
155 | } SlowPathReturnTypeEncoding; | |
156 | ||
157 | inline SlowPathReturnType encodeResult(void* a, void* b) | |
158 | { | |
159 | SlowPathReturnTypeEncoding u; | |
160 | u.pair.a = a; | |
161 | u.pair.b = b; | |
162 | return u.i; | |
163 | } | |
164 | ||
165 | inline void decodeResult(SlowPathReturnType result, void*& a, void*& b) | |
166 | { | |
167 | SlowPathReturnTypeEncoding u; | |
168 | u.i = result; | |
169 | a = u.pair.a; | |
170 | b = u.pair.b; | |
171 | } | |
172 | #endif // USE(JSVALUE32_64) | |
173 | ||
174 | #define SLOW_PATH | |
175 | ||
176 | #define SLOW_PATH_DECL(name) \ | |
177 | extern "C" SlowPathReturnType SLOW_PATH name(ExecState* exec, Instruction* pc) | |
178 | ||
179 | #define SLOW_PATH_HIDDEN_DECL(name) \ | |
180 | SLOW_PATH_DECL(name) WTF_INTERNAL | |
181 | ||
182 | SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck); | |
183 | SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck); | |
ed1e77d3 A |
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); | |
81345200 A |
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); | |
ed1e77d3 | 191 | SLOW_PATH_HIDDEN_DECL(slow_path_throw_tdz_error); |
81345200 A |
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); | |
ed1e77d3 | 204 | SLOW_PATH_HIDDEN_DECL(slow_path_to_string); |
81345200 A |
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); | |
ed1e77d3 | 220 | SLOW_PATH_HIDDEN_DECL(slow_path_is_object_or_null); |
81345200 A |
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); | |
ed1e77d3 A |
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); | |
81345200 A |
236 | |
237 | } // namespace JSC | |
6fe7ccc8 A |
238 | |
239 | #endif // CommonSlowPaths_h |