Changeset 43531 in webkit for trunk/JavaScriptCore/jit/JIT.cpp
- Timestamp:
- May 11, 2009, 6:06:58 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/jit/JIT.cpp
r43505 r43531 122 122 } 123 123 124 #define RECORD_JUMP_TARGET(targetOffset) \125 do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)126 127 124 void JIT::privateCompileMainPass() 128 125 { 129 126 Instruction* instructionsBegin = m_codeBlock->instructions().begin(); 130 127 unsigned instructionCount = m_codeBlock->instructions().size(); 131 unsigned propertyAccessInstructionIndex = 0; 132 unsigned globalResolveInfoIndex = 0; 133 unsigned callLinkInfoIndex = 0; 128 129 m_propertyAccessInstructionIndex = 0; 130 m_globalResolveInfoIndex = 0; 131 m_callLinkInfoIndex = 0; 134 132 135 133 for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) { … … 164 162 DEFINE_UNARY_OP(op_negate) 165 163 DEFINE_UNARY_OP(op_typeof) 164 165 // Arithmetic 166 167 case op_add: { 168 emit_op_add(currentInstruction); 169 NEXT_OPCODE(op_add); 170 } 171 case op_sub: { 172 emit_op_sub(currentInstruction); 173 NEXT_OPCODE(op_sub); 174 } 175 case op_mul: { 176 emit_op_mul(currentInstruction); 177 NEXT_OPCODE(op_mul); 178 } 179 case op_mod: { 180 emit_op_mod(currentInstruction); 181 NEXT_OPCODE(op_mod); 182 } 183 case op_bitand: { 184 emit_op_bitand(currentInstruction); 185 NEXT_OPCODE(op_bitand); 186 } 187 case op_lshift: { 188 emit_op_lshift(currentInstruction); 189 NEXT_OPCODE(op_lshift); 190 } 191 case op_rshift: { 192 emit_op_rshift(currentInstruction); 193 NEXT_OPCODE(op_rshift); 194 } 195 case op_pre_inc: { 196 emit_op_pre_inc(currentInstruction); 197 NEXT_OPCODE(op_pre_inc); 198 } 199 case op_pre_dec: { 200 emit_op_pre_dec(currentInstruction); 201 NEXT_OPCODE(op_pre_dec); 202 } 203 case op_post_inc: { 204 emit_op_post_inc(currentInstruction); 205 NEXT_OPCODE(op_post_inc); 206 } 207 case op_post_dec: { 208 emit_op_post_dec(currentInstruction); 209 NEXT_OPCODE(op_post_dec); 210 } 211 212 /* in JITOpcodes */ 213 case op_bitnot: { 214 emit_op_bitnot(currentInstruction); 215 NEXT_OPCODE(op_bitnot); 216 } 217 case op_bitxor: { 218 emit_op_bitxor(currentInstruction); 219 NEXT_OPCODE(op_bitxor); 220 } 221 case op_bitor: { 222 emit_op_bitor(currentInstruction); 223 NEXT_OPCODE(op_bitor); 224 } 225 case op_not: { 226 emit_op_not(currentInstruction); 227 NEXT_OPCODE(op_not); 228 } 229 /* in JITOpcodes */ 230 231 232 // Comparison 233 234 case op_eq: { 235 emit_op_eq(currentInstruction); 236 NEXT_OPCODE(op_eq); 237 } 238 case op_neq: { 239 emit_op_neq(currentInstruction); 240 NEXT_OPCODE(op_neq); 241 } 242 case op_eq_null: { 243 emit_op_eq_null(currentInstruction); 244 NEXT_OPCODE(op_eq_null); 245 } 246 case op_neq_null: { 247 emit_op_neq_null(currentInstruction); 248 NEXT_OPCODE(op_neq_null); 249 } 250 case op_stricteq: { 251 emit_op_stricteq(currentInstruction); 252 NEXT_OPCODE(op_stricteq); 253 } 254 case op_nstricteq: { 255 emit_op_nstricteq(currentInstruction); 256 NEXT_OPCODE(op_nstricteq); 257 } 258 259 260 // Jump / Loop 261 262 case op_jnless: { 263 emit_op_jnless(currentInstruction); 264 NEXT_OPCODE(op_jnless); 265 } 266 case op_jnlesseq: { 267 emit_op_jnlesseq(currentInstruction); 268 NEXT_OPCODE(op_jnlesseq); 269 } 270 case op_jmp: { 271 emit_op_jmp(currentInstruction); 272 NEXT_OPCODE(op_jmp); 273 } 274 case op_loop: { 275 emit_op_loop(currentInstruction); 276 NEXT_OPCODE(op_loop); 277 } 278 case op_loop_if_less: { 279 emit_op_loop_if_less(currentInstruction); 280 NEXT_OPCODE(op_loop_if_less); 281 } 282 case op_loop_if_lesseq: { 283 emit_op_loop_if_lesseq(currentInstruction); 284 NEXT_OPCODE(op_loop_if_lesseq); 285 } 286 case op_loop_if_true: { 287 emit_op_loop_if_true(currentInstruction); 288 NEXT_OPCODE(op_loop_if_true); 289 } 290 case op_jtrue: { 291 emit_op_jtrue(currentInstruction); 292 NEXT_OPCODE(op_jtrue); 293 } 294 case op_jfalse: { 295 emit_op_jfalse(currentInstruction); 296 NEXT_OPCODE(op_jfalse); 297 } 298 case op_jeq_null: { 299 emit_op_jeq_null(currentInstruction); 300 NEXT_OPCODE(op_jeq_null); 301 } 302 case op_jneq_null: { 303 emit_op_jneq_null(currentInstruction); 304 NEXT_OPCODE(op_jneq_null); 305 } 306 case op_jneq_ptr: { 307 emit_op_jneq_ptr(currentInstruction); 308 NEXT_OPCODE(op_jneq_ptr); 309 } 310 311 312 // Property Access 313 314 case op_get_by_id: { 315 emit_op_get_by_id(currentInstruction); 316 NEXT_OPCODE(op_get_by_id); 317 } 318 case op_put_by_id: { 319 emit_op_put_by_id(currentInstruction); 320 NEXT_OPCODE(op_put_by_id); 321 } 322 case op_del_by_id: { 323 emit_op_del_by_id(currentInstruction); 324 NEXT_OPCODE(op_del_by_id); 325 } 326 case op_get_by_val: { 327 emit_op_get_by_val(currentInstruction); 328 NEXT_OPCODE(op_get_by_val); 329 } 330 case op_put_by_val: { 331 emit_op_put_by_val(currentInstruction); 332 NEXT_OPCODE(op_put_by_val); 333 } 334 case op_put_by_index: { 335 emit_op_put_by_index(currentInstruction); 336 NEXT_OPCODE(op_put_by_index); 337 } 338 case op_put_getter: { 339 emit_op_put_getter(currentInstruction); 340 NEXT_OPCODE(op_put_getter); 341 } 342 case op_put_setter: { 343 emit_op_put_setter(currentInstruction); 344 NEXT_OPCODE(op_put_setter); 345 } 346 347 // Variables 348 349 case op_get_global_var: { 350 emit_op_get_global_var(currentInstruction); 351 NEXT_OPCODE(op_get_global_var); 352 } 353 case op_put_global_var: { 354 emit_op_put_global_var(currentInstruction); 355 NEXT_OPCODE(op_put_global_var); 356 } 357 case op_get_scoped_var: { 358 emit_op_get_scoped_var(currentInstruction); 359 NEXT_OPCODE(op_get_scoped_var); 360 } 361 case op_put_scoped_var: { 362 emit_op_put_scoped_var(currentInstruction); 363 NEXT_OPCODE(op_put_scoped_var); 364 } 365 366 // Call 367 368 case op_call: { 369 emit_op_call(currentInstruction); 370 NEXT_OPCODE(op_call); 371 } 372 case op_call_eval: { 373 emit_op_call_eval(currentInstruction); 374 NEXT_OPCODE(op_call_eval); 375 } 376 case op_load_varargs: { 377 emit_op_load_varargs(currentInstruction); 378 NEXT_OPCODE(op_load_varargs); 379 } 380 case op_call_varargs: { 381 emit_op_call_varargs(currentInstruction); 382 NEXT_OPCODE(op_call_varargs); 383 } 384 case op_construct: { 385 emit_op_construct(currentInstruction); 386 NEXT_OPCODE(op_construct); 387 } 388 case op_tear_off_activation: { 389 emit_op_tear_off_activation(currentInstruction); 390 NEXT_OPCODE(op_tear_off_activation); 391 } 392 case op_tear_off_arguments: { 393 emit_op_tear_off_arguments(currentInstruction); 394 NEXT_OPCODE(op_tear_off_arguments); 395 } 396 case op_ret: { 397 emit_op_ret(currentInstruction); 398 NEXT_OPCODE(op_ret); 399 } 400 401 402 // Profiling / Debugging 403 404 case op_profile_will_call: { 405 emit_op_profile_will_call(currentInstruction); 406 NEXT_OPCODE(op_profile_will_call); 407 } 408 case op_profile_did_call: { 409 emit_op_profile_did_call(currentInstruction); 410 NEXT_OPCODE(op_profile_did_call); 411 } 412 case op_debug: { 413 emit_op_debug(currentInstruction); 414 NEXT_OPCODE(op_debug); 415 } 416 417 418 // Unsorted 419 166 420 case op_mov: { 167 int src = currentInstruction[2].u.operand; 168 int dst = currentInstruction[1].u.operand; 169 170 if (m_codeBlock->isConstantRegisterIndex(src)) { 171 storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register))); 172 if (dst == m_lastResultBytecodeRegister) 173 killLastResultRegister(); 174 } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) { 175 // If either the src or dst is the cached register go though 176 // get/put registers to make sure we track this correctly. 177 emitGetVirtualRegister(src, regT0); 178 emitPutVirtualRegister(dst); 179 } else { 180 // Perform the copy via regT1; do not disturb any mapping in regT0. 181 loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1); 182 storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register))); 183 } 421 emit_op_mov(currentInstruction); 184 422 NEXT_OPCODE(op_mov); 185 423 } 186 case op_add: {187 compileFastArith_op_add(currentInstruction);188 NEXT_OPCODE(op_add);189 }190 424 case op_end: { 191 if (m_codeBlock->needsFullScopeChain()) 192 JITStubCall(this, JITStubs::cti_op_end).call(); 193 ASSERT(returnValueRegister != callFrameRegister); 194 emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); 195 push(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)))); 196 ret(); 425 emit_op_end(currentInstruction); 197 426 NEXT_OPCODE(op_end); 198 427 } 199 case op_jmp: {200 unsigned target = currentInstruction[1].u.operand;201 addJump(jump(), target + 1);202 RECORD_JUMP_TARGET(target + 1);203 NEXT_OPCODE(op_jmp);204 }205 case op_pre_inc: {206 compileFastArith_op_pre_inc(currentInstruction[1].u.operand);207 NEXT_OPCODE(op_pre_inc);208 }209 case op_loop: {210 emitTimeoutCheck();211 212 unsigned target = currentInstruction[1].u.operand;213 addJump(jump(), target + 1);214 NEXT_OPCODE(op_end);215 }216 case op_loop_if_less: {217 emitTimeoutCheck();218 219 unsigned op1 = currentInstruction[1].u.operand;220 unsigned op2 = currentInstruction[2].u.operand;221 unsigned target = currentInstruction[3].u.operand;222 if (isOperandConstantImmediateInt(op2)) {223 emitGetVirtualRegister(op1, regT0);224 emitJumpSlowCaseIfNotImmediateInteger(regT0);225 #if USE(ALTERNATE_JSIMMEDIATE)226 int32_t op2imm = getConstantOperandImmediateInt(op2);227 #else228 int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));229 #endif230 addJump(branch32(LessThan, regT0, Imm32(op2imm)), target + 3);231 } else if (isOperandConstantImmediateInt(op1)) {232 emitGetVirtualRegister(op2, regT1);233 emitJumpSlowCaseIfNotImmediateInteger(regT1);234 #if USE(ALTERNATE_JSIMMEDIATE)235 int32_t op1imm = getConstantOperandImmediateInt(op1);236 #else237 int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));238 #endif239 addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target + 3);240 } else {241 emitGetVirtualRegisters(op1, regT0, op2, regT1);242 emitJumpSlowCaseIfNotImmediateInteger(regT0);243 emitJumpSlowCaseIfNotImmediateInteger(regT1);244 addJump(branch32(LessThan, regT0, regT1), target + 3);245 }246 NEXT_OPCODE(op_loop_if_less);247 }248 case op_loop_if_lesseq: {249 emitTimeoutCheck();250 251 unsigned op1 = currentInstruction[1].u.operand;252 unsigned op2 = currentInstruction[2].u.operand;253 unsigned target = currentInstruction[3].u.operand;254 if (isOperandConstantImmediateInt(op2)) {255 emitGetVirtualRegister(op1, regT0);256 emitJumpSlowCaseIfNotImmediateInteger(regT0);257 #if USE(ALTERNATE_JSIMMEDIATE)258 int32_t op2imm = getConstantOperandImmediateInt(op2);259 #else260 int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));261 #endif262 addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target + 3);263 } else {264 emitGetVirtualRegisters(op1, regT0, op2, regT1);265 emitJumpSlowCaseIfNotImmediateInteger(regT0);266 emitJumpSlowCaseIfNotImmediateInteger(regT1);267 addJump(branch32(LessThanOrEqual, regT0, regT1), target + 3);268 }269 NEXT_OPCODE(op_loop_if_less);270 }271 428 case op_new_object: { 272 JITStubCall(this, JITStubs::cti_op_new_object).call(currentInstruction[1].u.operand);429 emit_op_new_object(currentInstruction); 273 430 NEXT_OPCODE(op_new_object); 274 431 } 275 case op_put_by_id: {276 compilePutByIdHotPath(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, propertyAccessInstructionIndex++);277 NEXT_OPCODE(op_put_by_id);278 }279 case op_get_by_id: {280 compileGetByIdHotPath(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), propertyAccessInstructionIndex++);281 NEXT_OPCODE(op_get_by_id);282 }283 432 case op_instanceof: { 284 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); // value 285 emitGetVirtualRegister(currentInstruction[3].u.operand, regT2); // baseVal 286 emitGetVirtualRegister(currentInstruction[4].u.operand, regT1); // proto 287 288 // check if any are immediates 289 move(regT0, regT3); 290 orPtr(regT2, regT3); 291 orPtr(regT1, regT3); 292 emitJumpSlowCaseIfNotJSCell(regT3); 293 294 // check that all are object type - this is a bit of a bithack to avoid excess branching; 295 // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType, 296 // this works because NumberType and StringType are smaller 297 move(Imm32(3 * ObjectType), regT3); 298 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT0); 299 loadPtr(Address(regT2, FIELD_OFFSET(JSCell, m_structure)), regT2); 300 loadPtr(Address(regT1, FIELD_OFFSET(JSCell, m_structure)), regT1); 301 sub32(Address(regT0, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3); 302 sub32(Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3); 303 addSlowCase(branch32(NotEqual, Address(regT1, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3)); 304 305 // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance 306 load32(Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), regT2); 307 and32(Imm32(ImplementsHasInstance | OverridesHasInstance), regT2); 308 addSlowCase(branch32(NotEqual, regT2, Imm32(ImplementsHasInstance))); 309 310 emitGetVirtualRegister(currentInstruction[2].u.operand, regT2); // reload value 311 emitGetVirtualRegister(currentInstruction[4].u.operand, regT1); // reload proto 312 313 // optimistically load true result 314 move(ImmPtr(JSValue::encode(jsBoolean(true))), regT0); 315 316 Label loop(this); 317 318 // load value's prototype 319 loadPtr(Address(regT2, FIELD_OFFSET(JSCell, m_structure)), regT2); 320 loadPtr(Address(regT2, FIELD_OFFSET(Structure, m_prototype)), regT2); 321 322 Jump exit = branchPtr(Equal, regT2, regT1); 323 324 branchPtr(NotEqual, regT2, ImmPtr(JSValue::encode(jsNull())), loop); 325 326 move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0); 327 328 exit.link(this); 329 330 emitPutVirtualRegister(currentInstruction[1].u.operand); 331 433 emit_op_instanceof(currentInstruction); 332 434 NEXT_OPCODE(op_instanceof); 333 435 } 334 case op_del_by_id: {335 JITStubCall stubCall(this, JITStubs::cti_op_del_by_id);336 stubCall.addArgument(currentInstruction[2].u.operand, regT2);337 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));338 stubCall.call(currentInstruction[1].u.operand);339 NEXT_OPCODE(op_del_by_id);340 }341 case op_mul: {342 compileFastArith_op_mul(currentInstruction);343 NEXT_OPCODE(op_mul);344 }345 436 case op_new_func: { 346 JITStubCall stubCall(this, JITStubs::cti_op_new_func); 347 stubCall.addArgument(ImmPtr(m_codeBlock->function(currentInstruction[2].u.operand))); 348 stubCall.call(currentInstruction[1].u.operand); 437 emit_op_new_func(currentInstruction); 349 438 NEXT_OPCODE(op_new_func); 350 439 } 351 case op_call: {352 compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);353 NEXT_OPCODE(op_call);354 }355 case op_call_eval: {356 compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);357 NEXT_OPCODE(op_call_eval);358 }359 case op_load_varargs: {360 JITStubCall stubCall(this, JITStubs::cti_op_load_varargs);361 stubCall.addArgument(Imm32(currentInstruction[2].u.operand));362 stubCall.call(currentInstruction[1].u.operand);363 NEXT_OPCODE(op_load_varargs);364 }365 case op_call_varargs: {366 compileOpCallVarargs(currentInstruction);367 NEXT_OPCODE(op_call_varargs);368 }369 case op_construct: {370 compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);371 NEXT_OPCODE(op_construct);372 }373 case op_get_global_var: {374 JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);375 move(ImmPtr(globalObject), regT0);376 emitGetVariableObjectRegister(regT0, currentInstruction[3].u.operand, regT0);377 emitPutVirtualRegister(currentInstruction[1].u.operand);378 NEXT_OPCODE(op_get_global_var);379 }380 case op_put_global_var: {381 emitGetVirtualRegister(currentInstruction[3].u.operand, regT1);382 JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);383 move(ImmPtr(globalObject), regT0);384 emitPutVariableObjectRegister(regT1, regT0, currentInstruction[2].u.operand);385 NEXT_OPCODE(op_put_global_var);386 }387 case op_get_scoped_var: {388 int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();389 390 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);391 while (skip--)392 loadPtr(Address(regT0, FIELD_OFFSET(ScopeChainNode, next)), regT0);393 394 loadPtr(Address(regT0, FIELD_OFFSET(ScopeChainNode, object)), regT0);395 emitGetVariableObjectRegister(regT0, currentInstruction[2].u.operand, regT0);396 emitPutVirtualRegister(currentInstruction[1].u.operand);397 NEXT_OPCODE(op_get_scoped_var);398 }399 case op_put_scoped_var: {400 int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();401 402 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);403 emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);404 while (skip--)405 loadPtr(Address(regT1, FIELD_OFFSET(ScopeChainNode, next)), regT1);406 407 loadPtr(Address(regT1, FIELD_OFFSET(ScopeChainNode, object)), regT1);408 emitPutVariableObjectRegister(regT0, regT1, currentInstruction[1].u.operand);409 NEXT_OPCODE(op_put_scoped_var);410 }411 case op_tear_off_activation: {412 JITStubCall stubCall(this, JITStubs::cti_op_tear_off_activation);413 stubCall.addArgument(currentInstruction[1].u.operand, regT2);414 stubCall.call();415 NEXT_OPCODE(op_tear_off_activation);416 }417 case op_tear_off_arguments: {418 JITStubCall(this, JITStubs::cti_op_tear_off_arguments).call();419 NEXT_OPCODE(op_tear_off_arguments);420 }421 case op_ret: {422 // We could JIT generate the deref, only calling out to C when the refcount hits zero.423 if (m_codeBlock->needsFullScopeChain())424 JITStubCall(this, JITStubs::cti_op_ret_scopeChain).call();425 426 ASSERT(callFrameRegister != regT1);427 ASSERT(regT1 != returnValueRegister);428 ASSERT(returnValueRegister != callFrameRegister);429 430 // Return the result in %eax.431 emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);432 433 // Grab the return address.434 emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);435 436 // Restore our caller's "r".437 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);438 439 // Return.440 push(regT1);441 ret();442 443 NEXT_OPCODE(op_ret);444 }445 440 case op_new_array: { 446 JITStubCall stubCall(this, JITStubs::cti_op_new_array); 447 stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); 448 stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); 449 stubCall.call(currentInstruction[1].u.operand); 441 emit_op_new_array(currentInstruction); 450 442 NEXT_OPCODE(op_new_array); 451 443 } 452 444 case op_resolve: { 453 JITStubCall stubCall(this, JITStubs::cti_op_resolve); 454 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); 455 stubCall.call(currentInstruction[1].u.operand); 445 emit_op_resolve(currentInstruction); 456 446 NEXT_OPCODE(op_resolve); 457 447 } 458 448 case op_construct_verify: { 459 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); 460 461 emitJumpSlowCaseIfNotJSCell(regT0); 462 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); 463 addSlowCase(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType))); 464 449 emit_op_construct_verify(currentInstruction); 465 450 NEXT_OPCODE(op_construct_verify); 466 451 } 467 452 case op_to_primitive: { 468 int dst = currentInstruction[1].u.operand; 469 int src = currentInstruction[2].u.operand; 470 471 emitGetVirtualRegister(src, regT0); 472 473 Jump isImm = emitJumpIfNotJSCell(regT0); 474 addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr))); 475 isImm.link(this); 476 477 if (dst != src) 478 emitPutVirtualRegister(dst); 479 453 emit_op_to_primitive(currentInstruction); 480 454 NEXT_OPCODE(op_to_primitive); 481 455 } 482 456 case op_strcat: { 483 JITStubCall stubCall(this, JITStubs::cti_op_strcat); 484 stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); 485 stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); 486 stubCall.call(currentInstruction[1].u.operand); 457 emit_op_strcat(currentInstruction); 487 458 NEXT_OPCODE(op_strcat); 488 459 } 489 case op_get_by_val: {490 emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);491 emitJumpSlowCaseIfNotImmediateInteger(regT1);492 #if USE(ALTERNATE_JSIMMEDIATE)493 // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.494 // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if495 // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation496 // size is always less than 4Gb). As such zero extending wil have been correct (and extending the value497 // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign498 // extending since it makes it easier to re-tag the value in the slow case.499 zeroExtend32ToPtr(regT1, regT1);500 #else501 emitFastArithImmToInt(regT1);502 #endif503 emitJumpSlowCaseIfNotJSCell(regT0);504 addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));505 506 // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff507 loadPtr(Address(regT0, FIELD_OFFSET(JSArray, m_storage)), regT2);508 addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, FIELD_OFFSET(JSArray, m_fastAccessCutoff))));509 510 // Get the value from the vector511 loadPtr(BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), regT0);512 emitPutVirtualRegister(currentInstruction[1].u.operand);513 NEXT_OPCODE(op_get_by_val);514 }515 460 case op_resolve_func: { 516 JITStubCall stubCall(this, JITStubs::cti_op_resolve_func); 517 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); 518 stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); 519 stubCall.call(currentInstruction[2].u.operand); 461 emit_op_resolve_func(currentInstruction); 520 462 NEXT_OPCODE(op_resolve_func); 521 463 } 522 case op_sub: {523 compileFastArith_op_sub(currentInstruction);524 NEXT_OPCODE(op_sub);525 }526 case op_put_by_val: {527 emitGetVirtualRegisters(currentInstruction[1].u.operand, regT0, currentInstruction[2].u.operand, regT1);528 emitJumpSlowCaseIfNotImmediateInteger(regT1);529 #if USE(ALTERNATE_JSIMMEDIATE)530 // See comment in op_get_by_val.531 zeroExtend32ToPtr(regT1, regT1);532 #else533 emitFastArithImmToInt(regT1);534 #endif535 emitJumpSlowCaseIfNotJSCell(regT0);536 addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));537 538 // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff539 loadPtr(Address(regT0, FIELD_OFFSET(JSArray, m_storage)), regT2);540 Jump inFastVector = branch32(Below, regT1, Address(regT0, FIELD_OFFSET(JSArray, m_fastAccessCutoff)));541 // No; oh well, check if the access if within the vector - if so, we may still be okay.542 addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, FIELD_OFFSET(ArrayStorage, m_vectorLength))));543 544 // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.545 // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff.546 addSlowCase(branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0]))));547 548 // All good - put the value into the array.549 inFastVector.link(this);550 emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);551 storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])));552 NEXT_OPCODE(op_put_by_val);553 }554 case op_loop_if_true: {555 emitTimeoutCheck();556 557 unsigned target = currentInstruction[2].u.operand;558 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);559 560 Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));561 addJump(emitJumpIfImmediateInteger(regT0), target + 2);562 563 addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);564 addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));565 566 isZero.link(this);567 NEXT_OPCODE(op_loop_if_true);568 };569 464 case op_resolve_base: { 570 JITStubCall stubCall(this, JITStubs::cti_op_resolve_base); 571 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); 572 stubCall.call(currentInstruction[1].u.operand); 465 emit_op_resolve_base(currentInstruction); 573 466 NEXT_OPCODE(op_resolve_base); 574 467 } 575 468 case op_resolve_skip: { 576 JITStubCall stubCall(this, JITStubs::cti_op_resolve_skip); 577 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); 578 stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain())); 579 stubCall.call(currentInstruction[1].u.operand); 469 emit_op_resolve_skip(currentInstruction); 580 470 NEXT_OPCODE(op_resolve_skip); 581 471 } 582 472 case op_resolve_global: { 583 // Fast case 584 void* globalObject = currentInstruction[2].u.jsCell; 585 Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand); 586 587 unsigned currentIndex = globalResolveInfoIndex++; 588 void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure); 589 void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset); 590 591 // Check Structure of global object 592 move(ImmPtr(globalObject), regT0); 593 loadPtr(structureAddress, regT1); 594 Jump noMatch = branchPtr(NotEqual, regT1, Address(regT0, FIELD_OFFSET(JSCell, m_structure))); // Structures don't match 595 596 // Load cached property 597 // Assume that the global object always uses external storage. 598 loadPtr(Address(regT0, FIELD_OFFSET(JSGlobalObject, m_externalStorage)), regT0); 599 load32(offsetAddr, regT1); 600 loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0); 601 emitPutVirtualRegister(currentInstruction[1].u.operand); 602 Jump end = jump(); 603 604 // Slow case 605 noMatch.link(this); 606 JITStubCall stubCall(this, JITStubs::cti_op_resolve_global); 607 stubCall.addArgument(ImmPtr(globalObject)); 608 stubCall.addArgument(ImmPtr(ident)); 609 stubCall.addArgument(Imm32(currentIndex)); 610 stubCall.call(currentInstruction[1].u.operand); 611 end.link(this); 473 emit_op_resolve_global(currentInstruction); 612 474 NEXT_OPCODE(op_resolve_global); 613 475 } 614 case op_pre_dec: {615 compileFastArith_op_pre_dec(currentInstruction[1].u.operand);616 NEXT_OPCODE(op_pre_dec);617 }618 case op_jnless: {619 unsigned target = currentInstruction[3].u.operand;620 compileFastArith_op_jnless(currentInstruction[1].u.operand, currentInstruction[2].u.operand, target);621 RECORD_JUMP_TARGET(target + 3);622 NEXT_OPCODE(op_jnless);623 }624 case op_jnlesseq: {625 unsigned target = currentInstruction[3].u.operand;626 compileFastArith_op_jnlesseq(currentInstruction[1].u.operand, currentInstruction[2].u.operand, target);627 RECORD_JUMP_TARGET(target + 3);628 NEXT_OPCODE(op_jnlesseq);629 }630 case op_not: {631 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);632 xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);633 addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));634 xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0);635 emitPutVirtualRegister(currentInstruction[1].u.operand);636 NEXT_OPCODE(op_not);637 }638 case op_jfalse: {639 unsigned target = currentInstruction[2].u.operand;640 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);641 642 addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target + 2);643 Jump isNonZero = emitJumpIfImmediateInteger(regT0);644 645 addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target + 2);646 addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));647 648 isNonZero.link(this);649 RECORD_JUMP_TARGET(target + 2);650 NEXT_OPCODE(op_jfalse);651 };652 case op_jeq_null: {653 unsigned src = currentInstruction[1].u.operand;654 unsigned target = currentInstruction[2].u.operand;655 656 emitGetVirtualRegister(src, regT0);657 Jump isImmediate = emitJumpIfNotJSCell(regT0);658 659 // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.660 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);661 addJump(branchTest32(NonZero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);662 Jump wasNotImmediate = jump();663 664 // Now handle the immediate cases - undefined & null665 isImmediate.link(this);666 andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);667 addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);668 669 wasNotImmediate.link(this);670 RECORD_JUMP_TARGET(target + 2);671 NEXT_OPCODE(op_jeq_null);672 };673 case op_jneq_null: {674 unsigned src = currentInstruction[1].u.operand;675 unsigned target = currentInstruction[2].u.operand;676 677 emitGetVirtualRegister(src, regT0);678 Jump isImmediate = emitJumpIfNotJSCell(regT0);679 680 // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.681 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);682 addJump(branchTest32(Zero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);683 Jump wasNotImmediate = jump();684 685 // Now handle the immediate cases - undefined & null686 isImmediate.link(this);687 andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);688 addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);689 690 wasNotImmediate.link(this);691 RECORD_JUMP_TARGET(target + 2);692 NEXT_OPCODE(op_jneq_null);693 }694 case op_jneq_ptr: {695 unsigned src = currentInstruction[1].u.operand;696 JSCell* ptr = currentInstruction[2].u.jsCell;697 unsigned target = currentInstruction[3].u.operand;698 699 emitGetVirtualRegister(src, regT0);700 addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target + 3);701 702 RECORD_JUMP_TARGET(target + 3);703 NEXT_OPCODE(op_jneq_ptr);704 }705 case op_post_inc: {706 compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand);707 NEXT_OPCODE(op_post_inc);708 }709 476 case op_unexpected_load: { 710 JSValue v = m_codeBlock->unexpectedConstant(currentInstruction[2].u.operand); 711 move(ImmPtr(JSValue::encode(v)), regT0); 712 emitPutVirtualRegister(currentInstruction[1].u.operand); 477 emit_op_unexpected_load(currentInstruction); 713 478 NEXT_OPCODE(op_unexpected_load); 714 479 } 715 480 case op_jsr: { 716 int retAddrDst = currentInstruction[1].u.operand; 717 int target = currentInstruction[2].u.operand; 718 DataLabelPtr storeLocation = storePtrWithPatch(Address(callFrameRegister, sizeof(Register) * retAddrDst)); 719 addJump(jump(), target + 2); 720 m_jsrSites.append(JSRInfo(storeLocation, label())); 721 killLastResultRegister(); 722 RECORD_JUMP_TARGET(target + 2); 481 emit_op_jsr(currentInstruction); 723 482 NEXT_OPCODE(op_jsr); 724 483 } 725 484 case op_sret: { 726 jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand)); 727 killLastResultRegister(); 485 emit_op_sret(currentInstruction); 728 486 NEXT_OPCODE(op_sret); 729 487 } 730 case op_eq: {731 emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);732 emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);733 set32(Equal, regT1, regT0, regT0);734 emitTagAsBoolImmediate(regT0);735 emitPutVirtualRegister(currentInstruction[1].u.operand);736 NEXT_OPCODE(op_eq);737 }738 case op_lshift: {739 compileFastArith_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);740 NEXT_OPCODE(op_lshift);741 }742 case op_bitand: {743 compileFastArith_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);744 NEXT_OPCODE(op_bitand);745 }746 case op_rshift: {747 compileFastArith_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);748 NEXT_OPCODE(op_rshift);749 }750 case op_bitnot: {751 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);752 emitJumpSlowCaseIfNotImmediateInteger(regT0);753 #if USE(ALTERNATE_JSIMMEDIATE)754 not32(regT0);755 emitFastArithIntToImmNoCheck(regT0, regT0);756 #else757 xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0);758 #endif759 emitPutVirtualRegister(currentInstruction[1].u.operand);760 NEXT_OPCODE(op_bitnot);761 }762 488 case op_resolve_with_base: { 763 JITStubCall stubCall(this, JITStubs::cti_op_resolve_with_base); 764 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); 765 stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); 766 stubCall.call(currentInstruction[2].u.operand); 489 emit_op_resolve_with_base(currentInstruction); 767 490 NEXT_OPCODE(op_resolve_with_base); 768 491 } 769 492 case op_new_func_exp: { 770 JITStubCall stubCall(this, JITStubs::cti_op_new_func_exp); 771 stubCall.addArgument(ImmPtr(m_codeBlock->functionExpression(currentInstruction[2].u.operand))); 772 stubCall.call(currentInstruction[1].u.operand); 493 emit_op_new_func_exp(currentInstruction); 773 494 NEXT_OPCODE(op_new_func_exp); 774 495 } 775 case op_mod: {776 compileFastArith_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);777 NEXT_OPCODE(op_mod);778 }779 case op_jtrue: {780 unsigned target = currentInstruction[2].u.operand;781 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);782 783 Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));784 addJump(emitJumpIfImmediateInteger(regT0), target + 2);785 786 addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);787 addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));788 789 isZero.link(this);790 RECORD_JUMP_TARGET(target + 2);791 NEXT_OPCODE(op_jtrue);792 }793 case op_neq: {794 emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);795 emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);796 set32(NotEqual, regT1, regT0, regT0);797 emitTagAsBoolImmediate(regT0);798 799 emitPutVirtualRegister(currentInstruction[1].u.operand);800 801 NEXT_OPCODE(op_neq);802 }803 case op_post_dec: {804 compileFastArith_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand);805 NEXT_OPCODE(op_post_dec);806 }807 case op_bitxor: {808 emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);809 emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);810 xorPtr(regT1, regT0);811 emitFastArithReTagImmediate(regT0, regT0);812 emitPutVirtualRegister(currentInstruction[1].u.operand);813 NEXT_OPCODE(op_bitxor);814 }815 496 case op_new_regexp: { 816 JITStubCall stubCall(this, JITStubs::cti_op_new_regexp); 817 stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand))); 818 stubCall.call(currentInstruction[1].u.operand); 497 emit_op_new_regexp(currentInstruction); 819 498 NEXT_OPCODE(op_new_regexp); 820 499 } 821 case op_bitor: {822 emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);823 emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);824 orPtr(regT1, regT0);825 emitPutVirtualRegister(currentInstruction[1].u.operand);826 NEXT_OPCODE(op_bitor);827 }828 500 case op_throw: { 829 JITStubCall stubCall(this, JITStubs::cti_op_throw); 830 stubCall.addArgument(currentInstruction[1].u.operand, regT2); 831 stubCall.call(); 832 ASSERT(regT0 == returnValueRegister); 833 #if PLATFORM(X86_64) 834 addPtr(Imm32(0x48), X86::esp); 835 pop(X86::ebx); 836 pop(X86::r15); 837 pop(X86::r14); 838 pop(X86::r13); 839 pop(X86::r12); 840 pop(X86::ebp); 841 ret(); 842 #else 843 addPtr(Imm32(0x1c), X86::esp); 844 pop(X86::ebx); 845 pop(X86::edi); 846 pop(X86::esi); 847 pop(X86::ebp); 848 ret(); 849 #endif 501 emit_op_throw(currentInstruction); 850 502 NEXT_OPCODE(op_throw); 851 503 } 852 504 case op_next_pname: { 853 JITStubCall stubCall(this, JITStubs::cti_op_next_pname); 854 stubCall.addArgument(currentInstruction[2].u.operand, regT2); 855 stubCall.call(); 856 Jump endOfIter = branchTestPtr(Zero, regT0); 857 emitPutVirtualRegister(currentInstruction[1].u.operand); 858 addJump(jump(), currentInstruction[3].u.operand + 3); 859 endOfIter.link(this); 505 emit_op_next_pname(currentInstruction); 860 506 NEXT_OPCODE(op_next_pname); 861 507 } 862 508 case op_push_scope: { 863 JITStubCall stubCall(this, JITStubs::cti_op_push_scope); 864 stubCall.addArgument(currentInstruction[1].u.operand, regT2); 865 stubCall.call(currentInstruction[1].u.operand); 509 emit_op_push_scope(currentInstruction); 866 510 NEXT_OPCODE(op_push_scope); 867 511 } 868 512 case op_pop_scope: { 869 JITStubCall(this, JITStubs::cti_op_pop_scope).call();513 emit_op_pop_scope(currentInstruction); 870 514 NEXT_OPCODE(op_pop_scope); 871 515 } 872 case op_stricteq: {873 compileOpStrictEq(currentInstruction, OpStrictEq);874 NEXT_OPCODE(op_stricteq);875 }876 case op_nstricteq: {877 compileOpStrictEq(currentInstruction, OpNStrictEq);878 NEXT_OPCODE(op_nstricteq);879 }880 516 case op_to_jsnumber: { 881 int srcVReg = currentInstruction[2].u.operand; 882 emitGetVirtualRegister(srcVReg, regT0); 883 884 Jump wasImmediate = emitJumpIfImmediateInteger(regT0); 885 886 emitJumpSlowCaseIfNotJSCell(regT0, srcVReg); 887 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2); 888 addSlowCase(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_type)), Imm32(NumberType))); 889 890 wasImmediate.link(this); 891 892 emitPutVirtualRegister(currentInstruction[1].u.operand); 517 emit_op_to_jsnumber(currentInstruction); 893 518 NEXT_OPCODE(op_to_jsnumber); 894 519 } 895 520 case op_push_new_scope: { 896 JITStubCall stubCall(this, JITStubs::cti_op_push_new_scope); 897 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); 898 stubCall.addArgument(currentInstruction[3].u.operand, regT2); 899 stubCall.call(currentInstruction[1].u.operand); 521 emit_op_push_new_scope(currentInstruction); 900 522 NEXT_OPCODE(op_push_new_scope); 901 523 } 902 524 case op_catch: { 903 emitGetCTIParam(offsetof(struct JITStackFrame, callFrame) / sizeof (void*), callFrameRegister); 904 emitPutVirtualRegister(currentInstruction[1].u.operand); 525 emit_op_catch(currentInstruction); 905 526 NEXT_OPCODE(op_catch); 906 527 } 907 528 case op_jmp_scopes: { 908 JITStubCall stubCall(this, JITStubs::cti_op_jmp_scopes); 909 stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); 910 stubCall.call(); 911 addJump(jump(), currentInstruction[2].u.operand + 2); 912 RECORD_JUMP_TARGET(currentInstruction[2].u.operand + 2); 529 emit_op_jmp_scopes(currentInstruction); 913 530 NEXT_OPCODE(op_jmp_scopes); 914 531 } 915 case op_put_by_index: {916 JITStubCall stubCall(this, JITStubs::cti_op_put_by_index);917 stubCall.addArgument(currentInstruction[1].u.operand, regT2);918 stubCall.addArgument(Imm32(currentInstruction[2].u.operand));919 stubCall.addArgument(currentInstruction[3].u.operand, regT2);920 stubCall.call();921 NEXT_OPCODE(op_put_by_index);922 }923 532 case op_switch_imm: { 924 unsigned tableIndex = currentInstruction[1].u.operand; 925 unsigned defaultOffset = currentInstruction[2].u.operand; 926 unsigned scrutinee = currentInstruction[3].u.operand; 927 928 // create jump table for switch destinations, track this switch statement. 929 SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex); 930 m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate)); 931 jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); 932 933 JITStubCall stubCall(this, JITStubs::cti_op_switch_imm); 934 stubCall.addArgument(scrutinee, regT2); 935 stubCall.addArgument(Imm32(tableIndex)); 936 stubCall.call(); 937 jump(regT0); 533 emit_op_switch_imm(currentInstruction); 938 534 NEXT_OPCODE(op_switch_imm); 939 535 } 940 536 case op_switch_char: { 941 unsigned tableIndex = currentInstruction[1].u.operand; 942 unsigned defaultOffset = currentInstruction[2].u.operand; 943 unsigned scrutinee = currentInstruction[3].u.operand; 944 945 // create jump table for switch destinations, track this switch statement. 946 SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex); 947 m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character)); 948 jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size()); 949 950 JITStubCall stubCall(this, JITStubs::cti_op_switch_char); 951 stubCall.addArgument(scrutinee, regT2); 952 stubCall.addArgument(Imm32(tableIndex)); 953 stubCall.call(); 954 jump(regT0); 537 emit_op_switch_char(currentInstruction); 955 538 NEXT_OPCODE(op_switch_char); 956 539 } 957 540 case op_switch_string: { 958 unsigned tableIndex = currentInstruction[1].u.operand; 959 unsigned defaultOffset = currentInstruction[2].u.operand; 960 unsigned scrutinee = currentInstruction[3].u.operand; 961 962 // create jump table for switch destinations, track this switch statement. 963 StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex); 964 m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset)); 965 966 JITStubCall stubCall(this, JITStubs::cti_op_switch_string); 967 stubCall.addArgument(scrutinee, regT2); 968 stubCall.addArgument(Imm32(tableIndex)); 969 stubCall.call(); 970 jump(regT0); 541 emit_op_switch_string(currentInstruction); 971 542 NEXT_OPCODE(op_switch_string); 972 543 } 973 case op_put_getter: {974 JITStubCall stubCall(this, JITStubs::cti_op_put_getter);975 stubCall.addArgument(currentInstruction[1].u.operand, regT2);976 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));977 stubCall.addArgument(currentInstruction[3].u.operand, regT2);978 stubCall.call();979 NEXT_OPCODE(op_put_getter);980 }981 case op_put_setter: {982 JITStubCall stubCall(this, JITStubs::cti_op_put_setter);983 stubCall.addArgument(currentInstruction[1].u.operand, regT2);984 stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));985 stubCall.addArgument(currentInstruction[3].u.operand, regT2);986 stubCall.call();987 NEXT_OPCODE(op_put_setter);988 }989 544 case op_new_error: { 990 JITStubCall stubCall(this, JITStubs::cti_op_new_error); 991 stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); 992 stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->unexpectedConstant(currentInstruction[3].u.operand)))); 993 stubCall.addArgument(Imm32(m_bytecodeIndex)); 994 stubCall.call(currentInstruction[1].u.operand); 545 emit_op_new_error(currentInstruction); 995 546 NEXT_OPCODE(op_new_error); 996 547 } 997 case op_debug: {998 JITStubCall stubCall(this, JITStubs::cti_op_debug);999 stubCall.addArgument(Imm32(currentInstruction[1].u.operand));1000 stubCall.addArgument(Imm32(currentInstruction[2].u.operand));1001 stubCall.addArgument(Imm32(currentInstruction[3].u.operand));1002 stubCall.call();1003 NEXT_OPCODE(op_debug);1004 }1005 case op_eq_null: {1006 unsigned dst = currentInstruction[1].u.operand;1007 unsigned src1 = currentInstruction[2].u.operand;1008 1009 emitGetVirtualRegister(src1, regT0);1010 Jump isImmediate = emitJumpIfNotJSCell(regT0);1011 1012 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);1013 setTest32(NonZero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);1014 1015 Jump wasNotImmediate = jump();1016 1017 isImmediate.link(this);1018 1019 andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);1020 setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);1021 1022 wasNotImmediate.link(this);1023 1024 emitTagAsBoolImmediate(regT0);1025 emitPutVirtualRegister(dst);1026 1027 NEXT_OPCODE(op_eq_null);1028 }1029 case op_neq_null: {1030 unsigned dst = currentInstruction[1].u.operand;1031 unsigned src1 = currentInstruction[2].u.operand;1032 1033 emitGetVirtualRegister(src1, regT0);1034 Jump isImmediate = emitJumpIfNotJSCell(regT0);1035 1036 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);1037 setTest32(Zero, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);1038 1039 Jump wasNotImmediate = jump();1040 1041 isImmediate.link(this);1042 1043 andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);1044 setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);1045 1046 wasNotImmediate.link(this);1047 1048 emitTagAsBoolImmediate(regT0);1049 emitPutVirtualRegister(dst);1050 1051 NEXT_OPCODE(op_neq_null);1052 }1053 548 case op_enter: { 1054 // Even though CTI doesn't use them, we initialize our constant 1055 // registers to zap stale pointers, to avoid unnecessarily prolonging 1056 // object lifetime and increasing GC pressure. 1057 size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters(); 1058 for (size_t j = 0; j < count; ++j) 1059 emitInitRegister(j); 1060 549 emit_op_enter(currentInstruction); 1061 550 NEXT_OPCODE(op_enter); 1062 551 } 1063 552 case op_enter_with_activation: { 1064 // Even though CTI doesn't use them, we initialize our constant 1065 // registers to zap stale pointers, to avoid unnecessarily prolonging 1066 // object lifetime and increasing GC pressure. 1067 size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters(); 1068 for (size_t j = 0; j < count; ++j) 1069 emitInitRegister(j); 1070 1071 JITStubCall(this, JITStubs::cti_op_push_activation).call(currentInstruction[1].u.operand); 553 emit_op_enter_with_activation(currentInstruction); 1072 554 NEXT_OPCODE(op_enter_with_activation); 1073 555 } 1074 556 case op_create_arguments: { 1075 if (m_codeBlock->m_numParameters == 1) 1076 JITStubCall(this, JITStubs::cti_op_create_arguments_no_params).call(); 1077 else 1078 JITStubCall(this, JITStubs::cti_op_create_arguments).call(); 557 emit_op_create_arguments(currentInstruction); 1079 558 NEXT_OPCODE(op_create_arguments); 1080 559 } 1081 560 case op_convert_this: { 1082 emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); 1083 1084 emitJumpSlowCaseIfNotJSCell(regT0); 1085 loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT1); 1086 addSlowCase(branchTest32(NonZero, Address(regT1, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); 1087 561 emit_op_convert_this(currentInstruction); 1088 562 NEXT_OPCODE(op_convert_this); 1089 563 } 1090 case op_profile_will_call: { 1091 emitGetCTIParam(FIELD_OFFSET(JITStackFrame, enabledProfilerReference) / sizeof (void*), regT0); 1092 Jump noProfiler = branchTestPtr(Zero, Address(regT0)); 1093 1094 JITStubCall stubCall(this, JITStubs::cti_op_profile_will_call); 1095 stubCall.addArgument(currentInstruction[1].u.operand, regT0); 1096 stubCall.call(); 1097 noProfiler.link(this); 1098 1099 NEXT_OPCODE(op_profile_will_call); 1100 } 1101 case op_profile_did_call: { 1102 emitGetCTIParam(FIELD_OFFSET(JITStackFrame, enabledProfilerReference) / sizeof (void*), regT0); 1103 Jump noProfiler = branchTestPtr(Zero, Address(regT0)); 1104 1105 JITStubCall stubCall(this, JITStubs::cti_op_profile_did_call); 1106 stubCall.addArgument(currentInstruction[1].u.operand, regT0); 1107 stubCall.call(); 1108 noProfiler.link(this); 1109 1110 NEXT_OPCODE(op_profile_did_call); 1111 } 564 565 566 // No implementation 567 1112 568 case op_get_array_length: 1113 569 case op_get_by_id_chain: … … 1125 581 } 1126 582 1127 ASSERT( propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());1128 ASSERT( callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());583 ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos()); 584 ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos()); 1129 585 1130 586 #ifndef NDEBUG … … 1146 602 { 1147 603 Instruction* instructionsBegin = m_codeBlock->instructions().begin(); 1148 unsigned propertyAccessInstructionIndex = 0; 1149 unsigned callLinkInfoIndex = 0; 604 605 m_propertyAccessInstructionIndex = 0; 606 m_callLinkInfoIndex = 0; 1150 607 1151 608 for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) { … … 1160 617 1161 618 switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode)) { 619 case op_add: { 620 emitSlow_op_add(currentInstruction, iter); 621 NEXT_OPCODE(op_add); 622 } 623 case op_sub: { 624 emitSlow_op_sub(currentInstruction, iter); 625 NEXT_OPCODE(op_sub); 626 } 627 case op_mul: { 628 emitSlow_op_mul(currentInstruction, iter); 629 NEXT_OPCODE(op_mul); 630 } 631 case op_mod: { 632 emitSlow_op_mod(currentInstruction, iter); 633 NEXT_OPCODE(op_mod); 634 } 635 case op_bitand: { 636 emitSlow_op_bitand(currentInstruction, iter); 637 NEXT_OPCODE(op_bitand); 638 } 639 case op_lshift: { 640 emitSlow_op_lshift(currentInstruction, iter); 641 NEXT_OPCODE(op_lshift); 642 } 643 case op_rshift: { 644 emitSlow_op_rshift(currentInstruction, iter); 645 NEXT_OPCODE(op_rshift); 646 } 647 case op_jnless: { 648 emitSlow_op_jnless(currentInstruction, iter); 649 NEXT_OPCODE(op_jnless); 650 } 651 case op_jnlesseq: { 652 emitSlow_op_jnlesseq(currentInstruction, iter); 653 NEXT_OPCODE(op_jnlesseq); 654 } 655 case op_pre_dec: { 656 emitSlow_op_pre_dec(currentInstruction, iter); 657 NEXT_OPCODE(op_pre_dec); 658 } 659 case op_pre_inc: { 660 emitSlow_op_pre_inc(currentInstruction, iter); 661 NEXT_OPCODE(op_pre_inc); 662 } 663 case op_post_inc: { 664 emitSlow_op_post_inc(currentInstruction, iter); 665 NEXT_OPCODE(op_post_inc); 666 } 667 case op_post_dec: { 668 emitSlow_op_post_dec(currentInstruction, iter); 669 NEXT_OPCODE(op_post_dec); 670 } 1162 671 case op_convert_this: { 1163 672 linkSlowCase(iter); … … 1167 676 stubCall.call(currentInstruction[1].u.operand); 1168 677 NEXT_OPCODE(op_convert_this); 1169 }1170 case op_add: {1171 compileFastArithSlow_op_add(currentInstruction, iter);1172 NEXT_OPCODE(op_add);1173 678 } 1174 679 case op_construct_verify: { … … 1218 723 1219 724 NEXT_OPCODE(op_get_by_val); 1220 }1221 case op_sub: {1222 compileFastArithSlow_op_sub(currentInstruction, iter);1223 NEXT_OPCODE(op_sub);1224 }1225 case op_rshift: {1226 compileFastArithSlow_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1227 NEXT_OPCODE(op_rshift);1228 }1229 case op_lshift: {1230 compileFastArithSlow_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1231 NEXT_OPCODE(op_lshift);1232 725 } 1233 726 case op_loop_if_less: { … … 1261 754 } 1262 755 case op_put_by_id: { 1263 compilePutByIdSlowCase(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, iter, propertyAccessInstructionIndex++);756 compilePutByIdSlowCase(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, iter, m_propertyAccessInstructionIndex++); 1264 757 NEXT_OPCODE(op_put_by_id); 1265 758 } 1266 759 case op_get_by_id: { 1267 compileGetByIdSlowCase(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), iter, propertyAccessInstructionIndex++);760 compileGetByIdSlowCase(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), iter, m_propertyAccessInstructionIndex++); 1268 761 NEXT_OPCODE(op_get_by_id); 1269 762 } … … 1289 782 NEXT_OPCODE(op_loop_if_lesseq); 1290 783 } 1291 case op_pre_inc: {1292 compileFastArithSlow_op_pre_inc(currentInstruction[1].u.operand, iter);1293 NEXT_OPCODE(op_pre_inc);1294 }1295 784 case op_put_by_val: { 1296 785 // Normal slow cases - either is not an immediate imm, or is an array. … … 1328 817 NEXT_OPCODE(op_loop_if_true); 1329 818 } 1330 case op_pre_dec: {1331 compileFastArithSlow_op_pre_dec(currentInstruction[1].u.operand, iter);1332 NEXT_OPCODE(op_pre_dec);1333 }1334 case op_jnless: {1335 compileFastArithSlow_op_jnless(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1336 NEXT_OPCODE(op_jnless);1337 }1338 case op_jnlesseq: {1339 compileFastArithSlow_op_jnlesseq(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1340 NEXT_OPCODE(op_jnlesseq);1341 }1342 819 case op_not: { 1343 820 linkSlowCase(iter); … … 1356 833 NEXT_OPCODE(op_jfalse); 1357 834 } 1358 case op_post_inc: {1359 compileFastArithSlow_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);1360 NEXT_OPCODE(op_post_inc);1361 }1362 835 case op_bitnot: { 1363 836 linkSlowCase(iter); … … 1366 839 stubCall.call(currentInstruction[1].u.operand); 1367 840 NEXT_OPCODE(op_bitnot); 1368 }1369 case op_bitand: {1370 compileFastArithSlow_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1371 NEXT_OPCODE(op_bitand);1372 841 } 1373 842 case op_jtrue: { … … 1378 847 emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2); 1379 848 NEXT_OPCODE(op_jtrue); 1380 }1381 case op_post_dec: {1382 compileFastArithSlow_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);1383 NEXT_OPCODE(op_post_dec);1384 849 } 1385 850 case op_bitxor: { … … 1444 909 NEXT_OPCODE(op_instanceof); 1445 910 } 1446 case op_mod: {1447 compileFastArithSlow_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);1448 NEXT_OPCODE(op_mod);1449 }1450 case op_mul: {1451 compileFastArithSlow_op_mul(currentInstruction, iter);1452 NEXT_OPCODE(op_mul);1453 }1454 1455 911 case op_call: { 1456 compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);912 compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, opcodeID); 1457 913 NEXT_OPCODE(op_call); 1458 914 } 1459 915 case op_call_eval: { 1460 compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);916 compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, opcodeID); 1461 917 NEXT_OPCODE(op_call_eval); 1462 918 } … … 1466 922 } 1467 923 case op_construct: { 1468 compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);924 compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, opcodeID); 1469 925 NEXT_OPCODE(op_construct); 1470 926 } … … 1490 946 1491 947 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 1492 ASSERT( propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());1493 #endif 1494 ASSERT( callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());948 ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos()); 949 #endif 950 ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos()); 1495 951 1496 952 #ifndef NDEBUG
Note:
See TracChangeset
for help on using the changeset viewer.