| 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 | #include "JIT.h" | 
| 28 |  | 
| 29 | #if ENABLE(JIT) | 
| 30 |  | 
| 31 | #include "CodeBlock.h" | 
| 32 | #include "JITInlineMethods.h" | 
| 33 | #include "JITStubCall.h" | 
| 34 | #include "JSArray.h" | 
| 35 | #include "JSFunction.h" | 
| 36 | #include "Interpreter.h" | 
| 37 | #include "ResultType.h" | 
| 38 | #include "SamplingTool.h" | 
| 39 |  | 
| 40 | #ifndef NDEBUG | 
| 41 | #include <stdio.h> | 
| 42 | #endif | 
| 43 |  | 
| 44 | using namespace std; | 
| 45 |  | 
| 46 | namespace JSC { | 
| 47 |  | 
| 48 | #if USE(JSVALUE32_64) | 
| 49 |  | 
| 50 | void JIT::emit_op_negate(Instruction* currentInstruction) | 
| 51 | { | 
| 52 |     unsigned dst = currentInstruction[1].u.operand; | 
| 53 |     unsigned src = currentInstruction[2].u.operand; | 
| 54 |  | 
| 55 |     emitLoad(src, regT1, regT0); | 
| 56 |  | 
| 57 |     Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); | 
| 58 |     addSlowCase(branch32(Equal, regT0, Imm32(0))); | 
| 59 |     addSlowCase(branchNeg32(Overflow, regT0)); | 
| 60 |     emitStoreInt32(dst, regT0, (dst == src)); | 
| 61 |  | 
| 62 |     Jump end = jump(); | 
| 63 |  | 
| 64 |     srcNotInt.link(this); | 
| 65 |     addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); | 
| 66 |  | 
| 67 |     xor32(Imm32(1 << 31), regT1); | 
| 68 |     store32(regT1, tagFor(dst)); | 
| 69 |     if (dst != src) | 
| 70 |         store32(regT0, payloadFor(dst)); | 
| 71 |  | 
| 72 |     end.link(this); | 
| 73 | } | 
| 74 |  | 
| 75 | void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 76 | { | 
| 77 |     unsigned dst = currentInstruction[1].u.operand; | 
| 78 |  | 
| 79 |     linkSlowCase(iter); // 0 check | 
| 80 |     linkSlowCase(iter); // overflow check | 
| 81 |     linkSlowCase(iter); // double check | 
| 82 |  | 
| 83 |     JITStubCall stubCall(this, cti_op_negate); | 
| 84 |     stubCall.addArgument(regT1, regT0); | 
| 85 |     stubCall.call(dst); | 
| 86 | } | 
| 87 |  | 
| 88 | void JIT::emit_op_jnless(Instruction* currentInstruction) | 
| 89 | { | 
| 90 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 91 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 92 |     unsigned target = currentInstruction[3].u.operand; | 
| 93 |  | 
| 94 |     JumpList notInt32Op1; | 
| 95 |     JumpList notInt32Op2; | 
| 96 |  | 
| 97 |     // Int32 less. | 
| 98 |     if (isOperandConstantImmediateInt(op1)) { | 
| 99 |         emitLoad(op2, regT3, regT2); | 
| 100 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 101 |         addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); | 
| 102 |     } else if (isOperandConstantImmediateInt(op2)) { | 
| 103 |         emitLoad(op1, regT1, regT0); | 
| 104 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 105 |         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); | 
| 106 |     } else { | 
| 107 |         emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 108 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 109 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 110 |         addJump(branch32(GreaterThanOrEqual, regT0, regT2), target); | 
| 111 |     } | 
| 112 |  | 
| 113 |     if (!supportsFloatingPoint()) { | 
| 114 |         addSlowCase(notInt32Op1); | 
| 115 |         addSlowCase(notInt32Op2); | 
| 116 |         return; | 
| 117 |     } | 
| 118 |     Jump end = jump(); | 
| 119 |  | 
| 120 |     // Double less. | 
| 121 |     emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); | 
| 122 |     end.link(this); | 
| 123 | } | 
| 124 |  | 
| 125 | void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 126 | { | 
| 127 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 128 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 129 |     unsigned target = currentInstruction[3].u.operand; | 
| 130 |  | 
| 131 |     if (!supportsFloatingPoint()) { | 
| 132 |         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 133 |             linkSlowCase(iter); // int32 check | 
| 134 |         linkSlowCase(iter); // int32 check | 
| 135 |     } else { | 
| 136 |         if (!isOperandConstantImmediateInt(op1)) { | 
| 137 |             linkSlowCase(iter); // double check | 
| 138 |             linkSlowCase(iter); // int32 check | 
| 139 |         } | 
| 140 |         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) | 
| 141 |             linkSlowCase(iter); // double check | 
| 142 |     } | 
| 143 |  | 
| 144 |     JITStubCall stubCall(this, cti_op_jless); | 
| 145 |     stubCall.addArgument(op1); | 
| 146 |     stubCall.addArgument(op2); | 
| 147 |     stubCall.call(); | 
| 148 |     emitJumpSlowToHot(branchTest32(Zero, regT0), target); | 
| 149 | } | 
| 150 |  | 
| 151 | void JIT::emit_op_jless(Instruction* currentInstruction) | 
| 152 | { | 
| 153 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 154 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 155 |     unsigned target = currentInstruction[3].u.operand; | 
| 156 |  | 
| 157 |     JumpList notInt32Op1; | 
| 158 |     JumpList notInt32Op2; | 
| 159 |  | 
| 160 |     // Int32 less. | 
| 161 |     if (isOperandConstantImmediateInt(op1)) { | 
| 162 |         emitLoad(op2, regT3, regT2); | 
| 163 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 164 |         addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); | 
| 165 |     } else if (isOperandConstantImmediateInt(op2)) { | 
| 166 |         emitLoad(op1, regT1, regT0); | 
| 167 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 168 |         addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); | 
| 169 |     } else { | 
| 170 |         emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 171 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 172 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 173 |         addJump(branch32(LessThan, regT0, regT2), target); | 
| 174 |     } | 
| 175 |  | 
| 176 |     if (!supportsFloatingPoint()) { | 
| 177 |         addSlowCase(notInt32Op1); | 
| 178 |         addSlowCase(notInt32Op2); | 
| 179 |         return; | 
| 180 |     } | 
| 181 |     Jump end = jump(); | 
| 182 |  | 
| 183 |     // Double less. | 
| 184 |     emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); | 
| 185 |     end.link(this); | 
| 186 | } | 
| 187 |  | 
| 188 | void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 189 | { | 
| 190 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 191 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 192 |     unsigned target = currentInstruction[3].u.operand; | 
| 193 |  | 
| 194 |     if (!supportsFloatingPoint()) { | 
| 195 |         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 196 |             linkSlowCase(iter); // int32 check | 
| 197 |         linkSlowCase(iter); // int32 check | 
| 198 |     } else { | 
| 199 |         if (!isOperandConstantImmediateInt(op1)) { | 
| 200 |             linkSlowCase(iter); // double check | 
| 201 |             linkSlowCase(iter); // int32 check | 
| 202 |         } | 
| 203 |         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) | 
| 204 |             linkSlowCase(iter); // double check | 
| 205 |     } | 
| 206 |  | 
| 207 |     JITStubCall stubCall(this, cti_op_jless); | 
| 208 |     stubCall.addArgument(op1); | 
| 209 |     stubCall.addArgument(op2); | 
| 210 |     stubCall.call(); | 
| 211 |     emitJumpSlowToHot(branchTest32(NonZero, regT0), target); | 
| 212 | } | 
| 213 |  | 
| 214 | void JIT::emit_op_jnlesseq(Instruction* currentInstruction) | 
| 215 | { | 
| 216 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 217 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 218 |     unsigned target = currentInstruction[3].u.operand; | 
| 219 |  | 
| 220 |     JumpList notInt32Op1; | 
| 221 |     JumpList notInt32Op2; | 
| 222 |  | 
| 223 |     // Int32 less. | 
| 224 |     if (isOperandConstantImmediateInt(op1)) { | 
| 225 |         emitLoad(op2, regT3, regT2); | 
| 226 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 227 |         addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); | 
| 228 |     } else if (isOperandConstantImmediateInt(op2)) { | 
| 229 |         emitLoad(op1, regT1, regT0); | 
| 230 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 231 |         addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); | 
| 232 |     } else { | 
| 233 |         emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 234 |         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 235 |         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 236 |         addJump(branch32(GreaterThan, regT0, regT2), target); | 
| 237 |     } | 
| 238 |  | 
| 239 |     if (!supportsFloatingPoint()) { | 
| 240 |         addSlowCase(notInt32Op1); | 
| 241 |         addSlowCase(notInt32Op2); | 
| 242 |         return; | 
| 243 |     } | 
| 244 |     Jump end = jump(); | 
| 245 |  | 
| 246 |     // Double less. | 
| 247 |     emitBinaryDoubleOp(op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); | 
| 248 |     end.link(this); | 
| 249 | } | 
| 250 |  | 
| 251 | void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 252 | { | 
| 253 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 254 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 255 |     unsigned target = currentInstruction[3].u.operand; | 
| 256 |  | 
| 257 |     if (!supportsFloatingPoint()) { | 
| 258 |         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 259 |             linkSlowCase(iter); // int32 check | 
| 260 |         linkSlowCase(iter); // int32 check | 
| 261 |     } else { | 
| 262 |         if (!isOperandConstantImmediateInt(op1)) { | 
| 263 |             linkSlowCase(iter); // double check | 
| 264 |             linkSlowCase(iter); // int32 check | 
| 265 |         } | 
| 266 |         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) | 
| 267 |             linkSlowCase(iter); // double check | 
| 268 |     } | 
| 269 |  | 
| 270 |     JITStubCall stubCall(this, cti_op_jlesseq); | 
| 271 |     stubCall.addArgument(op1); | 
| 272 |     stubCall.addArgument(op2); | 
| 273 |     stubCall.call(); | 
| 274 |     emitJumpSlowToHot(branchTest32(Zero, regT0), target); | 
| 275 | } | 
| 276 |  | 
| 277 | // LeftShift (<<) | 
| 278 |  | 
| 279 | void JIT::emit_op_lshift(Instruction* currentInstruction) | 
| 280 | { | 
| 281 |     unsigned dst = currentInstruction[1].u.operand; | 
| 282 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 283 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 284 |  | 
| 285 |     if (isOperandConstantImmediateInt(op2)) { | 
| 286 |         emitLoad(op1, regT1, regT0); | 
| 287 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 288 |         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); | 
| 289 |         emitStoreInt32(dst, regT0, dst == op1); | 
| 290 |         return; | 
| 291 |     } | 
| 292 |  | 
| 293 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 294 |     if (!isOperandConstantImmediateInt(op1)) | 
| 295 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 296 |     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 297 |     lshift32(regT2, regT0); | 
| 298 |     emitStoreInt32(dst, regT0, dst == op1 || dst == op2); | 
| 299 | } | 
| 300 |  | 
| 301 | void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 302 | { | 
| 303 |     unsigned dst = currentInstruction[1].u.operand; | 
| 304 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 305 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 306 |  | 
| 307 |     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 308 |         linkSlowCase(iter); // int32 check | 
| 309 |     linkSlowCase(iter); // int32 check | 
| 310 |  | 
| 311 |     JITStubCall stubCall(this, cti_op_lshift); | 
| 312 |     stubCall.addArgument(op1); | 
| 313 |     stubCall.addArgument(op2); | 
| 314 |     stubCall.call(dst); | 
| 315 | } | 
| 316 |  | 
| 317 | // RightShift (>>) | 
| 318 |  | 
| 319 | void JIT::emit_op_rshift(Instruction* currentInstruction) | 
| 320 | { | 
| 321 |     unsigned dst = currentInstruction[1].u.operand; | 
| 322 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 323 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 324 |  | 
| 325 |     if (isOperandConstantImmediateInt(op2)) { | 
| 326 |         emitLoad(op1, regT1, regT0); | 
| 327 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 328 |         rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); | 
| 329 |         emitStoreInt32(dst, regT0, dst == op1); | 
| 330 |         return; | 
| 331 |     } | 
| 332 |  | 
| 333 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 334 |     if (!isOperandConstantImmediateInt(op1)) | 
| 335 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 336 |     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 337 |     rshift32(regT2, regT0); | 
| 338 |     emitStoreInt32(dst, regT0, dst == op1 || dst == op2); | 
| 339 | } | 
| 340 |  | 
| 341 | void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 342 | { | 
| 343 |     unsigned dst = currentInstruction[1].u.operand; | 
| 344 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 345 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 346 |  | 
| 347 |     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 348 |         linkSlowCase(iter); // int32 check | 
| 349 |     linkSlowCase(iter); // int32 check | 
| 350 |  | 
| 351 |     JITStubCall stubCall(this, cti_op_rshift); | 
| 352 |     stubCall.addArgument(op1); | 
| 353 |     stubCall.addArgument(op2); | 
| 354 |     stubCall.call(dst); | 
| 355 | } | 
| 356 |  | 
| 357 | // BitAnd (&) | 
| 358 |  | 
| 359 | void JIT::emit_op_bitand(Instruction* currentInstruction) | 
| 360 | { | 
| 361 |     unsigned dst = currentInstruction[1].u.operand; | 
| 362 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 363 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 364 |  | 
| 365 |     unsigned op; | 
| 366 |     int32_t constant; | 
| 367 |     if (getOperandConstantImmediateInt(op1, op2, op, constant)) { | 
| 368 |         emitLoad(op, regT1, regT0); | 
| 369 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 370 |         and32(Imm32(constant), regT0); | 
| 371 |         emitStoreInt32(dst, regT0, (op == dst)); | 
| 372 |         return; | 
| 373 |     } | 
| 374 |  | 
| 375 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 376 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 377 |     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 378 |     and32(regT2, regT0); | 
| 379 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 380 | } | 
| 381 |  | 
| 382 | void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 383 | { | 
| 384 |     unsigned dst = currentInstruction[1].u.operand; | 
| 385 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 386 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 387 |  | 
| 388 |     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 389 |         linkSlowCase(iter); // int32 check | 
| 390 |     linkSlowCase(iter); // int32 check | 
| 391 |  | 
| 392 |     JITStubCall stubCall(this, cti_op_bitand); | 
| 393 |     stubCall.addArgument(op1); | 
| 394 |     stubCall.addArgument(op2); | 
| 395 |     stubCall.call(dst); | 
| 396 | } | 
| 397 |  | 
| 398 | // BitOr (|) | 
| 399 |  | 
| 400 | void JIT::emit_op_bitor(Instruction* currentInstruction) | 
| 401 | { | 
| 402 |     unsigned dst = currentInstruction[1].u.operand; | 
| 403 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 404 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 405 |  | 
| 406 |     unsigned op; | 
| 407 |     int32_t constant; | 
| 408 |     if (getOperandConstantImmediateInt(op1, op2, op, constant)) { | 
| 409 |         emitLoad(op, regT1, regT0); | 
| 410 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 411 |         or32(Imm32(constant), regT0); | 
| 412 |         emitStoreInt32(dst, regT0, (op == dst)); | 
| 413 |         return; | 
| 414 |     } | 
| 415 |  | 
| 416 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 417 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 418 |     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 419 |     or32(regT2, regT0); | 
| 420 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 421 | } | 
| 422 |  | 
| 423 | void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 424 | { | 
| 425 |     unsigned dst = currentInstruction[1].u.operand; | 
| 426 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 427 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 428 |  | 
| 429 |     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 430 |         linkSlowCase(iter); // int32 check | 
| 431 |     linkSlowCase(iter); // int32 check | 
| 432 |  | 
| 433 |     JITStubCall stubCall(this, cti_op_bitor); | 
| 434 |     stubCall.addArgument(op1); | 
| 435 |     stubCall.addArgument(op2); | 
| 436 |     stubCall.call(dst); | 
| 437 | } | 
| 438 |  | 
| 439 | // BitXor (^) | 
| 440 |  | 
| 441 | void JIT::emit_op_bitxor(Instruction* currentInstruction) | 
| 442 | { | 
| 443 |     unsigned dst = currentInstruction[1].u.operand; | 
| 444 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 445 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 446 |  | 
| 447 |     unsigned op; | 
| 448 |     int32_t constant; | 
| 449 |     if (getOperandConstantImmediateInt(op1, op2, op, constant)) { | 
| 450 |         emitLoad(op, regT1, regT0); | 
| 451 |         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 452 |         xor32(Imm32(constant), regT0); | 
| 453 |         emitStoreInt32(dst, regT0, (op == dst)); | 
| 454 |         return; | 
| 455 |     } | 
| 456 |  | 
| 457 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 458 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 459 |     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 460 |     xor32(regT2, regT0); | 
| 461 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 462 | } | 
| 463 |  | 
| 464 | void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 465 | { | 
| 466 |     unsigned dst = currentInstruction[1].u.operand; | 
| 467 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 468 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 469 |  | 
| 470 |     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) | 
| 471 |         linkSlowCase(iter); // int32 check | 
| 472 |     linkSlowCase(iter); // int32 check | 
| 473 |  | 
| 474 |     JITStubCall stubCall(this, cti_op_bitxor); | 
| 475 |     stubCall.addArgument(op1); | 
| 476 |     stubCall.addArgument(op2); | 
| 477 |     stubCall.call(dst); | 
| 478 | } | 
| 479 |  | 
| 480 | // BitNot (~) | 
| 481 |  | 
| 482 | void JIT::emit_op_bitnot(Instruction* currentInstruction) | 
| 483 | { | 
| 484 |     unsigned dst = currentInstruction[1].u.operand; | 
| 485 |     unsigned src = currentInstruction[2].u.operand; | 
| 486 |  | 
| 487 |     emitLoad(src, regT1, regT0); | 
| 488 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 489 |  | 
| 490 |     not32(regT0); | 
| 491 |     emitStoreInt32(dst, regT0, (dst == src)); | 
| 492 | } | 
| 493 |  | 
| 494 | void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 495 | { | 
| 496 |     unsigned dst = currentInstruction[1].u.operand; | 
| 497 |  | 
| 498 |     linkSlowCase(iter); // int32 check | 
| 499 |  | 
| 500 |     JITStubCall stubCall(this, cti_op_bitnot); | 
| 501 |     stubCall.addArgument(regT1, regT0); | 
| 502 |     stubCall.call(dst); | 
| 503 | } | 
| 504 |  | 
| 505 | // PostInc (i++) | 
| 506 |  | 
| 507 | void JIT::emit_op_post_inc(Instruction* currentInstruction) | 
| 508 | { | 
| 509 |     unsigned dst = currentInstruction[1].u.operand; | 
| 510 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 511 |      | 
| 512 |     emitLoad(srcDst, regT1, regT0); | 
| 513 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 514 |  | 
| 515 |     if (dst == srcDst) // x = x++ is a noop for ints. | 
| 516 |         return; | 
| 517 |  | 
| 518 |     emitStoreInt32(dst, regT0); | 
| 519 |  | 
| 520 |     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); | 
| 521 |     emitStoreInt32(srcDst, regT0, true); | 
| 522 | } | 
| 523 |  | 
| 524 | void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 525 | { | 
| 526 |     unsigned dst = currentInstruction[1].u.operand; | 
| 527 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 528 |  | 
| 529 |     linkSlowCase(iter); // int32 check | 
| 530 |     if (dst != srcDst) | 
| 531 |         linkSlowCase(iter); // overflow check | 
| 532 |  | 
| 533 |     JITStubCall stubCall(this, cti_op_post_inc); | 
| 534 |     stubCall.addArgument(srcDst); | 
| 535 |     stubCall.addArgument(Imm32(srcDst)); | 
| 536 |     stubCall.call(dst); | 
| 537 | } | 
| 538 |  | 
| 539 | // PostDec (i--) | 
| 540 |  | 
| 541 | void JIT::emit_op_post_dec(Instruction* currentInstruction) | 
| 542 | { | 
| 543 |     unsigned dst = currentInstruction[1].u.operand; | 
| 544 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 545 |  | 
| 546 |     emitLoad(srcDst, regT1, regT0); | 
| 547 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 548 |  | 
| 549 |     if (dst == srcDst) // x = x-- is a noop for ints. | 
| 550 |         return; | 
| 551 |  | 
| 552 |     emitStoreInt32(dst, regT0); | 
| 553 |  | 
| 554 |     addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); | 
| 555 |     emitStoreInt32(srcDst, regT0, true); | 
| 556 | } | 
| 557 |  | 
| 558 | void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 559 | { | 
| 560 |     unsigned dst = currentInstruction[1].u.operand; | 
| 561 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 562 |  | 
| 563 |     linkSlowCase(iter); // int32 check | 
| 564 |     if (dst != srcDst) | 
| 565 |         linkSlowCase(iter); // overflow check | 
| 566 |  | 
| 567 |     JITStubCall stubCall(this, cti_op_post_dec); | 
| 568 |     stubCall.addArgument(srcDst); | 
| 569 |     stubCall.addArgument(Imm32(srcDst)); | 
| 570 |     stubCall.call(dst); | 
| 571 | } | 
| 572 |  | 
| 573 | // PreInc (++i) | 
| 574 |  | 
| 575 | void JIT::emit_op_pre_inc(Instruction* currentInstruction) | 
| 576 | { | 
| 577 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 578 |  | 
| 579 |     emitLoad(srcDst, regT1, regT0); | 
| 580 |  | 
| 581 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 582 |     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); | 
| 583 |     emitStoreInt32(srcDst, regT0, true); | 
| 584 | } | 
| 585 |  | 
| 586 | void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 587 | { | 
| 588 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 589 |  | 
| 590 |     linkSlowCase(iter); // int32 check | 
| 591 |     linkSlowCase(iter); // overflow check | 
| 592 |  | 
| 593 |     JITStubCall stubCall(this, cti_op_pre_inc); | 
| 594 |     stubCall.addArgument(srcDst); | 
| 595 |     stubCall.call(srcDst); | 
| 596 | } | 
| 597 |  | 
| 598 | // PreDec (--i) | 
| 599 |  | 
| 600 | void JIT::emit_op_pre_dec(Instruction* currentInstruction) | 
| 601 | { | 
| 602 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 603 |  | 
| 604 |     emitLoad(srcDst, regT1, regT0); | 
| 605 |  | 
| 606 |     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 607 |     addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); | 
| 608 |     emitStoreInt32(srcDst, regT0, true); | 
| 609 | } | 
| 610 |  | 
| 611 | void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 612 | { | 
| 613 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 614 |  | 
| 615 |     linkSlowCase(iter); // int32 check | 
| 616 |     linkSlowCase(iter); // overflow check | 
| 617 |  | 
| 618 |     JITStubCall stubCall(this, cti_op_pre_dec); | 
| 619 |     stubCall.addArgument(srcDst); | 
| 620 |     stubCall.call(srcDst); | 
| 621 | } | 
| 622 |  | 
| 623 | // Addition (+) | 
| 624 |  | 
| 625 | void JIT::emit_op_add(Instruction* currentInstruction) | 
| 626 | { | 
| 627 |     unsigned dst = currentInstruction[1].u.operand; | 
| 628 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 629 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 630 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 631 |  | 
| 632 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { | 
| 633 |         JITStubCall stubCall(this, cti_op_add); | 
| 634 |         stubCall.addArgument(op1); | 
| 635 |         stubCall.addArgument(op2); | 
| 636 |         stubCall.call(dst); | 
| 637 |         return; | 
| 638 |     } | 
| 639 |  | 
| 640 |     JumpList notInt32Op1; | 
| 641 |     JumpList notInt32Op2; | 
| 642 |  | 
| 643 |     unsigned op; | 
| 644 |     int32_t constant; | 
| 645 |     if (getOperandConstantImmediateInt(op1, op2, op, constant)) { | 
| 646 |         emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second()); | 
| 647 |         return; | 
| 648 |     } | 
| 649 |  | 
| 650 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 651 |     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 652 |     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 653 |  | 
| 654 |     // Int32 case. | 
| 655 |     addSlowCase(branchAdd32(Overflow, regT2, regT0)); | 
| 656 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 657 |  | 
| 658 |     if (!supportsFloatingPoint()) { | 
| 659 |         addSlowCase(notInt32Op1); | 
| 660 |         addSlowCase(notInt32Op2); | 
| 661 |         return; | 
| 662 |     } | 
| 663 |     Jump end = jump(); | 
| 664 |  | 
| 665 |     // Double case. | 
| 666 |     emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2); | 
| 667 |     end.link(this); | 
| 668 | } | 
| 669 |  | 
| 670 | void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) | 
| 671 | { | 
| 672 |     // Int32 case. | 
| 673 |     emitLoad(op, regT1, regT0); | 
| 674 |     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); | 
| 675 |     addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0)); | 
| 676 |     emitStoreInt32(dst, regT0, (op == dst)); | 
| 677 |  | 
| 678 |     // Double case. | 
| 679 |     if (!supportsFloatingPoint()) { | 
| 680 |         addSlowCase(notInt32); | 
| 681 |         return; | 
| 682 |     } | 
| 683 |     Jump end = jump(); | 
| 684 |  | 
| 685 |     notInt32.link(this); | 
| 686 |     if (!opType.definitelyIsNumber()) | 
| 687 |         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); | 
| 688 |     move(Imm32(constant), regT2); | 
| 689 |     convertInt32ToDouble(regT2, fpRegT0); | 
| 690 |     emitLoadDouble(op, fpRegT1); | 
| 691 |     addDouble(fpRegT1, fpRegT0); | 
| 692 |     emitStoreDouble(dst, fpRegT0); | 
| 693 |  | 
| 694 |     end.link(this); | 
| 695 | } | 
| 696 |  | 
| 697 | void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 698 | { | 
| 699 |     unsigned dst = currentInstruction[1].u.operand; | 
| 700 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 701 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 702 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 703 |  | 
| 704 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) | 
| 705 |         return; | 
| 706 |  | 
| 707 |     unsigned op; | 
| 708 |     int32_t constant; | 
| 709 |     if (getOperandConstantImmediateInt(op1, op2, op, constant)) { | 
| 710 |         linkSlowCase(iter); // overflow check | 
| 711 |  | 
| 712 |         if (!supportsFloatingPoint()) | 
| 713 |             linkSlowCase(iter); // non-sse case | 
| 714 |         else { | 
| 715 |             ResultType opType = op == op1 ? types.first() : types.second(); | 
| 716 |             if (!opType.definitelyIsNumber()) | 
| 717 |                 linkSlowCase(iter); // double check | 
| 718 |         } | 
| 719 |     } else { | 
| 720 |         linkSlowCase(iter); // overflow check | 
| 721 |  | 
| 722 |         if (!supportsFloatingPoint()) { | 
| 723 |             linkSlowCase(iter); // int32 check | 
| 724 |             linkSlowCase(iter); // int32 check | 
| 725 |         } else { | 
| 726 |             if (!types.first().definitelyIsNumber()) | 
| 727 |                 linkSlowCase(iter); // double check | 
| 728 |  | 
| 729 |             if (!types.second().definitelyIsNumber()) { | 
| 730 |                 linkSlowCase(iter); // int32 check | 
| 731 |                 linkSlowCase(iter); // double check | 
| 732 |             } | 
| 733 |         } | 
| 734 |     } | 
| 735 |  | 
| 736 |     JITStubCall stubCall(this, cti_op_add); | 
| 737 |     stubCall.addArgument(op1); | 
| 738 |     stubCall.addArgument(op2); | 
| 739 |     stubCall.call(dst); | 
| 740 | } | 
| 741 |  | 
| 742 | // Subtraction (-) | 
| 743 |  | 
| 744 | void JIT::emit_op_sub(Instruction* currentInstruction) | 
| 745 | { | 
| 746 |     unsigned dst = currentInstruction[1].u.operand; | 
| 747 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 748 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 749 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 750 |  | 
| 751 |     JumpList notInt32Op1; | 
| 752 |     JumpList notInt32Op2; | 
| 753 |  | 
| 754 |     if (isOperandConstantImmediateInt(op2)) { | 
| 755 |         emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first()); | 
| 756 |         return; | 
| 757 |     } | 
| 758 |  | 
| 759 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 760 |     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 761 |     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 762 |  | 
| 763 |     // Int32 case. | 
| 764 |     addSlowCase(branchSub32(Overflow, regT2, regT0)); | 
| 765 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 766 |  | 
| 767 |     if (!supportsFloatingPoint()) { | 
| 768 |         addSlowCase(notInt32Op1); | 
| 769 |         addSlowCase(notInt32Op2); | 
| 770 |         return; | 
| 771 |     } | 
| 772 |     Jump end = jump(); | 
| 773 |  | 
| 774 |     // Double case. | 
| 775 |     emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2); | 
| 776 |     end.link(this); | 
| 777 | } | 
| 778 |  | 
| 779 | void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) | 
| 780 | { | 
| 781 |     // Int32 case. | 
| 782 |     emitLoad(op, regT1, regT0); | 
| 783 |     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); | 
| 784 |     addSlowCase(branchSub32(Overflow, Imm32(constant), regT0)); | 
| 785 |     emitStoreInt32(dst, regT0, (op == dst)); | 
| 786 |  | 
| 787 |     // Double case. | 
| 788 |     if (!supportsFloatingPoint()) { | 
| 789 |         addSlowCase(notInt32); | 
| 790 |         return; | 
| 791 |     } | 
| 792 |     Jump end = jump(); | 
| 793 |  | 
| 794 |     notInt32.link(this); | 
| 795 |     if (!opType.definitelyIsNumber()) | 
| 796 |         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); | 
| 797 |     move(Imm32(constant), regT2); | 
| 798 |     convertInt32ToDouble(regT2, fpRegT0); | 
| 799 |     emitLoadDouble(op, fpRegT1); | 
| 800 |     subDouble(fpRegT0, fpRegT1); | 
| 801 |     emitStoreDouble(dst, fpRegT1); | 
| 802 |  | 
| 803 |     end.link(this); | 
| 804 | } | 
| 805 |  | 
| 806 | void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 807 | { | 
| 808 |     unsigned dst = currentInstruction[1].u.operand; | 
| 809 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 810 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 811 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 812 |  | 
| 813 |     if (isOperandConstantImmediateInt(op2)) { | 
| 814 |         linkSlowCase(iter); // overflow check | 
| 815 |  | 
| 816 |         if (!supportsFloatingPoint() || !types.first().definitelyIsNumber()) | 
| 817 |             linkSlowCase(iter); // int32 or double check | 
| 818 |     } else { | 
| 819 |         linkSlowCase(iter); // overflow check | 
| 820 |  | 
| 821 |         if (!supportsFloatingPoint()) { | 
| 822 |             linkSlowCase(iter); // int32 check | 
| 823 |             linkSlowCase(iter); // int32 check | 
| 824 |         } else { | 
| 825 |             if (!types.first().definitelyIsNumber()) | 
| 826 |                 linkSlowCase(iter); // double check | 
| 827 |  | 
| 828 |             if (!types.second().definitelyIsNumber()) { | 
| 829 |                 linkSlowCase(iter); // int32 check | 
| 830 |                 linkSlowCase(iter); // double check | 
| 831 |             } | 
| 832 |         } | 
| 833 |     } | 
| 834 |  | 
| 835 |     JITStubCall stubCall(this, cti_op_sub); | 
| 836 |     stubCall.addArgument(op1); | 
| 837 |     stubCall.addArgument(op2); | 
| 838 |     stubCall.call(dst); | 
| 839 | } | 
| 840 |  | 
| 841 | void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters) | 
| 842 | { | 
| 843 |     JumpList end; | 
| 844 |      | 
| 845 |     if (!notInt32Op1.empty()) { | 
| 846 |         // Double case 1: Op1 is not int32; Op2 is unknown. | 
| 847 |         notInt32Op1.link(this); | 
| 848 |  | 
| 849 |         ASSERT(op1IsInRegisters); | 
| 850 |  | 
| 851 |         // Verify Op1 is double. | 
| 852 |         if (!types.first().definitelyIsNumber()) | 
| 853 |             addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); | 
| 854 |  | 
| 855 |         if (!op2IsInRegisters) | 
| 856 |             emitLoad(op2, regT3, regT2); | 
| 857 |  | 
| 858 |         Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag)); | 
| 859 |  | 
| 860 |         if (!types.second().definitelyIsNumber()) | 
| 861 |             addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 862 |  | 
| 863 |         convertInt32ToDouble(regT2, fpRegT0); | 
| 864 |         Jump doTheMath = jump(); | 
| 865 |  | 
| 866 |         // Load Op2 as double into double register. | 
| 867 |         doubleOp2.link(this); | 
| 868 |         emitLoadDouble(op2, fpRegT0); | 
| 869 |  | 
| 870 |         // Do the math. | 
| 871 |         doTheMath.link(this); | 
| 872 |         switch (opcodeID) { | 
| 873 |             case op_mul: | 
| 874 |                 emitLoadDouble(op1, fpRegT2); | 
| 875 |                 mulDouble(fpRegT2, fpRegT0); | 
| 876 |                 emitStoreDouble(dst, fpRegT0); | 
| 877 |                 break; | 
| 878 |             case op_add: | 
| 879 |                 emitLoadDouble(op1, fpRegT2); | 
| 880 |                 addDouble(fpRegT2, fpRegT0); | 
| 881 |                 emitStoreDouble(dst, fpRegT0); | 
| 882 |                 break; | 
| 883 |             case op_sub: | 
| 884 |                 emitLoadDouble(op1, fpRegT1); | 
| 885 |                 subDouble(fpRegT0, fpRegT1); | 
| 886 |                 emitStoreDouble(dst, fpRegT1); | 
| 887 |                 break; | 
| 888 |             case op_div: | 
| 889 |                 emitLoadDouble(op1, fpRegT1); | 
| 890 |                 divDouble(fpRegT0, fpRegT1); | 
| 891 |                 emitStoreDouble(dst, fpRegT1); | 
| 892 |                 break; | 
| 893 |             case op_jnless: | 
| 894 |                 emitLoadDouble(op1, fpRegT2); | 
| 895 |                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); | 
| 896 |                 break; | 
| 897 |             case op_jless: | 
| 898 |                 emitLoadDouble(op1, fpRegT2); | 
| 899 |                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); | 
| 900 |                 break; | 
| 901 |             case op_jnlesseq: | 
| 902 |                 emitLoadDouble(op1, fpRegT2); | 
| 903 |                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst); | 
| 904 |                 break; | 
| 905 |             default: | 
| 906 |                 ASSERT_NOT_REACHED(); | 
| 907 |         } | 
| 908 |  | 
| 909 |         if (!notInt32Op2.empty()) | 
| 910 |             end.append(jump()); | 
| 911 |     } | 
| 912 |  | 
| 913 |     if (!notInt32Op2.empty()) { | 
| 914 |         // Double case 2: Op1 is int32; Op2 is not int32. | 
| 915 |         notInt32Op2.link(this); | 
| 916 |  | 
| 917 |         ASSERT(op2IsInRegisters); | 
| 918 |  | 
| 919 |         if (!op1IsInRegisters) | 
| 920 |             emitLoadPayload(op1, regT0); | 
| 921 |  | 
| 922 |         convertInt32ToDouble(regT0, fpRegT0); | 
| 923 |  | 
| 924 |         // Verify op2 is double. | 
| 925 |         if (!types.second().definitelyIsNumber()) | 
| 926 |             addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag))); | 
| 927 |  | 
| 928 |         // Do the math. | 
| 929 |         switch (opcodeID) { | 
| 930 |             case op_mul: | 
| 931 |                 emitLoadDouble(op2, fpRegT2); | 
| 932 |                 mulDouble(fpRegT2, fpRegT0); | 
| 933 |                 emitStoreDouble(dst, fpRegT0); | 
| 934 |                 break; | 
| 935 |             case op_add: | 
| 936 |                 emitLoadDouble(op2, fpRegT2); | 
| 937 |                 addDouble(fpRegT2, fpRegT0); | 
| 938 |                 emitStoreDouble(dst, fpRegT0); | 
| 939 |                 break; | 
| 940 |             case op_sub: | 
| 941 |                 emitLoadDouble(op2, fpRegT2); | 
| 942 |                 subDouble(fpRegT2, fpRegT0); | 
| 943 |                 emitStoreDouble(dst, fpRegT0); | 
| 944 |                 break; | 
| 945 |             case op_div: | 
| 946 |                 emitLoadDouble(op2, fpRegT2); | 
| 947 |                 divDouble(fpRegT2, fpRegT0); | 
| 948 |                 emitStoreDouble(dst, fpRegT0); | 
| 949 |                 break; | 
| 950 |             case op_jnless: | 
| 951 |                 emitLoadDouble(op2, fpRegT1); | 
| 952 |                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); | 
| 953 |                 break; | 
| 954 |             case op_jless: | 
| 955 |                 emitLoadDouble(op2, fpRegT1); | 
| 956 |                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); | 
| 957 |                 break; | 
| 958 |             case op_jnlesseq: | 
| 959 |                 emitLoadDouble(op2, fpRegT1); | 
| 960 |                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); | 
| 961 |                 break; | 
| 962 |             default: | 
| 963 |                 ASSERT_NOT_REACHED(); | 
| 964 |         } | 
| 965 |     } | 
| 966 |  | 
| 967 |     end.link(this); | 
| 968 | } | 
| 969 |  | 
| 970 | // Multiplication (*) | 
| 971 |  | 
| 972 | void JIT::emit_op_mul(Instruction* currentInstruction) | 
| 973 | { | 
| 974 |     unsigned dst = currentInstruction[1].u.operand; | 
| 975 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 976 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 977 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 978 |  | 
| 979 |     JumpList notInt32Op1; | 
| 980 |     JumpList notInt32Op2; | 
| 981 |  | 
| 982 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 983 |     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 984 |     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 985 |  | 
| 986 |     // Int32 case. | 
| 987 |     move(regT0, regT3); | 
| 988 |     addSlowCase(branchMul32(Overflow, regT2, regT0)); | 
| 989 |     addSlowCase(branchTest32(Zero, regT0)); | 
| 990 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 991 |  | 
| 992 |     if (!supportsFloatingPoint()) { | 
| 993 |         addSlowCase(notInt32Op1); | 
| 994 |         addSlowCase(notInt32Op2); | 
| 995 |         return; | 
| 996 |     } | 
| 997 |     Jump end = jump(); | 
| 998 |  | 
| 999 |     // Double case. | 
| 1000 |     emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2); | 
| 1001 |     end.link(this); | 
| 1002 | } | 
| 1003 |  | 
| 1004 | void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1005 | { | 
| 1006 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1007 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1008 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1009 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 1010 |  | 
| 1011 |     Jump overflow = getSlowCase(iter); // overflow check | 
| 1012 |     linkSlowCase(iter); // zero result check | 
| 1013 |  | 
| 1014 |     Jump negZero = branchOr32(Signed, regT2, regT3); | 
| 1015 |     emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst)); | 
| 1016 |  | 
| 1017 |     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul)); | 
| 1018 |  | 
| 1019 |     negZero.link(this); | 
| 1020 |     overflow.link(this); | 
| 1021 |  | 
| 1022 |     if (!supportsFloatingPoint()) { | 
| 1023 |         linkSlowCase(iter); // int32 check | 
| 1024 |         linkSlowCase(iter); // int32 check | 
| 1025 |     } | 
| 1026 |  | 
| 1027 |     if (supportsFloatingPoint()) { | 
| 1028 |         if (!types.first().definitelyIsNumber()) | 
| 1029 |             linkSlowCase(iter); // double check | 
| 1030 |  | 
| 1031 |         if (!types.second().definitelyIsNumber()) { | 
| 1032 |             linkSlowCase(iter); // int32 check | 
| 1033 |             linkSlowCase(iter); // double check | 
| 1034 |         } | 
| 1035 |     } | 
| 1036 |  | 
| 1037 |     Label jitStubCall(this); | 
| 1038 |     JITStubCall stubCall(this, cti_op_mul); | 
| 1039 |     stubCall.addArgument(op1); | 
| 1040 |     stubCall.addArgument(op2); | 
| 1041 |     stubCall.call(dst); | 
| 1042 | } | 
| 1043 |  | 
| 1044 | // Division (/) | 
| 1045 |  | 
| 1046 | void JIT::emit_op_div(Instruction* currentInstruction) | 
| 1047 | { | 
| 1048 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1049 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1050 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1051 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 1052 |  | 
| 1053 |     if (!supportsFloatingPoint()) { | 
| 1054 |         addSlowCase(jump()); | 
| 1055 |         return; | 
| 1056 |     } | 
| 1057 |  | 
| 1058 |     // Int32 divide. | 
| 1059 |     JumpList notInt32Op1; | 
| 1060 |     JumpList notInt32Op2; | 
| 1061 |  | 
| 1062 |     JumpList end; | 
| 1063 |  | 
| 1064 |     emitLoad2(op1, regT1, regT0, op2, regT3, regT2); | 
| 1065 |  | 
| 1066 |     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); | 
| 1067 |     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); | 
| 1068 |  | 
| 1069 |     convertInt32ToDouble(regT0, fpRegT0); | 
| 1070 |     convertInt32ToDouble(regT2, fpRegT1); | 
| 1071 |     divDouble(fpRegT1, fpRegT0); | 
| 1072 |  | 
| 1073 |     JumpList doubleResult; | 
| 1074 |     branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1); | 
| 1075 |  | 
| 1076 |     // Int32 result. | 
| 1077 |     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); | 
| 1078 |     end.append(jump()); | 
| 1079 |  | 
| 1080 |     // Double result. | 
| 1081 |     doubleResult.link(this); | 
| 1082 |     emitStoreDouble(dst, fpRegT0); | 
| 1083 |     end.append(jump()); | 
| 1084 |  | 
| 1085 |     // Double divide. | 
| 1086 |     emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2); | 
| 1087 |     end.link(this); | 
| 1088 | } | 
| 1089 |  | 
| 1090 | void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1091 | { | 
| 1092 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1093 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1094 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1095 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 1096 |  | 
| 1097 |     if (!supportsFloatingPoint()) | 
| 1098 |         linkSlowCase(iter); | 
| 1099 |     else { | 
| 1100 |         if (!types.first().definitelyIsNumber()) | 
| 1101 |             linkSlowCase(iter); // double check | 
| 1102 |  | 
| 1103 |         if (!types.second().definitelyIsNumber()) { | 
| 1104 |             linkSlowCase(iter); // int32 check | 
| 1105 |             linkSlowCase(iter); // double check | 
| 1106 |         } | 
| 1107 |     } | 
| 1108 |  | 
| 1109 |     JITStubCall stubCall(this, cti_op_div); | 
| 1110 |     stubCall.addArgument(op1); | 
| 1111 |     stubCall.addArgument(op2); | 
| 1112 |     stubCall.call(dst); | 
| 1113 | } | 
| 1114 |  | 
| 1115 | // Mod (%) | 
| 1116 |  | 
| 1117 | /* ------------------------------ BEGIN: OP_MOD ------------------------------ */ | 
| 1118 |  | 
| 1119 | #if CPU(X86) || CPU(X86_64) | 
| 1120 |  | 
| 1121 | void JIT::emit_op_mod(Instruction* currentInstruction) | 
| 1122 | { | 
| 1123 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1124 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1125 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1126 |  | 
| 1127 |     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { | 
| 1128 |         emitLoad(op1, X86Registers::edx, X86Registers::eax); | 
| 1129 |         move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx); | 
| 1130 |         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); | 
| 1131 |         if (getConstantOperand(op2).asInt32() == -1) | 
| 1132 |             addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC | 
| 1133 |     } else { | 
| 1134 |         emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx); | 
| 1135 |         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); | 
| 1136 |         addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag))); | 
| 1137 |  | 
| 1138 |         addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC | 
| 1139 |         addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0 | 
| 1140 |     } | 
| 1141 |  | 
| 1142 |     move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0. | 
| 1143 |     m_assembler.cdq(); | 
| 1144 |     m_assembler.idivl_r(X86Registers::ecx); | 
| 1145 |      | 
| 1146 |     // If the remainder is zero and the dividend is negative, the result is -0. | 
| 1147 |     Jump storeResult1 = branchTest32(NonZero, X86Registers::edx); | 
| 1148 |     Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative | 
| 1149 |     emitStore(dst, jsNumber(m_globalData, -0.0)); | 
| 1150 |     Jump end = jump(); | 
| 1151 |  | 
| 1152 |     storeResult1.link(this); | 
| 1153 |     storeResult2.link(this); | 
| 1154 |     emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst)); | 
| 1155 |     end.link(this); | 
| 1156 | } | 
| 1157 |  | 
| 1158 | void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1159 | { | 
| 1160 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1161 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1162 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1163 |  | 
| 1164 |     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { | 
| 1165 |         linkSlowCase(iter); // int32 check | 
| 1166 |         if (getConstantOperand(op2).asInt32() == -1) | 
| 1167 |             linkSlowCase(iter); // 0x80000000 check | 
| 1168 |     } else { | 
| 1169 |         linkSlowCase(iter); // int32 check | 
| 1170 |         linkSlowCase(iter); // int32 check | 
| 1171 |         linkSlowCase(iter); // 0 check | 
| 1172 |         linkSlowCase(iter); // 0x80000000 check | 
| 1173 |     } | 
| 1174 |  | 
| 1175 |     JITStubCall stubCall(this, cti_op_mod); | 
| 1176 |     stubCall.addArgument(op1); | 
| 1177 |     stubCall.addArgument(op2); | 
| 1178 |     stubCall.call(dst); | 
| 1179 | } | 
| 1180 |  | 
| 1181 | #else // CPU(X86) || CPU(X86_64) | 
| 1182 |  | 
| 1183 | void JIT::emit_op_mod(Instruction* currentInstruction) | 
| 1184 | { | 
| 1185 |     unsigned dst = currentInstruction[1].u.operand; | 
| 1186 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1187 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1188 |  | 
| 1189 |     JITStubCall stubCall(this, cti_op_mod); | 
| 1190 |     stubCall.addArgument(op1); | 
| 1191 |     stubCall.addArgument(op2); | 
| 1192 |     stubCall.call(dst); | 
| 1193 | } | 
| 1194 |  | 
| 1195 | void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) | 
| 1196 | { | 
| 1197 | } | 
| 1198 |  | 
| 1199 | #endif // CPU(X86) || CPU(X86_64) | 
| 1200 |  | 
| 1201 | /* ------------------------------ END: OP_MOD ------------------------------ */ | 
| 1202 |  | 
| 1203 | #else // USE(JSVALUE32_64) | 
| 1204 |  | 
| 1205 | void JIT::emit_op_lshift(Instruction* currentInstruction) | 
| 1206 | { | 
| 1207 |     unsigned result = currentInstruction[1].u.operand; | 
| 1208 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1209 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1210 |  | 
| 1211 |     emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT2); | 
| 1212 |     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent. | 
| 1213 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1214 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT2); | 
| 1215 |     emitFastArithImmToInt(reg: regT0); | 
| 1216 |     emitFastArithImmToInt(reg: regT2); | 
| 1217 |     lshift32(shift_amount: regT2, dest: regT0); | 
| 1218 | #if USE(JSVALUE32) | 
| 1219 |     addSlowCase(branchAdd32(Overflow, regT0, regT0)); | 
| 1220 |     signExtend32ToPtr(regT0, regT0); | 
| 1221 | #endif | 
| 1222 |     emitFastArithReTagImmediate(src: regT0, dest: regT0); | 
| 1223 |     emitPutVirtualRegister(dst: result); | 
| 1224 | } | 
| 1225 |  | 
| 1226 | void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1227 | { | 
| 1228 |     unsigned result = currentInstruction[1].u.operand; | 
| 1229 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1230 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1231 |  | 
| 1232 | #if USE(JSVALUE64) | 
| 1233 |     UNUSED_PARAM(op1); | 
| 1234 |     UNUSED_PARAM(op2); | 
| 1235 |     linkSlowCase(iter); | 
| 1236 |     linkSlowCase(iter); | 
| 1237 | #else | 
| 1238 |     // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded. | 
| 1239 |     Jump notImm1 = getSlowCase(iter); | 
| 1240 |     Jump notImm2 = getSlowCase(iter); | 
| 1241 |     linkSlowCase(iter); | 
| 1242 |     emitGetVirtualRegisters(op1, regT0, op2, regT2); | 
| 1243 |     notImm1.link(this); | 
| 1244 |     notImm2.link(this); | 
| 1245 | #endif | 
| 1246 |     JITStubCall stubCall(this, cti_op_lshift); | 
| 1247 |     stubCall.addArgument(argument: regT0); | 
| 1248 |     stubCall.addArgument(argument: regT2); | 
| 1249 |     stubCall.call(dst: result); | 
| 1250 | } | 
| 1251 |  | 
| 1252 | void JIT::emit_op_rshift(Instruction* currentInstruction) | 
| 1253 | { | 
| 1254 |     unsigned result = currentInstruction[1].u.operand; | 
| 1255 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1256 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1257 |  | 
| 1258 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1259 |         // isOperandConstantImmediateInt(op2) => 1 SlowCase | 
| 1260 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 1261 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1262 |         // Mask with 0x1f as per ecma-262 11.7.2 step 7. | 
| 1263 |         rshift32(imm: Imm32(getConstantOperandImmediateInt(src: op2) & 0x1f), dest: regT0); | 
| 1264 |     } else { | 
| 1265 |         emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT2); | 
| 1266 |         if (supportsFloatingPointTruncate()) { | 
| 1267 |             Jump lhsIsInt = emitJumpIfImmediateInteger(reg: regT0); | 
| 1268 | #if USE(JSVALUE64) | 
| 1269 |             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases | 
| 1270 |             addSlowCase(jump: emitJumpIfNotImmediateNumber(reg: regT0)); | 
| 1271 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1272 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1273 |             addSlowCase(jump: branchTruncateDoubleToInt32(src: fpRegT0, dest: regT0)); | 
| 1274 | #else | 
| 1275 |             // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell) | 
| 1276 |             emitJumpSlowCaseIfNotJSCell(regT0, op1); | 
| 1277 |             addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get())); | 
| 1278 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1279 |             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0)); | 
| 1280 |             addSlowCase(branchAdd32(Overflow, regT0, regT0)); | 
| 1281 | #endif | 
| 1282 |             lhsIsInt.link(masm: this); | 
| 1283 |             emitJumpSlowCaseIfNotImmediateInteger(reg: regT2); | 
| 1284 |         } else { | 
| 1285 |             // !supportsFloatingPoint() => 2 SlowCases | 
| 1286 |             emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1287 |             emitJumpSlowCaseIfNotImmediateInteger(reg: regT2); | 
| 1288 |         } | 
| 1289 |         emitFastArithImmToInt(reg: regT2); | 
| 1290 |         rshift32(shift_amount: regT2, dest: regT0); | 
| 1291 | #if USE(JSVALUE32) | 
| 1292 |         signExtend32ToPtr(regT0, regT0); | 
| 1293 | #endif | 
| 1294 |     } | 
| 1295 | #if USE(JSVALUE64) | 
| 1296 |     emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 1297 | #else | 
| 1298 |     orPtr(Imm32(JSImmediate::TagTypeNumber), regT0); | 
| 1299 | #endif | 
| 1300 |     emitPutVirtualRegister(dst: result); | 
| 1301 | } | 
| 1302 |  | 
| 1303 | void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1304 | { | 
| 1305 |     unsigned result = currentInstruction[1].u.operand; | 
| 1306 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1307 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1308 |  | 
| 1309 |     JITStubCall stubCall(this, cti_op_rshift); | 
| 1310 |  | 
| 1311 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1312 |         linkSlowCase(iter); | 
| 1313 |         stubCall.addArgument(argument: regT0); | 
| 1314 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 1315 |     } else { | 
| 1316 |         if (supportsFloatingPointTruncate()) { | 
| 1317 | #if USE(JSVALUE64) | 
| 1318 |             linkSlowCase(iter); | 
| 1319 |             linkSlowCase(iter); | 
| 1320 |             linkSlowCase(iter); | 
| 1321 | #else | 
| 1322 |             linkSlowCaseIfNotJSCell(iter, op1); | 
| 1323 |             linkSlowCase(iter); | 
| 1324 |             linkSlowCase(iter); | 
| 1325 |             linkSlowCase(iter); | 
| 1326 |             linkSlowCase(iter); | 
| 1327 | #endif | 
| 1328 |             // We're reloading op1 to regT0 as we can no longer guarantee that | 
| 1329 |             // we have not munged the operand.  It may have already been shifted | 
| 1330 |             // correctly, but it still will not have been tagged. | 
| 1331 |             stubCall.addArgument(src: op1, scratchRegister: regT0); | 
| 1332 |             stubCall.addArgument(argument: regT2); | 
| 1333 |         } else { | 
| 1334 |             linkSlowCase(iter); | 
| 1335 |             linkSlowCase(iter); | 
| 1336 |             stubCall.addArgument(argument: regT0); | 
| 1337 |             stubCall.addArgument(argument: regT2); | 
| 1338 |         } | 
| 1339 |     } | 
| 1340 |  | 
| 1341 |     stubCall.call(dst: result); | 
| 1342 | } | 
| 1343 |  | 
| 1344 | void JIT::emit_op_jnless(Instruction* currentInstruction) | 
| 1345 | { | 
| 1346 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1347 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1348 |     unsigned target = currentInstruction[3].u.operand; | 
| 1349 |  | 
| 1350 |     // We generate inline code for the following cases in the fast path: | 
| 1351 |     // - int immediate to constant int immediate | 
| 1352 |     // - constant int immediate to int immediate | 
| 1353 |     // - int immediate to int immediate | 
| 1354 |  | 
| 1355 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1356 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 1357 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1358 | #if USE(JSVALUE64) | 
| 1359 |         int32_t op2imm = getConstantOperandImmediateInt(src: op2); | 
| 1360 | #else | 
| 1361 |         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); | 
| 1362 | #endif | 
| 1363 |         addJump(jump: branch32(cond: GreaterThanOrEqual, left: regT0, right: Imm32(op2imm)), relativeOffset: target); | 
| 1364 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1365 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 1366 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1367 | #if USE(JSVALUE64) | 
| 1368 |         int32_t op1imm = getConstantOperandImmediateInt(src: op1); | 
| 1369 | #else | 
| 1370 |         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); | 
| 1371 | #endif | 
| 1372 |         addJump(jump: branch32(cond: LessThanOrEqual, left: regT1, right: Imm32(op1imm)), relativeOffset: target); | 
| 1373 |     } else { | 
| 1374 |         emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT1); | 
| 1375 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1376 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1377 |  | 
| 1378 |         addJump(jump: branch32(cond: GreaterThanOrEqual, left: regT0, right: regT1), relativeOffset: target); | 
| 1379 |     } | 
| 1380 | } | 
| 1381 |  | 
| 1382 | void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1383 | { | 
| 1384 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1385 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1386 |     unsigned target = currentInstruction[3].u.operand; | 
| 1387 |  | 
| 1388 |     // We generate inline code for the following cases in the slow path: | 
| 1389 |     // - floating-point number to constant int immediate | 
| 1390 |     // - constant int immediate to floating-point number | 
| 1391 |     // - floating-point number to floating-point number. | 
| 1392 |  | 
| 1393 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1394 |         linkSlowCase(iter); | 
| 1395 |  | 
| 1396 |         if (supportsFloatingPoint()) { | 
| 1397 | #if USE(JSVALUE64) | 
| 1398 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1399 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1400 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1401 | #else | 
| 1402 |             Jump fail1; | 
| 1403 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1404 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1405 |  | 
| 1406 |             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1407 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1408 | #endif | 
| 1409 |              | 
| 1410 |             int32_t op2imm = getConstantOperand(src: op2).asInt32();; | 
| 1411 |                      | 
| 1412 |             move(imm: Imm32(op2imm), dest: regT1); | 
| 1413 |             convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 1414 |  | 
| 1415 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrEqualOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1416 |  | 
| 1417 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1418 |  | 
| 1419 | #if USE(JSVALUE64) | 
| 1420 |             fail1.link(masm: this); | 
| 1421 | #else | 
| 1422 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1423 |                 fail1.link(this); | 
| 1424 |             fail2.link(this); | 
| 1425 | #endif | 
| 1426 |         } | 
| 1427 |  | 
| 1428 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1429 |         stubCall.addArgument(argument: regT0); | 
| 1430 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 1431 |         stubCall.call(); | 
| 1432 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1433 |  | 
| 1434 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1435 |         linkSlowCase(iter); | 
| 1436 |  | 
| 1437 |         if (supportsFloatingPoint()) { | 
| 1438 | #if USE(JSVALUE64) | 
| 1439 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1440 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1441 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1442 | #else | 
| 1443 |             Jump fail1; | 
| 1444 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1445 |                 fail1 = emitJumpIfNotJSCell(regT1); | 
| 1446 |              | 
| 1447 |             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1448 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1449 | #endif | 
| 1450 |              | 
| 1451 |             int32_t op1imm = getConstantOperand(src: op1).asInt32();; | 
| 1452 |                      | 
| 1453 |             move(imm: Imm32(op1imm), dest: regT0); | 
| 1454 |             convertInt32ToDouble(src: regT0, dest: fpRegT0); | 
| 1455 |  | 
| 1456 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrEqualOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1457 |  | 
| 1458 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1459 |  | 
| 1460 | #if USE(JSVALUE64) | 
| 1461 |             fail1.link(masm: this); | 
| 1462 | #else | 
| 1463 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1464 |                 fail1.link(this); | 
| 1465 |             fail2.link(this); | 
| 1466 | #endif | 
| 1467 |         } | 
| 1468 |  | 
| 1469 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1470 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 1471 |         stubCall.addArgument(argument: regT1); | 
| 1472 |         stubCall.call(); | 
| 1473 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1474 |  | 
| 1475 |     } else { | 
| 1476 |         linkSlowCase(iter); | 
| 1477 |  | 
| 1478 |         if (supportsFloatingPoint()) { | 
| 1479 | #if USE(JSVALUE64) | 
| 1480 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1481 |             Jump fail2 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1482 |             Jump fail3 = emitJumpIfImmediateInteger(reg: regT1); | 
| 1483 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1484 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1485 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1486 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1487 | #else | 
| 1488 |             Jump fail1; | 
| 1489 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1490 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1491 |  | 
| 1492 |             Jump fail2; | 
| 1493 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1494 |                 fail2 = emitJumpIfNotJSCell(regT1); | 
| 1495 |  | 
| 1496 |             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1497 |             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1498 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1499 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1500 | #endif | 
| 1501 |  | 
| 1502 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrEqualOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1503 |  | 
| 1504 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1505 |  | 
| 1506 | #if USE(JSVALUE64) | 
| 1507 |             fail1.link(masm: this); | 
| 1508 |             fail2.link(masm: this); | 
| 1509 |             fail3.link(masm: this); | 
| 1510 | #else | 
| 1511 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1512 |                 fail1.link(this); | 
| 1513 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1514 |                 fail2.link(this); | 
| 1515 |             fail3.link(this); | 
| 1516 |             fail4.link(this); | 
| 1517 | #endif | 
| 1518 |         } | 
| 1519 |  | 
| 1520 |         linkSlowCase(iter); | 
| 1521 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1522 |         stubCall.addArgument(argument: regT0); | 
| 1523 |         stubCall.addArgument(argument: regT1); | 
| 1524 |         stubCall.call(); | 
| 1525 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1526 |     } | 
| 1527 | } | 
| 1528 |  | 
| 1529 | void JIT::emit_op_jless(Instruction* currentInstruction) | 
| 1530 | { | 
| 1531 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1532 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1533 |     unsigned target = currentInstruction[3].u.operand; | 
| 1534 |  | 
| 1535 |     // We generate inline code for the following cases in the fast path: | 
| 1536 |     // - int immediate to constant int immediate | 
| 1537 |     // - constant int immediate to int immediate | 
| 1538 |     // - int immediate to int immediate | 
| 1539 |  | 
| 1540 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1541 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 1542 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1543 | #if USE(JSVALUE64) | 
| 1544 |         int32_t op2imm = getConstantOperandImmediateInt(src: op2); | 
| 1545 | #else | 
| 1546 |         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); | 
| 1547 | #endif | 
| 1548 |         addJump(jump: branch32(cond: LessThan, left: regT0, right: Imm32(op2imm)), relativeOffset: target); | 
| 1549 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1550 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 1551 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1552 | #if USE(JSVALUE64) | 
| 1553 |         int32_t op1imm = getConstantOperandImmediateInt(src: op1); | 
| 1554 | #else | 
| 1555 |         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); | 
| 1556 | #endif | 
| 1557 |         addJump(jump: branch32(cond: GreaterThan, left: regT1, right: Imm32(op1imm)), relativeOffset: target); | 
| 1558 |     } else { | 
| 1559 |         emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT1); | 
| 1560 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1561 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1562 |  | 
| 1563 |         addJump(jump: branch32(cond: LessThan, left: regT0, right: regT1), relativeOffset: target); | 
| 1564 |     } | 
| 1565 | } | 
| 1566 |  | 
| 1567 | void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1568 | { | 
| 1569 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1570 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1571 |     unsigned target = currentInstruction[3].u.operand; | 
| 1572 |  | 
| 1573 |     // We generate inline code for the following cases in the slow path: | 
| 1574 |     // - floating-point number to constant int immediate | 
| 1575 |     // - constant int immediate to floating-point number | 
| 1576 |     // - floating-point number to floating-point number. | 
| 1577 |  | 
| 1578 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1579 |         linkSlowCase(iter); | 
| 1580 |  | 
| 1581 |         if (supportsFloatingPoint()) { | 
| 1582 | #if USE(JSVALUE64) | 
| 1583 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1584 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1585 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1586 | #else | 
| 1587 |             Jump fail1; | 
| 1588 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1589 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1590 |  | 
| 1591 |             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1592 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1593 | #endif | 
| 1594 |              | 
| 1595 |             int32_t op2imm = getConstantOperand(src: op2).asInt32(); | 
| 1596 |                      | 
| 1597 |             move(imm: Imm32(op2imm), dest: regT1); | 
| 1598 |             convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 1599 |  | 
| 1600 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThan, left: fpRegT0, right: fpRegT1), relativeOffset: target); | 
| 1601 |  | 
| 1602 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1603 |  | 
| 1604 | #if USE(JSVALUE64) | 
| 1605 |             fail1.link(masm: this); | 
| 1606 | #else | 
| 1607 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1608 |                 fail1.link(this); | 
| 1609 |             fail2.link(this); | 
| 1610 | #endif | 
| 1611 |         } | 
| 1612 |  | 
| 1613 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1614 |         stubCall.addArgument(argument: regT0); | 
| 1615 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 1616 |         stubCall.call(); | 
| 1617 |         emitJumpSlowToHot(jump: branchTest32(cond: NonZero, reg: regT0), relativeOffset: target); | 
| 1618 |  | 
| 1619 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1620 |         linkSlowCase(iter); | 
| 1621 |  | 
| 1622 |         if (supportsFloatingPoint()) { | 
| 1623 | #if USE(JSVALUE64) | 
| 1624 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1625 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1626 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1627 | #else | 
| 1628 |             Jump fail1; | 
| 1629 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1630 |                 fail1 = emitJumpIfNotJSCell(regT1); | 
| 1631 |              | 
| 1632 |             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1633 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1634 | #endif | 
| 1635 |              | 
| 1636 |             int32_t op1imm = getConstantOperand(src: op1).asInt32(); | 
| 1637 |                      | 
| 1638 |             move(imm: Imm32(op1imm), dest: regT0); | 
| 1639 |             convertInt32ToDouble(src: regT0, dest: fpRegT0); | 
| 1640 |  | 
| 1641 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThan, left: fpRegT0, right: fpRegT1), relativeOffset: target); | 
| 1642 |  | 
| 1643 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1644 |  | 
| 1645 | #if USE(JSVALUE64) | 
| 1646 |             fail1.link(masm: this); | 
| 1647 | #else | 
| 1648 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1649 |                 fail1.link(this); | 
| 1650 |             fail2.link(this); | 
| 1651 | #endif | 
| 1652 |         } | 
| 1653 |  | 
| 1654 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1655 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 1656 |         stubCall.addArgument(argument: regT1); | 
| 1657 |         stubCall.call(); | 
| 1658 |         emitJumpSlowToHot(jump: branchTest32(cond: NonZero, reg: regT0), relativeOffset: target); | 
| 1659 |  | 
| 1660 |     } else { | 
| 1661 |         linkSlowCase(iter); | 
| 1662 |  | 
| 1663 |         if (supportsFloatingPoint()) { | 
| 1664 | #if USE(JSVALUE64) | 
| 1665 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1666 |             Jump fail2 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1667 |             Jump fail3 = emitJumpIfImmediateInteger(reg: regT1); | 
| 1668 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1669 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1670 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1671 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1672 | #else | 
| 1673 |             Jump fail1; | 
| 1674 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1675 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1676 |  | 
| 1677 |             Jump fail2; | 
| 1678 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1679 |                 fail2 = emitJumpIfNotJSCell(regT1); | 
| 1680 |  | 
| 1681 |             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1682 |             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1683 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1684 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1685 | #endif | 
| 1686 |  | 
| 1687 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThan, left: fpRegT0, right: fpRegT1), relativeOffset: target); | 
| 1688 |  | 
| 1689 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnless)); | 
| 1690 |  | 
| 1691 | #if USE(JSVALUE64) | 
| 1692 |             fail1.link(masm: this); | 
| 1693 |             fail2.link(masm: this); | 
| 1694 |             fail3.link(masm: this); | 
| 1695 | #else | 
| 1696 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1697 |                 fail1.link(this); | 
| 1698 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1699 |                 fail2.link(this); | 
| 1700 |             fail3.link(this); | 
| 1701 |             fail4.link(this); | 
| 1702 | #endif | 
| 1703 |         } | 
| 1704 |  | 
| 1705 |         linkSlowCase(iter); | 
| 1706 |         JITStubCall stubCall(this, cti_op_jless); | 
| 1707 |         stubCall.addArgument(argument: regT0); | 
| 1708 |         stubCall.addArgument(argument: regT1); | 
| 1709 |         stubCall.call(); | 
| 1710 |         emitJumpSlowToHot(jump: branchTest32(cond: NonZero, reg: regT0), relativeOffset: target); | 
| 1711 |     } | 
| 1712 | } | 
| 1713 |  | 
| 1714 | void JIT::emit_op_jnlesseq(Instruction* currentInstruction) | 
| 1715 | { | 
| 1716 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1717 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1718 |     unsigned target = currentInstruction[3].u.operand; | 
| 1719 |  | 
| 1720 |     // We generate inline code for the following cases in the fast path: | 
| 1721 |     // - int immediate to constant int immediate | 
| 1722 |     // - constant int immediate to int immediate | 
| 1723 |     // - int immediate to int immediate | 
| 1724 |  | 
| 1725 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1726 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 1727 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1728 | #if USE(JSVALUE64) | 
| 1729 |         int32_t op2imm = getConstantOperandImmediateInt(src: op2); | 
| 1730 | #else | 
| 1731 |         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); | 
| 1732 | #endif | 
| 1733 |         addJump(jump: branch32(cond: GreaterThan, left: regT0, right: Imm32(op2imm)), relativeOffset: target); | 
| 1734 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1735 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 1736 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1737 | #if USE(JSVALUE64) | 
| 1738 |         int32_t op1imm = getConstantOperandImmediateInt(src: op1); | 
| 1739 | #else | 
| 1740 |         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); | 
| 1741 | #endif | 
| 1742 |         addJump(jump: branch32(cond: LessThan, left: regT1, right: Imm32(op1imm)), relativeOffset: target); | 
| 1743 |     } else { | 
| 1744 |         emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT1); | 
| 1745 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1746 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 1747 |  | 
| 1748 |         addJump(jump: branch32(cond: GreaterThan, left: regT0, right: regT1), relativeOffset: target); | 
| 1749 |     } | 
| 1750 | } | 
| 1751 |  | 
| 1752 | void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1753 | { | 
| 1754 |     unsigned op1 = currentInstruction[1].u.operand; | 
| 1755 |     unsigned op2 = currentInstruction[2].u.operand; | 
| 1756 |     unsigned target = currentInstruction[3].u.operand; | 
| 1757 |  | 
| 1758 |     // We generate inline code for the following cases in the slow path: | 
| 1759 |     // - floating-point number to constant int immediate | 
| 1760 |     // - constant int immediate to floating-point number | 
| 1761 |     // - floating-point number to floating-point number. | 
| 1762 |  | 
| 1763 |     if (isOperandConstantImmediateInt(src: op2)) { | 
| 1764 |         linkSlowCase(iter); | 
| 1765 |  | 
| 1766 |         if (supportsFloatingPoint()) { | 
| 1767 | #if USE(JSVALUE64) | 
| 1768 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1769 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1770 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1771 | #else | 
| 1772 |             Jump fail1; | 
| 1773 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1774 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1775 |  | 
| 1776 |             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1777 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1778 | #endif | 
| 1779 |              | 
| 1780 |             int32_t op2imm = getConstantOperand(src: op2).asInt32();; | 
| 1781 |                      | 
| 1782 |             move(imm: Imm32(op2imm), dest: regT1); | 
| 1783 |             convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 1784 |  | 
| 1785 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1786 |  | 
| 1787 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnlesseq)); | 
| 1788 |  | 
| 1789 | #if USE(JSVALUE64) | 
| 1790 |             fail1.link(masm: this); | 
| 1791 | #else | 
| 1792 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1793 |                 fail1.link(this); | 
| 1794 |             fail2.link(this); | 
| 1795 | #endif | 
| 1796 |         } | 
| 1797 |  | 
| 1798 |         JITStubCall stubCall(this, cti_op_jlesseq); | 
| 1799 |         stubCall.addArgument(argument: regT0); | 
| 1800 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 1801 |         stubCall.call(); | 
| 1802 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1803 |  | 
| 1804 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 1805 |         linkSlowCase(iter); | 
| 1806 |  | 
| 1807 |         if (supportsFloatingPoint()) { | 
| 1808 | #if USE(JSVALUE64) | 
| 1809 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1810 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1811 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1812 | #else | 
| 1813 |             Jump fail1; | 
| 1814 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1815 |                 fail1 = emitJumpIfNotJSCell(regT1); | 
| 1816 |              | 
| 1817 |             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1818 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1819 | #endif | 
| 1820 |              | 
| 1821 |             int32_t op1imm = getConstantOperand(src: op1).asInt32();; | 
| 1822 |                      | 
| 1823 |             move(imm: Imm32(op1imm), dest: regT0); | 
| 1824 |             convertInt32ToDouble(src: regT0, dest: fpRegT0); | 
| 1825 |  | 
| 1826 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1827 |  | 
| 1828 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnlesseq)); | 
| 1829 |  | 
| 1830 | #if USE(JSVALUE64) | 
| 1831 |             fail1.link(masm: this); | 
| 1832 | #else | 
| 1833 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1834 |                 fail1.link(this); | 
| 1835 |             fail2.link(this); | 
| 1836 | #endif | 
| 1837 |         } | 
| 1838 |  | 
| 1839 |         JITStubCall stubCall(this, cti_op_jlesseq); | 
| 1840 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 1841 |         stubCall.addArgument(argument: regT1); | 
| 1842 |         stubCall.call(); | 
| 1843 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1844 |  | 
| 1845 |     } else { | 
| 1846 |         linkSlowCase(iter); | 
| 1847 |  | 
| 1848 |         if (supportsFloatingPoint()) { | 
| 1849 | #if USE(JSVALUE64) | 
| 1850 |             Jump fail1 = emitJumpIfNotImmediateNumber(reg: regT0); | 
| 1851 |             Jump fail2 = emitJumpIfNotImmediateNumber(reg: regT1); | 
| 1852 |             Jump fail3 = emitJumpIfImmediateInteger(reg: regT1); | 
| 1853 |             addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 1854 |             addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 1855 |             movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 1856 |             movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 1857 | #else | 
| 1858 |             Jump fail1; | 
| 1859 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1860 |                 fail1 = emitJumpIfNotJSCell(regT0); | 
| 1861 |  | 
| 1862 |             Jump fail2; | 
| 1863 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1864 |                 fail2 = emitJumpIfNotJSCell(regT1); | 
| 1865 |  | 
| 1866 |             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); | 
| 1867 |             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); | 
| 1868 |             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 1869 |             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 1870 | #endif | 
| 1871 |  | 
| 1872 |             emitJumpSlowToHot(jump: branchDouble(cond: DoubleLessThanOrUnordered, left: fpRegT1, right: fpRegT0), relativeOffset: target); | 
| 1873 |  | 
| 1874 |             emitJumpSlowToHot(jump: jump(), OPCODE_LENGTH(op_jnlesseq)); | 
| 1875 |  | 
| 1876 | #if USE(JSVALUE64) | 
| 1877 |             fail1.link(masm: this); | 
| 1878 |             fail2.link(masm: this); | 
| 1879 |             fail3.link(masm: this); | 
| 1880 | #else | 
| 1881 |             if (!m_codeBlock->isKnownNotImmediate(op1)) | 
| 1882 |                 fail1.link(this); | 
| 1883 |             if (!m_codeBlock->isKnownNotImmediate(op2)) | 
| 1884 |                 fail2.link(this); | 
| 1885 |             fail3.link(this); | 
| 1886 |             fail4.link(this); | 
| 1887 | #endif | 
| 1888 |         } | 
| 1889 |  | 
| 1890 |         linkSlowCase(iter); | 
| 1891 |         JITStubCall stubCall(this, cti_op_jlesseq); | 
| 1892 |         stubCall.addArgument(argument: regT0); | 
| 1893 |         stubCall.addArgument(argument: regT1); | 
| 1894 |         stubCall.call(); | 
| 1895 |         emitJumpSlowToHot(jump: branchTest32(cond: Zero, reg: regT0), relativeOffset: target); | 
| 1896 |     } | 
| 1897 | } | 
| 1898 |  | 
| 1899 | void JIT::emit_op_bitand(Instruction* currentInstruction) | 
| 1900 | { | 
| 1901 |     unsigned result = currentInstruction[1].u.operand; | 
| 1902 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1903 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1904 |  | 
| 1905 |     if (isOperandConstantImmediateInt(src: op1)) { | 
| 1906 |         emitGetVirtualRegister(src: op2, dst: regT0); | 
| 1907 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1908 | #if USE(JSVALUE64) | 
| 1909 |         int32_t imm = getConstantOperandImmediateInt(src: op1); | 
| 1910 |         andPtr(imm: Imm32(imm), srcDest: regT0); | 
| 1911 |         if (imm >= 0) | 
| 1912 |             emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 1913 | #else | 
| 1914 |         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0); | 
| 1915 | #endif | 
| 1916 |     } else if (isOperandConstantImmediateInt(src: op2)) { | 
| 1917 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 1918 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1919 | #if USE(JSVALUE64) | 
| 1920 |         int32_t imm = getConstantOperandImmediateInt(src: op2); | 
| 1921 |         andPtr(imm: Imm32(imm), srcDest: regT0); | 
| 1922 |         if (imm >= 0) | 
| 1923 |             emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 1924 | #else | 
| 1925 |         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0); | 
| 1926 | #endif | 
| 1927 |     } else { | 
| 1928 |         emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT1); | 
| 1929 |         andPtr(src: regT1, dest: regT0); | 
| 1930 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1931 |     } | 
| 1932 |     emitPutVirtualRegister(dst: result); | 
| 1933 | } | 
| 1934 |  | 
| 1935 | void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1936 | { | 
| 1937 |     unsigned result = currentInstruction[1].u.operand; | 
| 1938 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 1939 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 1940 |  | 
| 1941 |     linkSlowCase(iter); | 
| 1942 |     if (isOperandConstantImmediateInt(src: op1)) { | 
| 1943 |         JITStubCall stubCall(this, cti_op_bitand); | 
| 1944 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 1945 |         stubCall.addArgument(argument: regT0); | 
| 1946 |         stubCall.call(dst: result); | 
| 1947 |     } else if (isOperandConstantImmediateInt(src: op2)) { | 
| 1948 |         JITStubCall stubCall(this, cti_op_bitand); | 
| 1949 |         stubCall.addArgument(argument: regT0); | 
| 1950 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 1951 |         stubCall.call(dst: result); | 
| 1952 |     } else { | 
| 1953 |         JITStubCall stubCall(this, cti_op_bitand); | 
| 1954 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 1955 |         stubCall.addArgument(argument: regT1); | 
| 1956 |         stubCall.call(dst: result); | 
| 1957 |     } | 
| 1958 | } | 
| 1959 |  | 
| 1960 | void JIT::emit_op_post_inc(Instruction* currentInstruction) | 
| 1961 | { | 
| 1962 |     unsigned result = currentInstruction[1].u.operand; | 
| 1963 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 1964 |  | 
| 1965 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 1966 |     move(src: regT0, dest: regT1); | 
| 1967 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 1968 | #if USE(JSVALUE64) | 
| 1969 |     addSlowCase(jump: branchAdd32(cond: Overflow, imm: Imm32(1), dest: regT1)); | 
| 1970 |     emitFastArithIntToImmNoCheck(src: regT1, dest: regT1); | 
| 1971 | #else | 
| 1972 |     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); | 
| 1973 |     signExtend32ToPtr(regT1, regT1); | 
| 1974 | #endif | 
| 1975 |     emitPutVirtualRegister(dst: srcDst, from: regT1); | 
| 1976 |     emitPutVirtualRegister(dst: result); | 
| 1977 | } | 
| 1978 |  | 
| 1979 | void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 1980 | { | 
| 1981 |     unsigned result = currentInstruction[1].u.operand; | 
| 1982 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 1983 |  | 
| 1984 |     linkSlowCase(iter); | 
| 1985 |     linkSlowCase(iter); | 
| 1986 |     JITStubCall stubCall(this, cti_op_post_inc); | 
| 1987 |     stubCall.addArgument(argument: regT0); | 
| 1988 |     stubCall.addArgument(argument: Imm32(srcDst)); | 
| 1989 |     stubCall.call(dst: result); | 
| 1990 | } | 
| 1991 |  | 
| 1992 | void JIT::emit_op_post_dec(Instruction* currentInstruction) | 
| 1993 | { | 
| 1994 |     unsigned result = currentInstruction[1].u.operand; | 
| 1995 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 1996 |  | 
| 1997 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 1998 |     move(src: regT0, dest: regT1); | 
| 1999 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2000 | #if USE(JSVALUE64) | 
| 2001 |     addSlowCase(jump: branchSub32(cond: Zero, imm: Imm32(1), dest: regT1)); | 
| 2002 |     emitFastArithIntToImmNoCheck(src: regT1, dest: regT1); | 
| 2003 | #else | 
| 2004 |     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1)); | 
| 2005 |     signExtend32ToPtr(regT1, regT1); | 
| 2006 | #endif | 
| 2007 |     emitPutVirtualRegister(dst: srcDst, from: regT1); | 
| 2008 |     emitPutVirtualRegister(dst: result); | 
| 2009 | } | 
| 2010 |  | 
| 2011 | void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2012 | { | 
| 2013 |     unsigned result = currentInstruction[1].u.operand; | 
| 2014 |     unsigned srcDst = currentInstruction[2].u.operand; | 
| 2015 |  | 
| 2016 |     linkSlowCase(iter); | 
| 2017 |     linkSlowCase(iter); | 
| 2018 |     JITStubCall stubCall(this, cti_op_post_dec); | 
| 2019 |     stubCall.addArgument(argument: regT0); | 
| 2020 |     stubCall.addArgument(argument: Imm32(srcDst)); | 
| 2021 |     stubCall.call(dst: result); | 
| 2022 | } | 
| 2023 |  | 
| 2024 | void JIT::emit_op_pre_inc(Instruction* currentInstruction) | 
| 2025 | { | 
| 2026 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 2027 |  | 
| 2028 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 2029 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2030 | #if USE(JSVALUE64) | 
| 2031 |     addSlowCase(jump: branchAdd32(cond: Overflow, imm: Imm32(1), dest: regT0)); | 
| 2032 |     emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 2033 | #else | 
| 2034 |     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); | 
| 2035 |     signExtend32ToPtr(regT0, regT0); | 
| 2036 | #endif | 
| 2037 |     emitPutVirtualRegister(dst: srcDst); | 
| 2038 | } | 
| 2039 |  | 
| 2040 | void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2041 | { | 
| 2042 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 2043 |  | 
| 2044 |     Jump notImm = getSlowCase(iter); | 
| 2045 |     linkSlowCase(iter); | 
| 2046 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 2047 |     notImm.link(masm: this); | 
| 2048 |     JITStubCall stubCall(this, cti_op_pre_inc); | 
| 2049 |     stubCall.addArgument(argument: regT0); | 
| 2050 |     stubCall.call(dst: srcDst); | 
| 2051 | } | 
| 2052 |  | 
| 2053 | void JIT::emit_op_pre_dec(Instruction* currentInstruction) | 
| 2054 | { | 
| 2055 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 2056 |  | 
| 2057 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 2058 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2059 | #if USE(JSVALUE64) | 
| 2060 |     addSlowCase(jump: branchSub32(cond: Zero, imm: Imm32(1), dest: regT0)); | 
| 2061 |     emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 2062 | #else | 
| 2063 |     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0)); | 
| 2064 |     signExtend32ToPtr(regT0, regT0); | 
| 2065 | #endif | 
| 2066 |     emitPutVirtualRegister(dst: srcDst); | 
| 2067 | } | 
| 2068 |  | 
| 2069 | void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2070 | { | 
| 2071 |     unsigned srcDst = currentInstruction[1].u.operand; | 
| 2072 |  | 
| 2073 |     Jump notImm = getSlowCase(iter); | 
| 2074 |     linkSlowCase(iter); | 
| 2075 |     emitGetVirtualRegister(src: srcDst, dst: regT0); | 
| 2076 |     notImm.link(masm: this); | 
| 2077 |     JITStubCall stubCall(this, cti_op_pre_dec); | 
| 2078 |     stubCall.addArgument(argument: regT0); | 
| 2079 |     stubCall.call(dst: srcDst); | 
| 2080 | } | 
| 2081 |  | 
| 2082 | /* ------------------------------ BEGIN: OP_MOD ------------------------------ */ | 
| 2083 |  | 
| 2084 | #if CPU(X86) || CPU(X86_64) | 
| 2085 |  | 
| 2086 | void JIT::emit_op_mod(Instruction* currentInstruction) | 
| 2087 | { | 
| 2088 |     unsigned result = currentInstruction[1].u.operand; | 
| 2089 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2090 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2091 |  | 
| 2092 |     emitGetVirtualRegisters(src1: op1, dst1: X86Registers::eax, src2: op2, dst2: X86Registers::ecx); | 
| 2093 |     emitJumpSlowCaseIfNotImmediateInteger(reg: X86Registers::eax); | 
| 2094 |     emitJumpSlowCaseIfNotImmediateInteger(reg: X86Registers::ecx); | 
| 2095 | #if USE(JSVALUE64) | 
| 2096 |     addSlowCase(jump: branchPtr(cond: Equal, left: X86Registers::ecx, right: ImmPtr(JSValue::encode(value: jsNumber(globalData: m_globalData, i: 0))))); | 
| 2097 |     m_assembler.cdq(); | 
| 2098 |     m_assembler.idivl_r(dst: X86Registers::ecx); | 
| 2099 | #else | 
| 2100 |     emitFastArithDeTagImmediate(X86Registers::eax); | 
| 2101 |     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx)); | 
| 2102 |     m_assembler.cdq(); | 
| 2103 |     m_assembler.idivl_r(X86Registers::ecx); | 
| 2104 |     signExtend32ToPtr(X86Registers::edx, X86Registers::edx); | 
| 2105 | #endif | 
| 2106 |     emitFastArithReTagImmediate(src: X86Registers::edx, dest: X86Registers::eax); | 
| 2107 |     emitPutVirtualRegister(dst: result); | 
| 2108 | } | 
| 2109 |  | 
| 2110 | void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2111 | { | 
| 2112 |     unsigned result = currentInstruction[1].u.operand; | 
| 2113 |  | 
| 2114 | #if USE(JSVALUE64) | 
| 2115 |     linkSlowCase(iter); | 
| 2116 |     linkSlowCase(iter); | 
| 2117 |     linkSlowCase(iter); | 
| 2118 | #else | 
| 2119 |     Jump notImm1 = getSlowCase(iter); | 
| 2120 |     Jump notImm2 = getSlowCase(iter); | 
| 2121 |     linkSlowCase(iter); | 
| 2122 |     emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax); | 
| 2123 |     emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx); | 
| 2124 |     notImm1.link(this); | 
| 2125 |     notImm2.link(this); | 
| 2126 | #endif | 
| 2127 |     JITStubCall stubCall(this, cti_op_mod); | 
| 2128 |     stubCall.addArgument(argument: X86Registers::eax); | 
| 2129 |     stubCall.addArgument(argument: X86Registers::ecx); | 
| 2130 |     stubCall.call(dst: result); | 
| 2131 | } | 
| 2132 |  | 
| 2133 | #else // CPU(X86) || CPU(X86_64) | 
| 2134 |  | 
| 2135 | void JIT::emit_op_mod(Instruction* currentInstruction) | 
| 2136 | { | 
| 2137 |     unsigned result = currentInstruction[1].u.operand; | 
| 2138 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2139 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2140 |  | 
| 2141 |     JITStubCall stubCall(this, cti_op_mod); | 
| 2142 |     stubCall.addArgument(op1, regT2); | 
| 2143 |     stubCall.addArgument(op2, regT2); | 
| 2144 |     stubCall.call(result); | 
| 2145 | } | 
| 2146 |  | 
| 2147 | void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) | 
| 2148 | { | 
| 2149 |     ASSERT_NOT_REACHED(); | 
| 2150 | } | 
| 2151 |  | 
| 2152 | #endif // CPU(X86) || CPU(X86_64) | 
| 2153 |  | 
| 2154 | /* ------------------------------ END: OP_MOD ------------------------------ */ | 
| 2155 |  | 
| 2156 | #if USE(JSVALUE64) | 
| 2157 |  | 
| 2158 | /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */ | 
| 2159 |  | 
| 2160 | void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes) | 
| 2161 | { | 
| 2162 |     emitGetVirtualRegisters(src1: op1, dst1: regT0, src2: op2, dst2: regT1); | 
| 2163 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2164 |     emitJumpSlowCaseIfNotImmediateInteger(reg: regT1); | 
| 2165 |     if (opcodeID == op_add) | 
| 2166 |         addSlowCase(jump: branchAdd32(cond: Overflow, src: regT1, dest: regT0)); | 
| 2167 |     else if (opcodeID == op_sub) | 
| 2168 |         addSlowCase(jump: branchSub32(cond: Overflow, src: regT1, dest: regT0)); | 
| 2169 |     else { | 
| 2170 |         ASSERT(opcodeID == op_mul); | 
| 2171 |         addSlowCase(jump: branchMul32(cond: Overflow, src: regT1, dest: regT0)); | 
| 2172 |         addSlowCase(jump: branchTest32(cond: Zero, reg: regT0)); | 
| 2173 |     } | 
| 2174 |     emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 2175 | } | 
| 2176 |  | 
| 2177 | void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase) | 
| 2178 | { | 
| 2179 |     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset. | 
| 2180 |     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0); | 
| 2181 |      | 
| 2182 |     Jump notImm1; | 
| 2183 |     Jump notImm2; | 
| 2184 |     if (op1HasImmediateIntFastCase) { | 
| 2185 |         notImm2 = getSlowCase(iter); | 
| 2186 |     } else if (op2HasImmediateIntFastCase) { | 
| 2187 |         notImm1 = getSlowCase(iter); | 
| 2188 |     } else { | 
| 2189 |         notImm1 = getSlowCase(iter); | 
| 2190 |         notImm2 = getSlowCase(iter); | 
| 2191 |     } | 
| 2192 |  | 
| 2193 |     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare. | 
| 2194 |     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number. | 
| 2195 |         linkSlowCase(iter); | 
| 2196 |     emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2197 |  | 
| 2198 |     Label stubFunctionCall(this); | 
| 2199 |     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul); | 
| 2200 |     if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) { | 
| 2201 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2202 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 2203 |     } | 
| 2204 |     stubCall.addArgument(argument: regT0); | 
| 2205 |     stubCall.addArgument(argument: regT1); | 
| 2206 |     stubCall.call(dst: result); | 
| 2207 |     Jump end = jump(); | 
| 2208 |  | 
| 2209 |     if (op1HasImmediateIntFastCase) { | 
| 2210 |         notImm2.link(masm: this); | 
| 2211 |         if (!types.second().definitelyIsNumber()) | 
| 2212 |             emitJumpIfNotImmediateNumber(reg: regT0).linkTo(label: stubFunctionCall, masm: this); | 
| 2213 |         emitGetVirtualRegister(src: op1, dst: regT1); | 
| 2214 |         convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 2215 |         addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2216 |         movePtrToDouble(src: regT0, dest: fpRegT2); | 
| 2217 |     } else if (op2HasImmediateIntFastCase) { | 
| 2218 |         notImm1.link(masm: this); | 
| 2219 |         if (!types.first().definitelyIsNumber()) | 
| 2220 |             emitJumpIfNotImmediateNumber(reg: regT0).linkTo(label: stubFunctionCall, masm: this); | 
| 2221 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 2222 |         convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 2223 |         addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2224 |         movePtrToDouble(src: regT0, dest: fpRegT2); | 
| 2225 |     } else { | 
| 2226 |         // if we get here, eax is not an int32, edx not yet checked. | 
| 2227 |         notImm1.link(masm: this); | 
| 2228 |         if (!types.first().definitelyIsNumber()) | 
| 2229 |             emitJumpIfNotImmediateNumber(reg: regT0).linkTo(label: stubFunctionCall, masm: this); | 
| 2230 |         if (!types.second().definitelyIsNumber()) | 
| 2231 |             emitJumpIfNotImmediateNumber(reg: regT1).linkTo(label: stubFunctionCall, masm: this); | 
| 2232 |         addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2233 |         movePtrToDouble(src: regT0, dest: fpRegT1); | 
| 2234 |         Jump op2isDouble = emitJumpIfNotImmediateInteger(reg: regT1); | 
| 2235 |         convertInt32ToDouble(src: regT1, dest: fpRegT2); | 
| 2236 |         Jump op2wasInteger = jump(); | 
| 2237 |  | 
| 2238 |         // if we get here, eax IS an int32, edx is not. | 
| 2239 |         notImm2.link(masm: this); | 
| 2240 |         if (!types.second().definitelyIsNumber()) | 
| 2241 |             emitJumpIfNotImmediateNumber(reg: regT1).linkTo(label: stubFunctionCall, masm: this); | 
| 2242 |         convertInt32ToDouble(src: regT0, dest: fpRegT1); | 
| 2243 |         op2isDouble.link(masm: this); | 
| 2244 |         addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 2245 |         movePtrToDouble(src: regT1, dest: fpRegT2); | 
| 2246 |         op2wasInteger.link(masm: this); | 
| 2247 |     } | 
| 2248 |  | 
| 2249 |     if (opcodeID == op_add) | 
| 2250 |         addDouble(src: fpRegT2, dest: fpRegT1); | 
| 2251 |     else if (opcodeID == op_sub) | 
| 2252 |         subDouble(src: fpRegT2, dest: fpRegT1); | 
| 2253 |     else if (opcodeID == op_mul) | 
| 2254 |         mulDouble(src: fpRegT2, dest: fpRegT1); | 
| 2255 |     else { | 
| 2256 |         ASSERT(opcodeID == op_div); | 
| 2257 |         divDouble(src: fpRegT2, dest: fpRegT1); | 
| 2258 |     } | 
| 2259 |     moveDoubleToPtr(src: fpRegT1, dest: regT0); | 
| 2260 |     subPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2261 |     emitPutVirtualRegister(dst: result, from: regT0); | 
| 2262 |  | 
| 2263 |     end.link(masm: this); | 
| 2264 | } | 
| 2265 |  | 
| 2266 | void JIT::emit_op_add(Instruction* currentInstruction) | 
| 2267 | { | 
| 2268 |     unsigned result = currentInstruction[1].u.operand; | 
| 2269 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2270 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2271 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2272 |  | 
| 2273 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { | 
| 2274 |         JITStubCall stubCall(this, cti_op_add); | 
| 2275 |         stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 2276 |         stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 2277 |         stubCall.call(dst: result); | 
| 2278 |         return; | 
| 2279 |     } | 
| 2280 |  | 
| 2281 |     if (isOperandConstantImmediateInt(src: op1)) { | 
| 2282 |         emitGetVirtualRegister(src: op2, dst: regT0); | 
| 2283 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2284 |         addSlowCase(jump: branchAdd32(cond: Overflow, imm: Imm32(getConstantOperandImmediateInt(src: op1)), dest: regT0)); | 
| 2285 |         emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 2286 |     } else if (isOperandConstantImmediateInt(src: op2)) { | 
| 2287 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2288 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2289 |         addSlowCase(jump: branchAdd32(cond: Overflow, imm: Imm32(getConstantOperandImmediateInt(src: op2)), dest: regT0)); | 
| 2290 |         emitFastArithIntToImmNoCheck(src: regT0, dest: regT0); | 
| 2291 |     } else | 
| 2292 |         compileBinaryArithOp(opcodeID: op_add, result, op1, op2, types); | 
| 2293 |  | 
| 2294 |     emitPutVirtualRegister(dst: result); | 
| 2295 | } | 
| 2296 |  | 
| 2297 | void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2298 | { | 
| 2299 |     unsigned result = currentInstruction[1].u.operand; | 
| 2300 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2301 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2302 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2303 |  | 
| 2304 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) | 
| 2305 |         return; | 
| 2306 |  | 
| 2307 |     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(src: op1); | 
| 2308 |     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(src: op2); | 
| 2309 |     compileBinaryArithOpSlowCase(opcodeID: op_add, iter, result, op1, op2, types: OperandTypes::fromInt(value: currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase); | 
| 2310 | } | 
| 2311 |  | 
| 2312 | void JIT::emit_op_mul(Instruction* currentInstruction) | 
| 2313 | { | 
| 2314 |     unsigned result = currentInstruction[1].u.operand; | 
| 2315 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2316 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2317 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2318 |  | 
| 2319 |     // For now, only plant a fast int case if the constant operand is greater than zero. | 
| 2320 |     int32_t value; | 
| 2321 |     if (isOperandConstantImmediateInt(src: op1) && ((value = getConstantOperandImmediateInt(src: op1)) > 0)) { | 
| 2322 |         emitGetVirtualRegister(src: op2, dst: regT0); | 
| 2323 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2324 |         addSlowCase(jump: branchMul32(cond: Overflow, imm: Imm32(value), src: regT0, dest: regT0)); | 
| 2325 |         emitFastArithReTagImmediate(src: regT0, dest: regT0); | 
| 2326 |     } else if (isOperandConstantImmediateInt(src: op2) && ((value = getConstantOperandImmediateInt(src: op2)) > 0)) { | 
| 2327 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2328 |         emitJumpSlowCaseIfNotImmediateInteger(reg: regT0); | 
| 2329 |         addSlowCase(jump: branchMul32(cond: Overflow, imm: Imm32(value), src: regT0, dest: regT0)); | 
| 2330 |         emitFastArithReTagImmediate(src: regT0, dest: regT0); | 
| 2331 |     } else | 
| 2332 |         compileBinaryArithOp(opcodeID: op_mul, result, op1, op2, types); | 
| 2333 |  | 
| 2334 |     emitPutVirtualRegister(dst: result); | 
| 2335 | } | 
| 2336 |  | 
| 2337 | void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2338 | { | 
| 2339 |     unsigned result = currentInstruction[1].u.operand; | 
| 2340 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2341 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2342 |  | 
| 2343 |     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(src: op1) && getConstantOperandImmediateInt(src: op1) > 0; | 
| 2344 |     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(src: op2) && getConstantOperandImmediateInt(src: op2) > 0; | 
| 2345 |     compileBinaryArithOpSlowCase(opcodeID: op_mul, iter, result, op1, op2, types: OperandTypes::fromInt(value: currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase); | 
| 2346 | } | 
| 2347 |  | 
| 2348 | void JIT::emit_op_div(Instruction* currentInstruction) | 
| 2349 | { | 
| 2350 |     unsigned dst = currentInstruction[1].u.operand; | 
| 2351 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2352 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2353 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2354 |  | 
| 2355 |     if (isOperandConstantImmediateDouble(src: op1)) { | 
| 2356 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2357 |         addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2358 |         movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 2359 |     } else if (isOperandConstantImmediateInt(src: op1)) { | 
| 2360 |         emitLoadInt32ToDouble(index: op1, value: fpRegT0); | 
| 2361 |     } else { | 
| 2362 |         emitGetVirtualRegister(src: op1, dst: regT0); | 
| 2363 |         if (!types.first().definitelyIsNumber()) | 
| 2364 |             emitJumpSlowCaseIfNotImmediateNumber(reg: regT0); | 
| 2365 |         Jump notInt = emitJumpIfNotImmediateInteger(reg: regT0); | 
| 2366 |         convertInt32ToDouble(src: regT0, dest: fpRegT0); | 
| 2367 |         Jump skipDoubleLoad = jump(); | 
| 2368 |         notInt.link(masm: this); | 
| 2369 |         addPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2370 |         movePtrToDouble(src: regT0, dest: fpRegT0); | 
| 2371 |         skipDoubleLoad.link(masm: this); | 
| 2372 |     } | 
| 2373 |      | 
| 2374 |     if (isOperandConstantImmediateDouble(src: op2)) { | 
| 2375 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 2376 |         addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 2377 |         movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 2378 |     } else if (isOperandConstantImmediateInt(src: op2)) { | 
| 2379 |         emitLoadInt32ToDouble(index: op2, value: fpRegT1); | 
| 2380 |     } else { | 
| 2381 |         emitGetVirtualRegister(src: op2, dst: regT1); | 
| 2382 |         if (!types.second().definitelyIsNumber()) | 
| 2383 |             emitJumpSlowCaseIfNotImmediateNumber(reg: regT1); | 
| 2384 |         Jump notInt = emitJumpIfNotImmediateInteger(reg: regT1); | 
| 2385 |         convertInt32ToDouble(src: regT1, dest: fpRegT1); | 
| 2386 |         Jump skipDoubleLoad = jump(); | 
| 2387 |         notInt.link(masm: this); | 
| 2388 |         addPtr(src: tagTypeNumberRegister, dest: regT1); | 
| 2389 |         movePtrToDouble(src: regT1, dest: fpRegT1); | 
| 2390 |         skipDoubleLoad.link(masm: this); | 
| 2391 |     } | 
| 2392 |     divDouble(src: fpRegT1, dest: fpRegT0); | 
| 2393 |  | 
| 2394 |     // Double result. | 
| 2395 |     moveDoubleToPtr(src: fpRegT0, dest: regT0); | 
| 2396 |     subPtr(src: tagTypeNumberRegister, dest: regT0); | 
| 2397 |  | 
| 2398 |     emitPutVirtualRegister(dst, from: regT0); | 
| 2399 | } | 
| 2400 |  | 
| 2401 | void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2402 | { | 
| 2403 |     unsigned result = currentInstruction[1].u.operand; | 
| 2404 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2405 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2406 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2407 |     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) { | 
| 2408 | #ifndef NDEBUG | 
| 2409 |         breakpoint(); | 
| 2410 | #endif | 
| 2411 |         return; | 
| 2412 |     } | 
| 2413 |     if (!isOperandConstantImmediateDouble(src: op1) && !isOperandConstantImmediateInt(src: op1)) { | 
| 2414 |         if (!types.first().definitelyIsNumber()) | 
| 2415 |             linkSlowCase(iter); | 
| 2416 |     } | 
| 2417 |     if (!isOperandConstantImmediateDouble(src: op2) && !isOperandConstantImmediateInt(src: op2)) { | 
| 2418 |         if (!types.second().definitelyIsNumber()) | 
| 2419 |             linkSlowCase(iter); | 
| 2420 |     } | 
| 2421 |     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. | 
| 2422 |     JITStubCall stubCall(this, cti_op_div); | 
| 2423 |     stubCall.addArgument(src: op1, scratchRegister: regT2); | 
| 2424 |     stubCall.addArgument(src: op2, scratchRegister: regT2); | 
| 2425 |     stubCall.call(dst: result); | 
| 2426 | } | 
| 2427 |  | 
| 2428 | void JIT::emit_op_sub(Instruction* currentInstruction) | 
| 2429 | { | 
| 2430 |     unsigned result = currentInstruction[1].u.operand; | 
| 2431 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2432 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2433 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2434 |  | 
| 2435 |     compileBinaryArithOp(opcodeID: op_sub, result, op1, op2, types); | 
| 2436 |     emitPutVirtualRegister(dst: result); | 
| 2437 | } | 
| 2438 |  | 
| 2439 | void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2440 | { | 
| 2441 |     unsigned result = currentInstruction[1].u.operand; | 
| 2442 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2443 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2444 |     OperandTypes types = OperandTypes::fromInt(value: currentInstruction[4].u.operand); | 
| 2445 |  | 
| 2446 |     compileBinaryArithOpSlowCase(opcodeID: op_sub, iter, result, op1, op2, types, op1HasImmediateIntFastCase: false, op2HasImmediateIntFastCase: false); | 
| 2447 | } | 
| 2448 |  | 
| 2449 | #else // USE(JSVALUE64) | 
| 2450 |  | 
| 2451 | /* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */ | 
| 2452 |  | 
| 2453 | void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) | 
| 2454 | { | 
| 2455 |     Structure* numberStructure = m_globalData->numberStructure.get(); | 
| 2456 |     Jump wasJSNumberCell1; | 
| 2457 |     Jump wasJSNumberCell2; | 
| 2458 |  | 
| 2459 |     emitGetVirtualRegisters(src1, regT0, src2, regT1); | 
| 2460 |  | 
| 2461 |     if (types.second().isReusable() && supportsFloatingPoint()) { | 
| 2462 |         ASSERT(types.second().mightBeNumber()); | 
| 2463 |  | 
| 2464 |         // Check op2 is a number | 
| 2465 |         Jump op2imm = emitJumpIfImmediateInteger(regT1); | 
| 2466 |         if (!types.second().definitelyIsNumber()) { | 
| 2467 |             emitJumpSlowCaseIfNotJSCell(regT1, src2); | 
| 2468 |             addSlowCase(checkStructure(regT1, numberStructure)); | 
| 2469 |         } | 
| 2470 |  | 
| 2471 |         // (1) In this case src2 is a reusable number cell. | 
| 2472 |         //     Slow case if src1 is not a number type. | 
| 2473 |         Jump op1imm = emitJumpIfImmediateInteger(regT0); | 
| 2474 |         if (!types.first().definitelyIsNumber()) { | 
| 2475 |             emitJumpSlowCaseIfNotJSCell(regT0, src1); | 
| 2476 |             addSlowCase(checkStructure(regT0, numberStructure)); | 
| 2477 |         } | 
| 2478 |  | 
| 2479 |         // (1a) if we get here, src1 is also a number cell | 
| 2480 |         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 2481 |         Jump loadedDouble = jump(); | 
| 2482 |         // (1b) if we get here, src1 is an immediate | 
| 2483 |         op1imm.link(this); | 
| 2484 |         emitFastArithImmToInt(regT0); | 
| 2485 |         convertInt32ToDouble(regT0, fpRegT0); | 
| 2486 |         // (1c)  | 
| 2487 |         loadedDouble.link(this); | 
| 2488 |         if (opcodeID == op_add) | 
| 2489 |             addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 2490 |         else if (opcodeID == op_sub) | 
| 2491 |             subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 2492 |         else { | 
| 2493 |             ASSERT(opcodeID == op_mul); | 
| 2494 |             mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 2495 |         } | 
| 2496 |  | 
| 2497 |         // Store the result to the JSNumberCell and jump. | 
| 2498 |         storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value))); | 
| 2499 |         move(regT1, regT0); | 
| 2500 |         emitPutVirtualRegister(dst); | 
| 2501 |         wasJSNumberCell2 = jump(); | 
| 2502 |  | 
| 2503 |         // (2) This handles cases where src2 is an immediate number. | 
| 2504 |         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows. | 
| 2505 |         op2imm.link(this); | 
| 2506 |         emitJumpSlowCaseIfNotImmediateInteger(regT0); | 
| 2507 |     } else if (types.first().isReusable() && supportsFloatingPoint()) { | 
| 2508 |         ASSERT(types.first().mightBeNumber()); | 
| 2509 |  | 
| 2510 |         // Check op1 is a number | 
| 2511 |         Jump op1imm = emitJumpIfImmediateInteger(regT0); | 
| 2512 |         if (!types.first().definitelyIsNumber()) { | 
| 2513 |             emitJumpSlowCaseIfNotJSCell(regT0, src1); | 
| 2514 |             addSlowCase(checkStructure(regT0, numberStructure)); | 
| 2515 |         } | 
| 2516 |  | 
| 2517 |         // (1) In this case src1 is a reusable number cell. | 
| 2518 |         //     Slow case if src2 is not a number type. | 
| 2519 |         Jump op2imm = emitJumpIfImmediateInteger(regT1); | 
| 2520 |         if (!types.second().definitelyIsNumber()) { | 
| 2521 |             emitJumpSlowCaseIfNotJSCell(regT1, src2); | 
| 2522 |             addSlowCase(checkStructure(regT1, numberStructure)); | 
| 2523 |         } | 
| 2524 |  | 
| 2525 |         // (1a) if we get here, src2 is also a number cell | 
| 2526 |         loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); | 
| 2527 |         Jump loadedDouble = jump(); | 
| 2528 |         // (1b) if we get here, src2 is an immediate | 
| 2529 |         op2imm.link(this); | 
| 2530 |         emitFastArithImmToInt(regT1); | 
| 2531 |         convertInt32ToDouble(regT1, fpRegT1); | 
| 2532 |         // (1c)  | 
| 2533 |         loadedDouble.link(this); | 
| 2534 |         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); | 
| 2535 |         if (opcodeID == op_add) | 
| 2536 |             addDouble(fpRegT1, fpRegT0); | 
| 2537 |         else if (opcodeID == op_sub) | 
| 2538 |             subDouble(fpRegT1, fpRegT0); | 
| 2539 |         else { | 
| 2540 |             ASSERT(opcodeID == op_mul); | 
| 2541 |             mulDouble(fpRegT1, fpRegT0); | 
| 2542 |         } | 
| 2543 |         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value))); | 
| 2544 |         emitPutVirtualRegister(dst); | 
| 2545 |  | 
| 2546 |         // Store the result to the JSNumberCell and jump. | 
| 2547 |         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value))); | 
| 2548 |         emitPutVirtualRegister(dst); | 
| 2549 |         wasJSNumberCell1 = jump(); | 
| 2550 |  | 
| 2551 |         // (2) This handles cases where src1 is an immediate number. | 
| 2552 |         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows. | 
| 2553 |         op1imm.link(this); | 
| 2554 |         emitJumpSlowCaseIfNotImmediateInteger(regT1); | 
| 2555 |     } else | 
| 2556 |         emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2); | 
| 2557 |  | 
| 2558 |     if (opcodeID == op_add) { | 
| 2559 |         emitFastArithDeTagImmediate(regT0); | 
| 2560 |         addSlowCase(branchAdd32(Overflow, regT1, regT0)); | 
| 2561 |     } else  if (opcodeID == op_sub) { | 
| 2562 |         addSlowCase(branchSub32(Overflow, regT1, regT0)); | 
| 2563 |         signExtend32ToPtr(regT0, regT0); | 
| 2564 |         emitFastArithReTagImmediate(regT0, regT0); | 
| 2565 |     } else { | 
| 2566 |         ASSERT(opcodeID == op_mul); | 
| 2567 |         // convert eax & edx from JSImmediates to ints, and check if either are zero | 
| 2568 |         emitFastArithImmToInt(regT1); | 
| 2569 |         Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0); | 
| 2570 |         Jump op2NonZero = branchTest32(NonZero, regT1); | 
| 2571 |         op1Zero.link(this); | 
| 2572 |         // if either input is zero, add the two together, and check if the result is < 0. | 
| 2573 |         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.  | 
| 2574 |         move(regT0, regT2); | 
| 2575 |         addSlowCase(branchAdd32(Signed, regT1, regT2)); | 
| 2576 |         // Skip the above check if neither input is zero | 
| 2577 |         op2NonZero.link(this); | 
| 2578 |         addSlowCase(branchMul32(Overflow, regT1, regT0)); | 
| 2579 |         signExtend32ToPtr(regT0, regT0); | 
| 2580 |         emitFastArithReTagImmediate(regT0, regT0); | 
| 2581 |     } | 
| 2582 |     emitPutVirtualRegister(dst); | 
| 2583 |  | 
| 2584 |     if (types.second().isReusable() && supportsFloatingPoint()) | 
| 2585 |         wasJSNumberCell2.link(this); | 
| 2586 |     else if (types.first().isReusable() && supportsFloatingPoint()) | 
| 2587 |         wasJSNumberCell1.link(this); | 
| 2588 | } | 
| 2589 |  | 
| 2590 | void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types) | 
| 2591 | { | 
| 2592 |     linkSlowCase(iter); | 
| 2593 |     if (types.second().isReusable() && supportsFloatingPoint()) { | 
| 2594 |         if (!types.first().definitelyIsNumber()) { | 
| 2595 |             linkSlowCaseIfNotJSCell(iter, src1); | 
| 2596 |             linkSlowCase(iter); | 
| 2597 |         } | 
| 2598 |         if (!types.second().definitelyIsNumber()) { | 
| 2599 |             linkSlowCaseIfNotJSCell(iter, src2); | 
| 2600 |             linkSlowCase(iter); | 
| 2601 |         } | 
| 2602 |     } else if (types.first().isReusable() && supportsFloatingPoint()) { | 
| 2603 |         if (!types.first().definitelyIsNumber()) { | 
| 2604 |             linkSlowCaseIfNotJSCell(iter, src1); | 
| 2605 |             linkSlowCase(iter); | 
| 2606 |         } | 
| 2607 |         if (!types.second().definitelyIsNumber()) { | 
| 2608 |             linkSlowCaseIfNotJSCell(iter, src2); | 
| 2609 |             linkSlowCase(iter); | 
| 2610 |         } | 
| 2611 |     } | 
| 2612 |     linkSlowCase(iter); | 
| 2613 |  | 
| 2614 |     // additional entry point to handle -0 cases. | 
| 2615 |     if (opcodeID == op_mul) | 
| 2616 |         linkSlowCase(iter); | 
| 2617 |  | 
| 2618 |     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul); | 
| 2619 |     stubCall.addArgument(src1, regT2); | 
| 2620 |     stubCall.addArgument(src2, regT2); | 
| 2621 |     stubCall.call(dst); | 
| 2622 | } | 
| 2623 |  | 
| 2624 | void JIT::emit_op_add(Instruction* currentInstruction) | 
| 2625 | { | 
| 2626 |     unsigned result = currentInstruction[1].u.operand; | 
| 2627 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2628 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2629 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 2630 |  | 
| 2631 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { | 
| 2632 |         JITStubCall stubCall(this, cti_op_add); | 
| 2633 |         stubCall.addArgument(op1, regT2); | 
| 2634 |         stubCall.addArgument(op2, regT2); | 
| 2635 |         stubCall.call(result); | 
| 2636 |         return; | 
| 2637 |     } | 
| 2638 |  | 
| 2639 |     if (isOperandConstantImmediateInt(op1)) { | 
| 2640 |         emitGetVirtualRegister(op2, regT0); | 
| 2641 |         emitJumpSlowCaseIfNotImmediateInteger(regT0); | 
| 2642 |         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0)); | 
| 2643 |         signExtend32ToPtr(regT0, regT0); | 
| 2644 |         emitPutVirtualRegister(result); | 
| 2645 |     } else if (isOperandConstantImmediateInt(op2)) { | 
| 2646 |         emitGetVirtualRegister(op1, regT0); | 
| 2647 |         emitJumpSlowCaseIfNotImmediateInteger(regT0); | 
| 2648 |         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0)); | 
| 2649 |         signExtend32ToPtr(regT0, regT0); | 
| 2650 |         emitPutVirtualRegister(result); | 
| 2651 |     } else { | 
| 2652 |         compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); | 
| 2653 |     } | 
| 2654 | } | 
| 2655 |  | 
| 2656 | void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2657 | { | 
| 2658 |     unsigned result = currentInstruction[1].u.operand; | 
| 2659 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2660 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2661 |  | 
| 2662 |     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 2663 |     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) | 
| 2664 |         return; | 
| 2665 |  | 
| 2666 |     if (isOperandConstantImmediateInt(op1)) { | 
| 2667 |         Jump notImm = getSlowCase(iter); | 
| 2668 |         linkSlowCase(iter); | 
| 2669 |         sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0); | 
| 2670 |         notImm.link(this); | 
| 2671 |         JITStubCall stubCall(this, cti_op_add); | 
| 2672 |         stubCall.addArgument(op1, regT2); | 
| 2673 |         stubCall.addArgument(regT0); | 
| 2674 |         stubCall.call(result); | 
| 2675 |     } else if (isOperandConstantImmediateInt(op2)) { | 
| 2676 |         Jump notImm = getSlowCase(iter); | 
| 2677 |         linkSlowCase(iter); | 
| 2678 |         sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0); | 
| 2679 |         notImm.link(this); | 
| 2680 |         JITStubCall stubCall(this, cti_op_add); | 
| 2681 |         stubCall.addArgument(regT0); | 
| 2682 |         stubCall.addArgument(op2, regT2); | 
| 2683 |         stubCall.call(result); | 
| 2684 |     } else { | 
| 2685 |         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); | 
| 2686 |         ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber()); | 
| 2687 |         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types); | 
| 2688 |     } | 
| 2689 | } | 
| 2690 |  | 
| 2691 | void JIT::emit_op_mul(Instruction* currentInstruction) | 
| 2692 | { | 
| 2693 |     unsigned result = currentInstruction[1].u.operand; | 
| 2694 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2695 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2696 |  | 
| 2697 |     // For now, only plant a fast int case if the constant operand is greater than zero. | 
| 2698 |     int32_t value; | 
| 2699 |     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) { | 
| 2700 |         emitGetVirtualRegister(op2, regT0); | 
| 2701 |         emitJumpSlowCaseIfNotImmediateInteger(regT0); | 
| 2702 |         emitFastArithDeTagImmediate(regT0); | 
| 2703 |         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); | 
| 2704 |         signExtend32ToPtr(regT0, regT0); | 
| 2705 |         emitFastArithReTagImmediate(regT0, regT0); | 
| 2706 |         emitPutVirtualRegister(result); | 
| 2707 |     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { | 
| 2708 |         emitGetVirtualRegister(op1, regT0); | 
| 2709 |         emitJumpSlowCaseIfNotImmediateInteger(regT0); | 
| 2710 |         emitFastArithDeTagImmediate(regT0); | 
| 2711 |         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); | 
| 2712 |         signExtend32ToPtr(regT0, regT0); | 
| 2713 |         emitFastArithReTagImmediate(regT0, regT0); | 
| 2714 |         emitPutVirtualRegister(result); | 
| 2715 |     } else | 
| 2716 |         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); | 
| 2717 | } | 
| 2718 |  | 
| 2719 | void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2720 | { | 
| 2721 |     unsigned result = currentInstruction[1].u.operand; | 
| 2722 |     unsigned op1 = currentInstruction[2].u.operand; | 
| 2723 |     unsigned op2 = currentInstruction[3].u.operand; | 
| 2724 |  | 
| 2725 |     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0)) | 
| 2726 |         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) { | 
| 2727 |         linkSlowCase(iter); | 
| 2728 |         linkSlowCase(iter); | 
| 2729 |         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0. | 
| 2730 |         JITStubCall stubCall(this, cti_op_mul); | 
| 2731 |         stubCall.addArgument(op1, regT2); | 
| 2732 |         stubCall.addArgument(op2, regT2); | 
| 2733 |         stubCall.call(result); | 
| 2734 |     } else | 
| 2735 |         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand)); | 
| 2736 | } | 
| 2737 |  | 
| 2738 | void JIT::emit_op_sub(Instruction* currentInstruction) | 
| 2739 | { | 
| 2740 |     compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); | 
| 2741 | } | 
| 2742 |  | 
| 2743 | void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) | 
| 2744 | { | 
| 2745 |     compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand)); | 
| 2746 | } | 
| 2747 |  | 
| 2748 | #endif // USE(JSVALUE64) | 
| 2749 |  | 
| 2750 | /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */ | 
| 2751 |  | 
| 2752 | #endif // USE(JSVALUE32_64) | 
| 2753 |  | 
| 2754 | } // namespace JSC | 
| 2755 |  | 
| 2756 | #endif // ENABLE(JIT) | 
| 2757 |  |