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