1/* 2 * Copyright (C) 2011, 2012 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 DFGCapabilities_h 27#define DFGCapabilities_h 28 29#include "Intrinsic.h" 30#include "DFGCommon.h" 31#include "DFGNode.h" 32#include "Executable.h" 33#include "Options.h" 34#include "Interpreter.h" 35#include <wtf/Platform.h> 36 37namespace JSC { namespace DFG { 38 39#if ENABLE(DFG_JIT) 40// Fast check functions; if they return true it is still necessary to 41// check opcodes. 42bool mightCompileEval(CodeBlock*); 43bool mightCompileProgram(CodeBlock*); 44bool mightCompileFunctionForCall(CodeBlock*); 45bool mightCompileFunctionForConstruct(CodeBlock*); 46bool mightInlineFunctionForCall(CodeBlock*); 47bool mightInlineFunctionForClosureCall(CodeBlock*); 48bool mightInlineFunctionForConstruct(CodeBlock*); 49 50// Opcode checking. 51inline bool canInlineResolveOperations(ResolveOperations* operations) 52{ 53 for (unsigned i = 0; i < operations->size(); i++) { 54 switch (operations->data()[i].m_operation) { 55 case ResolveOperation::ReturnGlobalObjectAsBase: 56 case ResolveOperation::SetBaseToGlobal: 57 case ResolveOperation::SetBaseToUndefined: 58 case ResolveOperation::GetAndReturnGlobalProperty: 59 case ResolveOperation::GetAndReturnGlobalVar: 60 case ResolveOperation::GetAndReturnGlobalVarWatchable: 61 case ResolveOperation::SkipScopes: 62 case ResolveOperation::SetBaseToScope: 63 case ResolveOperation::ReturnScopeAsBase: 64 case ResolveOperation::GetAndReturnScopedVar: 65 continue; 66 67 case ResolveOperation::Fail: 68 // Fall-back resolves don't know how to deal with the ExecState* having a different 69 // global object (and scope) than the inlined code that is invoking that resolve. 70 return false; 71 72 case ResolveOperation::SkipTopScopeNode: 73 // We don't inline code blocks that create activations. Creation of 74 // activations is the only thing that leads to SkipTopScopeNode. 75 return false; 76 77 case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope: 78 // This would be easy to support in all cases. 79 return false; 80 } 81 } 82 return true; 83} 84 85inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*) 86{ 87 switch (opcodeID) { 88 case op_enter: 89 case op_convert_this: 90 case op_create_this: 91 case op_get_callee: 92 case op_bitand: 93 case op_bitor: 94 case op_bitxor: 95 case op_rshift: 96 case op_lshift: 97 case op_urshift: 98 case op_inc: 99 case op_dec: 100 case op_add: 101 case op_sub: 102 case op_negate: 103 case op_mul: 104 case op_mod: 105 case op_div: 106#if ENABLE(DEBUG_WITH_BREAKPOINT) 107 case op_debug: 108#endif 109 case op_mov: 110 case op_check_has_instance: 111 case op_instanceof: 112 case op_is_undefined: 113 case op_is_boolean: 114 case op_is_number: 115 case op_is_string: 116 case op_is_object: 117 case op_is_function: 118 case op_not: 119 case op_less: 120 case op_lesseq: 121 case op_greater: 122 case op_greatereq: 123 case op_eq: 124 case op_eq_null: 125 case op_stricteq: 126 case op_neq: 127 case op_neq_null: 128 case op_nstricteq: 129 case op_get_by_val: 130 case op_put_by_val: 131 case op_get_by_id: 132 case op_get_by_id_out_of_line: 133 case op_get_array_length: 134 case op_put_by_id: 135 case op_put_by_id_out_of_line: 136 case op_put_by_id_transition_direct: 137 case op_put_by_id_transition_direct_out_of_line: 138 case op_put_by_id_transition_normal: 139 case op_put_by_id_transition_normal_out_of_line: 140 case op_init_global_const_nop: 141 case op_init_global_const: 142 case op_init_global_const_check: 143 case op_jmp: 144 case op_jtrue: 145 case op_jfalse: 146 case op_jeq_null: 147 case op_jneq_null: 148 case op_jless: 149 case op_jlesseq: 150 case op_jgreater: 151 case op_jgreatereq: 152 case op_jnless: 153 case op_jnlesseq: 154 case op_jngreater: 155 case op_jngreatereq: 156 case op_loop_hint: 157 case op_ret: 158 case op_end: 159 case op_call_put_result: 160 case op_new_object: 161 case op_new_array: 162 case op_new_array_with_size: 163 case op_new_array_buffer: 164 case op_strcat: 165 case op_to_primitive: 166 case op_throw: 167 case op_throw_static_error: 168 case op_call: 169 case op_construct: 170 case op_new_regexp: 171 case op_init_lazy_reg: 172 case op_create_activation: 173 case op_tear_off_activation: 174 case op_create_arguments: 175 case op_tear_off_arguments: 176 case op_new_func: 177 case op_new_func_exp: 178 case op_get_argument_by_val: 179 case op_get_arguments_length: 180 case op_jneq_ptr: 181 case op_put_to_base_variable: 182 case op_put_to_base: 183 case op_typeof: 184 case op_to_number: 185 return CanCompile; 186 187 case op_call_varargs: 188 return MayInline; 189 190 case op_resolve: 191 case op_resolve_global_property: 192 case op_resolve_global_var: 193 case op_resolve_scoped_var: 194 case op_resolve_scoped_var_on_top_scope: 195 case op_resolve_scoped_var_with_top_scope_check: 196 return CanCompile; 197 198 case op_get_scoped_var: 199 case op_put_scoped_var: 200 return CanCompile; 201 202 case op_resolve_base_to_global: 203 case op_resolve_base_to_global_dynamic: 204 case op_resolve_base_to_scope: 205 case op_resolve_base_to_scope_with_top_scope_check: 206 case op_resolve_base: 207 case op_resolve_with_base: 208 case op_resolve_with_this: 209 return CanCompile; 210 211 default: 212 return CannotCompile; 213 } 214} 215 216inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc) 217{ 218 switch (opcodeID) { 219 case op_resolve: 220 case op_resolve_global_property: 221 case op_resolve_global_var: 222 case op_resolve_scoped_var: 223 case op_resolve_scoped_var_on_top_scope: 224 case op_resolve_scoped_var_with_top_scope_check: 225 return canInlineResolveOperations(pc[3].u.resolveOperations); 226 227 case op_resolve_base_to_global: 228 case op_resolve_base_to_global_dynamic: 229 case op_resolve_base_to_scope: 230 case op_resolve_base_to_scope_with_top_scope_check: 231 case op_resolve_base: 232 case op_resolve_with_base: 233 case op_resolve_with_this: 234 return canInlineResolveOperations(pc[4].u.resolveOperations); 235 236 case op_get_scoped_var: 237 case op_put_scoped_var: 238 return !codeBlock->needsFullScopeChain(); 239 240 // Inlining doesn't correctly remap regular expression operands. 241 case op_new_regexp: 242 243 // We don't support inlining code that creates activations or has nested functions. 244 case op_create_activation: 245 case op_tear_off_activation: 246 case op_new_func: 247 case op_new_func_exp: 248 return false; 249 250 // Inlining supports op_call_varargs if it's a call that just forwards the caller's 251 // arguments. 252 case op_call_varargs: 253 return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister(); 254 255 default: 256 return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile; 257 } 258} 259 260CapabilityLevel canCompileOpcodes(CodeBlock*); 261bool canInlineOpcodes(CodeBlock*); 262#else // ENABLE(DFG_JIT) 263inline bool mightCompileEval(CodeBlock*) { return false; } 264inline bool mightCompileProgram(CodeBlock*) { return false; } 265inline bool mightCompileFunctionForCall(CodeBlock*) { return false; } 266inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; } 267inline bool mightInlineFunctionForCall(CodeBlock*) { return false; } 268inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; } 269inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; } 270 271inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; } 272inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; } 273inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; } 274inline bool canInlineOpcodes(CodeBlock*) { return false; } 275#endif // ENABLE(DFG_JIT) 276 277inline CapabilityLevel canCompileEval(CodeBlock* codeBlock) 278{ 279 if (!mightCompileEval(codeBlock)) 280 return CannotCompile; 281 282 return canCompileOpcodes(codeBlock); 283} 284 285inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock) 286{ 287 if (!mightCompileProgram(codeBlock)) 288 return CannotCompile; 289 290 return canCompileOpcodes(codeBlock); 291} 292 293inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock) 294{ 295 if (!mightCompileFunctionForCall(codeBlock)) 296 return CannotCompile; 297 298 return canCompileOpcodes(codeBlock); 299} 300 301inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock) 302{ 303 if (!mightCompileFunctionForConstruct(codeBlock)) 304 return CannotCompile; 305 306 return canCompileOpcodes(codeBlock); 307} 308 309inline bool canInlineFunctionForCall(CodeBlock* codeBlock) 310{ 311 return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock); 312} 313 314inline bool canInlineFunctionForClosureCall(CodeBlock* codeBlock) 315{ 316 return mightInlineFunctionForClosureCall(codeBlock) && canInlineOpcodes(codeBlock); 317} 318 319inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock) 320{ 321 return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock); 322} 323 324inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind) 325{ 326 if (kind == CodeForCall) 327 return mightInlineFunctionForCall(codeBlock); 328 ASSERT(kind == CodeForConstruct); 329 return mightInlineFunctionForConstruct(codeBlock); 330} 331 332inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall) 333{ 334 if (isClosureCall) { 335 ASSERT(kind == CodeForCall); 336 return canInlineFunctionForClosureCall(codeBlock); 337 } 338 if (kind == CodeForCall) 339 return canInlineFunctionForCall(codeBlock); 340 ASSERT(kind == CodeForConstruct); 341 return canInlineFunctionForConstruct(codeBlock); 342} 343 344} } // namespace JSC::DFG 345 346#endif // DFGCapabilities_h 347 348