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
38namespace 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
47namespace CommonSlowPaths {
48
49struct ArityCheckData {
50    unsigned paddedStackSpace;
51    void* thunkToCall;
52    void* returnPC;
53};
54
55ALWAYS_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
72inline 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(exec, propName.toString(exec)->value(exec));
89    if (exec->vm().exception())
90        return false;
91    return baseObj->hasProperty(exec, property);
92}
93
94} // namespace CommonSlowPaths
95
96class ExecState;
97struct Instruction;
98
99#if USE(JSVALUE64)
100// According to C++ rules, a type used for the return signature of function with C linkage (i.e.
101// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
102// warnings, or worse, a change in the ABI used to return these types.
103struct SlowPathReturnType {
104    void* a;
105    void* b;
106};
107
108inline SlowPathReturnType encodeResult(void* a, void* b)
109{
110    SlowPathReturnType result;
111    result.a = a;
112    result.b = b;
113    return result;
114}
115
116inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
117{
118    a = result.a;
119    b = result.b;
120}
121
122#else // USE(JSVALUE32_64)
123typedef int64_t SlowPathReturnType;
124
125typedef union {
126    struct {
127        void* a;
128        void* b;
129    } pair;
130    int64_t i;
131} SlowPathReturnTypeEncoding;
132
133inline SlowPathReturnType encodeResult(void* a, void* b)
134{
135    SlowPathReturnTypeEncoding u;
136    u.pair.a = a;
137    u.pair.b = b;
138    return u.i;
139}
140
141inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
142{
143    SlowPathReturnTypeEncoding u;
144    u.i = result;
145    a = u.pair.a;
146    b = u.pair.b;
147}
148#endif // USE(JSVALUE32_64)
149
150#define SLOW_PATH
151
152#define SLOW_PATH_DECL(name) \
153extern "C" SlowPathReturnType SLOW_PATH name(ExecState* exec, Instruction* pc)
154
155#define SLOW_PATH_HIDDEN_DECL(name) \
156SLOW_PATH_DECL(name) WTF_INTERNAL
157
158SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck);
159SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
160SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry);
161SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
162SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
163SLOW_PATH_HIDDEN_DECL(slow_path_enter);
164SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
165SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
166SLOW_PATH_HIDDEN_DECL(slow_path_captured_mov);
167SLOW_PATH_HIDDEN_DECL(slow_path_new_captured_func);
168SLOW_PATH_HIDDEN_DECL(slow_path_not);
169SLOW_PATH_HIDDEN_DECL(slow_path_eq);
170SLOW_PATH_HIDDEN_DECL(slow_path_neq);
171SLOW_PATH_HIDDEN_DECL(slow_path_stricteq);
172SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq);
173SLOW_PATH_HIDDEN_DECL(slow_path_less);
174SLOW_PATH_HIDDEN_DECL(slow_path_lesseq);
175SLOW_PATH_HIDDEN_DECL(slow_path_greater);
176SLOW_PATH_HIDDEN_DECL(slow_path_greatereq);
177SLOW_PATH_HIDDEN_DECL(slow_path_inc);
178SLOW_PATH_HIDDEN_DECL(slow_path_dec);
179SLOW_PATH_HIDDEN_DECL(slow_path_to_number);
180SLOW_PATH_HIDDEN_DECL(slow_path_negate);
181SLOW_PATH_HIDDEN_DECL(slow_path_add);
182SLOW_PATH_HIDDEN_DECL(slow_path_mul);
183SLOW_PATH_HIDDEN_DECL(slow_path_sub);
184SLOW_PATH_HIDDEN_DECL(slow_path_div);
185SLOW_PATH_HIDDEN_DECL(slow_path_mod);
186SLOW_PATH_HIDDEN_DECL(slow_path_lshift);
187SLOW_PATH_HIDDEN_DECL(slow_path_rshift);
188SLOW_PATH_HIDDEN_DECL(slow_path_urshift);
189SLOW_PATH_HIDDEN_DECL(slow_path_unsigned);
190SLOW_PATH_HIDDEN_DECL(slow_path_bitand);
191SLOW_PATH_HIDDEN_DECL(slow_path_bitor);
192SLOW_PATH_HIDDEN_DECL(slow_path_bitxor);
193SLOW_PATH_HIDDEN_DECL(slow_path_typeof);
194SLOW_PATH_HIDDEN_DECL(slow_path_is_object);
195SLOW_PATH_HIDDEN_DECL(slow_path_is_function);
196SLOW_PATH_HIDDEN_DECL(slow_path_in);
197SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
198SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
199SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
200
201} // namespace JSC
202
203#endif // CommonSlowPaths_h
204