]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JITArithmetic.cpp
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / jit / JITArithmetic.cpp
CommitLineData
9dae56ea
A
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
4e4e5a6f 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9dae56ea
A
24 */
25
26#include "config.h"
9dae56ea
A
27
28#if ENABLE(JIT)
14957cd0 29#include "JIT.h"
9dae56ea
A
30
31#include "CodeBlock.h"
93a37866 32#include "JITInlines.h"
81345200 33#include "JITOperations.h"
4e4e5a6f 34#include "JITStubs.h"
9dae56ea
A
35#include "JSArray.h"
36#include "JSFunction.h"
37#include "Interpreter.h"
81345200 38#include "JSCInlines.h"
9dae56ea
A
39#include "ResultType.h"
40#include "SamplingTool.h"
81345200 41#include "SlowPathCall.h"
9dae56ea 42
ba379fdc
A
43
44namespace JSC {
45
6fe7ccc8
A
46void JIT::emit_op_jless(Instruction* currentInstruction)
47{
81345200
A
48 int op1 = currentInstruction[1].u.operand;
49 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
50 unsigned target = currentInstruction[3].u.operand;
51
52 emit_compareAndJump(op_jless, op1, op2, target, LessThan);
53}
54
55void JIT::emit_op_jlesseq(Instruction* currentInstruction)
56{
81345200
A
57 int op1 = currentInstruction[1].u.operand;
58 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
59 unsigned target = currentInstruction[3].u.operand;
60
61 emit_compareAndJump(op_jlesseq, op1, op2, target, LessThanOrEqual);
62}
63
64void JIT::emit_op_jgreater(Instruction* currentInstruction)
65{
81345200
A
66 int op1 = currentInstruction[1].u.operand;
67 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
68 unsigned target = currentInstruction[3].u.operand;
69
70 emit_compareAndJump(op_jgreater, op1, op2, target, GreaterThan);
71}
72
73void JIT::emit_op_jgreatereq(Instruction* currentInstruction)
74{
81345200
A
75 int op1 = currentInstruction[1].u.operand;
76 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
77 unsigned target = currentInstruction[3].u.operand;
78
79 emit_compareAndJump(op_jgreatereq, op1, op2, target, GreaterThanOrEqual);
80}
81
82void JIT::emit_op_jnless(Instruction* currentInstruction)
83{
81345200
A
84 int op1 = currentInstruction[1].u.operand;
85 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
86 unsigned target = currentInstruction[3].u.operand;
87
88 emit_compareAndJump(op_jnless, op1, op2, target, GreaterThanOrEqual);
89}
90
91void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
92{
81345200
A
93 int op1 = currentInstruction[1].u.operand;
94 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
95 unsigned target = currentInstruction[3].u.operand;
96
97 emit_compareAndJump(op_jnlesseq, op1, op2, target, GreaterThan);
98}
99
100void JIT::emit_op_jngreater(Instruction* currentInstruction)
101{
81345200
A
102 int op1 = currentInstruction[1].u.operand;
103 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
104 unsigned target = currentInstruction[3].u.operand;
105
106 emit_compareAndJump(op_jngreater, op1, op2, target, LessThanOrEqual);
107}
108
109void JIT::emit_op_jngreatereq(Instruction* currentInstruction)
110{
81345200
A
111 int op1 = currentInstruction[1].u.operand;
112 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
113 unsigned target = currentInstruction[3].u.operand;
114
115 emit_compareAndJump(op_jngreatereq, op1, op2, target, LessThan);
116}
117
118void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
119{
81345200
A
120 int op1 = currentInstruction[1].u.operand;
121 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
122 unsigned target = currentInstruction[3].u.operand;
123
81345200 124 emit_compareAndJumpSlow(op1, op2, target, DoubleLessThan, operationCompareLess, false, iter);
6fe7ccc8
A
125}
126
127void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
128{
81345200
A
129 int op1 = currentInstruction[1].u.operand;
130 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
131 unsigned target = currentInstruction[3].u.operand;
132
81345200 133 emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrEqual, operationCompareLessEq, false, iter);
6fe7ccc8
A
134}
135
136void JIT::emitSlow_op_jgreater(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
137{
81345200
A
138 int op1 = currentInstruction[1].u.operand;
139 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
140 unsigned target = currentInstruction[3].u.operand;
141
81345200 142 emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThan, operationCompareGreater, false, iter);
6fe7ccc8
A
143}
144
145void JIT::emitSlow_op_jgreatereq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
146{
81345200
A
147 int op1 = currentInstruction[1].u.operand;
148 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
149 unsigned target = currentInstruction[3].u.operand;
150
81345200 151 emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrEqual, operationCompareGreaterEq, false, iter);
6fe7ccc8
A
152}
153
154void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
155{
81345200
A
156 int op1 = currentInstruction[1].u.operand;
157 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
158 unsigned target = currentInstruction[3].u.operand;
159
81345200 160 emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrEqualOrUnordered, operationCompareLess, true, iter);
6fe7ccc8
A
161}
162
163void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
164{
81345200
A
165 int op1 = currentInstruction[1].u.operand;
166 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
167 unsigned target = currentInstruction[3].u.operand;
168
81345200 169 emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrUnordered, operationCompareLessEq, true, iter);
6fe7ccc8
A
170}
171
172void JIT::emitSlow_op_jngreater(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
173{
81345200
A
174 int op1 = currentInstruction[1].u.operand;
175 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
176 unsigned target = currentInstruction[3].u.operand;
177
81345200 178 emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrEqualOrUnordered, operationCompareGreater, true, iter);
6fe7ccc8
A
179}
180
181void JIT::emitSlow_op_jngreatereq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
182{
81345200
A
183 int op1 = currentInstruction[1].u.operand;
184 int op2 = currentInstruction[2].u.operand;
6fe7ccc8
A
185 unsigned target = currentInstruction[3].u.operand;
186
81345200 187 emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrUnordered, operationCompareGreaterEq, true, iter);
6fe7ccc8
A
188}
189
190#if USE(JSVALUE64)
191
192void JIT::emit_op_negate(Instruction* currentInstruction)
193{
81345200
A
194 int dst = currentInstruction[1].u.operand;
195 int src = currentInstruction[2].u.operand;
6fe7ccc8
A
196
197 emitGetVirtualRegister(src, regT0);
198
199 Jump srcNotInt = emitJumpIfNotImmediateInteger(regT0);
200 addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff)));
201 neg32(regT0);
202 emitFastArithReTagImmediate(regT0, regT0);
203
204 Jump end = jump();
205
206 srcNotInt.link(this);
207 emitJumpSlowCaseIfNotImmediateNumber(regT0);
208
93a37866
A
209 move(TrustedImm64((int64_t)0x8000000000000000ull), regT1);
210 xor64(regT1, regT0);
6fe7ccc8
A
211
212 end.link(this);
213 emitPutVirtualRegister(dst);
214}
215
216void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
217{
6fe7ccc8
A
218 linkSlowCase(iter); // 0x7fffffff check
219 linkSlowCase(iter); // double check
220
81345200
A
221 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_negate);
222 slowPathCall.call();
6fe7ccc8
A
223}
224
ba379fdc
A
225void JIT::emit_op_lshift(Instruction* currentInstruction)
226{
81345200
A
227 int result = currentInstruction[1].u.operand;
228 int op1 = currentInstruction[2].u.operand;
229 int op2 = currentInstruction[3].u.operand;
ba379fdc
A
230
231 emitGetVirtualRegisters(op1, regT0, op2, regT2);
232 // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
233 emitJumpSlowCaseIfNotImmediateInteger(regT0);
234 emitJumpSlowCaseIfNotImmediateInteger(regT2);
235 emitFastArithImmToInt(regT0);
236 emitFastArithImmToInt(regT2);
ba379fdc 237 lshift32(regT2, regT0);
ba379fdc
A
238 emitFastArithReTagImmediate(regT0, regT0);
239 emitPutVirtualRegister(result);
240}
241
242void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
243{
ba379fdc
A
244 linkSlowCase(iter);
245 linkSlowCase(iter);
81345200
A
246 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_lshift);
247 slowPathCall.call();
ba379fdc
A
248}
249
250void JIT::emit_op_rshift(Instruction* currentInstruction)
251{
81345200
A
252 int result = currentInstruction[1].u.operand;
253 int op1 = currentInstruction[2].u.operand;
254 int op2 = currentInstruction[3].u.operand;
ba379fdc
A
255
256 if (isOperandConstantImmediateInt(op2)) {
257 // isOperandConstantImmediateInt(op2) => 1 SlowCase
258 emitGetVirtualRegister(op1, regT0);
259 emitJumpSlowCaseIfNotImmediateInteger(regT0);
260 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
ba379fdc 261 rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
ba379fdc
A
262 } else {
263 emitGetVirtualRegisters(op1, regT0, op2, regT2);
264 if (supportsFloatingPointTruncate()) {
265 Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
ba379fdc
A
266 // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
267 addSlowCase(emitJumpIfNotImmediateNumber(regT0));
93a37866
A
268 add64(tagTypeNumberRegister, regT0);
269 move64ToDouble(regT0, fpRegT0);
ba379fdc 270 addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
ba379fdc
A
271 lhsIsInt.link(this);
272 emitJumpSlowCaseIfNotImmediateInteger(regT2);
273 } else {
274 // !supportsFloatingPoint() => 2 SlowCases
275 emitJumpSlowCaseIfNotImmediateInteger(regT0);
276 emitJumpSlowCaseIfNotImmediateInteger(regT2);
277 }
278 emitFastArithImmToInt(regT2);
ba379fdc 279 rshift32(regT2, regT0);
ba379fdc 280 }
ba379fdc 281 emitFastArithIntToImmNoCheck(regT0, regT0);
ba379fdc
A
282 emitPutVirtualRegister(result);
283}
284
285void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
286{
81345200 287 int op2 = currentInstruction[3].u.operand;
ba379fdc 288
81345200 289 if (isOperandConstantImmediateInt(op2))
ba379fdc 290 linkSlowCase(iter);
81345200
A
291
292 else {
ba379fdc 293 if (supportsFloatingPointTruncate()) {
ba379fdc
A
294 linkSlowCase(iter);
295 linkSlowCase(iter);
296 linkSlowCase(iter);
ba379fdc
A
297 } else {
298 linkSlowCase(iter);
299 linkSlowCase(iter);
ba379fdc
A
300 }
301 }
302
81345200
A
303 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_rshift);
304 slowPathCall.call();
ba379fdc
A
305}
306
4e4e5a6f
A
307void JIT::emit_op_urshift(Instruction* currentInstruction)
308{
81345200
A
309 int result = currentInstruction[1].u.operand;
310 int op1 = currentInstruction[2].u.operand;
311 int op2 = currentInstruction[3].u.operand;
4e4e5a6f 312
4e4e5a6f 313 if (isOperandConstantImmediateInt(op2)) {
81345200 314 // isOperandConstantImmediateInt(op2) => 1 SlowCase
4e4e5a6f
A
315 emitGetVirtualRegister(op1, regT0);
316 emitJumpSlowCaseIfNotImmediateInteger(regT0);
81345200
A
317 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
318 urshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
319 } else {
320 emitGetVirtualRegisters(op1, regT0, op2, regT2);
321 if (supportsFloatingPointTruncate()) {
322 Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
323 // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
324 addSlowCase(emitJumpIfNotImmediateNumber(regT0));
325 add64(tagTypeNumberRegister, regT0);
326 move64ToDouble(regT0, fpRegT0);
327 addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
328 lhsIsInt.link(this);
329 emitJumpSlowCaseIfNotImmediateInteger(regT2);
330 } else {
331 // !supportsFloatingPoint() => 2 SlowCases
332 emitJumpSlowCaseIfNotImmediateInteger(regT0);
333 emitJumpSlowCaseIfNotImmediateInteger(regT2);
334 }
335 emitFastArithImmToInt(regT2);
336 urshift32(regT2, regT0);
4e4e5a6f 337 }
81345200
A
338 emitFastArithIntToImmNoCheck(regT0, regT0);
339 emitPutVirtualRegister(result);
4e4e5a6f
A
340}
341
342void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
343{
81345200
A
344 int op2 = currentInstruction[3].u.operand;
345
346 if (isOperandConstantImmediateInt(op2))
347 linkSlowCase(iter);
348
349 else {
4e4e5a6f 350 if (supportsFloatingPointTruncate()) {
81345200
A
351 linkSlowCase(iter);
352 linkSlowCase(iter);
353 linkSlowCase(iter);
354 } else {
355 linkSlowCase(iter);
356 linkSlowCase(iter);
4e4e5a6f 357 }
4e4e5a6f 358 }
81345200
A
359
360 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_urshift);
361 slowPathCall.call();
362}
363
364void JIT::emit_op_unsigned(Instruction* currentInstruction)
365{
366 int result = currentInstruction[1].u.operand;
367 int op1 = currentInstruction[2].u.operand;
4e4e5a6f 368
81345200
A
369 emitGetVirtualRegister(op1, regT0);
370 emitJumpSlowCaseIfNotImmediateInteger(regT0);
371 addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
372 emitFastArithReTagImmediate(regT0, regT0);
373 emitPutVirtualRegister(result, regT0);
4e4e5a6f
A
374}
375
81345200
A
376void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
377{
378 linkSlowCase(iter);
379 linkSlowCase(iter);
380
381 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned);
382 slowPathCall.call();
383}
384
385void JIT::emit_compareAndJump(OpcodeID, int op1, int op2, unsigned target, RelationalCondition condition)
9dae56ea 386{
ba379fdc
A
387 // We generate inline code for the following cases in the fast path:
388 // - int immediate to constant int immediate
389 // - constant int immediate to int immediate
390 // - int immediate to int immediate
391
4e4e5a6f
A
392 if (isOperandConstantImmediateChar(op1)) {
393 emitGetVirtualRegister(op2, regT0);
394 addSlowCase(emitJumpIfNotJSCell(regT0));
395 JumpList failures;
396 emitLoadCharacterString(regT0, regT0, failures);
397 addSlowCase(failures);
6fe7ccc8 398 addJump(branch32(commute(condition), regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
4e4e5a6f
A
399 return;
400 }
401 if (isOperandConstantImmediateChar(op2)) {
402 emitGetVirtualRegister(op1, regT0);
403 addSlowCase(emitJumpIfNotJSCell(regT0));
404 JumpList failures;
405 emitLoadCharacterString(regT0, regT0, failures);
406 addSlowCase(failures);
6fe7ccc8 407 addJump(branch32(condition, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
4e4e5a6f
A
408 return;
409 }
ba379fdc
A
410 if (isOperandConstantImmediateInt(op2)) {
411 emitGetVirtualRegister(op1, regT0);
412 emitJumpSlowCaseIfNotImmediateInteger(regT0);
ba379fdc 413 int32_t op2imm = getConstantOperandImmediateInt(op2);
6fe7ccc8 414 addJump(branch32(condition, regT0, Imm32(op2imm)), target);
ba379fdc
A
415 } else if (isOperandConstantImmediateInt(op1)) {
416 emitGetVirtualRegister(op2, regT1);
417 emitJumpSlowCaseIfNotImmediateInteger(regT1);
ba379fdc 418 int32_t op1imm = getConstantOperandImmediateInt(op1);
6fe7ccc8 419 addJump(branch32(commute(condition), regT1, Imm32(op1imm)), target);
ba379fdc
A
420 } else {
421 emitGetVirtualRegisters(op1, regT0, op2, regT1);
422 emitJumpSlowCaseIfNotImmediateInteger(regT0);
423 emitJumpSlowCaseIfNotImmediateInteger(regT1);
424
6fe7ccc8 425 addJump(branch32(condition, regT0, regT1), target);
ba379fdc 426 }
9dae56ea
A
427}
428
81345200 429void JIT::emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition condition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 430{
6fe7ccc8
A
431 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jlesseq), OPCODE_LENGTH_op_jlesseq_equals_op_jless);
432 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jnless), OPCODE_LENGTH_op_jnless_equals_op_jless);
433 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jnlesseq), OPCODE_LENGTH_op_jnlesseq_equals_op_jless);
434 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jgreater), OPCODE_LENGTH_op_jgreater_equals_op_jless);
435 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jgreatereq), OPCODE_LENGTH_op_jgreatereq_equals_op_jless);
436 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jngreater), OPCODE_LENGTH_op_jngreater_equals_op_jless);
437 COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jngreatereq), OPCODE_LENGTH_op_jngreatereq_equals_op_jless);
438
ba379fdc
A
439 // We generate inline code for the following cases in the slow path:
440 // - floating-point number to constant int immediate
441 // - constant int immediate to floating-point number
442 // - floating-point number to floating-point number.
4e4e5a6f
A
443 if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
444 linkSlowCase(iter);
445 linkSlowCase(iter);
446 linkSlowCase(iter);
447 linkSlowCase(iter);
81345200
A
448
449 emitGetVirtualRegister(op1, argumentGPR0);
450 emitGetVirtualRegister(op2, argumentGPR1);
451 callOperation(operation, argumentGPR0, argumentGPR1);
452 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
4e4e5a6f
A
453 return;
454 }
455
9dae56ea 456 if (isOperandConstantImmediateInt(op2)) {
ba379fdc
A
457 linkSlowCase(iter);
458
459 if (supportsFloatingPoint()) {
ba379fdc 460 Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
93a37866
A
461 add64(tagTypeNumberRegister, regT0);
462 move64ToDouble(regT0, fpRegT0);
4e4e5a6f 463
6fe7ccc8 464 int32_t op2imm = getConstantOperand(op2).asInt32();
4e4e5a6f 465
ba379fdc
A
466 move(Imm32(op2imm), regT1);
467 convertInt32ToDouble(regT1, fpRegT1);
468
6fe7ccc8 469 emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
ba379fdc 470
6fe7ccc8 471 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
ba379fdc 472
ba379fdc 473 fail1.link(this);
ba379fdc
A
474 }
475
81345200
A
476 emitGetVirtualRegister(op2, regT1);
477 callOperation(operation, regT0, regT1);
478 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
ba379fdc
A
479 } else if (isOperandConstantImmediateInt(op1)) {
480 linkSlowCase(iter);
481
482 if (supportsFloatingPoint()) {
ba379fdc 483 Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
93a37866
A
484 add64(tagTypeNumberRegister, regT1);
485 move64ToDouble(regT1, fpRegT1);
4e4e5a6f 486
6fe7ccc8 487 int32_t op1imm = getConstantOperand(op1).asInt32();
4e4e5a6f 488
ba379fdc
A
489 move(Imm32(op1imm), regT0);
490 convertInt32ToDouble(regT0, fpRegT0);
491
6fe7ccc8 492 emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
ba379fdc 493
6fe7ccc8 494 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
ba379fdc 495
ba379fdc 496 fail1.link(this);
ba379fdc
A
497 }
498
81345200
A
499 emitGetVirtualRegister(op1, regT2);
500 callOperation(operation, regT2, regT1);
501 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
ba379fdc 502 } else {
9dae56ea 503 linkSlowCase(iter);
9dae56ea 504
ba379fdc 505 if (supportsFloatingPoint()) {
ba379fdc
A
506 Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
507 Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
508 Jump fail3 = emitJumpIfImmediateInteger(regT1);
93a37866
A
509 add64(tagTypeNumberRegister, regT0);
510 add64(tagTypeNumberRegister, regT1);
511 move64ToDouble(regT0, fpRegT0);
512 move64ToDouble(regT1, fpRegT1);
ba379fdc 513
6fe7ccc8 514 emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
ba379fdc 515
6fe7ccc8 516 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
ba379fdc 517
ba379fdc
A
518 fail1.link(this);
519 fail2.link(this);
520 fail3.link(this);
ba379fdc
A
521 }
522
523 linkSlowCase(iter);
81345200
A
524 callOperation(operation, regT0, regT1);
525 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
ba379fdc 526 }
9dae56ea
A
527}
528
ba379fdc 529void JIT::emit_op_bitand(Instruction* currentInstruction)
9dae56ea 530{
81345200
A
531 int result = currentInstruction[1].u.operand;
532 int op1 = currentInstruction[2].u.operand;
533 int op2 = currentInstruction[3].u.operand;
ba379fdc 534
9dae56ea 535 if (isOperandConstantImmediateInt(op1)) {
ba379fdc
A
536 emitGetVirtualRegister(op2, regT0);
537 emitJumpSlowCaseIfNotImmediateInteger(regT0);
9dae56ea 538 int32_t imm = getConstantOperandImmediateInt(op1);
93a37866 539 and64(Imm32(imm), regT0);
9dae56ea 540 if (imm >= 0)
ba379fdc 541 emitFastArithIntToImmNoCheck(regT0, regT0);
9dae56ea 542 } else if (isOperandConstantImmediateInt(op2)) {
ba379fdc
A
543 emitGetVirtualRegister(op1, regT0);
544 emitJumpSlowCaseIfNotImmediateInteger(regT0);
9dae56ea 545 int32_t imm = getConstantOperandImmediateInt(op2);
93a37866 546 and64(Imm32(imm), regT0);
9dae56ea 547 if (imm >= 0)
ba379fdc 548 emitFastArithIntToImmNoCheck(regT0, regT0);
9dae56ea 549 } else {
ba379fdc 550 emitGetVirtualRegisters(op1, regT0, op2, regT1);
93a37866 551 and64(regT1, regT0);
ba379fdc 552 emitJumpSlowCaseIfNotImmediateInteger(regT0);
9dae56ea
A
553 }
554 emitPutVirtualRegister(result);
555}
ba379fdc
A
556
557void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea
A
558{
559 linkSlowCase(iter);
81345200
A
560
561 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitand);
562 slowPathCall.call();
9dae56ea
A
563}
564
93a37866 565void JIT::emit_op_inc(Instruction* currentInstruction)
9dae56ea 566{
81345200 567 int srcDst = currentInstruction[1].u.operand;
ba379fdc
A
568
569 emitGetVirtualRegister(srcDst, regT0);
570 emitJumpSlowCaseIfNotImmediateInteger(regT0);
14957cd0 571 addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
ba379fdc 572 emitFastArithIntToImmNoCheck(regT0, regT0);
9dae56ea
A
573 emitPutVirtualRegister(srcDst);
574}
ba379fdc 575
93a37866 576void JIT::emitSlow_op_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 577{
9dae56ea 578 linkSlowCase(iter);
81345200
A
579 linkSlowCase(iter);
580 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_inc);
581 slowPathCall.call();
9dae56ea
A
582}
583
93a37866 584void JIT::emit_op_dec(Instruction* currentInstruction)
9dae56ea 585{
81345200 586 int srcDst = currentInstruction[1].u.operand;
ba379fdc
A
587
588 emitGetVirtualRegister(srcDst, regT0);
589 emitJumpSlowCaseIfNotImmediateInteger(regT0);
6fe7ccc8 590 addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
ba379fdc 591 emitFastArithIntToImmNoCheck(regT0, regT0);
9dae56ea
A
592 emitPutVirtualRegister(srcDst);
593}
ba379fdc 594
93a37866 595void JIT::emitSlow_op_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 596{
9dae56ea 597 linkSlowCase(iter);
81345200
A
598 linkSlowCase(iter);
599 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_dec);
600 slowPathCall.call();
9dae56ea
A
601}
602
ba379fdc 603/* ------------------------------ BEGIN: OP_MOD ------------------------------ */
9dae56ea 604
6fe7ccc8 605#if CPU(X86) || CPU(X86_64)
9dae56ea 606
ba379fdc 607void JIT::emit_op_mod(Instruction* currentInstruction)
9dae56ea 608{
81345200
A
609 int result = currentInstruction[1].u.operand;
610 int op1 = currentInstruction[2].u.operand;
611 int op2 = currentInstruction[3].u.operand;
9dae56ea 612
14957cd0
A
613 // Make sure registers are correct for x86 IDIV instructions.
614 ASSERT(regT0 == X86Registers::eax);
615 ASSERT(regT1 == X86Registers::edx);
616 ASSERT(regT2 == X86Registers::ecx);
14957cd0 617
6fe7ccc8
A
618 emitGetVirtualRegisters(op1, regT3, op2, regT2);
619 emitJumpSlowCaseIfNotImmediateInteger(regT3);
14957cd0
A
620 emitJumpSlowCaseIfNotImmediateInteger(regT2);
621
6fe7ccc8
A
622 move(regT3, regT0);
623 addSlowCase(branchTest32(Zero, regT2));
624 Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1));
625 addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1)));
626 denominatorNotNeg1.link(this);
14957cd0
A
627 m_assembler.cdq();
628 m_assembler.idivl_r(regT2);
6fe7ccc8
A
629 Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
630 addSlowCase(branchTest32(Zero, regT1));
631 numeratorPositive.link(this);
14957cd0 632 emitFastArithReTagImmediate(regT1, regT0);
9dae56ea
A
633 emitPutVirtualRegister(result);
634}
9dae56ea 635
ba379fdc 636void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 637{
6fe7ccc8
A
638 linkSlowCase(iter);
639 linkSlowCase(iter);
ba379fdc
A
640 linkSlowCase(iter);
641 linkSlowCase(iter);
ba379fdc 642 linkSlowCase(iter);
81345200
A
643 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod);
644 slowPathCall.call();
9dae56ea
A
645}
646
6fe7ccc8 647#else // CPU(X86) || CPU(X86_64)
ba379fdc
A
648
649void JIT::emit_op_mod(Instruction* currentInstruction)
9dae56ea 650{
81345200
A
651 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod);
652 slowPathCall.call();
9dae56ea 653}
ba379fdc 654
93a37866 655void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
9dae56ea 656{
93a37866 657 UNREACHABLE_FOR_PLATFORM();
9dae56ea
A
658}
659
f9bf01c6 660#endif // CPU(X86) || CPU(X86_64)
ba379fdc
A
661
662/* ------------------------------ END: OP_MOD ------------------------------ */
663
ba379fdc 664/* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
9dae56ea 665
81345200 666void JIT::compileBinaryArithOp(OpcodeID opcodeID, int, int op1, int op2, OperandTypes)
9dae56ea 667{
ba379fdc
A
668 emitGetVirtualRegisters(op1, regT0, op2, regT1);
669 emitJumpSlowCaseIfNotImmediateInteger(regT0);
670 emitJumpSlowCaseIfNotImmediateInteger(regT1);
6fe7ccc8 671 RareCaseProfile* profile = m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
9dae56ea 672 if (opcodeID == op_add)
ba379fdc 673 addSlowCase(branchAdd32(Overflow, regT1, regT0));
9dae56ea 674 else if (opcodeID == op_sub)
ba379fdc 675 addSlowCase(branchSub32(Overflow, regT1, regT0));
9dae56ea
A
676 else {
677 ASSERT(opcodeID == op_mul);
93a37866 678 if (shouldEmitProfiling()) {
6fe7ccc8
A
679 // We want to be able to measure if this is taking the slow case just
680 // because of negative zero. If this produces positive zero, then we
681 // don't want the slow case to be taken because that will throw off
682 // speculative compilation.
683 move(regT0, regT2);
684 addSlowCase(branchMul32(Overflow, regT1, regT2));
685 JumpList done;
686 done.append(branchTest32(NonZero, regT2));
687 Jump negativeZero = branch32(LessThan, regT0, TrustedImm32(0));
688 done.append(branch32(GreaterThanOrEqual, regT1, TrustedImm32(0)));
689 negativeZero.link(this);
690 // We only get here if we have a genuine negative zero. Record this,
691 // so that the speculative JIT knows that we failed speculation
692 // because of a negative zero.
693 add32(TrustedImm32(1), AbsoluteAddress(&profile->m_counter));
694 addSlowCase(jump());
695 done.link(this);
696 move(regT2, regT0);
697 } else {
698 addSlowCase(branchMul32(Overflow, regT1, regT0));
699 addSlowCase(branchTest32(Zero, regT0));
700 }
9dae56ea 701 }
ba379fdc 702 emitFastArithIntToImmNoCheck(regT0, regT0);
9dae56ea
A
703}
704
81345200 705void JIT::compileBinaryArithOpSlowCase(Instruction* currentInstruction, OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, int result, int op1, int op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
9dae56ea
A
706{
707 // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
14957cd0 708 COMPILE_ASSERT(((TagTypeNumber + DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
4e4e5a6f 709
f9bf01c6
A
710 Jump notImm1;
711 Jump notImm2;
712 if (op1HasImmediateIntFastCase) {
713 notImm2 = getSlowCase(iter);
714 } else if (op2HasImmediateIntFastCase) {
715 notImm1 = getSlowCase(iter);
716 } else {
717 notImm1 = getSlowCase(iter);
718 notImm2 = getSlowCase(iter);
719 }
9dae56ea
A
720
721 linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
f9bf01c6 722 if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
9dae56ea 723 linkSlowCase(iter);
9dae56ea
A
724
725 Label stubFunctionCall(this);
81345200
A
726
727 JITSlowPathCall slowPathCall(this, currentInstruction, opcodeID == op_add ? slow_path_add : opcodeID == op_sub ? slow_path_sub : slow_path_mul);
728 slowPathCall.call();
9dae56ea
A
729 Jump end = jump();
730
f9bf01c6
A
731 if (op1HasImmediateIntFastCase) {
732 notImm2.link(this);
733 if (!types.second().definitelyIsNumber())
734 emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
735 emitGetVirtualRegister(op1, regT1);
736 convertInt32ToDouble(regT1, fpRegT1);
93a37866
A
737 add64(tagTypeNumberRegister, regT0);
738 move64ToDouble(regT0, fpRegT2);
f9bf01c6
A
739 } else if (op2HasImmediateIntFastCase) {
740 notImm1.link(this);
741 if (!types.first().definitelyIsNumber())
742 emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
743 emitGetVirtualRegister(op2, regT1);
744 convertInt32ToDouble(regT1, fpRegT1);
93a37866
A
745 add64(tagTypeNumberRegister, regT0);
746 move64ToDouble(regT0, fpRegT2);
f9bf01c6
A
747 } else {
748 // if we get here, eax is not an int32, edx not yet checked.
749 notImm1.link(this);
750 if (!types.first().definitelyIsNumber())
751 emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
752 if (!types.second().definitelyIsNumber())
753 emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
93a37866
A
754 add64(tagTypeNumberRegister, regT0);
755 move64ToDouble(regT0, fpRegT1);
f9bf01c6
A
756 Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
757 convertInt32ToDouble(regT1, fpRegT2);
758 Jump op2wasInteger = jump();
759
760 // if we get here, eax IS an int32, edx is not.
761 notImm2.link(this);
762 if (!types.second().definitelyIsNumber())
763 emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
764 convertInt32ToDouble(regT0, fpRegT1);
765 op2isDouble.link(this);
93a37866
A
766 add64(tagTypeNumberRegister, regT1);
767 move64ToDouble(regT1, fpRegT2);
f9bf01c6
A
768 op2wasInteger.link(this);
769 }
9dae56ea
A
770
771 if (opcodeID == op_add)
ba379fdc 772 addDouble(fpRegT2, fpRegT1);
9dae56ea 773 else if (opcodeID == op_sub)
ba379fdc 774 subDouble(fpRegT2, fpRegT1);
f9bf01c6 775 else if (opcodeID == op_mul)
ba379fdc 776 mulDouble(fpRegT2, fpRegT1);
f9bf01c6
A
777 else {
778 ASSERT(opcodeID == op_div);
779 divDouble(fpRegT2, fpRegT1);
9dae56ea 780 }
93a37866
A
781 moveDoubleTo64(fpRegT1, regT0);
782 sub64(tagTypeNumberRegister, regT0);
ba379fdc 783 emitPutVirtualRegister(result, regT0);
9dae56ea
A
784
785 end.link(this);
786}
787
ba379fdc 788void JIT::emit_op_add(Instruction* currentInstruction)
9dae56ea 789{
81345200
A
790 int result = currentInstruction[1].u.operand;
791 int op1 = currentInstruction[2].u.operand;
792 int op2 = currentInstruction[3].u.operand;
9dae56ea
A
793 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
794
795 if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
6fe7ccc8 796 addSlowCase();
81345200
A
797 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add);
798 slowPathCall.call();
9dae56ea
A
799 return;
800 }
801
802 if (isOperandConstantImmediateInt(op1)) {
ba379fdc
A
803 emitGetVirtualRegister(op2, regT0);
804 emitJumpSlowCaseIfNotImmediateInteger(regT0);
6fe7ccc8
A
805 addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op1)), regT1));
806 emitFastArithIntToImmNoCheck(regT1, regT0);
9dae56ea 807 } else if (isOperandConstantImmediateInt(op2)) {
ba379fdc
A
808 emitGetVirtualRegister(op1, regT0);
809 emitJumpSlowCaseIfNotImmediateInteger(regT0);
6fe7ccc8
A
810 addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op2)), regT1));
811 emitFastArithIntToImmNoCheck(regT1, regT0);
9dae56ea
A
812 } else
813 compileBinaryArithOp(op_add, result, op1, op2, types);
814
815 emitPutVirtualRegister(result);
816}
ba379fdc
A
817
818void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 819{
81345200
A
820 int result = currentInstruction[1].u.operand;
821 int op1 = currentInstruction[2].u.operand;
822 int op2 = currentInstruction[3].u.operand;
f9bf01c6 823 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
9dae56ea 824
6fe7ccc8
A
825 if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
826 linkDummySlowCase(iter);
f9bf01c6 827 return;
6fe7ccc8 828 }
f9bf01c6
A
829
830 bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
831 bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
81345200 832 compileBinaryArithOpSlowCase(currentInstruction, op_add, iter, result, op1, op2, types, op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
9dae56ea
A
833}
834
ba379fdc 835void JIT::emit_op_mul(Instruction* currentInstruction)
9dae56ea 836{
81345200
A
837 int result = currentInstruction[1].u.operand;
838 int op1 = currentInstruction[2].u.operand;
839 int op2 = currentInstruction[3].u.operand;
9dae56ea
A
840 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
841
842 // For now, only plant a fast int case if the constant operand is greater than zero.
843 int32_t value;
844 if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
6fe7ccc8
A
845 // Add a special fast case profile because the DFG JIT will expect one.
846 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
ba379fdc
A
847 emitGetVirtualRegister(op2, regT0);
848 emitJumpSlowCaseIfNotImmediateInteger(regT0);
6fe7ccc8
A
849 addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1));
850 emitFastArithReTagImmediate(regT1, regT0);
9dae56ea 851 } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
6fe7ccc8
A
852 // Add a special fast case profile because the DFG JIT will expect one.
853 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
ba379fdc
A
854 emitGetVirtualRegister(op1, regT0);
855 emitJumpSlowCaseIfNotImmediateInteger(regT0);
6fe7ccc8
A
856 addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1));
857 emitFastArithReTagImmediate(regT1, regT0);
9dae56ea
A
858 } else
859 compileBinaryArithOp(op_mul, result, op1, op2, types);
860
861 emitPutVirtualRegister(result);
862}
ba379fdc
A
863
864void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 865{
81345200
A
866 int result = currentInstruction[1].u.operand;
867 int op1 = currentInstruction[2].u.operand;
868 int op2 = currentInstruction[3].u.operand;
9dae56ea
A
869 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
870
f9bf01c6
A
871 bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
872 bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
81345200 873 compileBinaryArithOpSlowCase(currentInstruction, op_mul, iter, result, op1, op2, types, op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
f9bf01c6
A
874}
875
876void JIT::emit_op_div(Instruction* currentInstruction)
877{
81345200
A
878 int dst = currentInstruction[1].u.operand;
879 int op1 = currentInstruction[2].u.operand;
880 int op2 = currentInstruction[3].u.operand;
f9bf01c6
A
881 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
882
883 if (isOperandConstantImmediateDouble(op1)) {
884 emitGetVirtualRegister(op1, regT0);
93a37866
A
885 add64(tagTypeNumberRegister, regT0);
886 move64ToDouble(regT0, fpRegT0);
f9bf01c6
A
887 } else if (isOperandConstantImmediateInt(op1)) {
888 emitLoadInt32ToDouble(op1, fpRegT0);
889 } else {
890 emitGetVirtualRegister(op1, regT0);
891 if (!types.first().definitelyIsNumber())
892 emitJumpSlowCaseIfNotImmediateNumber(regT0);
893 Jump notInt = emitJumpIfNotImmediateInteger(regT0);
894 convertInt32ToDouble(regT0, fpRegT0);
895 Jump skipDoubleLoad = jump();
896 notInt.link(this);
93a37866
A
897 add64(tagTypeNumberRegister, regT0);
898 move64ToDouble(regT0, fpRegT0);
f9bf01c6
A
899 skipDoubleLoad.link(this);
900 }
4e4e5a6f 901
f9bf01c6
A
902 if (isOperandConstantImmediateDouble(op2)) {
903 emitGetVirtualRegister(op2, regT1);
93a37866
A
904 add64(tagTypeNumberRegister, regT1);
905 move64ToDouble(regT1, fpRegT1);
f9bf01c6
A
906 } else if (isOperandConstantImmediateInt(op2)) {
907 emitLoadInt32ToDouble(op2, fpRegT1);
908 } else {
909 emitGetVirtualRegister(op2, regT1);
910 if (!types.second().definitelyIsNumber())
911 emitJumpSlowCaseIfNotImmediateNumber(regT1);
912 Jump notInt = emitJumpIfNotImmediateInteger(regT1);
913 convertInt32ToDouble(regT1, fpRegT1);
914 Jump skipDoubleLoad = jump();
915 notInt.link(this);
93a37866
A
916 add64(tagTypeNumberRegister, regT1);
917 move64ToDouble(regT1, fpRegT1);
f9bf01c6
A
918 skipDoubleLoad.link(this);
919 }
920 divDouble(fpRegT1, fpRegT0);
6fe7ccc8 921
6fe7ccc8
A
922 // Is the result actually an integer? The DFG JIT would really like to know. If it's
923 // not an integer, we increment a count. If this together with the slow case counter
924 // are below threshold then the DFG JIT will compile this division with a specualtion
925 // that the remainder is zero.
926
927 // As well, there are cases where a double result here would cause an important field
928 // in the heap to sometimes have doubles in it, resulting in double predictions getting
929 // propagated to a use site where it might cause damage (such as the index to an array
930 // access). So if we are DFG compiling anything in the program, we want this code to
931 // ensure that it produces integers whenever possible.
932
6fe7ccc8
A
933 JumpList notInteger;
934 branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1);
935 // If we've got an integer, we might as well make that the result of the division.
936 emitFastArithReTagImmediate(regT0, regT0);
937 Jump isInteger = jump();
938 notInteger.link(this);
93a37866
A
939 moveDoubleTo64(fpRegT0, regT0);
940 Jump doubleZero = branchTest64(Zero, regT0);
6fe7ccc8 941 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
93a37866
A
942 sub64(tagTypeNumberRegister, regT0);
943 Jump trueDouble = jump();
944 doubleZero.link(this);
945 move(tagTypeNumberRegister, regT0);
946 trueDouble.link(this);
6fe7ccc8 947 isInteger.link(this);
f9bf01c6
A
948
949 emitPutVirtualRegister(dst, regT0);
950}
951
952void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
953{
81345200
A
954 int op1 = currentInstruction[2].u.operand;
955 int op2 = currentInstruction[3].u.operand;
f9bf01c6
A
956 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
957 if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
81345200
A
958 if (!ASSERT_DISABLED)
959 abortWithReason(JITDivOperandsAreNotNumbers);
f9bf01c6
A
960 return;
961 }
962 if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
963 if (!types.first().definitelyIsNumber())
964 linkSlowCase(iter);
965 }
966 if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
967 if (!types.second().definitelyIsNumber())
968 linkSlowCase(iter);
969 }
970 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
81345200
A
971 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
972 slowPathCall.call();
9dae56ea
A
973}
974
ba379fdc 975void JIT::emit_op_sub(Instruction* currentInstruction)
9dae56ea 976{
81345200
A
977 int result = currentInstruction[1].u.operand;
978 int op1 = currentInstruction[2].u.operand;
979 int op2 = currentInstruction[3].u.operand;
9dae56ea
A
980 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
981
982 compileBinaryArithOp(op_sub, result, op1, op2, types);
9dae56ea
A
983 emitPutVirtualRegister(result);
984}
ba379fdc
A
985
986void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
9dae56ea 987{
81345200
A
988 int result = currentInstruction[1].u.operand;
989 int op1 = currentInstruction[2].u.operand;
990 int op2 = currentInstruction[3].u.operand;
9dae56ea
A
991 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
992
81345200 993 compileBinaryArithOpSlowCase(currentInstruction, op_sub, iter, result, op1, op2, types, false, false);
9dae56ea
A
994}
995
ba379fdc
A
996/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
997
6fe7ccc8
A
998#endif // USE(JSVALUE64)
999
9dae56ea
A
1000} // namespace JSC
1001
1002#endif // ENABLE(JIT)