2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 #include "CodeBlock.h"
32 #include "JITInlineMethods.h"
33 #include "JITStubCall.h"
35 #include "JSFunction.h"
36 #include "Interpreter.h"
37 #include "ResultType.h"
38 #include "SamplingTool.h"
50 void JIT::emit_op_negate(Instruction
* currentInstruction
)
52 unsigned dst
= currentInstruction
[1].u
.operand
;
53 unsigned src
= currentInstruction
[2].u
.operand
;
55 emitLoad(src
, regT1
, regT0
);
57 Jump srcNotInt
= branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
));
58 addSlowCase(branch32(Equal
, regT0
, Imm32(0)));
61 emitStoreInt32(dst
, regT0
, (dst
== src
));
66 addSlowCase(branch32(Above
, regT1
, Imm32(JSValue::LowestTag
)));
68 xor32(Imm32(1 << 31), regT1
);
69 store32(regT1
, tagFor(dst
));
71 store32(regT0
, payloadFor(dst
));
76 void JIT::emitSlow_op_negate(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
78 unsigned dst
= currentInstruction
[1].u
.operand
;
80 linkSlowCase(iter
); // 0 check
81 linkSlowCase(iter
); // double check
83 JITStubCall
stubCall(this, cti_op_negate
);
84 stubCall
.addArgument(regT1
, regT0
);
88 void JIT::emit_op_jnless(Instruction
* currentInstruction
)
90 unsigned op1
= currentInstruction
[1].u
.operand
;
91 unsigned op2
= currentInstruction
[2].u
.operand
;
92 unsigned target
= currentInstruction
[3].u
.operand
;
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
);
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
);
113 if (!supportsFloatingPoint()) {
114 addSlowCase(notInt32Op1
);
115 addSlowCase(notInt32Op2
);
121 emitBinaryDoubleOp(op_jnless
, target
, op1
, op2
, OperandTypes(), notInt32Op1
, notInt32Op2
, !isOperandConstantImmediateInt(op1
), isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
));
125 void JIT::emitSlow_op_jnless(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
127 unsigned op1
= currentInstruction
[1].u
.operand
;
128 unsigned op2
= currentInstruction
[2].u
.operand
;
129 unsigned target
= currentInstruction
[3].u
.operand
;
131 if (!supportsFloatingPoint()) {
132 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
133 linkSlowCase(iter
); // int32 check
134 linkSlowCase(iter
); // int32 check
136 if (!isOperandConstantImmediateInt(op1
)) {
137 linkSlowCase(iter
); // double check
138 linkSlowCase(iter
); // int32 check
140 if (isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
))
141 linkSlowCase(iter
); // double check
144 JITStubCall
stubCall(this, cti_op_jless
);
145 stubCall
.addArgument(op1
);
146 stubCall
.addArgument(op2
);
148 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
151 void JIT::emit_op_jless(Instruction
* currentInstruction
)
153 unsigned op1
= currentInstruction
[1].u
.operand
;
154 unsigned op2
= currentInstruction
[2].u
.operand
;
155 unsigned target
= currentInstruction
[3].u
.operand
;
157 JumpList notInt32Op1
;
158 JumpList notInt32Op2
;
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
);
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
);
176 if (!supportsFloatingPoint()) {
177 addSlowCase(notInt32Op1
);
178 addSlowCase(notInt32Op2
);
184 emitBinaryDoubleOp(op_jless
, target
, op1
, op2
, OperandTypes(), notInt32Op1
, notInt32Op2
, !isOperandConstantImmediateInt(op1
), isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
));
188 void JIT::emitSlow_op_jless(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
190 unsigned op1
= currentInstruction
[1].u
.operand
;
191 unsigned op2
= currentInstruction
[2].u
.operand
;
192 unsigned target
= currentInstruction
[3].u
.operand
;
194 if (!supportsFloatingPoint()) {
195 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
196 linkSlowCase(iter
); // int32 check
197 linkSlowCase(iter
); // int32 check
199 if (!isOperandConstantImmediateInt(op1
)) {
200 linkSlowCase(iter
); // double check
201 linkSlowCase(iter
); // int32 check
203 if (isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
))
204 linkSlowCase(iter
); // double check
207 JITStubCall
stubCall(this, cti_op_jless
);
208 stubCall
.addArgument(op1
);
209 stubCall
.addArgument(op2
);
211 emitJumpSlowToHot(branchTest32(NonZero
, regT0
), target
);
214 void JIT::emit_op_jnlesseq(Instruction
* currentInstruction
)
216 unsigned op1
= currentInstruction
[1].u
.operand
;
217 unsigned op2
= currentInstruction
[2].u
.operand
;
218 unsigned target
= currentInstruction
[3].u
.operand
;
220 JumpList notInt32Op1
;
221 JumpList notInt32Op2
;
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
);
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
);
239 if (!supportsFloatingPoint()) {
240 addSlowCase(notInt32Op1
);
241 addSlowCase(notInt32Op2
);
247 emitBinaryDoubleOp(op_jnlesseq
, target
, op1
, op2
, OperandTypes(), notInt32Op1
, notInt32Op2
, !isOperandConstantImmediateInt(op1
), isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
));
251 void JIT::emitSlow_op_jnlesseq(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
253 unsigned op1
= currentInstruction
[1].u
.operand
;
254 unsigned op2
= currentInstruction
[2].u
.operand
;
255 unsigned target
= currentInstruction
[3].u
.operand
;
257 if (!supportsFloatingPoint()) {
258 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
259 linkSlowCase(iter
); // int32 check
260 linkSlowCase(iter
); // int32 check
262 if (!isOperandConstantImmediateInt(op1
)) {
263 linkSlowCase(iter
); // double check
264 linkSlowCase(iter
); // int32 check
266 if (isOperandConstantImmediateInt(op1
) || !isOperandConstantImmediateInt(op2
))
267 linkSlowCase(iter
); // double check
270 JITStubCall
stubCall(this, cti_op_jlesseq
);
271 stubCall
.addArgument(op1
);
272 stubCall
.addArgument(op2
);
274 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
279 void JIT::emit_op_lshift(Instruction
* currentInstruction
)
281 unsigned dst
= currentInstruction
[1].u
.operand
;
282 unsigned op1
= currentInstruction
[2].u
.operand
;
283 unsigned op2
= currentInstruction
[3].u
.operand
;
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
);
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
);
301 void JIT::emitSlow_op_lshift(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
303 unsigned dst
= currentInstruction
[1].u
.operand
;
304 unsigned op1
= currentInstruction
[2].u
.operand
;
305 unsigned op2
= currentInstruction
[3].u
.operand
;
307 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
308 linkSlowCase(iter
); // int32 check
309 linkSlowCase(iter
); // int32 check
311 JITStubCall
stubCall(this, cti_op_lshift
);
312 stubCall
.addArgument(op1
);
313 stubCall
.addArgument(op2
);
319 void JIT::emit_op_rshift(Instruction
* currentInstruction
)
321 unsigned dst
= currentInstruction
[1].u
.operand
;
322 unsigned op1
= currentInstruction
[2].u
.operand
;
323 unsigned op2
= currentInstruction
[3].u
.operand
;
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
);
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
);
341 void JIT::emitSlow_op_rshift(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
343 unsigned dst
= currentInstruction
[1].u
.operand
;
344 unsigned op1
= currentInstruction
[2].u
.operand
;
345 unsigned op2
= currentInstruction
[3].u
.operand
;
347 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
348 linkSlowCase(iter
); // int32 check
349 linkSlowCase(iter
); // int32 check
351 JITStubCall
stubCall(this, cti_op_rshift
);
352 stubCall
.addArgument(op1
);
353 stubCall
.addArgument(op2
);
359 void JIT::emit_op_bitand(Instruction
* currentInstruction
)
361 unsigned dst
= currentInstruction
[1].u
.operand
;
362 unsigned op1
= currentInstruction
[2].u
.operand
;
363 unsigned op2
= currentInstruction
[3].u
.operand
;
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
));
375 emitLoad2(op1
, regT1
, regT0
, op2
, regT3
, regT2
);
376 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
377 addSlowCase(branch32(NotEqual
, regT3
, Imm32(JSValue::Int32Tag
)));
379 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
382 void JIT::emitSlow_op_bitand(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
384 unsigned dst
= currentInstruction
[1].u
.operand
;
385 unsigned op1
= currentInstruction
[2].u
.operand
;
386 unsigned op2
= currentInstruction
[3].u
.operand
;
388 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
389 linkSlowCase(iter
); // int32 check
390 linkSlowCase(iter
); // int32 check
392 JITStubCall
stubCall(this, cti_op_bitand
);
393 stubCall
.addArgument(op1
);
394 stubCall
.addArgument(op2
);
400 void JIT::emit_op_bitor(Instruction
* currentInstruction
)
402 unsigned dst
= currentInstruction
[1].u
.operand
;
403 unsigned op1
= currentInstruction
[2].u
.operand
;
404 unsigned op2
= currentInstruction
[3].u
.operand
;
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
));
416 emitLoad2(op1
, regT1
, regT0
, op2
, regT3
, regT2
);
417 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
418 addSlowCase(branch32(NotEqual
, regT3
, Imm32(JSValue::Int32Tag
)));
420 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
423 void JIT::emitSlow_op_bitor(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
425 unsigned dst
= currentInstruction
[1].u
.operand
;
426 unsigned op1
= currentInstruction
[2].u
.operand
;
427 unsigned op2
= currentInstruction
[3].u
.operand
;
429 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
430 linkSlowCase(iter
); // int32 check
431 linkSlowCase(iter
); // int32 check
433 JITStubCall
stubCall(this, cti_op_bitor
);
434 stubCall
.addArgument(op1
);
435 stubCall
.addArgument(op2
);
441 void JIT::emit_op_bitxor(Instruction
* currentInstruction
)
443 unsigned dst
= currentInstruction
[1].u
.operand
;
444 unsigned op1
= currentInstruction
[2].u
.operand
;
445 unsigned op2
= currentInstruction
[3].u
.operand
;
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
));
457 emitLoad2(op1
, regT1
, regT0
, op2
, regT3
, regT2
);
458 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
459 addSlowCase(branch32(NotEqual
, regT3
, Imm32(JSValue::Int32Tag
)));
461 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
464 void JIT::emitSlow_op_bitxor(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
466 unsigned dst
= currentInstruction
[1].u
.operand
;
467 unsigned op1
= currentInstruction
[2].u
.operand
;
468 unsigned op2
= currentInstruction
[3].u
.operand
;
470 if (!isOperandConstantImmediateInt(op1
) && !isOperandConstantImmediateInt(op2
))
471 linkSlowCase(iter
); // int32 check
472 linkSlowCase(iter
); // int32 check
474 JITStubCall
stubCall(this, cti_op_bitxor
);
475 stubCall
.addArgument(op1
);
476 stubCall
.addArgument(op2
);
482 void JIT::emit_op_bitnot(Instruction
* currentInstruction
)
484 unsigned dst
= currentInstruction
[1].u
.operand
;
485 unsigned src
= currentInstruction
[2].u
.operand
;
487 emitLoad(src
, regT1
, regT0
);
488 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
491 emitStoreInt32(dst
, regT0
, (dst
== src
));
494 void JIT::emitSlow_op_bitnot(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
496 unsigned dst
= currentInstruction
[1].u
.operand
;
498 linkSlowCase(iter
); // int32 check
500 JITStubCall
stubCall(this, cti_op_bitnot
);
501 stubCall
.addArgument(regT1
, regT0
);
507 void JIT::emit_op_post_inc(Instruction
* currentInstruction
)
509 unsigned dst
= currentInstruction
[1].u
.operand
;
510 unsigned srcDst
= currentInstruction
[2].u
.operand
;
512 emitLoad(srcDst
, regT1
, regT0
);
513 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
515 if (dst
== srcDst
) // x = x++ is a noop for ints.
518 emitStoreInt32(dst
, regT0
);
520 addSlowCase(branchAdd32(Overflow
, Imm32(1), regT0
));
521 emitStoreInt32(srcDst
, regT0
, true);
524 void JIT::emitSlow_op_post_inc(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
526 unsigned dst
= currentInstruction
[1].u
.operand
;
527 unsigned srcDst
= currentInstruction
[2].u
.operand
;
529 linkSlowCase(iter
); // int32 check
531 linkSlowCase(iter
); // overflow check
533 JITStubCall
stubCall(this, cti_op_post_inc
);
534 stubCall
.addArgument(srcDst
);
535 stubCall
.addArgument(Imm32(srcDst
));
541 void JIT::emit_op_post_dec(Instruction
* currentInstruction
)
543 unsigned dst
= currentInstruction
[1].u
.operand
;
544 unsigned srcDst
= currentInstruction
[2].u
.operand
;
546 emitLoad(srcDst
, regT1
, regT0
);
547 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
549 if (dst
== srcDst
) // x = x-- is a noop for ints.
552 emitStoreInt32(dst
, regT0
);
554 addSlowCase(branchSub32(Overflow
, Imm32(1), regT0
));
555 emitStoreInt32(srcDst
, regT0
, true);
558 void JIT::emitSlow_op_post_dec(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
560 unsigned dst
= currentInstruction
[1].u
.operand
;
561 unsigned srcDst
= currentInstruction
[2].u
.operand
;
563 linkSlowCase(iter
); // int32 check
565 linkSlowCase(iter
); // overflow check
567 JITStubCall
stubCall(this, cti_op_post_dec
);
568 stubCall
.addArgument(srcDst
);
569 stubCall
.addArgument(Imm32(srcDst
));
575 void JIT::emit_op_pre_inc(Instruction
* currentInstruction
)
577 unsigned srcDst
= currentInstruction
[1].u
.operand
;
579 emitLoad(srcDst
, regT1
, regT0
);
581 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
582 addSlowCase(branchAdd32(Overflow
, Imm32(1), regT0
));
583 emitStoreInt32(srcDst
, regT0
, true);
586 void JIT::emitSlow_op_pre_inc(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
588 unsigned srcDst
= currentInstruction
[1].u
.operand
;
590 linkSlowCase(iter
); // int32 check
591 linkSlowCase(iter
); // overflow check
593 JITStubCall
stubCall(this, cti_op_pre_inc
);
594 stubCall
.addArgument(srcDst
);
595 stubCall
.call(srcDst
);
600 void JIT::emit_op_pre_dec(Instruction
* currentInstruction
)
602 unsigned srcDst
= currentInstruction
[1].u
.operand
;
604 emitLoad(srcDst
, regT1
, regT0
);
606 addSlowCase(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
607 addSlowCase(branchSub32(Overflow
, Imm32(1), regT0
));
608 emitStoreInt32(srcDst
, regT0
, true);
611 void JIT::emitSlow_op_pre_dec(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
613 unsigned srcDst
= currentInstruction
[1].u
.operand
;
615 linkSlowCase(iter
); // int32 check
616 linkSlowCase(iter
); // overflow check
618 JITStubCall
stubCall(this, cti_op_pre_dec
);
619 stubCall
.addArgument(srcDst
);
620 stubCall
.call(srcDst
);
625 void JIT::emit_op_add(Instruction
* currentInstruction
)
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
);
632 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber()) {
633 JITStubCall
stubCall(this, cti_op_add
);
634 stubCall
.addArgument(op1
);
635 stubCall
.addArgument(op2
);
640 JumpList notInt32Op1
;
641 JumpList notInt32Op2
;
645 if (getOperandConstantImmediateInt(op1
, op2
, op
, constant
)) {
646 emitAdd32Constant(dst
, op
, constant
, op
== op1
? types
.first() : types
.second());
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
)));
655 addSlowCase(branchAdd32(Overflow
, regT2
, regT0
));
656 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
658 if (!supportsFloatingPoint()) {
659 addSlowCase(notInt32Op1
);
660 addSlowCase(notInt32Op2
);
666 emitBinaryDoubleOp(op_add
, dst
, op1
, op2
, types
, notInt32Op1
, notInt32Op2
);
670 void JIT::emitAdd32Constant(unsigned dst
, unsigned op
, int32_t constant
, ResultType opType
)
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
));
679 if (!supportsFloatingPoint()) {
680 addSlowCase(notInt32
);
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
);
697 void JIT::emitSlow_op_add(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
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
);
704 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber())
709 if (getOperandConstantImmediateInt(op1
, op2
, op
, constant
)) {
710 linkSlowCase(iter
); // overflow check
712 if (!supportsFloatingPoint())
713 linkSlowCase(iter
); // non-sse case
715 ResultType opType
= op
== op1
? types
.first() : types
.second();
716 if (!opType
.definitelyIsNumber())
717 linkSlowCase(iter
); // double check
720 linkSlowCase(iter
); // overflow check
722 if (!supportsFloatingPoint()) {
723 linkSlowCase(iter
); // int32 check
724 linkSlowCase(iter
); // int32 check
726 if (!types
.first().definitelyIsNumber())
727 linkSlowCase(iter
); // double check
729 if (!types
.second().definitelyIsNumber()) {
730 linkSlowCase(iter
); // int32 check
731 linkSlowCase(iter
); // double check
736 JITStubCall
stubCall(this, cti_op_add
);
737 stubCall
.addArgument(op1
);
738 stubCall
.addArgument(op2
);
744 void JIT::emit_op_sub(Instruction
* currentInstruction
)
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
);
751 JumpList notInt32Op1
;
752 JumpList notInt32Op2
;
754 if (isOperandConstantImmediateInt(op2
)) {
755 emitSub32Constant(dst
, op1
, getConstantOperand(op2
).asInt32(), types
.first());
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
)));
764 addSlowCase(branchSub32(Overflow
, regT2
, regT0
));
765 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
767 if (!supportsFloatingPoint()) {
768 addSlowCase(notInt32Op1
);
769 addSlowCase(notInt32Op2
);
775 emitBinaryDoubleOp(op_sub
, dst
, op1
, op2
, types
, notInt32Op1
, notInt32Op2
);
779 void JIT::emitSub32Constant(unsigned dst
, unsigned op
, int32_t constant
, ResultType opType
)
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
));
788 if (!supportsFloatingPoint()) {
789 addSlowCase(notInt32
);
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
);
806 void JIT::emitSlow_op_sub(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
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
);
813 if (isOperandConstantImmediateInt(op2
)) {
814 linkSlowCase(iter
); // overflow check
816 if (!supportsFloatingPoint() || !types
.first().definitelyIsNumber())
817 linkSlowCase(iter
); // int32 or double check
819 linkSlowCase(iter
); // overflow check
821 if (!supportsFloatingPoint()) {
822 linkSlowCase(iter
); // int32 check
823 linkSlowCase(iter
); // int32 check
825 if (!types
.first().definitelyIsNumber())
826 linkSlowCase(iter
); // double check
828 if (!types
.second().definitelyIsNumber()) {
829 linkSlowCase(iter
); // int32 check
830 linkSlowCase(iter
); // double check
835 JITStubCall
stubCall(this, cti_op_sub
);
836 stubCall
.addArgument(op1
);
837 stubCall
.addArgument(op2
);
841 void JIT::emitBinaryDoubleOp(OpcodeID opcodeID
, unsigned dst
, unsigned op1
, unsigned op2
, OperandTypes types
, JumpList
& notInt32Op1
, JumpList
& notInt32Op2
, bool op1IsInRegisters
, bool op2IsInRegisters
)
845 if (!notInt32Op1
.empty()) {
846 // Double case 1: Op1 is not int32; Op2 is unknown.
847 notInt32Op1
.link(this);
849 ASSERT(op1IsInRegisters
);
851 // Verify Op1 is double.
852 if (!types
.first().definitelyIsNumber())
853 addSlowCase(branch32(Above
, regT1
, Imm32(JSValue::LowestTag
)));
855 if (!op2IsInRegisters
)
856 emitLoad(op2
, regT3
, regT2
);
858 Jump doubleOp2
= branch32(Below
, regT3
, Imm32(JSValue::LowestTag
));
860 if (!types
.second().definitelyIsNumber())
861 addSlowCase(branch32(NotEqual
, regT3
, Imm32(JSValue::Int32Tag
)));
863 convertInt32ToDouble(regT2
, fpRegT0
);
864 Jump doTheMath
= jump();
866 // Load Op2 as double into double register.
867 doubleOp2
.link(this);
868 emitLoadDouble(op2
, fpRegT0
);
871 doTheMath
.link(this);
874 emitLoadDouble(op1
, fpRegT2
);
875 mulDouble(fpRegT2
, fpRegT0
);
876 emitStoreDouble(dst
, fpRegT0
);
879 emitLoadDouble(op1
, fpRegT2
);
880 addDouble(fpRegT2
, fpRegT0
);
881 emitStoreDouble(dst
, fpRegT0
);
884 emitLoadDouble(op1
, fpRegT1
);
885 subDouble(fpRegT0
, fpRegT1
);
886 emitStoreDouble(dst
, fpRegT1
);
889 emitLoadDouble(op1
, fpRegT1
);
890 divDouble(fpRegT0
, fpRegT1
);
891 emitStoreDouble(dst
, fpRegT1
);
894 emitLoadDouble(op1
, fpRegT2
);
895 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered
, fpRegT0
, fpRegT2
), dst
);
898 emitLoadDouble(op1
, fpRegT2
);
899 addJump(branchDouble(DoubleLessThan
, fpRegT2
, fpRegT0
), dst
);
902 emitLoadDouble(op1
, fpRegT2
);
903 addJump(branchDouble(DoubleLessThanOrUnordered
, fpRegT0
, fpRegT2
), dst
);
906 ASSERT_NOT_REACHED();
909 if (!notInt32Op2
.empty())
913 if (!notInt32Op2
.empty()) {
914 // Double case 2: Op1 is int32; Op2 is not int32.
915 notInt32Op2
.link(this);
917 ASSERT(op2IsInRegisters
);
919 if (!op1IsInRegisters
)
920 emitLoadPayload(op1
, regT0
);
922 convertInt32ToDouble(regT0
, fpRegT0
);
924 // Verify op2 is double.
925 if (!types
.second().definitelyIsNumber())
926 addSlowCase(branch32(Above
, regT3
, Imm32(JSValue::LowestTag
)));
931 emitLoadDouble(op2
, fpRegT2
);
932 mulDouble(fpRegT2
, fpRegT0
);
933 emitStoreDouble(dst
, fpRegT0
);
936 emitLoadDouble(op2
, fpRegT2
);
937 addDouble(fpRegT2
, fpRegT0
);
938 emitStoreDouble(dst
, fpRegT0
);
941 emitLoadDouble(op2
, fpRegT2
);
942 subDouble(fpRegT2
, fpRegT0
);
943 emitStoreDouble(dst
, fpRegT0
);
946 emitLoadDouble(op2
, fpRegT2
);
947 divDouble(fpRegT2
, fpRegT0
);
948 emitStoreDouble(dst
, fpRegT0
);
951 emitLoadDouble(op2
, fpRegT1
);
952 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered
, fpRegT1
, fpRegT0
), dst
);
955 emitLoadDouble(op2
, fpRegT1
);
956 addJump(branchDouble(DoubleLessThan
, fpRegT0
, fpRegT1
), dst
);
959 emitLoadDouble(op2
, fpRegT1
);
960 addJump(branchDouble(DoubleLessThanOrUnordered
, fpRegT1
, fpRegT0
), dst
);
963 ASSERT_NOT_REACHED();
970 // Multiplication (*)
972 void JIT::emit_op_mul(Instruction
* currentInstruction
)
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
);
979 JumpList notInt32Op1
;
980 JumpList notInt32Op2
;
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
)));
988 addSlowCase(branchMul32(Overflow
, regT2
, regT0
));
989 addSlowCase(branchTest32(Zero
, regT0
));
990 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
992 if (!supportsFloatingPoint()) {
993 addSlowCase(notInt32Op1
);
994 addSlowCase(notInt32Op2
);
1000 emitBinaryDoubleOp(op_mul
, dst
, op1
, op2
, types
, notInt32Op1
, notInt32Op2
);
1004 void JIT::emitSlow_op_mul(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
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
);
1011 Jump overflow
= getSlowCase(iter
); // overflow check
1012 linkSlowCase(iter
); // zero result check
1014 Jump negZero
= branchOr32(Signed
, regT2
, regT3
);
1015 emitStoreInt32(dst
, Imm32(0), (op1
== dst
|| op2
== dst
));
1017 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul
));
1020 overflow
.link(this);
1022 if (!supportsFloatingPoint()) {
1023 linkSlowCase(iter
); // int32 check
1024 linkSlowCase(iter
); // int32 check
1027 if (supportsFloatingPoint()) {
1028 if (!types
.first().definitelyIsNumber())
1029 linkSlowCase(iter
); // double check
1031 if (!types
.second().definitelyIsNumber()) {
1032 linkSlowCase(iter
); // int32 check
1033 linkSlowCase(iter
); // double check
1037 Label
jitStubCall(this);
1038 JITStubCall
stubCall(this, cti_op_mul
);
1039 stubCall
.addArgument(op1
);
1040 stubCall
.addArgument(op2
);
1046 void JIT::emit_op_div(Instruction
* currentInstruction
)
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
);
1053 if (!supportsFloatingPoint()) {
1054 addSlowCase(jump());
1059 JumpList notInt32Op1
;
1060 JumpList notInt32Op2
;
1064 emitLoad2(op1
, regT1
, regT0
, op2
, regT3
, regT2
);
1066 notInt32Op1
.append(branch32(NotEqual
, regT1
, Imm32(JSValue::Int32Tag
)));
1067 notInt32Op2
.append(branch32(NotEqual
, regT3
, Imm32(JSValue::Int32Tag
)));
1069 convertInt32ToDouble(regT0
, fpRegT0
);
1070 convertInt32ToDouble(regT2
, fpRegT1
);
1071 divDouble(fpRegT1
, fpRegT0
);
1073 JumpList doubleResult
;
1074 branchConvertDoubleToInt32(fpRegT0
, regT0
, doubleResult
, fpRegT1
);
1077 emitStoreInt32(dst
, regT0
, (op1
== dst
|| op2
== dst
));
1081 doubleResult
.link(this);
1082 emitStoreDouble(dst
, fpRegT0
);
1086 emitBinaryDoubleOp(op_div
, dst
, op1
, op2
, types
, notInt32Op1
, notInt32Op2
);
1090 void JIT::emitSlow_op_div(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
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
);
1097 if (!supportsFloatingPoint())
1100 if (!types
.first().definitelyIsNumber())
1101 linkSlowCase(iter
); // double check
1103 if (!types
.second().definitelyIsNumber()) {
1104 linkSlowCase(iter
); // int32 check
1105 linkSlowCase(iter
); // double check
1109 JITStubCall
stubCall(this, cti_op_div
);
1110 stubCall
.addArgument(op1
);
1111 stubCall
.addArgument(op2
);
1117 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
1119 #if CPU(X86) || CPU(X86_64)
1121 void JIT::emit_op_mod(Instruction
* currentInstruction
)
1123 unsigned dst
= currentInstruction
[1].u
.operand
;
1124 unsigned op1
= currentInstruction
[2].u
.operand
;
1125 unsigned op2
= currentInstruction
[3].u
.operand
;
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
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
)));
1138 addSlowCase(branch32(Equal
, X86Registers::eax
, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1139 addSlowCase(branch32(Equal
, X86Registers::ecx
, Imm32(0))); // divide by 0
1142 move(X86Registers::eax
, X86Registers::ebx
); // Save dividend payload, in case of 0.
1144 m_assembler
.idivl_r(X86Registers::ecx
);
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));
1152 storeResult1
.link(this);
1153 storeResult2
.link(this);
1154 emitStoreInt32(dst
, X86Registers::edx
, (op1
== dst
|| op2
== dst
));
1158 void JIT::emitSlow_op_mod(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1160 unsigned dst
= currentInstruction
[1].u
.operand
;
1161 unsigned op1
= currentInstruction
[2].u
.operand
;
1162 unsigned op2
= currentInstruction
[3].u
.operand
;
1164 if (isOperandConstantImmediateInt(op2
) && getConstantOperand(op2
).asInt32() != 0) {
1165 linkSlowCase(iter
); // int32 check
1166 if (getConstantOperand(op2
).asInt32() == -1)
1167 linkSlowCase(iter
); // 0x80000000 check
1169 linkSlowCase(iter
); // int32 check
1170 linkSlowCase(iter
); // int32 check
1171 linkSlowCase(iter
); // 0 check
1172 linkSlowCase(iter
); // 0x80000000 check
1175 JITStubCall
stubCall(this, cti_op_mod
);
1176 stubCall
.addArgument(op1
);
1177 stubCall
.addArgument(op2
);
1181 #else // CPU(X86) || CPU(X86_64)
1183 void JIT::emit_op_mod(Instruction
* currentInstruction
)
1185 unsigned dst
= currentInstruction
[1].u
.operand
;
1186 unsigned op1
= currentInstruction
[2].u
.operand
;
1187 unsigned op2
= currentInstruction
[3].u
.operand
;
1189 JITStubCall
stubCall(this, cti_op_mod
);
1190 stubCall
.addArgument(op1
);
1191 stubCall
.addArgument(op2
);
1195 void JIT::emitSlow_op_mod(Instruction
*, Vector
<SlowCaseEntry
>::iterator
&)
1199 #endif // CPU(X86) || CPU(X86_64)
1201 /* ------------------------------ END: OP_MOD ------------------------------ */
1203 #else // USE(JSVALUE32_64)
1205 void JIT::emit_op_lshift(Instruction
* currentInstruction
)
1207 unsigned result
= currentInstruction
[1].u
.operand
;
1208 unsigned op1
= currentInstruction
[2].u
.operand
;
1209 unsigned op2
= currentInstruction
[3].u
.operand
;
1211 emitGetVirtualRegisters(op1
, regT0
, op2
, regT2
);
1212 // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
1213 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1214 emitJumpSlowCaseIfNotImmediateInteger(regT2
);
1215 emitFastArithImmToInt(regT0
);
1216 emitFastArithImmToInt(regT2
);
1217 lshift32(regT2
, regT0
);
1219 addSlowCase(branchAdd32(Overflow
, regT0
, regT0
));
1220 signExtend32ToPtr(regT0
, regT0
);
1222 emitFastArithReTagImmediate(regT0
, regT0
);
1223 emitPutVirtualRegister(result
);
1226 void JIT::emitSlow_op_lshift(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1228 unsigned result
= currentInstruction
[1].u
.operand
;
1229 unsigned op1
= currentInstruction
[2].u
.operand
;
1230 unsigned op2
= currentInstruction
[3].u
.operand
;
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
);
1242 emitGetVirtualRegisters(op1
, regT0
, op2
, regT2
);
1246 JITStubCall
stubCall(this, cti_op_lshift
);
1247 stubCall
.addArgument(regT0
);
1248 stubCall
.addArgument(regT2
);
1249 stubCall
.call(result
);
1252 void JIT::emit_op_rshift(Instruction
* currentInstruction
)
1254 unsigned result
= currentInstruction
[1].u
.operand
;
1255 unsigned op1
= currentInstruction
[2].u
.operand
;
1256 unsigned op2
= currentInstruction
[3].u
.operand
;
1258 if (isOperandConstantImmediateInt(op2
)) {
1259 // isOperandConstantImmediateInt(op2) => 1 SlowCase
1260 emitGetVirtualRegister(op1
, regT0
);
1261 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1262 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
1263 rshift32(Imm32(getConstantOperandImmediateInt(op2
) & 0x1f), regT0
);
1265 emitGetVirtualRegisters(op1
, regT0
, op2
, regT2
);
1266 if (supportsFloatingPointTruncate()) {
1267 Jump lhsIsInt
= emitJumpIfImmediateInteger(regT0
);
1269 // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
1270 addSlowCase(emitJumpIfNotImmediateNumber(regT0
));
1271 addPtr(tagTypeNumberRegister
, regT0
);
1272 movePtrToDouble(regT0
, fpRegT0
);
1273 addSlowCase(branchTruncateDoubleToInt32(fpRegT0
, regT0
));
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
));
1282 lhsIsInt
.link(this);
1283 emitJumpSlowCaseIfNotImmediateInteger(regT2
);
1285 // !supportsFloatingPoint() => 2 SlowCases
1286 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1287 emitJumpSlowCaseIfNotImmediateInteger(regT2
);
1289 emitFastArithImmToInt(regT2
);
1290 rshift32(regT2
, regT0
);
1292 signExtend32ToPtr(regT0
, regT0
);
1296 emitFastArithIntToImmNoCheck(regT0
, regT0
);
1298 orPtr(Imm32(JSImmediate::TagTypeNumber
), regT0
);
1300 emitPutVirtualRegister(result
);
1303 void JIT::emitSlow_op_rshift(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1305 unsigned result
= currentInstruction
[1].u
.operand
;
1306 unsigned op1
= currentInstruction
[2].u
.operand
;
1307 unsigned op2
= currentInstruction
[3].u
.operand
;
1309 JITStubCall
stubCall(this, cti_op_rshift
);
1311 if (isOperandConstantImmediateInt(op2
)) {
1313 stubCall
.addArgument(regT0
);
1314 stubCall
.addArgument(op2
, regT2
);
1316 if (supportsFloatingPointTruncate()) {
1322 linkSlowCaseIfNotJSCell(iter
, op1
);
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(op1
, regT0
);
1332 stubCall
.addArgument(regT2
);
1336 stubCall
.addArgument(regT0
);
1337 stubCall
.addArgument(regT2
);
1341 stubCall
.call(result
);
1344 void JIT::emit_op_jnless(Instruction
* currentInstruction
)
1346 unsigned op1
= currentInstruction
[1].u
.operand
;
1347 unsigned op2
= currentInstruction
[2].u
.operand
;
1348 unsigned target
= currentInstruction
[3].u
.operand
;
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
1355 if (isOperandConstantImmediateInt(op2
)) {
1356 emitGetVirtualRegister(op1
, regT0
);
1357 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1359 int32_t op2imm
= getConstantOperandImmediateInt(op2
);
1361 int32_t op2imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2
)));
1363 addJump(branch32(GreaterThanOrEqual
, regT0
, Imm32(op2imm
)), target
);
1364 } else if (isOperandConstantImmediateInt(op1
)) {
1365 emitGetVirtualRegister(op2
, regT1
);
1366 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1368 int32_t op1imm
= getConstantOperandImmediateInt(op1
);
1370 int32_t op1imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1
)));
1372 addJump(branch32(LessThanOrEqual
, regT1
, Imm32(op1imm
)), target
);
1374 emitGetVirtualRegisters(op1
, regT0
, op2
, regT1
);
1375 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1376 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1378 addJump(branch32(GreaterThanOrEqual
, regT0
, regT1
), target
);
1382 void JIT::emitSlow_op_jnless(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1384 unsigned op1
= currentInstruction
[1].u
.operand
;
1385 unsigned op2
= currentInstruction
[2].u
.operand
;
1386 unsigned target
= currentInstruction
[3].u
.operand
;
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.
1393 if (isOperandConstantImmediateInt(op2
)) {
1396 if (supportsFloatingPoint()) {
1398 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1399 addPtr(tagTypeNumberRegister
, regT0
);
1400 movePtrToDouble(regT0
, fpRegT0
);
1403 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1404 fail1
= emitJumpIfNotJSCell(regT0
);
1406 Jump fail2
= checkStructure(regT0
, m_globalData
->numberStructure
.get());
1407 loadDouble(Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
1410 int32_t op2imm
= getConstantOperand(op2
).asInt32();;
1412 move(Imm32(op2imm
), regT1
);
1413 convertInt32ToDouble(regT1
, fpRegT1
);
1415 emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered
, fpRegT1
, fpRegT0
), target
);
1417 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1422 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1428 JITStubCall
stubCall(this, cti_op_jless
);
1429 stubCall
.addArgument(regT0
);
1430 stubCall
.addArgument(op2
, regT2
);
1432 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1434 } else if (isOperandConstantImmediateInt(op1
)) {
1437 if (supportsFloatingPoint()) {
1439 Jump fail1
= emitJumpIfNotImmediateNumber(regT1
);
1440 addPtr(tagTypeNumberRegister
, regT1
);
1441 movePtrToDouble(regT1
, fpRegT1
);
1444 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1445 fail1
= emitJumpIfNotJSCell(regT1
);
1447 Jump fail2
= checkStructure(regT1
, m_globalData
->numberStructure
.get());
1448 loadDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT1
);
1451 int32_t op1imm
= getConstantOperand(op1
).asInt32();;
1453 move(Imm32(op1imm
), regT0
);
1454 convertInt32ToDouble(regT0
, fpRegT0
);
1456 emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered
, fpRegT1
, fpRegT0
), target
);
1458 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1463 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1469 JITStubCall
stubCall(this, cti_op_jless
);
1470 stubCall
.addArgument(op1
, regT2
);
1471 stubCall
.addArgument(regT1
);
1473 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1478 if (supportsFloatingPoint()) {
1480 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1481 Jump fail2
= emitJumpIfNotImmediateNumber(regT1
);
1482 Jump fail3
= emitJumpIfImmediateInteger(regT1
);
1483 addPtr(tagTypeNumberRegister
, regT0
);
1484 addPtr(tagTypeNumberRegister
, regT1
);
1485 movePtrToDouble(regT0
, fpRegT0
);
1486 movePtrToDouble(regT1
, fpRegT1
);
1489 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1490 fail1
= emitJumpIfNotJSCell(regT0
);
1493 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1494 fail2
= emitJumpIfNotJSCell(regT1
);
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
);
1502 emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered
, fpRegT1
, fpRegT0
), target
);
1504 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1511 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1513 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1521 JITStubCall
stubCall(this, cti_op_jless
);
1522 stubCall
.addArgument(regT0
);
1523 stubCall
.addArgument(regT1
);
1525 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1529 void JIT::emit_op_jless(Instruction
* currentInstruction
)
1531 unsigned op1
= currentInstruction
[1].u
.operand
;
1532 unsigned op2
= currentInstruction
[2].u
.operand
;
1533 unsigned target
= currentInstruction
[3].u
.operand
;
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
1540 if (isOperandConstantImmediateInt(op2
)) {
1541 emitGetVirtualRegister(op1
, regT0
);
1542 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1544 int32_t op2imm
= getConstantOperandImmediateInt(op2
);
1546 int32_t op2imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2
)));
1548 addJump(branch32(LessThan
, regT0
, Imm32(op2imm
)), target
);
1549 } else if (isOperandConstantImmediateInt(op1
)) {
1550 emitGetVirtualRegister(op2
, regT1
);
1551 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1553 int32_t op1imm
= getConstantOperandImmediateInt(op1
);
1555 int32_t op1imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1
)));
1557 addJump(branch32(GreaterThan
, regT1
, Imm32(op1imm
)), target
);
1559 emitGetVirtualRegisters(op1
, regT0
, op2
, regT1
);
1560 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1561 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1563 addJump(branch32(LessThan
, regT0
, regT1
), target
);
1567 void JIT::emitSlow_op_jless(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1569 unsigned op1
= currentInstruction
[1].u
.operand
;
1570 unsigned op2
= currentInstruction
[2].u
.operand
;
1571 unsigned target
= currentInstruction
[3].u
.operand
;
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.
1578 if (isOperandConstantImmediateInt(op2
)) {
1581 if (supportsFloatingPoint()) {
1583 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1584 addPtr(tagTypeNumberRegister
, regT0
);
1585 movePtrToDouble(regT0
, fpRegT0
);
1588 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1589 fail1
= emitJumpIfNotJSCell(regT0
);
1591 Jump fail2
= checkStructure(regT0
, m_globalData
->numberStructure
.get());
1592 loadDouble(Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
1595 int32_t op2imm
= getConstantOperand(op2
).asInt32();
1597 move(Imm32(op2imm
), regT1
);
1598 convertInt32ToDouble(regT1
, fpRegT1
);
1600 emitJumpSlowToHot(branchDouble(DoubleLessThan
, fpRegT0
, fpRegT1
), target
);
1602 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1607 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1613 JITStubCall
stubCall(this, cti_op_jless
);
1614 stubCall
.addArgument(regT0
);
1615 stubCall
.addArgument(op2
, regT2
);
1617 emitJumpSlowToHot(branchTest32(NonZero
, regT0
), target
);
1619 } else if (isOperandConstantImmediateInt(op1
)) {
1622 if (supportsFloatingPoint()) {
1624 Jump fail1
= emitJumpIfNotImmediateNumber(regT1
);
1625 addPtr(tagTypeNumberRegister
, regT1
);
1626 movePtrToDouble(regT1
, fpRegT1
);
1629 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1630 fail1
= emitJumpIfNotJSCell(regT1
);
1632 Jump fail2
= checkStructure(regT1
, m_globalData
->numberStructure
.get());
1633 loadDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT1
);
1636 int32_t op1imm
= getConstantOperand(op1
).asInt32();
1638 move(Imm32(op1imm
), regT0
);
1639 convertInt32ToDouble(regT0
, fpRegT0
);
1641 emitJumpSlowToHot(branchDouble(DoubleLessThan
, fpRegT0
, fpRegT1
), target
);
1643 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1648 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1654 JITStubCall
stubCall(this, cti_op_jless
);
1655 stubCall
.addArgument(op1
, regT2
);
1656 stubCall
.addArgument(regT1
);
1658 emitJumpSlowToHot(branchTest32(NonZero
, regT0
), target
);
1663 if (supportsFloatingPoint()) {
1665 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1666 Jump fail2
= emitJumpIfNotImmediateNumber(regT1
);
1667 Jump fail3
= emitJumpIfImmediateInteger(regT1
);
1668 addPtr(tagTypeNumberRegister
, regT0
);
1669 addPtr(tagTypeNumberRegister
, regT1
);
1670 movePtrToDouble(regT0
, fpRegT0
);
1671 movePtrToDouble(regT1
, fpRegT1
);
1674 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1675 fail1
= emitJumpIfNotJSCell(regT0
);
1678 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1679 fail2
= emitJumpIfNotJSCell(regT1
);
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
);
1687 emitJumpSlowToHot(branchDouble(DoubleLessThan
, fpRegT0
, fpRegT1
), target
);
1689 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless
));
1696 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1698 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1706 JITStubCall
stubCall(this, cti_op_jless
);
1707 stubCall
.addArgument(regT0
);
1708 stubCall
.addArgument(regT1
);
1710 emitJumpSlowToHot(branchTest32(NonZero
, regT0
), target
);
1714 void JIT::emit_op_jnlesseq(Instruction
* currentInstruction
)
1716 unsigned op1
= currentInstruction
[1].u
.operand
;
1717 unsigned op2
= currentInstruction
[2].u
.operand
;
1718 unsigned target
= currentInstruction
[3].u
.operand
;
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
1725 if (isOperandConstantImmediateInt(op2
)) {
1726 emitGetVirtualRegister(op1
, regT0
);
1727 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1729 int32_t op2imm
= getConstantOperandImmediateInt(op2
);
1731 int32_t op2imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2
)));
1733 addJump(branch32(GreaterThan
, regT0
, Imm32(op2imm
)), target
);
1734 } else if (isOperandConstantImmediateInt(op1
)) {
1735 emitGetVirtualRegister(op2
, regT1
);
1736 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1738 int32_t op1imm
= getConstantOperandImmediateInt(op1
);
1740 int32_t op1imm
= static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1
)));
1742 addJump(branch32(LessThan
, regT1
, Imm32(op1imm
)), target
);
1744 emitGetVirtualRegisters(op1
, regT0
, op2
, regT1
);
1745 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1746 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
1748 addJump(branch32(GreaterThan
, regT0
, regT1
), target
);
1752 void JIT::emitSlow_op_jnlesseq(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1754 unsigned op1
= currentInstruction
[1].u
.operand
;
1755 unsigned op2
= currentInstruction
[2].u
.operand
;
1756 unsigned target
= currentInstruction
[3].u
.operand
;
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.
1763 if (isOperandConstantImmediateInt(op2
)) {
1766 if (supportsFloatingPoint()) {
1768 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1769 addPtr(tagTypeNumberRegister
, regT0
);
1770 movePtrToDouble(regT0
, fpRegT0
);
1773 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1774 fail1
= emitJumpIfNotJSCell(regT0
);
1776 Jump fail2
= checkStructure(regT0
, m_globalData
->numberStructure
.get());
1777 loadDouble(Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
1780 int32_t op2imm
= getConstantOperand(op2
).asInt32();;
1782 move(Imm32(op2imm
), regT1
);
1783 convertInt32ToDouble(regT1
, fpRegT1
);
1785 emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered
, fpRegT1
, fpRegT0
), target
);
1787 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq
));
1792 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1798 JITStubCall
stubCall(this, cti_op_jlesseq
);
1799 stubCall
.addArgument(regT0
);
1800 stubCall
.addArgument(op2
, regT2
);
1802 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1804 } else if (isOperandConstantImmediateInt(op1
)) {
1807 if (supportsFloatingPoint()) {
1809 Jump fail1
= emitJumpIfNotImmediateNumber(regT1
);
1810 addPtr(tagTypeNumberRegister
, regT1
);
1811 movePtrToDouble(regT1
, fpRegT1
);
1814 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1815 fail1
= emitJumpIfNotJSCell(regT1
);
1817 Jump fail2
= checkStructure(regT1
, m_globalData
->numberStructure
.get());
1818 loadDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT1
);
1821 int32_t op1imm
= getConstantOperand(op1
).asInt32();;
1823 move(Imm32(op1imm
), regT0
);
1824 convertInt32ToDouble(regT0
, fpRegT0
);
1826 emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered
, fpRegT1
, fpRegT0
), target
);
1828 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq
));
1833 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1839 JITStubCall
stubCall(this, cti_op_jlesseq
);
1840 stubCall
.addArgument(op1
, regT2
);
1841 stubCall
.addArgument(regT1
);
1843 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1848 if (supportsFloatingPoint()) {
1850 Jump fail1
= emitJumpIfNotImmediateNumber(regT0
);
1851 Jump fail2
= emitJumpIfNotImmediateNumber(regT1
);
1852 Jump fail3
= emitJumpIfImmediateInteger(regT1
);
1853 addPtr(tagTypeNumberRegister
, regT0
);
1854 addPtr(tagTypeNumberRegister
, regT1
);
1855 movePtrToDouble(regT0
, fpRegT0
);
1856 movePtrToDouble(regT1
, fpRegT1
);
1859 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1860 fail1
= emitJumpIfNotJSCell(regT0
);
1863 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1864 fail2
= emitJumpIfNotJSCell(regT1
);
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
);
1872 emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered
, fpRegT1
, fpRegT0
), target
);
1874 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq
));
1881 if (!m_codeBlock
->isKnownNotImmediate(op1
))
1883 if (!m_codeBlock
->isKnownNotImmediate(op2
))
1891 JITStubCall
stubCall(this, cti_op_jlesseq
);
1892 stubCall
.addArgument(regT0
);
1893 stubCall
.addArgument(regT1
);
1895 emitJumpSlowToHot(branchTest32(Zero
, regT0
), target
);
1899 void JIT::emit_op_bitand(Instruction
* currentInstruction
)
1901 unsigned result
= currentInstruction
[1].u
.operand
;
1902 unsigned op1
= currentInstruction
[2].u
.operand
;
1903 unsigned op2
= currentInstruction
[3].u
.operand
;
1905 if (isOperandConstantImmediateInt(op1
)) {
1906 emitGetVirtualRegister(op2
, regT0
);
1907 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1909 int32_t imm
= getConstantOperandImmediateInt(op1
);
1910 andPtr(Imm32(imm
), regT0
);
1912 emitFastArithIntToImmNoCheck(regT0
, regT0
);
1914 andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1
)))), regT0
);
1916 } else if (isOperandConstantImmediateInt(op2
)) {
1917 emitGetVirtualRegister(op1
, regT0
);
1918 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1920 int32_t imm
= getConstantOperandImmediateInt(op2
);
1921 andPtr(Imm32(imm
), regT0
);
1923 emitFastArithIntToImmNoCheck(regT0
, regT0
);
1925 andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2
)))), regT0
);
1928 emitGetVirtualRegisters(op1
, regT0
, op2
, regT1
);
1929 andPtr(regT1
, regT0
);
1930 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1932 emitPutVirtualRegister(result
);
1935 void JIT::emitSlow_op_bitand(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1937 unsigned result
= currentInstruction
[1].u
.operand
;
1938 unsigned op1
= currentInstruction
[2].u
.operand
;
1939 unsigned op2
= currentInstruction
[3].u
.operand
;
1942 if (isOperandConstantImmediateInt(op1
)) {
1943 JITStubCall
stubCall(this, cti_op_bitand
);
1944 stubCall
.addArgument(op1
, regT2
);
1945 stubCall
.addArgument(regT0
);
1946 stubCall
.call(result
);
1947 } else if (isOperandConstantImmediateInt(op2
)) {
1948 JITStubCall
stubCall(this, cti_op_bitand
);
1949 stubCall
.addArgument(regT0
);
1950 stubCall
.addArgument(op2
, regT2
);
1951 stubCall
.call(result
);
1953 JITStubCall
stubCall(this, cti_op_bitand
);
1954 stubCall
.addArgument(op1
, regT2
);
1955 stubCall
.addArgument(regT1
);
1956 stubCall
.call(result
);
1960 void JIT::emit_op_post_inc(Instruction
* currentInstruction
)
1962 unsigned result
= currentInstruction
[1].u
.operand
;
1963 unsigned srcDst
= currentInstruction
[2].u
.operand
;
1965 emitGetVirtualRegister(srcDst
, regT0
);
1967 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
1969 addSlowCase(branchAdd32(Overflow
, Imm32(1), regT1
));
1970 emitFastArithIntToImmNoCheck(regT1
, regT1
);
1972 addSlowCase(branchAdd32(Overflow
, Imm32(1 << JSImmediate::IntegerPayloadShift
), regT1
));
1973 signExtend32ToPtr(regT1
, regT1
);
1975 emitPutVirtualRegister(srcDst
, regT1
);
1976 emitPutVirtualRegister(result
);
1979 void JIT::emitSlow_op_post_inc(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
1981 unsigned result
= currentInstruction
[1].u
.operand
;
1982 unsigned srcDst
= currentInstruction
[2].u
.operand
;
1986 JITStubCall
stubCall(this, cti_op_post_inc
);
1987 stubCall
.addArgument(regT0
);
1988 stubCall
.addArgument(Imm32(srcDst
));
1989 stubCall
.call(result
);
1992 void JIT::emit_op_post_dec(Instruction
* currentInstruction
)
1994 unsigned result
= currentInstruction
[1].u
.operand
;
1995 unsigned srcDst
= currentInstruction
[2].u
.operand
;
1997 emitGetVirtualRegister(srcDst
, regT0
);
1999 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2001 addSlowCase(branchSub32(Zero
, Imm32(1), regT1
));
2002 emitFastArithIntToImmNoCheck(regT1
, regT1
);
2004 addSlowCase(branchSub32(Zero
, Imm32(1 << JSImmediate::IntegerPayloadShift
), regT1
));
2005 signExtend32ToPtr(regT1
, regT1
);
2007 emitPutVirtualRegister(srcDst
, regT1
);
2008 emitPutVirtualRegister(result
);
2011 void JIT::emitSlow_op_post_dec(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2013 unsigned result
= currentInstruction
[1].u
.operand
;
2014 unsigned srcDst
= currentInstruction
[2].u
.operand
;
2018 JITStubCall
stubCall(this, cti_op_post_dec
);
2019 stubCall
.addArgument(regT0
);
2020 stubCall
.addArgument(Imm32(srcDst
));
2021 stubCall
.call(result
);
2024 void JIT::emit_op_pre_inc(Instruction
* currentInstruction
)
2026 unsigned srcDst
= currentInstruction
[1].u
.operand
;
2028 emitGetVirtualRegister(srcDst
, regT0
);
2029 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2031 addSlowCase(branchAdd32(Overflow
, Imm32(1), regT0
));
2032 emitFastArithIntToImmNoCheck(regT0
, regT0
);
2034 addSlowCase(branchAdd32(Overflow
, Imm32(1 << JSImmediate::IntegerPayloadShift
), regT0
));
2035 signExtend32ToPtr(regT0
, regT0
);
2037 emitPutVirtualRegister(srcDst
);
2040 void JIT::emitSlow_op_pre_inc(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2042 unsigned srcDst
= currentInstruction
[1].u
.operand
;
2044 Jump notImm
= getSlowCase(iter
);
2046 emitGetVirtualRegister(srcDst
, regT0
);
2048 JITStubCall
stubCall(this, cti_op_pre_inc
);
2049 stubCall
.addArgument(regT0
);
2050 stubCall
.call(srcDst
);
2053 void JIT::emit_op_pre_dec(Instruction
* currentInstruction
)
2055 unsigned srcDst
= currentInstruction
[1].u
.operand
;
2057 emitGetVirtualRegister(srcDst
, regT0
);
2058 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2060 addSlowCase(branchSub32(Zero
, Imm32(1), regT0
));
2061 emitFastArithIntToImmNoCheck(regT0
, regT0
);
2063 addSlowCase(branchSub32(Zero
, Imm32(1 << JSImmediate::IntegerPayloadShift
), regT0
));
2064 signExtend32ToPtr(regT0
, regT0
);
2066 emitPutVirtualRegister(srcDst
);
2069 void JIT::emitSlow_op_pre_dec(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2071 unsigned srcDst
= currentInstruction
[1].u
.operand
;
2073 Jump notImm
= getSlowCase(iter
);
2075 emitGetVirtualRegister(srcDst
, regT0
);
2077 JITStubCall
stubCall(this, cti_op_pre_dec
);
2078 stubCall
.addArgument(regT0
);
2079 stubCall
.call(srcDst
);
2082 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
2084 #if CPU(X86) || CPU(X86_64)
2086 void JIT::emit_op_mod(Instruction
* currentInstruction
)
2088 unsigned result
= currentInstruction
[1].u
.operand
;
2089 unsigned op1
= currentInstruction
[2].u
.operand
;
2090 unsigned op2
= currentInstruction
[3].u
.operand
;
2092 emitGetVirtualRegisters(op1
, X86Registers::eax
, op2
, X86Registers::ecx
);
2093 emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax
);
2094 emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx
);
2096 addSlowCase(branchPtr(Equal
, X86Registers::ecx
, ImmPtr(JSValue::encode(jsNumber(m_globalData
, 0)))));
2098 m_assembler
.idivl_r(X86Registers::ecx
);
2100 emitFastArithDeTagImmediate(X86Registers::eax
);
2101 addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx
));
2103 m_assembler
.idivl_r(X86Registers::ecx
);
2104 signExtend32ToPtr(X86Registers::edx
, X86Registers::edx
);
2106 emitFastArithReTagImmediate(X86Registers::edx
, X86Registers::eax
);
2107 emitPutVirtualRegister(result
);
2110 void JIT::emitSlow_op_mod(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2112 unsigned result
= currentInstruction
[1].u
.operand
;
2119 Jump notImm1
= getSlowCase(iter
);
2120 Jump notImm2
= getSlowCase(iter
);
2122 emitFastArithReTagImmediate(X86Registers::eax
, X86Registers::eax
);
2123 emitFastArithReTagImmediate(X86Registers::ecx
, X86Registers::ecx
);
2127 JITStubCall
stubCall(this, cti_op_mod
);
2128 stubCall
.addArgument(X86Registers::eax
);
2129 stubCall
.addArgument(X86Registers::ecx
);
2130 stubCall
.call(result
);
2133 #else // CPU(X86) || CPU(X86_64)
2135 void JIT::emit_op_mod(Instruction
* currentInstruction
)
2137 unsigned result
= currentInstruction
[1].u
.operand
;
2138 unsigned op1
= currentInstruction
[2].u
.operand
;
2139 unsigned op2
= currentInstruction
[3].u
.operand
;
2141 JITStubCall
stubCall(this, cti_op_mod
);
2142 stubCall
.addArgument(op1
, regT2
);
2143 stubCall
.addArgument(op2
, regT2
);
2144 stubCall
.call(result
);
2147 void JIT::emitSlow_op_mod(Instruction
*, Vector
<SlowCaseEntry
>::iterator
&)
2149 ASSERT_NOT_REACHED();
2152 #endif // CPU(X86) || CPU(X86_64)
2154 /* ------------------------------ END: OP_MOD ------------------------------ */
2158 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2160 void JIT::compileBinaryArithOp(OpcodeID opcodeID
, unsigned, unsigned op1
, unsigned op2
, OperandTypes
)
2162 emitGetVirtualRegisters(op1
, regT0
, op2
, regT1
);
2163 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2164 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
2165 if (opcodeID
== op_add
)
2166 addSlowCase(branchAdd32(Overflow
, regT1
, regT0
));
2167 else if (opcodeID
== op_sub
)
2168 addSlowCase(branchSub32(Overflow
, regT1
, regT0
));
2170 ASSERT(opcodeID
== op_mul
);
2171 addSlowCase(branchMul32(Overflow
, regT1
, regT0
));
2172 addSlowCase(branchTest32(Zero
, regT0
));
2174 emitFastArithIntToImmNoCheck(regT0
, regT0
);
2177 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID
, Vector
<SlowCaseEntry
>::iterator
& iter
, unsigned result
, unsigned op1
, unsigned op2
, OperandTypes types
, bool op1HasImmediateIntFastCase
, bool op2HasImmediateIntFastCase
)
2179 // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
2180 COMPILE_ASSERT(((JSImmediate::TagTypeNumber
+ JSImmediate::DoubleEncodeOffset
) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0
);
2184 if (op1HasImmediateIntFastCase
) {
2185 notImm2
= getSlowCase(iter
);
2186 } else if (op2HasImmediateIntFastCase
) {
2187 notImm1
= getSlowCase(iter
);
2189 notImm1
= getSlowCase(iter
);
2190 notImm2
= getSlowCase(iter
);
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.
2196 emitGetVirtualRegister(op1
, regT0
);
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(op1
, regT0
);
2202 emitGetVirtualRegister(op2
, regT1
);
2204 stubCall
.addArgument(regT0
);
2205 stubCall
.addArgument(regT1
);
2206 stubCall
.call(result
);
2209 if (op1HasImmediateIntFastCase
) {
2211 if (!types
.second().definitelyIsNumber())
2212 emitJumpIfNotImmediateNumber(regT0
).linkTo(stubFunctionCall
, this);
2213 emitGetVirtualRegister(op1
, regT1
);
2214 convertInt32ToDouble(regT1
, fpRegT1
);
2215 addPtr(tagTypeNumberRegister
, regT0
);
2216 movePtrToDouble(regT0
, fpRegT2
);
2217 } else if (op2HasImmediateIntFastCase
) {
2219 if (!types
.first().definitelyIsNumber())
2220 emitJumpIfNotImmediateNumber(regT0
).linkTo(stubFunctionCall
, this);
2221 emitGetVirtualRegister(op2
, regT1
);
2222 convertInt32ToDouble(regT1
, fpRegT1
);
2223 addPtr(tagTypeNumberRegister
, regT0
);
2224 movePtrToDouble(regT0
, fpRegT2
);
2226 // if we get here, eax is not an int32, edx not yet checked.
2228 if (!types
.first().definitelyIsNumber())
2229 emitJumpIfNotImmediateNumber(regT0
).linkTo(stubFunctionCall
, this);
2230 if (!types
.second().definitelyIsNumber())
2231 emitJumpIfNotImmediateNumber(regT1
).linkTo(stubFunctionCall
, this);
2232 addPtr(tagTypeNumberRegister
, regT0
);
2233 movePtrToDouble(regT0
, fpRegT1
);
2234 Jump op2isDouble
= emitJumpIfNotImmediateInteger(regT1
);
2235 convertInt32ToDouble(regT1
, fpRegT2
);
2236 Jump op2wasInteger
= jump();
2238 // if we get here, eax IS an int32, edx is not.
2240 if (!types
.second().definitelyIsNumber())
2241 emitJumpIfNotImmediateNumber(regT1
).linkTo(stubFunctionCall
, this);
2242 convertInt32ToDouble(regT0
, fpRegT1
);
2243 op2isDouble
.link(this);
2244 addPtr(tagTypeNumberRegister
, regT1
);
2245 movePtrToDouble(regT1
, fpRegT2
);
2246 op2wasInteger
.link(this);
2249 if (opcodeID
== op_add
)
2250 addDouble(fpRegT2
, fpRegT1
);
2251 else if (opcodeID
== op_sub
)
2252 subDouble(fpRegT2
, fpRegT1
);
2253 else if (opcodeID
== op_mul
)
2254 mulDouble(fpRegT2
, fpRegT1
);
2256 ASSERT(opcodeID
== op_div
);
2257 divDouble(fpRegT2
, fpRegT1
);
2259 moveDoubleToPtr(fpRegT1
, regT0
);
2260 subPtr(tagTypeNumberRegister
, regT0
);
2261 emitPutVirtualRegister(result
, regT0
);
2266 void JIT::emit_op_add(Instruction
* currentInstruction
)
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(currentInstruction
[4].u
.operand
);
2273 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber()) {
2274 JITStubCall
stubCall(this, cti_op_add
);
2275 stubCall
.addArgument(op1
, regT2
);
2276 stubCall
.addArgument(op2
, regT2
);
2277 stubCall
.call(result
);
2281 if (isOperandConstantImmediateInt(op1
)) {
2282 emitGetVirtualRegister(op2
, regT0
);
2283 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2284 addSlowCase(branchAdd32(Overflow
, Imm32(getConstantOperandImmediateInt(op1
)), regT0
));
2285 emitFastArithIntToImmNoCheck(regT0
, regT0
);
2286 } else if (isOperandConstantImmediateInt(op2
)) {
2287 emitGetVirtualRegister(op1
, regT0
);
2288 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2289 addSlowCase(branchAdd32(Overflow
, Imm32(getConstantOperandImmediateInt(op2
)), regT0
));
2290 emitFastArithIntToImmNoCheck(regT0
, regT0
);
2292 compileBinaryArithOp(op_add
, result
, op1
, op2
, types
);
2294 emitPutVirtualRegister(result
);
2297 void JIT::emitSlow_op_add(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
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(currentInstruction
[4].u
.operand
);
2304 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber())
2307 bool op1HasImmediateIntFastCase
= isOperandConstantImmediateInt(op1
);
2308 bool op2HasImmediateIntFastCase
= !op1HasImmediateIntFastCase
&& isOperandConstantImmediateInt(op2
);
2309 compileBinaryArithOpSlowCase(op_add
, iter
, result
, op1
, op2
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
), op1HasImmediateIntFastCase
, op2HasImmediateIntFastCase
);
2312 void JIT::emit_op_mul(Instruction
* currentInstruction
)
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(currentInstruction
[4].u
.operand
);
2319 // For now, only plant a fast int case if the constant operand is greater than zero.
2321 if (isOperandConstantImmediateInt(op1
) && ((value
= getConstantOperandImmediateInt(op1
)) > 0)) {
2322 emitGetVirtualRegister(op2
, regT0
);
2323 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2324 addSlowCase(branchMul32(Overflow
, Imm32(value
), regT0
, regT0
));
2325 emitFastArithReTagImmediate(regT0
, regT0
);
2326 } else if (isOperandConstantImmediateInt(op2
) && ((value
= getConstantOperandImmediateInt(op2
)) > 0)) {
2327 emitGetVirtualRegister(op1
, regT0
);
2328 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2329 addSlowCase(branchMul32(Overflow
, Imm32(value
), regT0
, regT0
));
2330 emitFastArithReTagImmediate(regT0
, regT0
);
2332 compileBinaryArithOp(op_mul
, result
, op1
, op2
, types
);
2334 emitPutVirtualRegister(result
);
2337 void JIT::emitSlow_op_mul(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2339 unsigned result
= currentInstruction
[1].u
.operand
;
2340 unsigned op1
= currentInstruction
[2].u
.operand
;
2341 unsigned op2
= currentInstruction
[3].u
.operand
;
2342 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2344 bool op1HasImmediateIntFastCase
= isOperandConstantImmediateInt(op1
) && getConstantOperandImmediateInt(op1
) > 0;
2345 bool op2HasImmediateIntFastCase
= !op1HasImmediateIntFastCase
&& isOperandConstantImmediateInt(op2
) && getConstantOperandImmediateInt(op2
) > 0;
2346 compileBinaryArithOpSlowCase(op_mul
, iter
, result
, op1
, op2
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
), op1HasImmediateIntFastCase
, op2HasImmediateIntFastCase
);
2349 void JIT::emit_op_div(Instruction
* currentInstruction
)
2351 unsigned dst
= currentInstruction
[1].u
.operand
;
2352 unsigned op1
= currentInstruction
[2].u
.operand
;
2353 unsigned op2
= currentInstruction
[3].u
.operand
;
2354 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2356 if (isOperandConstantImmediateDouble(op1
)) {
2357 emitGetVirtualRegister(op1
, regT0
);
2358 addPtr(tagTypeNumberRegister
, regT0
);
2359 movePtrToDouble(regT0
, fpRegT0
);
2360 } else if (isOperandConstantImmediateInt(op1
)) {
2361 emitLoadInt32ToDouble(op1
, fpRegT0
);
2363 emitGetVirtualRegister(op1
, regT0
);
2364 if (!types
.first().definitelyIsNumber())
2365 emitJumpSlowCaseIfNotImmediateNumber(regT0
);
2366 Jump notInt
= emitJumpIfNotImmediateInteger(regT0
);
2367 convertInt32ToDouble(regT0
, fpRegT0
);
2368 Jump skipDoubleLoad
= jump();
2370 addPtr(tagTypeNumberRegister
, regT0
);
2371 movePtrToDouble(regT0
, fpRegT0
);
2372 skipDoubleLoad
.link(this);
2375 if (isOperandConstantImmediateDouble(op2
)) {
2376 emitGetVirtualRegister(op2
, regT1
);
2377 addPtr(tagTypeNumberRegister
, regT1
);
2378 movePtrToDouble(regT1
, fpRegT1
);
2379 } else if (isOperandConstantImmediateInt(op2
)) {
2380 emitLoadInt32ToDouble(op2
, fpRegT1
);
2382 emitGetVirtualRegister(op2
, regT1
);
2383 if (!types
.second().definitelyIsNumber())
2384 emitJumpSlowCaseIfNotImmediateNumber(regT1
);
2385 Jump notInt
= emitJumpIfNotImmediateInteger(regT1
);
2386 convertInt32ToDouble(regT1
, fpRegT1
);
2387 Jump skipDoubleLoad
= jump();
2389 addPtr(tagTypeNumberRegister
, regT1
);
2390 movePtrToDouble(regT1
, fpRegT1
);
2391 skipDoubleLoad
.link(this);
2393 divDouble(fpRegT1
, fpRegT0
);
2396 moveDoubleToPtr(fpRegT0
, regT0
);
2397 subPtr(tagTypeNumberRegister
, regT0
);
2399 emitPutVirtualRegister(dst
, regT0
);
2402 void JIT::emitSlow_op_div(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2404 unsigned result
= currentInstruction
[1].u
.operand
;
2405 unsigned op1
= currentInstruction
[2].u
.operand
;
2406 unsigned op2
= currentInstruction
[3].u
.operand
;
2407 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2408 if (types
.first().definitelyIsNumber() && types
.second().definitelyIsNumber()) {
2414 if (!isOperandConstantImmediateDouble(op1
) && !isOperandConstantImmediateInt(op1
)) {
2415 if (!types
.first().definitelyIsNumber())
2418 if (!isOperandConstantImmediateDouble(op2
) && !isOperandConstantImmediateInt(op2
)) {
2419 if (!types
.second().definitelyIsNumber())
2422 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2423 JITStubCall
stubCall(this, cti_op_div
);
2424 stubCall
.addArgument(op1
, regT2
);
2425 stubCall
.addArgument(op2
, regT2
);
2426 stubCall
.call(result
);
2429 void JIT::emit_op_sub(Instruction
* currentInstruction
)
2431 unsigned result
= currentInstruction
[1].u
.operand
;
2432 unsigned op1
= currentInstruction
[2].u
.operand
;
2433 unsigned op2
= currentInstruction
[3].u
.operand
;
2434 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2436 compileBinaryArithOp(op_sub
, result
, op1
, op2
, types
);
2437 emitPutVirtualRegister(result
);
2440 void JIT::emitSlow_op_sub(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2442 unsigned result
= currentInstruction
[1].u
.operand
;
2443 unsigned op1
= currentInstruction
[2].u
.operand
;
2444 unsigned op2
= currentInstruction
[3].u
.operand
;
2445 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2447 compileBinaryArithOpSlowCase(op_sub
, iter
, result
, op1
, op2
, types
, false, false);
2450 #else // USE(JSVALUE64)
2452 /* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2454 void JIT::compileBinaryArithOp(OpcodeID opcodeID
, unsigned dst
, unsigned src1
, unsigned src2
, OperandTypes types
)
2456 Structure
* numberStructure
= m_globalData
->numberStructure
.get();
2457 Jump wasJSNumberCell1
;
2458 Jump wasJSNumberCell2
;
2460 emitGetVirtualRegisters(src1
, regT0
, src2
, regT1
);
2462 if (types
.second().isReusable() && supportsFloatingPoint()) {
2463 ASSERT(types
.second().mightBeNumber());
2465 // Check op2 is a number
2466 Jump op2imm
= emitJumpIfImmediateInteger(regT1
);
2467 if (!types
.second().definitelyIsNumber()) {
2468 emitJumpSlowCaseIfNotJSCell(regT1
, src2
);
2469 addSlowCase(checkStructure(regT1
, numberStructure
));
2472 // (1) In this case src2 is a reusable number cell.
2473 // Slow case if src1 is not a number type.
2474 Jump op1imm
= emitJumpIfImmediateInteger(regT0
);
2475 if (!types
.first().definitelyIsNumber()) {
2476 emitJumpSlowCaseIfNotJSCell(regT0
, src1
);
2477 addSlowCase(checkStructure(regT0
, numberStructure
));
2480 // (1a) if we get here, src1 is also a number cell
2481 loadDouble(Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
2482 Jump loadedDouble
= jump();
2483 // (1b) if we get here, src1 is an immediate
2485 emitFastArithImmToInt(regT0
);
2486 convertInt32ToDouble(regT0
, fpRegT0
);
2488 loadedDouble
.link(this);
2489 if (opcodeID
== op_add
)
2490 addDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
2491 else if (opcodeID
== op_sub
)
2492 subDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
2494 ASSERT(opcodeID
== op_mul
);
2495 mulDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
2498 // Store the result to the JSNumberCell and jump.
2499 storeDouble(fpRegT0
, Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)));
2501 emitPutVirtualRegister(dst
);
2502 wasJSNumberCell2
= jump();
2504 // (2) This handles cases where src2 is an immediate number.
2505 // Two slow cases - either src1 isn't an immediate, or the subtract overflows.
2507 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2508 } else if (types
.first().isReusable() && supportsFloatingPoint()) {
2509 ASSERT(types
.first().mightBeNumber());
2511 // Check op1 is a number
2512 Jump op1imm
= emitJumpIfImmediateInteger(regT0
);
2513 if (!types
.first().definitelyIsNumber()) {
2514 emitJumpSlowCaseIfNotJSCell(regT0
, src1
);
2515 addSlowCase(checkStructure(regT0
, numberStructure
));
2518 // (1) In this case src1 is a reusable number cell.
2519 // Slow case if src2 is not a number type.
2520 Jump op2imm
= emitJumpIfImmediateInteger(regT1
);
2521 if (!types
.second().definitelyIsNumber()) {
2522 emitJumpSlowCaseIfNotJSCell(regT1
, src2
);
2523 addSlowCase(checkStructure(regT1
, numberStructure
));
2526 // (1a) if we get here, src2 is also a number cell
2527 loadDouble(Address(regT1
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT1
);
2528 Jump loadedDouble
= jump();
2529 // (1b) if we get here, src2 is an immediate
2531 emitFastArithImmToInt(regT1
);
2532 convertInt32ToDouble(regT1
, fpRegT1
);
2534 loadedDouble
.link(this);
2535 loadDouble(Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)), fpRegT0
);
2536 if (opcodeID
== op_add
)
2537 addDouble(fpRegT1
, fpRegT0
);
2538 else if (opcodeID
== op_sub
)
2539 subDouble(fpRegT1
, fpRegT0
);
2541 ASSERT(opcodeID
== op_mul
);
2542 mulDouble(fpRegT1
, fpRegT0
);
2544 storeDouble(fpRegT0
, Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)));
2545 emitPutVirtualRegister(dst
);
2547 // Store the result to the JSNumberCell and jump.
2548 storeDouble(fpRegT0
, Address(regT0
, OBJECT_OFFSETOF(JSNumberCell
, m_value
)));
2549 emitPutVirtualRegister(dst
);
2550 wasJSNumberCell1
= jump();
2552 // (2) This handles cases where src1 is an immediate number.
2553 // Two slow cases - either src2 isn't an immediate, or the subtract overflows.
2555 emitJumpSlowCaseIfNotImmediateInteger(regT1
);
2557 emitJumpSlowCaseIfNotImmediateIntegers(regT0
, regT1
, regT2
);
2559 if (opcodeID
== op_add
) {
2560 emitFastArithDeTagImmediate(regT0
);
2561 addSlowCase(branchAdd32(Overflow
, regT1
, regT0
));
2562 } else if (opcodeID
== op_sub
) {
2563 addSlowCase(branchSub32(Overflow
, regT1
, regT0
));
2564 signExtend32ToPtr(regT0
, regT0
);
2565 emitFastArithReTagImmediate(regT0
, regT0
);
2567 ASSERT(opcodeID
== op_mul
);
2568 // convert eax & edx from JSImmediates to ints, and check if either are zero
2569 emitFastArithImmToInt(regT1
);
2570 Jump op1Zero
= emitFastArithDeTagImmediateJumpIfZero(regT0
);
2571 Jump op2NonZero
= branchTest32(NonZero
, regT1
);
2573 // if either input is zero, add the two together, and check if the result is < 0.
2574 // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
2576 addSlowCase(branchAdd32(Signed
, regT1
, regT2
));
2577 // Skip the above check if neither input is zero
2578 op2NonZero
.link(this);
2579 addSlowCase(branchMul32(Overflow
, regT1
, regT0
));
2580 signExtend32ToPtr(regT0
, regT0
);
2581 emitFastArithReTagImmediate(regT0
, regT0
);
2583 emitPutVirtualRegister(dst
);
2585 if (types
.second().isReusable() && supportsFloatingPoint())
2586 wasJSNumberCell2
.link(this);
2587 else if (types
.first().isReusable() && supportsFloatingPoint())
2588 wasJSNumberCell1
.link(this);
2591 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID
, Vector
<SlowCaseEntry
>::iterator
& iter
, unsigned dst
, unsigned src1
, unsigned src2
, OperandTypes types
)
2594 if (types
.second().isReusable() && supportsFloatingPoint()) {
2595 if (!types
.first().definitelyIsNumber()) {
2596 linkSlowCaseIfNotJSCell(iter
, src1
);
2599 if (!types
.second().definitelyIsNumber()) {
2600 linkSlowCaseIfNotJSCell(iter
, src2
);
2603 } else if (types
.first().isReusable() && supportsFloatingPoint()) {
2604 if (!types
.first().definitelyIsNumber()) {
2605 linkSlowCaseIfNotJSCell(iter
, src1
);
2608 if (!types
.second().definitelyIsNumber()) {
2609 linkSlowCaseIfNotJSCell(iter
, src2
);
2615 // additional entry point to handle -0 cases.
2616 if (opcodeID
== op_mul
)
2619 JITStubCall
stubCall(this, opcodeID
== op_add
? cti_op_add
: opcodeID
== op_sub
? cti_op_sub
: cti_op_mul
);
2620 stubCall
.addArgument(src1
, regT2
);
2621 stubCall
.addArgument(src2
, regT2
);
2625 void JIT::emit_op_add(Instruction
* currentInstruction
)
2627 unsigned result
= currentInstruction
[1].u
.operand
;
2628 unsigned op1
= currentInstruction
[2].u
.operand
;
2629 unsigned op2
= currentInstruction
[3].u
.operand
;
2630 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2632 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber()) {
2633 JITStubCall
stubCall(this, cti_op_add
);
2634 stubCall
.addArgument(op1
, regT2
);
2635 stubCall
.addArgument(op2
, regT2
);
2636 stubCall
.call(result
);
2640 if (isOperandConstantImmediateInt(op1
)) {
2641 emitGetVirtualRegister(op2
, regT0
);
2642 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2643 addSlowCase(branchAdd32(Overflow
, Imm32(getConstantOperandImmediateInt(op1
) << JSImmediate::IntegerPayloadShift
), regT0
));
2644 signExtend32ToPtr(regT0
, regT0
);
2645 emitPutVirtualRegister(result
);
2646 } else if (isOperandConstantImmediateInt(op2
)) {
2647 emitGetVirtualRegister(op1
, regT0
);
2648 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2649 addSlowCase(branchAdd32(Overflow
, Imm32(getConstantOperandImmediateInt(op2
) << JSImmediate::IntegerPayloadShift
), regT0
));
2650 signExtend32ToPtr(regT0
, regT0
);
2651 emitPutVirtualRegister(result
);
2653 compileBinaryArithOp(op_add
, result
, op1
, op2
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
));
2657 void JIT::emitSlow_op_add(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2659 unsigned result
= currentInstruction
[1].u
.operand
;
2660 unsigned op1
= currentInstruction
[2].u
.operand
;
2661 unsigned op2
= currentInstruction
[3].u
.operand
;
2663 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2664 if (!types
.first().mightBeNumber() || !types
.second().mightBeNumber())
2667 if (isOperandConstantImmediateInt(op1
)) {
2668 Jump notImm
= getSlowCase(iter
);
2670 sub32(Imm32(getConstantOperandImmediateInt(op1
) << JSImmediate::IntegerPayloadShift
), regT0
);
2672 JITStubCall
stubCall(this, cti_op_add
);
2673 stubCall
.addArgument(op1
, regT2
);
2674 stubCall
.addArgument(regT0
);
2675 stubCall
.call(result
);
2676 } else if (isOperandConstantImmediateInt(op2
)) {
2677 Jump notImm
= getSlowCase(iter
);
2679 sub32(Imm32(getConstantOperandImmediateInt(op2
) << JSImmediate::IntegerPayloadShift
), regT0
);
2681 JITStubCall
stubCall(this, cti_op_add
);
2682 stubCall
.addArgument(regT0
);
2683 stubCall
.addArgument(op2
, regT2
);
2684 stubCall
.call(result
);
2686 OperandTypes types
= OperandTypes::fromInt(currentInstruction
[4].u
.operand
);
2687 ASSERT(types
.first().mightBeNumber() && types
.second().mightBeNumber());
2688 compileBinaryArithOpSlowCase(op_add
, iter
, result
, op1
, op2
, types
);
2692 void JIT::emit_op_mul(Instruction
* currentInstruction
)
2694 unsigned result
= currentInstruction
[1].u
.operand
;
2695 unsigned op1
= currentInstruction
[2].u
.operand
;
2696 unsigned op2
= currentInstruction
[3].u
.operand
;
2698 // For now, only plant a fast int case if the constant operand is greater than zero.
2700 if (isOperandConstantImmediateInt(op1
) && ((value
= getConstantOperandImmediateInt(op1
)) > 0)) {
2701 emitGetVirtualRegister(op2
, regT0
);
2702 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2703 emitFastArithDeTagImmediate(regT0
);
2704 addSlowCase(branchMul32(Overflow
, Imm32(value
), regT0
, regT0
));
2705 signExtend32ToPtr(regT0
, regT0
);
2706 emitFastArithReTagImmediate(regT0
, regT0
);
2707 emitPutVirtualRegister(result
);
2708 } else if (isOperandConstantImmediateInt(op2
) && ((value
= getConstantOperandImmediateInt(op2
)) > 0)) {
2709 emitGetVirtualRegister(op1
, regT0
);
2710 emitJumpSlowCaseIfNotImmediateInteger(regT0
);
2711 emitFastArithDeTagImmediate(regT0
);
2712 addSlowCase(branchMul32(Overflow
, Imm32(value
), regT0
, regT0
));
2713 signExtend32ToPtr(regT0
, regT0
);
2714 emitFastArithReTagImmediate(regT0
, regT0
);
2715 emitPutVirtualRegister(result
);
2717 compileBinaryArithOp(op_mul
, result
, op1
, op2
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
));
2720 void JIT::emitSlow_op_mul(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2722 unsigned result
= currentInstruction
[1].u
.operand
;
2723 unsigned op1
= currentInstruction
[2].u
.operand
;
2724 unsigned op2
= currentInstruction
[3].u
.operand
;
2726 if ((isOperandConstantImmediateInt(op1
) && (getConstantOperandImmediateInt(op1
) > 0))
2727 || (isOperandConstantImmediateInt(op2
) && (getConstantOperandImmediateInt(op2
) > 0))) {
2730 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2731 JITStubCall
stubCall(this, cti_op_mul
);
2732 stubCall
.addArgument(op1
, regT2
);
2733 stubCall
.addArgument(op2
, regT2
);
2734 stubCall
.call(result
);
2736 compileBinaryArithOpSlowCase(op_mul
, iter
, result
, op1
, op2
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
));
2739 void JIT::emit_op_sub(Instruction
* currentInstruction
)
2741 compileBinaryArithOp(op_sub
, currentInstruction
[1].u
.operand
, currentInstruction
[2].u
.operand
, currentInstruction
[3].u
.operand
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
));
2744 void JIT::emitSlow_op_sub(Instruction
* currentInstruction
, Vector
<SlowCaseEntry
>::iterator
& iter
)
2746 compileBinaryArithOpSlowCase(op_sub
, iter
, currentInstruction
[1].u
.operand
, currentInstruction
[2].u
.operand
, currentInstruction
[3].u
.operand
, OperandTypes::fromInt(currentInstruction
[4].u
.operand
));
2749 #endif // USE(JSVALUE64)
2751 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
2753 #endif // USE(JSVALUE32_64)
2757 #endif // ENABLE(JIT)