a56358cd6e0977743e87b3c165e2cea1aa47eda6
[WebKit-https.git] / Source / JavaScriptCore / runtime / CommonSlowPaths.h
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 #ifndef CommonSlowPaths_h
27 #define CommonSlowPaths_h
28
29 #include "CodeBlock.h"
30 #include "CodeSpecializationKind.h"
31 #include "ExceptionHelpers.h"
32 #include "JSStackInlines.h"
33 #include "NameInstance.h"
34 #include "StackAlignment.h"
35 #include "VM.h"
36 #include <wtf/StdLibExtras.h>
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
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)
56 {
57     JSFunction* callee = jsCast<JSFunction*>(exec->callee());
58     ASSERT(!callee->isHostFunction());
59     CodeBlock* newCodeBlock = callee->jsExecutable()->codeBlockFor(kind);
60     int argumentCountIncludingThis = exec->argumentCountIncludingThis();
61     
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);
66
67     if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace))
68         return -1;
69     return paddedStackSpace / stackAlignmentRegisters();
70 }
71
72 inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
73 {
74     if (!baseVal.isObject()) {
75         exec->vm().throwException(exec, createInvalidParameterError(exec, "in", baseVal));
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
85     if (isName(propName))
86         return baseObj->hasProperty(exec, jsCast<NameInstance*>(propName.asCell())->privateName());
87
88     Identifier property = propName.toString(exec)->toIdentifier(exec);
89     if (exec->vm().exception())
90         return false;
91     return baseObj->hasProperty(exec, property);
92 }
93
94 inline void tryCachePutToScopeGlobal(
95     ExecState* exec, CodeBlock* codeBlock, Instruction* pc, JSObject* scope,
96     ResolveModeAndType modeAndType, PutPropertySlot& slot)
97 {
98     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
99     
100     if (modeAndType.type() != GlobalProperty && modeAndType.type() != GlobalPropertyWithVarInjectionChecks)
101         return;
102     
103     if (!slot.isCacheablePut()
104         || slot.base() != scope
105         || !scope->structure()->propertyAccessesAreCacheable())
106         return;
107     
108     if (slot.type() == PutPropertySlot::NewProperty) {
109         // Don't cache if we've done a transition. We want to detect the first replace so that we
110         // can invalidate the watchpoint.
111         return;
112     }
113     
114     scope->structure()->didCachePropertyReplacement(exec->vm(), slot.cachedOffset());
115
116     ConcurrentJITLocker locker(codeBlock->m_lock);
117     pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
118     pc[6].u.operand = slot.cachedOffset();
119 }
120
121 } // namespace CommonSlowPaths
122
123 class ExecState;
124 struct Instruction;
125
126 #if USE(JSVALUE64)
127 // According to C++ rules, a type used for the return signature of function with C linkage (i.e.
128 // 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
129 // warnings, or worse, a change in the ABI used to return these types.
130 struct SlowPathReturnType {
131     void* a;
132     void* b;
133 };
134
135 inline SlowPathReturnType encodeResult(void* a, void* b)
136 {
137     SlowPathReturnType result;
138     result.a = a;
139     result.b = b;
140     return result;
141 }
142
143 inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
144 {
145     a = result.a;
146     b = result.b;
147 }
148
149 #else // USE(JSVALUE32_64)
150 typedef int64_t SlowPathReturnType;
151
152 typedef union {
153     struct {
154         void* a;
155         void* b;
156     } pair;
157     int64_t i;
158 } SlowPathReturnTypeEncoding;
159
160 inline SlowPathReturnType encodeResult(void* a, void* b)
161 {
162     SlowPathReturnTypeEncoding u;
163     u.pair.a = a;
164     u.pair.b = b;
165     return u.i;
166 }
167
168 inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
169 {
170     SlowPathReturnTypeEncoding u;
171     u.i = result;
172     a = u.pair.a;
173     b = u.pair.b;
174 }
175 #endif // USE(JSVALUE32_64)
176     
177 #define SLOW_PATH
178     
179 #define SLOW_PATH_DECL(name) \
180 extern "C" SlowPathReturnType SLOW_PATH name(ExecState* exec, Instruction* pc)
181     
182 #define SLOW_PATH_HIDDEN_DECL(name) \
183 SLOW_PATH_DECL(name) WTF_INTERNAL
184     
185 SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck);
186 SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
187 SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry);
188 SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
189 SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
190 SLOW_PATH_HIDDEN_DECL(slow_path_enter);
191 SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
192 SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
193 SLOW_PATH_HIDDEN_DECL(slow_path_not);
194 SLOW_PATH_HIDDEN_DECL(slow_path_eq);
195 SLOW_PATH_HIDDEN_DECL(slow_path_neq);
196 SLOW_PATH_HIDDEN_DECL(slow_path_stricteq);
197 SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq);
198 SLOW_PATH_HIDDEN_DECL(slow_path_less);
199 SLOW_PATH_HIDDEN_DECL(slow_path_lesseq);
200 SLOW_PATH_HIDDEN_DECL(slow_path_greater);
201 SLOW_PATH_HIDDEN_DECL(slow_path_greatereq);
202 SLOW_PATH_HIDDEN_DECL(slow_path_inc);
203 SLOW_PATH_HIDDEN_DECL(slow_path_dec);
204 SLOW_PATH_HIDDEN_DECL(slow_path_to_number);
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_function);
221 SLOW_PATH_HIDDEN_DECL(slow_path_in);
222 SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
223 SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
224 SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
225 SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length);
226 SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property);
227 SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
228 SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
229 SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
230 SLOW_PATH_HIDDEN_DECL(slow_path_get_structure_property_enumerator);
231 SLOW_PATH_HIDDEN_DECL(slow_path_get_generic_property_enumerator);
232 SLOW_PATH_HIDDEN_DECL(slow_path_next_enumerator_pname);
233 SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
234 SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
235
236 } // namespace JSC
237
238 #endif // CommonSlowPaths_h