1/* 2* Copyright (C) 2008 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#include "config.h" 27 28#if ENABLE(JIT) 29#if USE(JSVALUE32_64) 30#include "JIT.h" 31 32#include "CodeBlock.h" 33#include "JITInlines.h" 34#include "JITStubs.h" 35#include "JSArray.h" 36#include "JSFunction.h" 37#include "Interpreter.h" 38#include "JSCInlines.h" 39#include "ResultType.h" 40#include "SamplingTool.h" 41#include "SlowPathCall.h" 42 43 44namespace JSC { 45 46void JIT::emit_op_negate(Instruction* currentInstruction) 47{ 48 int dst = currentInstruction[1].u.operand; 49 int src = currentInstruction[2].u.operand; 50 51 emitLoad(src, regT1, regT0); 52 53 Jump srcNotInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); 54 addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff))); 55 neg32(regT0); 56 emitStoreInt32(dst, regT0, (dst == src)); 57 58 Jump end = jump(); 59 60 srcNotInt.link(this); 61 addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); 62 63 xor32(TrustedImm32(1 << 31), regT1); 64 store32(regT1, tagFor(dst)); 65 if (dst != src) 66 store32(regT0, payloadFor(dst)); 67 68 end.link(this); 69} 70 71void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 72{ 73 linkSlowCase(iter); // 0x7fffffff check 74 linkSlowCase(iter); // double check 75 76 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_negate); 77 slowPathCall.call(); 78} 79 80void JIT::emit_compareAndJump(OpcodeID opcode, int op1, int op2, unsigned target, RelationalCondition condition) 81{ 82 JumpList notInt32Op1; 83 JumpList notInt32Op2; 84 85 // Character less. 86 if (isOperandConstantImmediateChar(op1)) { 87 emitLoad(op2, regT1, regT0); 88 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); 89 JumpList failures; 90 emitLoadCharacterString(regT0, regT0, failures); 91 addSlowCase(failures); 92 addJump(branch32(commute(condition), regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); 93 return; 94 } 95 if (isOperandConstantImmediateChar(op2)) { 96 emitLoad(op1, regT1, regT0); 97 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); 98 JumpList failures; 99 emitLoadCharacterString(regT0, regT0, failures); 100 addSlowCase(failures); 101 addJump(branch32(condition, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); 102 return; 103 } 104 if (isOperandConstantImmediateInt(op1)) { 105 emitLoad(op2, regT3, regT2); 106 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 107 addJump(branch32(commute(condition), regT2, Imm32(getConstantOperand(op1).asInt32())), target); 108 } else if (isOperandConstantImmediateInt(op2)) { 109 emitLoad(op1, regT1, regT0); 110 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 111 addJump(branch32(condition, regT0, Imm32(getConstantOperand(op2).asInt32())), target); 112 } else { 113 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 114 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 115 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 116 addJump(branch32(condition, regT0, regT2), target); 117 } 118 119 if (!supportsFloatingPoint()) { 120 addSlowCase(notInt32Op1); 121 addSlowCase(notInt32Op2); 122 return; 123 } 124 Jump end = jump(); 125 126 // Double less. 127 emitBinaryDoubleOp(opcode, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); 128 end.link(this); 129} 130 131void JIT::emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector<SlowCaseEntry>::iterator& iter) 132{ 133 if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { 134 linkSlowCase(iter); 135 linkSlowCase(iter); 136 linkSlowCase(iter); 137 linkSlowCase(iter); 138 } else { 139 if (!supportsFloatingPoint()) { 140 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 141 linkSlowCase(iter); // int32 check 142 linkSlowCase(iter); // int32 check 143 } else { 144 if (!isOperandConstantImmediateInt(op1)) { 145 linkSlowCase(iter); // double check 146 linkSlowCase(iter); // int32 check 147 } 148 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 149 linkSlowCase(iter); // double check 150 } 151 } 152 emitLoad(op1, regT1, regT0); 153 emitLoad(op2, regT3, regT2); 154 callOperation(operation, regT1, regT0, regT3, regT2); 155 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target); 156} 157 158// LeftShift (<<) 159 160void JIT::emit_op_lshift(Instruction* currentInstruction) 161{ 162 int dst = currentInstruction[1].u.operand; 163 int op1 = currentInstruction[2].u.operand; 164 int op2 = currentInstruction[3].u.operand; 165 166 if (isOperandConstantImmediateInt(op2)) { 167 emitLoad(op1, regT1, regT0); 168 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 169 lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); 170 emitStoreInt32(dst, regT0, dst == op1); 171 return; 172 } 173 174 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 175 if (!isOperandConstantImmediateInt(op1)) 176 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 177 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 178 lshift32(regT2, regT0); 179 emitStoreInt32(dst, regT0, dst == op1 || dst == op2); 180} 181 182void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 183{ 184 int op1 = currentInstruction[2].u.operand; 185 int op2 = currentInstruction[3].u.operand; 186 187 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 188 linkSlowCase(iter); // int32 check 189 linkSlowCase(iter); // int32 check 190 191 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_lshift); 192 slowPathCall.call(); 193} 194 195// RightShift (>>) and UnsignedRightShift (>>>) helper 196 197void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned) 198{ 199 int dst = currentInstruction[1].u.operand; 200 int op1 = currentInstruction[2].u.operand; 201 int op2 = currentInstruction[3].u.operand; 202 203 // Slow case of rshift makes assumptions about what registers hold the 204 // shift arguments, so any changes must be updated there as well. 205 if (isOperandConstantImmediateInt(op2)) { 206 emitLoad(op1, regT1, regT0); 207 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 208 int shift = getConstantOperand(op2).asInt32() & 0x1f; 209 if (shift) { 210 if (isUnsigned) 211 urshift32(Imm32(shift), regT0); 212 else 213 rshift32(Imm32(shift), regT0); 214 } 215 emitStoreInt32(dst, regT0, dst == op1); 216 } else { 217 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 218 if (!isOperandConstantImmediateInt(op1)) 219 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 220 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 221 if (isUnsigned) 222 urshift32(regT2, regT0); 223 else 224 rshift32(regT2, regT0); 225 emitStoreInt32(dst, regT0, dst == op1); 226 } 227} 228 229void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned) 230{ 231 int dst = currentInstruction[1].u.operand; 232 int op1 = currentInstruction[2].u.operand; 233 int op2 = currentInstruction[3].u.operand; 234 if (isOperandConstantImmediateInt(op2)) { 235 int shift = getConstantOperand(op2).asInt32() & 0x1f; 236 // op1 = regT1:regT0 237 linkSlowCase(iter); // int32 check 238 if (supportsFloatingPointTruncate()) { 239 JumpList failures; 240 failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag))); 241 emitLoadDouble(op1, fpRegT0); 242 failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); 243 if (shift) { 244 if (isUnsigned) 245 urshift32(Imm32(shift), regT0); 246 else 247 rshift32(Imm32(shift), regT0); 248 } 249 move(TrustedImm32(JSValue::Int32Tag), regT1); 250 emitStoreInt32(dst, regT0, false); 251 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); 252 failures.link(this); 253 } 254 } else { 255 // op1 = regT1:regT0 256 // op2 = regT3:regT2 257 if (!isOperandConstantImmediateInt(op1)) { 258 linkSlowCase(iter); // int32 check -- op1 is not an int 259 if (supportsFloatingPointTruncate()) { 260 JumpList failures; 261 failures.append(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); // op1 is not a double 262 emitLoadDouble(op1, fpRegT0); 263 failures.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // op2 is not an int 264 failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); 265 if (isUnsigned) 266 urshift32(regT2, regT0); 267 else 268 rshift32(regT2, regT0); 269 move(TrustedImm32(JSValue::Int32Tag), regT1); 270 emitStoreInt32(dst, regT0, false); 271 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); 272 failures.link(this); 273 } 274 } 275 276 linkSlowCase(iter); // int32 check - op2 is not an int 277 } 278 279 JITSlowPathCall slowPathCall(this, currentInstruction, isUnsigned ? slow_path_urshift : slow_path_rshift); 280 slowPathCall.call(); 281} 282 283// RightShift (>>) 284 285void JIT::emit_op_rshift(Instruction* currentInstruction) 286{ 287 emitRightShift(currentInstruction, false); 288} 289 290void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 291{ 292 emitRightShiftSlowCase(currentInstruction, iter, false); 293} 294 295// UnsignedRightShift (>>>) 296 297void JIT::emit_op_urshift(Instruction* currentInstruction) 298{ 299 emitRightShift(currentInstruction, true); 300} 301 302void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 303{ 304 emitRightShiftSlowCase(currentInstruction, iter, true); 305} 306 307void JIT::emit_op_unsigned(Instruction* currentInstruction) 308{ 309 int result = currentInstruction[1].u.operand; 310 int op1 = currentInstruction[2].u.operand; 311 312 emitLoad(op1, regT1, regT0); 313 314 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 315 addSlowCase(branch32(LessThan, regT0, TrustedImm32(0))); 316 emitStoreInt32(result, regT0, result == op1); 317} 318 319void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 320{ 321 linkSlowCase(iter); 322 linkSlowCase(iter); 323 324 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned); 325 slowPathCall.call(); 326} 327 328// BitAnd (&) 329 330void JIT::emit_op_bitand(Instruction* currentInstruction) 331{ 332 int dst = currentInstruction[1].u.operand; 333 int op1 = currentInstruction[2].u.operand; 334 int op2 = currentInstruction[3].u.operand; 335 336 int op; 337 int32_t constant; 338 if (getOperandConstantImmediateInt(op1, op2, op, constant)) { 339 emitLoad(op, regT1, regT0); 340 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 341 and32(Imm32(constant), regT0); 342 emitStoreInt32(dst, regT0, dst == op); 343 return; 344 } 345 346 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 347 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 348 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 349 and32(regT2, regT0); 350 emitStoreInt32(dst, regT0, op1 == dst || op2 == dst); 351} 352 353void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 354{ 355 int op1 = currentInstruction[2].u.operand; 356 int op2 = currentInstruction[3].u.operand; 357 358 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 359 linkSlowCase(iter); // int32 check 360 linkSlowCase(iter); // int32 check 361 362 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitand); 363 slowPathCall.call(); 364} 365 366// BitOr (|) 367 368void JIT::emit_op_bitor(Instruction* currentInstruction) 369{ 370 int dst = currentInstruction[1].u.operand; 371 int op1 = currentInstruction[2].u.operand; 372 int op2 = currentInstruction[3].u.operand; 373 374 int op; 375 int32_t constant; 376 if (getOperandConstantImmediateInt(op1, op2, op, constant)) { 377 emitLoad(op, regT1, regT0); 378 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 379 or32(Imm32(constant), regT0); 380 emitStoreInt32(dst, regT0, op == dst); 381 return; 382 } 383 384 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 385 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 386 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 387 or32(regT2, regT0); 388 emitStoreInt32(dst, regT0, op1 == dst || op2 == dst); 389} 390 391void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 392{ 393 int op1 = currentInstruction[2].u.operand; 394 int op2 = currentInstruction[3].u.operand; 395 396 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 397 linkSlowCase(iter); // int32 check 398 linkSlowCase(iter); // int32 check 399 400 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitor); 401 slowPathCall.call(); 402} 403 404// BitXor (^) 405 406void JIT::emit_op_bitxor(Instruction* currentInstruction) 407{ 408 int dst = currentInstruction[1].u.operand; 409 int op1 = currentInstruction[2].u.operand; 410 int op2 = currentInstruction[3].u.operand; 411 412 int op; 413 int32_t constant; 414 if (getOperandConstantImmediateInt(op1, op2, op, constant)) { 415 emitLoad(op, regT1, regT0); 416 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 417 xor32(Imm32(constant), regT0); 418 emitStoreInt32(dst, regT0, op == dst); 419 return; 420 } 421 422 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 423 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 424 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 425 xor32(regT2, regT0); 426 emitStoreInt32(dst, regT0, op1 == dst || op2 == dst); 427} 428 429void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 430{ 431 int op1 = currentInstruction[2].u.operand; 432 int op2 = currentInstruction[3].u.operand; 433 434 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 435 linkSlowCase(iter); // int32 check 436 linkSlowCase(iter); // int32 check 437 438 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitxor); 439 slowPathCall.call(); 440} 441 442void JIT::emit_op_inc(Instruction* currentInstruction) 443{ 444 int srcDst = currentInstruction[1].u.operand; 445 446 emitLoad(srcDst, regT1, regT0); 447 448 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 449 addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0)); 450 emitStoreInt32(srcDst, regT0, true); 451} 452 453void JIT::emitSlow_op_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 454{ 455 linkSlowCase(iter); // int32 check 456 linkSlowCase(iter); // overflow check 457 458 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_inc); 459 slowPathCall.call(); 460} 461 462void JIT::emit_op_dec(Instruction* currentInstruction) 463{ 464 int srcDst = currentInstruction[1].u.operand; 465 466 emitLoad(srcDst, regT1, regT0); 467 468 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 469 addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0)); 470 emitStoreInt32(srcDst, regT0, true); 471} 472 473void JIT::emitSlow_op_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 474{ 475 linkSlowCase(iter); // int32 check 476 linkSlowCase(iter); // overflow check 477 478 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_dec); 479 slowPathCall.call(); 480} 481 482// Addition (+) 483 484void JIT::emit_op_add(Instruction* currentInstruction) 485{ 486 int dst = currentInstruction[1].u.operand; 487 int op1 = currentInstruction[2].u.operand; 488 int op2 = currentInstruction[3].u.operand; 489 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 490 491 if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { 492 addSlowCase(); 493 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add); 494 slowPathCall.call(); 495 return; 496 } 497 498 JumpList notInt32Op1; 499 JumpList notInt32Op2; 500 501 int op; 502 int32_t constant; 503 if (getOperandConstantImmediateInt(op1, op2, op, constant)) { 504 emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second()); 505 return; 506 } 507 508 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 509 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 510 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 511 512 // Int32 case. 513 addSlowCase(branchAdd32(Overflow, regT2, regT0)); 514 emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); 515 516 if (!supportsFloatingPoint()) { 517 addSlowCase(notInt32Op1); 518 addSlowCase(notInt32Op2); 519 return; 520 } 521 Jump end = jump(); 522 523 // Double case. 524 emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2); 525 end.link(this); 526} 527 528void JIT::emitAdd32Constant(int dst, int op, int32_t constant, ResultType opType) 529{ 530 // Int32 case. 531 emitLoad(op, regT1, regT2); 532 Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); 533 addSlowCase(branchAdd32(Overflow, regT2, Imm32(constant), regT0)); 534 emitStoreInt32(dst, regT0, (op == dst)); 535 536 // Double case. 537 if (!supportsFloatingPoint()) { 538 addSlowCase(notInt32); 539 return; 540 } 541 Jump end = jump(); 542 543 notInt32.link(this); 544 if (!opType.definitelyIsNumber()) 545 addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); 546 move(Imm32(constant), regT2); 547 convertInt32ToDouble(regT2, fpRegT0); 548 emitLoadDouble(op, fpRegT1); 549 addDouble(fpRegT1, fpRegT0); 550 emitStoreDouble(dst, fpRegT0); 551 552 end.link(this); 553} 554 555void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 556{ 557 int op1 = currentInstruction[2].u.operand; 558 int op2 = currentInstruction[3].u.operand; 559 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 560 561 if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { 562 linkDummySlowCase(iter); 563 return; 564 } 565 566 int op; 567 int32_t constant; 568 if (getOperandConstantImmediateInt(op1, op2, op, constant)) { 569 linkSlowCase(iter); // overflow check 570 571 if (!supportsFloatingPoint()) 572 linkSlowCase(iter); // non-sse case 573 else { 574 ResultType opType = op == op1 ? types.first() : types.second(); 575 if (!opType.definitelyIsNumber()) 576 linkSlowCase(iter); // double check 577 } 578 } else { 579 linkSlowCase(iter); // overflow check 580 581 if (!supportsFloatingPoint()) { 582 linkSlowCase(iter); // int32 check 583 linkSlowCase(iter); // int32 check 584 } else { 585 if (!types.first().definitelyIsNumber()) 586 linkSlowCase(iter); // double check 587 588 if (!types.second().definitelyIsNumber()) { 589 linkSlowCase(iter); // int32 check 590 linkSlowCase(iter); // double check 591 } 592 } 593 } 594 595 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add); 596 slowPathCall.call(); 597} 598 599// Subtraction (-) 600 601void JIT::emit_op_sub(Instruction* currentInstruction) 602{ 603 int dst = currentInstruction[1].u.operand; 604 int op1 = currentInstruction[2].u.operand; 605 int op2 = currentInstruction[3].u.operand; 606 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 607 608 JumpList notInt32Op1; 609 JumpList notInt32Op2; 610 611 if (isOperandConstantImmediateInt(op2)) { 612 emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first()); 613 return; 614 } 615 616 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 617 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 618 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 619 620 // Int32 case. 621 addSlowCase(branchSub32(Overflow, regT2, regT0)); 622 emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); 623 624 if (!supportsFloatingPoint()) { 625 addSlowCase(notInt32Op1); 626 addSlowCase(notInt32Op2); 627 return; 628 } 629 Jump end = jump(); 630 631 // Double case. 632 emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2); 633 end.link(this); 634} 635 636void JIT::emitSub32Constant(int dst, int op, int32_t constant, ResultType opType) 637{ 638 // Int32 case. 639 emitLoad(op, regT1, regT0); 640 Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); 641 addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2, regT3)); 642 emitStoreInt32(dst, regT2, (op == dst)); 643 644 // Double case. 645 if (!supportsFloatingPoint()) { 646 addSlowCase(notInt32); 647 return; 648 } 649 Jump end = jump(); 650 651 notInt32.link(this); 652 if (!opType.definitelyIsNumber()) 653 addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); 654 move(Imm32(constant), regT2); 655 convertInt32ToDouble(regT2, fpRegT0); 656 emitLoadDouble(op, fpRegT1); 657 subDouble(fpRegT0, fpRegT1); 658 emitStoreDouble(dst, fpRegT1); 659 660 end.link(this); 661} 662 663void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 664{ 665 int op2 = currentInstruction[3].u.operand; 666 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 667 668 if (isOperandConstantImmediateInt(op2)) { 669 linkSlowCase(iter); // overflow check 670 671 if (!supportsFloatingPoint() || !types.first().definitelyIsNumber()) 672 linkSlowCase(iter); // int32 or double check 673 } else { 674 linkSlowCase(iter); // overflow check 675 676 if (!supportsFloatingPoint()) { 677 linkSlowCase(iter); // int32 check 678 linkSlowCase(iter); // int32 check 679 } else { 680 if (!types.first().definitelyIsNumber()) 681 linkSlowCase(iter); // double check 682 683 if (!types.second().definitelyIsNumber()) { 684 linkSlowCase(iter); // int32 check 685 linkSlowCase(iter); // double check 686 } 687 } 688 } 689 690 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub); 691 slowPathCall.call(); 692} 693 694void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, int dst, int op1, int op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters) 695{ 696 JumpList end; 697 698 if (!notInt32Op1.empty()) { 699 // Double case 1: Op1 is not int32; Op2 is unknown. 700 notInt32Op1.link(this); 701 702 ASSERT(op1IsInRegisters); 703 704 // Verify Op1 is double. 705 if (!types.first().definitelyIsNumber()) 706 addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); 707 708 if (!op2IsInRegisters) 709 emitLoad(op2, regT3, regT2); 710 711 Jump doubleOp2 = branch32(Below, regT3, TrustedImm32(JSValue::LowestTag)); 712 713 if (!types.second().definitelyIsNumber()) 714 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 715 716 convertInt32ToDouble(regT2, fpRegT0); 717 Jump doTheMath = jump(); 718 719 // Load Op2 as double into double register. 720 doubleOp2.link(this); 721 emitLoadDouble(op2, fpRegT0); 722 723 // Do the math. 724 doTheMath.link(this); 725 switch (opcodeID) { 726 case op_mul: 727 emitLoadDouble(op1, fpRegT2); 728 mulDouble(fpRegT2, fpRegT0); 729 emitStoreDouble(dst, fpRegT0); 730 break; 731 case op_add: 732 emitLoadDouble(op1, fpRegT2); 733 addDouble(fpRegT2, fpRegT0); 734 emitStoreDouble(dst, fpRegT0); 735 break; 736 case op_sub: 737 emitLoadDouble(op1, fpRegT1); 738 subDouble(fpRegT0, fpRegT1); 739 emitStoreDouble(dst, fpRegT1); 740 break; 741 case op_div: { 742 emitLoadDouble(op1, fpRegT1); 743 divDouble(fpRegT0, fpRegT1); 744 745 // Is the result actually an integer? The DFG JIT would really like to know. If it's 746 // not an integer, we increment a count. If this together with the slow case counter 747 // are below threshold then the DFG JIT will compile this division with a specualtion 748 // that the remainder is zero. 749 750 // As well, there are cases where a double result here would cause an important field 751 // in the heap to sometimes have doubles in it, resulting in double predictions getting 752 // propagated to a use site where it might cause damage (such as the index to an array 753 // access). So if we are DFG compiling anything in the program, we want this code to 754 // ensure that it produces integers whenever possible. 755 756 // FIXME: This will fail to convert to integer if the result is zero. We should 757 // distinguish between positive zero and negative zero here. 758 759 JumpList notInteger; 760 branchConvertDoubleToInt32(fpRegT1, regT2, notInteger, fpRegT0); 761 // If we've got an integer, we might as well make that the result of the division. 762 emitStoreInt32(dst, regT2); 763 Jump isInteger = jump(); 764 notInteger.link(this); 765 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); 766 emitStoreDouble(dst, fpRegT1); 767 isInteger.link(this); 768 break; 769 } 770 case op_jless: 771 emitLoadDouble(op1, fpRegT2); 772 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); 773 break; 774 case op_jlesseq: 775 emitLoadDouble(op1, fpRegT2); 776 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst); 777 break; 778 case op_jgreater: 779 emitLoadDouble(op1, fpRegT2); 780 addJump(branchDouble(DoubleGreaterThan, fpRegT2, fpRegT0), dst); 781 break; 782 case op_jgreatereq: 783 emitLoadDouble(op1, fpRegT2); 784 addJump(branchDouble(DoubleGreaterThanOrEqual, fpRegT2, fpRegT0), dst); 785 break; 786 case op_jnless: 787 emitLoadDouble(op1, fpRegT2); 788 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); 789 break; 790 case op_jnlesseq: 791 emitLoadDouble(op1, fpRegT2); 792 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst); 793 break; 794 case op_jngreater: 795 emitLoadDouble(op1, fpRegT2); 796 addJump(branchDouble(DoubleGreaterThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); 797 break; 798 case op_jngreatereq: 799 emitLoadDouble(op1, fpRegT2); 800 addJump(branchDouble(DoubleGreaterThanOrUnordered, fpRegT0, fpRegT2), dst); 801 break; 802 default: 803 RELEASE_ASSERT_NOT_REACHED(); 804 } 805 806 if (!notInt32Op2.empty()) 807 end.append(jump()); 808 } 809 810 if (!notInt32Op2.empty()) { 811 // Double case 2: Op1 is int32; Op2 is not int32. 812 notInt32Op2.link(this); 813 814 ASSERT(op2IsInRegisters); 815 816 if (!op1IsInRegisters) 817 emitLoadPayload(op1, regT0); 818 819 convertInt32ToDouble(regT0, fpRegT0); 820 821 // Verify op2 is double. 822 if (!types.second().definitelyIsNumber()) 823 addSlowCase(branch32(Above, regT3, TrustedImm32(JSValue::LowestTag))); 824 825 // Do the math. 826 switch (opcodeID) { 827 case op_mul: 828 emitLoadDouble(op2, fpRegT2); 829 mulDouble(fpRegT2, fpRegT0); 830 emitStoreDouble(dst, fpRegT0); 831 break; 832 case op_add: 833 emitLoadDouble(op2, fpRegT2); 834 addDouble(fpRegT2, fpRegT0); 835 emitStoreDouble(dst, fpRegT0); 836 break; 837 case op_sub: 838 emitLoadDouble(op2, fpRegT2); 839 subDouble(fpRegT2, fpRegT0); 840 emitStoreDouble(dst, fpRegT0); 841 break; 842 case op_div: { 843 emitLoadDouble(op2, fpRegT2); 844 divDouble(fpRegT2, fpRegT0); 845 // Is the result actually an integer? The DFG JIT would really like to know. If it's 846 // not an integer, we increment a count. If this together with the slow case counter 847 // are below threshold then the DFG JIT will compile this division with a specualtion 848 // that the remainder is zero. 849 850 // As well, there are cases where a double result here would cause an important field 851 // in the heap to sometimes have doubles in it, resulting in double predictions getting 852 // propagated to a use site where it might cause damage (such as the index to an array 853 // access). So if we are DFG compiling anything in the program, we want this code to 854 // ensure that it produces integers whenever possible. 855 856 // FIXME: This will fail to convert to integer if the result is zero. We should 857 // distinguish between positive zero and negative zero here. 858 859 JumpList notInteger; 860 branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1); 861 // If we've got an integer, we might as well make that the result of the division. 862 emitStoreInt32(dst, regT2); 863 Jump isInteger = jump(); 864 notInteger.link(this); 865 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); 866 emitStoreDouble(dst, fpRegT0); 867 isInteger.link(this); 868 break; 869 } 870 case op_jless: 871 emitLoadDouble(op2, fpRegT1); 872 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); 873 break; 874 case op_jlesseq: 875 emitLoadDouble(op2, fpRegT1); 876 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT1), dst); 877 break; 878 case op_jgreater: 879 emitLoadDouble(op2, fpRegT1); 880 addJump(branchDouble(DoubleGreaterThan, fpRegT0, fpRegT1), dst); 881 break; 882 case op_jgreatereq: 883 emitLoadDouble(op2, fpRegT1); 884 addJump(branchDouble(DoubleGreaterThanOrEqual, fpRegT0, fpRegT1), dst); 885 break; 886 case op_jnless: 887 emitLoadDouble(op2, fpRegT1); 888 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); 889 break; 890 case op_jnlesseq: 891 emitLoadDouble(op2, fpRegT1); 892 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); 893 break; 894 case op_jngreater: 895 emitLoadDouble(op2, fpRegT1); 896 addJump(branchDouble(DoubleGreaterThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); 897 break; 898 case op_jngreatereq: 899 emitLoadDouble(op2, fpRegT1); 900 addJump(branchDouble(DoubleGreaterThanOrUnordered, fpRegT1, fpRegT0), dst); 901 break; 902 default: 903 RELEASE_ASSERT_NOT_REACHED(); 904 } 905 } 906 907 end.link(this); 908} 909 910// Multiplication (*) 911 912void JIT::emit_op_mul(Instruction* currentInstruction) 913{ 914 int dst = currentInstruction[1].u.operand; 915 int op1 = currentInstruction[2].u.operand; 916 int op2 = currentInstruction[3].u.operand; 917 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 918 919 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset); 920 921 JumpList notInt32Op1; 922 JumpList notInt32Op2; 923 924 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 925 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 926 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 927 928 // Int32 case. 929 move(regT0, regT3); 930 addSlowCase(branchMul32(Overflow, regT2, regT0)); 931 addSlowCase(branchTest32(Zero, regT0)); 932 emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); 933 934 if (!supportsFloatingPoint()) { 935 addSlowCase(notInt32Op1); 936 addSlowCase(notInt32Op2); 937 return; 938 } 939 Jump end = jump(); 940 941 // Double case. 942 emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2); 943 end.link(this); 944} 945 946void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 947{ 948 int dst = currentInstruction[1].u.operand; 949 int op1 = currentInstruction[2].u.operand; 950 int op2 = currentInstruction[3].u.operand; 951 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 952 953 Jump overflow = getSlowCase(iter); // overflow check 954 linkSlowCase(iter); // zero result check 955 956 Jump negZero = branchOr32(Signed, regT2, regT3); 957 emitStoreInt32(dst, TrustedImm32(0), (op1 == dst || op2 == dst)); 958 959 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul)); 960 961 negZero.link(this); 962 // We only get here if we have a genuine negative zero. Record this, 963 // so that the speculative JIT knows that we failed speculation 964 // because of a negative zero. 965 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); 966 overflow.link(this); 967 968 if (!supportsFloatingPoint()) { 969 linkSlowCase(iter); // int32 check 970 linkSlowCase(iter); // int32 check 971 } 972 973 if (supportsFloatingPoint()) { 974 if (!types.first().definitelyIsNumber()) 975 linkSlowCase(iter); // double check 976 977 if (!types.second().definitelyIsNumber()) { 978 linkSlowCase(iter); // int32 check 979 linkSlowCase(iter); // double check 980 } 981 } 982 983 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); 984 slowPathCall.call(); 985} 986 987// Division (/) 988 989void JIT::emit_op_div(Instruction* currentInstruction) 990{ 991 int dst = currentInstruction[1].u.operand; 992 int op1 = currentInstruction[2].u.operand; 993 int op2 = currentInstruction[3].u.operand; 994 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 995 996 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset); 997 998 if (!supportsFloatingPoint()) { 999 addSlowCase(jump()); 1000 return; 1001 } 1002 1003 // Int32 divide. 1004 JumpList notInt32Op1; 1005 JumpList notInt32Op2; 1006 1007 JumpList end; 1008 1009 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 1010 1011 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 1012 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 1013 1014 convertInt32ToDouble(regT0, fpRegT0); 1015 convertInt32ToDouble(regT2, fpRegT1); 1016 divDouble(fpRegT1, fpRegT0); 1017 // Is the result actually an integer? The DFG JIT would really like to know. If it's 1018 // not an integer, we increment a count. If this together with the slow case counter 1019 // are below threshold then the DFG JIT will compile this division with a specualtion 1020 // that the remainder is zero. 1021 1022 // As well, there are cases where a double result here would cause an important field 1023 // in the heap to sometimes have doubles in it, resulting in double predictions getting 1024 // propagated to a use site where it might cause damage (such as the index to an array 1025 // access). So if we are DFG compiling anything in the program, we want this code to 1026 // ensure that it produces integers whenever possible. 1027 1028 // FIXME: This will fail to convert to integer if the result is zero. We should 1029 // distinguish between positive zero and negative zero here. 1030 1031 JumpList notInteger; 1032 branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1); 1033 // If we've got an integer, we might as well make that the result of the division. 1034 emitStoreInt32(dst, regT2); 1035 end.append(jump()); 1036 notInteger.link(this); 1037 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); 1038 emitStoreDouble(dst, fpRegT0); 1039 end.append(jump()); 1040 1041 // Double divide. 1042 emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2); 1043 end.link(this); 1044} 1045 1046void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1047{ 1048 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 1049 1050 if (!supportsFloatingPoint()) 1051 linkSlowCase(iter); 1052 else { 1053 if (!types.first().definitelyIsNumber()) 1054 linkSlowCase(iter); // double check 1055 1056 if (!types.second().definitelyIsNumber()) { 1057 linkSlowCase(iter); // int32 check 1058 linkSlowCase(iter); // double check 1059 } 1060 } 1061 1062 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); 1063 slowPathCall.call(); 1064} 1065 1066// Mod (%) 1067 1068/* ------------------------------ BEGIN: OP_MOD ------------------------------ */ 1069 1070void JIT::emit_op_mod(Instruction* currentInstruction) 1071{ 1072#if CPU(X86) || CPU(X86_64) 1073 int dst = currentInstruction[1].u.operand; 1074 int op1 = currentInstruction[2].u.operand; 1075 int op2 = currentInstruction[3].u.operand; 1076 1077 // Make sure registers are correct for x86 IDIV instructions. 1078 ASSERT(regT0 == X86Registers::eax); 1079 ASSERT(regT1 == X86Registers::edx); 1080 ASSERT(regT2 == X86Registers::ecx); 1081 ASSERT(regT3 == X86Registers::ebx); 1082 1083 emitLoad2(op1, regT0, regT3, op2, regT1, regT2); 1084 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); 1085 addSlowCase(branch32(NotEqual, regT0, TrustedImm32(JSValue::Int32Tag))); 1086 1087 move(regT3, regT0); 1088 addSlowCase(branchTest32(Zero, regT2)); 1089 Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1)); 1090 addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1))); 1091 denominatorNotNeg1.link(this); 1092 m_assembler.cdq(); 1093 m_assembler.idivl_r(regT2); 1094 Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0)); 1095 addSlowCase(branchTest32(Zero, regT1)); 1096 numeratorPositive.link(this); 1097 emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst)); 1098#else 1099 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod); 1100 slowPathCall.call(); 1101#endif 1102} 1103 1104void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1105{ 1106#if CPU(X86) || CPU(X86_64) 1107 linkSlowCase(iter); 1108 linkSlowCase(iter); 1109 linkSlowCase(iter); 1110 linkSlowCase(iter); 1111 linkSlowCase(iter); 1112 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod); 1113 slowPathCall.call(); 1114#else 1115 UNUSED_PARAM(currentInstruction); 1116 UNUSED_PARAM(iter); 1117 // We would have really useful assertions here if it wasn't for the compiler's 1118 // insistence on attribute noreturn. 1119 // RELEASE_ASSERT_NOT_REACHED(); 1120#endif 1121} 1122 1123/* ------------------------------ END: OP_MOD ------------------------------ */ 1124 1125} // namespace JSC 1126 1127#endif // USE(JSVALUE32_64) 1128#endif // ENABLE(JIT) 1129