1/* 2 * Copyright (C) 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. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef BytecodeUseDef_h 27#define BytecodeUseDef_h 28 29#include "CodeBlock.h" 30 31namespace JSC { 32 33template<typename Functor> 34void computeUsesForBytecodeOffset( 35 CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor) 36{ 37 Interpreter* interpreter = codeBlock->vm()->interpreter; 38 Instruction* instructionsBegin = codeBlock->instructions().begin(); 39 Instruction* instruction = &instructionsBegin[bytecodeOffset]; 40 OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); 41 switch (opcodeID) { 42 // No uses. 43 case op_new_regexp: 44 case op_new_array_buffer: 45 case op_throw_static_error: 46 case op_debug: 47 case op_resolve_scope: 48 case op_pop_scope: 49 case op_jneq_ptr: 50 case op_new_func_exp: 51 case op_loop_hint: 52 case op_jmp: 53 case op_new_object: 54 case op_init_lazy_reg: 55 case op_get_callee: 56 case op_enter: 57 case op_catch: 58 case op_touch_entry: 59 return; 60 case op_new_func: 61 case op_new_captured_func: 62 case op_create_activation: 63 case op_create_arguments: 64 case op_to_this: 65 case op_tear_off_activation: 66 case op_profile_will_call: 67 case op_profile_did_call: 68 case op_throw: 69 case op_push_with_scope: 70 case op_end: 71 case op_ret: 72 case op_jtrue: 73 case op_jfalse: 74 case op_jeq_null: 75 case op_jneq_null: 76 case op_dec: 77 case op_inc: { 78 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 79 return; 80 } 81 case op_ret_object_or_this: 82 case op_jlesseq: 83 case op_jgreater: 84 case op_jgreatereq: 85 case op_jnless: 86 case op_jnlesseq: 87 case op_jngreater: 88 case op_jngreatereq: 89 case op_jless: { 90 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 91 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 92 return; 93 } 94 case op_put_by_val_direct: 95 case op_put_by_val: { 96 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 97 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 98 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 99 return; 100 } 101 case op_put_by_index: 102 case op_put_by_id_transition_direct: 103 case op_put_by_id_transition_direct_out_of_line: 104 case op_put_by_id_transition_normal: 105 case op_put_by_id_transition_normal_out_of_line: 106 case op_put_by_id_out_of_line: 107 case op_put_by_id: 108 case op_put_to_scope: { 109 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 110 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 111 return; 112 } 113 case op_put_getter_setter: { 114 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 115 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 116 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); 117 return; 118 } 119 case op_init_global_const_nop: 120 case op_init_global_const: 121 case op_push_name_scope: 122 case op_get_from_scope: 123 case op_to_primitive: 124 case op_get_by_id: 125 case op_get_by_id_out_of_line: 126 case op_get_array_length: 127 case op_get_arguments_length: 128 case op_typeof: 129 case op_is_undefined: 130 case op_is_boolean: 131 case op_is_number: 132 case op_is_string: 133 case op_is_object: 134 case op_is_function: 135 case op_to_number: 136 case op_negate: 137 case op_neq_null: 138 case op_eq_null: 139 case op_not: 140 case op_mov: 141 case op_captured_mov: 142 case op_new_array_with_size: 143 case op_create_this: 144 case op_get_pnames: 145 case op_del_by_id: 146 case op_unsigned: { 147 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 148 return; 149 } 150 case op_get_by_val: 151 case op_get_argument_by_val: 152 case op_in: 153 case op_instanceof: 154 case op_check_has_instance: 155 case op_add: 156 case op_mul: 157 case op_div: 158 case op_mod: 159 case op_sub: 160 case op_lshift: 161 case op_rshift: 162 case op_urshift: 163 case op_bitand: 164 case op_bitxor: 165 case op_bitor: 166 case op_less: 167 case op_lesseq: 168 case op_greater: 169 case op_greatereq: 170 case op_nstricteq: 171 case op_stricteq: 172 case op_neq: 173 case op_eq: 174 case op_del_by_val: { 175 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 176 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 177 return; 178 } 179 case op_construct_varargs: 180 case op_call_varargs: { 181 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 182 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 183 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); 184 return; 185 } 186 case op_next_pname: { 187 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 188 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 189 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); 190 functor(codeBlock, instruction, opcodeID, instruction[5].u.operand); 191 return; 192 } 193 case op_get_by_pname: { 194 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 195 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 196 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); 197 functor(codeBlock, instruction, opcodeID, instruction[5].u.operand); 198 functor(codeBlock, instruction, opcodeID, instruction[6].u.operand); 199 return; 200 } 201 case op_switch_string: 202 case op_switch_char: 203 case op_switch_imm: { 204 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 205 return; 206 } 207 case op_new_array: 208 case op_strcat: { 209 int base = instruction[2].u.operand; 210 int count = instruction[3].u.operand; 211 for (int i = 0; i < count; i++) 212 functor(codeBlock, instruction, opcodeID, base - i); 213 return; 214 } 215 case op_construct: 216 case op_call_eval: 217 case op_call: { 218 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 219 int argCount = instruction[3].u.operand; 220 int registerOffset = -instruction[4].u.operand; 221 int lastArg = registerOffset + CallFrame::thisArgumentOffset(); 222 for (int i = opcodeID == op_construct ? 1 : 0; i < argCount; i++) 223 functor(codeBlock, instruction, opcodeID, lastArg + i); 224 return; 225 } 226 case op_tear_off_arguments: { 227 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 228 functor(codeBlock, instruction, opcodeID, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset()); 229 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 230 return; 231 } 232 default: 233 RELEASE_ASSERT_NOT_REACHED(); 234 break; 235 } 236} 237 238template<typename Functor> 239void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor) 240{ 241 Interpreter* interpreter = codeBlock->vm()->interpreter; 242 Instruction* instructionsBegin = codeBlock->instructions().begin(); 243 Instruction* instruction = &instructionsBegin[bytecodeOffset]; 244 OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); 245 switch (opcodeID) { 246 // These don't define anything. 247 case op_init_global_const: 248 case op_init_global_const_nop: 249 case op_push_name_scope: 250 case op_push_with_scope: 251 case op_put_to_scope: 252 case op_pop_scope: 253 case op_end: 254 case op_profile_will_call: 255 case op_profile_did_call: 256 case op_throw: 257 case op_throw_static_error: 258 case op_debug: 259 case op_ret: 260 case op_ret_object_or_this: 261 case op_jmp: 262 case op_jtrue: 263 case op_jfalse: 264 case op_jeq_null: 265 case op_jneq_null: 266 case op_jneq_ptr: 267 case op_jless: 268 case op_jlesseq: 269 case op_jgreater: 270 case op_jgreatereq: 271 case op_jnless: 272 case op_jnlesseq: 273 case op_jngreater: 274 case op_jngreatereq: 275 case op_loop_hint: 276 case op_switch_imm: 277 case op_switch_char: 278 case op_switch_string: 279 case op_put_by_id: 280 case op_put_by_id_out_of_line: 281 case op_put_by_id_transition_direct: 282 case op_put_by_id_transition_direct_out_of_line: 283 case op_put_by_id_transition_normal: 284 case op_put_by_id_transition_normal_out_of_line: 285 case op_put_getter_setter: 286 case op_put_by_val: 287 case op_put_by_val_direct: 288 case op_put_by_index: 289 case op_tear_off_arguments: 290 case op_touch_entry: 291#define LLINT_HELPER_OPCODES(opcode, length) case opcode: 292 FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); 293#undef LLINT_HELPER_OPCODES 294 return; 295 // These all have a single destination for the first argument. 296 case op_next_pname: 297 case op_resolve_scope: 298 case op_strcat: 299 case op_tear_off_activation: 300 case op_to_primitive: 301 case op_catch: 302 case op_create_this: 303 case op_new_array: 304 case op_new_array_buffer: 305 case op_new_array_with_size: 306 case op_new_regexp: 307 case op_new_func: 308 case op_new_captured_func: 309 case op_new_func_exp: 310 case op_call_varargs: 311 case op_construct_varargs: 312 case op_get_from_scope: 313 case op_call: 314 case op_call_eval: 315 case op_construct: 316 case op_get_by_id: 317 case op_get_by_id_out_of_line: 318 case op_get_array_length: 319 case op_check_has_instance: 320 case op_instanceof: 321 case op_get_by_val: 322 case op_get_argument_by_val: 323 case op_get_by_pname: 324 case op_get_arguments_length: 325 case op_typeof: 326 case op_is_undefined: 327 case op_is_boolean: 328 case op_is_number: 329 case op_is_string: 330 case op_is_object: 331 case op_is_function: 332 case op_in: 333 case op_to_number: 334 case op_negate: 335 case op_add: 336 case op_mul: 337 case op_div: 338 case op_mod: 339 case op_sub: 340 case op_lshift: 341 case op_rshift: 342 case op_urshift: 343 case op_bitand: 344 case op_bitxor: 345 case op_bitor: 346 case op_inc: 347 case op_dec: 348 case op_eq: 349 case op_neq: 350 case op_stricteq: 351 case op_nstricteq: 352 case op_less: 353 case op_lesseq: 354 case op_greater: 355 case op_greatereq: 356 case op_neq_null: 357 case op_eq_null: 358 case op_not: 359 case op_mov: 360 case op_captured_mov: 361 case op_new_object: 362 case op_to_this: 363 case op_get_callee: 364 case op_init_lazy_reg: 365 case op_create_activation: 366 case op_create_arguments: 367 case op_del_by_id: 368 case op_del_by_val: 369 case op_unsigned: { 370 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 371 return; 372 } 373 case op_get_pnames: { 374 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 375 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); 376 functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); 377 return; 378 } 379 case op_enter: { 380 for (unsigned i = codeBlock->m_numVars; i--;) 381 functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset()); 382 return; 383 } } 384} 385 386} // namespace JSC 387 388#endif // BytecodeUseDef_h 389 390