efd1de02ebee94596be0acc5f563ce27b499ebbd
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGJITCodeGenerator64.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGJITCodeGenerator.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGJITCompilerInlineMethods.h"
32 #include "DFGSpeculativeJIT.h"
33 #include "LinkBuffer.h"
34
35 namespace JSC { namespace DFG {
36
37 #if USE(JSVALUE64)
38
39 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
40 {
41     Node& node = at(nodeIndex);
42     VirtualRegister virtualRegister = node.virtualRegister();
43     GenerationInfo& info = m_generationInfo[virtualRegister];
44
45     if (info.registerFormat() == DataFormatNone) {
46         GPRReg gpr = allocate();
47
48         if (node.hasConstant()) {
49             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
50             if (isInt32Constant(nodeIndex)) {
51                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
52                 info.fillInteger(gpr);
53                 returnFormat = DataFormatInteger;
54                 return gpr;
55             }
56             if (isNumberConstant(nodeIndex)) {
57                 JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));
58                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
59             } else {
60                 ASSERT(isJSConstant(nodeIndex));
61                 JSValue jsValue = valueOfJSConstant(nodeIndex);
62                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
63             }
64         } else if (info.spillFormat() == DataFormatInteger) {
65             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
66             m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
67             // Tag it, since fillInteger() is used when we want a boxed integer.
68             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
69         } else {
70             ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
71             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
72             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
73         }
74
75         // Since we statically know that we're filling an integer, and values
76         // in the RegisterFile are boxed, this must be DataFormatJSInteger.
77         // We will check this with a jitAssert below.
78         info.fillJSValue(gpr, DataFormatJSInteger);
79         unlock(gpr);
80     }
81
82     switch (info.registerFormat()) {
83     case DataFormatNone:
84         // Should have filled, above.
85     case DataFormatJSDouble:
86     case DataFormatDouble:
87     case DataFormatJS:
88     case DataFormatCell:
89     case DataFormatJSCell:
90     case DataFormatBoolean:
91     case DataFormatJSBoolean:
92     case DataFormatStorage:
93         // Should only be calling this function if we know this operand to be integer.
94         ASSERT_NOT_REACHED();
95
96     case DataFormatJSInteger: {
97         GPRReg gpr = info.gpr();
98         m_gprs.lock(gpr);
99         m_jit.jitAssertIsJSInt32(gpr);
100         returnFormat = DataFormatJSInteger;
101         return gpr;
102     }
103
104     case DataFormatInteger: {
105         GPRReg gpr = info.gpr();
106         m_gprs.lock(gpr);
107         m_jit.jitAssertIsInt32(gpr);
108         returnFormat = DataFormatInteger;
109         return gpr;
110     }
111     }
112
113     ASSERT_NOT_REACHED();
114     return InvalidGPRReg;
115 }
116
117 FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
118 {
119     Node& node = at(nodeIndex);
120     VirtualRegister virtualRegister = node.virtualRegister();
121     GenerationInfo& info = m_generationInfo[virtualRegister];
122
123     if (info.registerFormat() == DataFormatNone) {
124         if (node.hasConstant()) {
125             GPRReg gpr = allocate();
126         
127             if (isInt32Constant(nodeIndex)) {
128                 // FIXME: should not be reachable?
129                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
130                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
131                 info.fillInteger(gpr);
132                 unlock(gpr);
133             } else if (isNumberConstant(nodeIndex)) {
134                 FPRReg fpr = fprAllocate();
135                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
136                 m_jit.movePtrToDouble(gpr, fpr);
137                 unlock(gpr);
138
139                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
140                 info.fillDouble(fpr);
141                 return fpr;
142             } else {
143                 // FIXME: should not be reachable?
144                 ASSERT(isJSConstant(nodeIndex));
145                 JSValue jsValue = valueOfJSConstant(nodeIndex);
146                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
147                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
148                 info.fillJSValue(gpr, DataFormatJS);
149                 unlock(gpr);
150             }
151         } else {
152             DataFormat spillFormat = info.spillFormat();
153             switch (spillFormat) {
154             case DataFormatDouble: {
155                 FPRReg fpr = fprAllocate();
156                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
157                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
158                 info.fillDouble(fpr);
159                 return fpr;
160             }
161                 
162             case DataFormatInteger: {
163                 GPRReg gpr = allocate();
164                 
165                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
166                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
167                 info.fillInteger(gpr);
168                 unlock(gpr);
169                 break;
170             }
171
172             default:
173                 GPRReg gpr = allocate();
174         
175                 ASSERT(spillFormat & DataFormatJS);
176                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
177                 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
178                 info.fillJSValue(gpr, spillFormat);
179                 unlock(gpr);
180                 break;
181             }
182         }
183     }
184
185     switch (info.registerFormat()) {
186     case DataFormatNone:
187         // Should have filled, above.
188     case DataFormatCell:
189     case DataFormatJSCell:
190     case DataFormatBoolean:
191     case DataFormatJSBoolean:
192     case DataFormatStorage:
193         // Should only be calling this function if we know this operand to be numeric.
194         ASSERT_NOT_REACHED();
195
196     case DataFormatJS: {
197         GPRReg jsValueGpr = info.gpr();
198         m_gprs.lock(jsValueGpr);
199         FPRReg fpr = fprAllocate();
200         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
201
202         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
203
204         m_jit.jitAssertIsJSDouble(jsValueGpr);
205
206         // First, if we get here we have a double encoded as a JSValue
207         m_jit.move(jsValueGpr, tempGpr);
208         unboxDouble(tempGpr, fpr);
209         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
210
211         // Finally, handle integers.
212         isInteger.link(&m_jit);
213         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
214         hasUnboxedDouble.link(&m_jit);
215
216         m_gprs.release(jsValueGpr);
217         m_gprs.unlock(jsValueGpr);
218         m_gprs.unlock(tempGpr);
219         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
220         info.fillDouble(fpr);
221         info.killSpilled();
222         return fpr;
223     }
224
225     case DataFormatJSInteger:
226     case DataFormatInteger: {
227         FPRReg fpr = fprAllocate();
228         GPRReg gpr = info.gpr();
229         m_gprs.lock(gpr);
230         m_jit.convertInt32ToDouble(gpr, fpr);
231         m_gprs.unlock(gpr);
232         return fpr;
233     }
234
235     // Unbox the double
236     case DataFormatJSDouble: {
237         GPRReg gpr = info.gpr();
238         FPRReg fpr = fprAllocate();
239         if (m_gprs.isLocked(gpr)) {
240             // Make sure we don't trample gpr if it is in use.
241             GPRReg temp = allocate();
242             m_jit.move(gpr, temp);
243             unboxDouble(temp, fpr);
244             unlock(temp);
245         } else
246             unboxDouble(gpr, fpr);
247
248         m_gprs.release(gpr);
249         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
250
251         info.fillDouble(fpr);
252         return fpr;
253     }
254
255     case DataFormatDouble: {
256         FPRReg fpr = info.fpr();
257         m_fprs.lock(fpr);
258         return fpr;
259     }
260     }
261
262     ASSERT_NOT_REACHED();
263     return InvalidFPRReg;
264 }
265
266 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
267 {
268     Node& node = at(nodeIndex);
269     VirtualRegister virtualRegister = node.virtualRegister();
270     GenerationInfo& info = m_generationInfo[virtualRegister];
271
272     switch (info.registerFormat()) {
273     case DataFormatNone: {
274         GPRReg gpr = allocate();
275
276         if (node.hasConstant()) {
277             if (isInt32Constant(nodeIndex)) {
278                 info.fillJSValue(gpr, DataFormatJSInteger);
279                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
280                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
281             } else if (isNumberConstant(nodeIndex)) {
282                 info.fillJSValue(gpr, DataFormatJSDouble);
283                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));
284                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
285             } else {
286                 ASSERT(isJSConstant(nodeIndex));
287                 JSValue jsValue = valueOfJSConstant(nodeIndex);
288                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
289                 info.fillJSValue(gpr, DataFormatJS);
290             }
291
292             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
293         } else {
294             DataFormat spillFormat = info.spillFormat();
295             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
296             if (spillFormat == DataFormatInteger) {
297                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
298                 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
299                 spillFormat = DataFormatJSInteger;
300             } else {
301                 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
302                 if (spillFormat == DataFormatDouble) {
303                     // Need to box the double, since we want a JSValue.
304                     m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
305                     spillFormat = DataFormatJSDouble;
306                 } else
307                     ASSERT(spillFormat & DataFormatJS);
308             }
309             info.fillJSValue(gpr, spillFormat);
310         }
311         return gpr;
312     }
313
314     case DataFormatInteger: {
315         GPRReg gpr = info.gpr();
316         // If the register has already been locked we need to take a copy.
317         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
318         if (m_gprs.isLocked(gpr)) {
319             GPRReg result = allocate();
320             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
321             return result;
322         }
323         m_gprs.lock(gpr);
324         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
325         info.fillJSValue(gpr, DataFormatJSInteger);
326         return gpr;
327     }
328
329     case DataFormatDouble: {
330         FPRReg fpr = info.fpr();
331         GPRReg gpr = boxDouble(fpr);
332
333         // Update all info
334         info.fillJSValue(gpr, DataFormatJSDouble);
335         m_fprs.release(fpr);
336         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
337
338         return gpr;
339     }
340
341     case DataFormatCell:
342         // No retag required on JSVALUE64!
343     case DataFormatJS:
344     case DataFormatJSInteger:
345     case DataFormatJSDouble:
346     case DataFormatJSCell:
347     case DataFormatJSBoolean: {
348         GPRReg gpr = info.gpr();
349         m_gprs.lock(gpr);
350         return gpr;
351     }
352         
353     case DataFormatBoolean:
354     case DataFormatStorage:
355         // this type currently never occurs
356         ASSERT_NOT_REACHED();
357     }
358
359     ASSERT_NOT_REACHED();
360     return InvalidGPRReg;
361 }
362
363 void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node)
364 {
365     if (isKnownNumeric(node.child1())) {
366         JSValueOperand op1(this, node.child1());
367         GPRTemporary result(this, op1);
368         m_jit.move(op1.gpr(), result.gpr());
369         jsValueResult(result.gpr(), m_compileIndex);
370         return;
371     }
372
373     JSValueOperand op1(this, node.child1());
374     GPRTemporary result(this);
375     
376     ASSERT(!isInt32Constant(node.child1()));
377     ASSERT(!isNumberConstant(node.child1()));
378     
379     GPRReg jsValueGpr = op1.gpr();
380     GPRReg gpr = result.gpr();
381     op1.use();
382
383     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
384     JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
385
386     // First, if we get here we have a double encoded as a JSValue
387     m_jit.move(jsValueGpr, gpr);
388     JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
389
390     // Next handle cells (& other JS immediates)
391     nonNumeric.link(&m_jit);
392     silentSpillAllRegisters(gpr);
393     callOperation(dfgConvertJSValueToNumber, FPRInfo::returnValueFPR, jsValueGpr);
394     boxDouble(FPRInfo::returnValueFPR, gpr);
395     silentFillAllRegisters(gpr);
396     JITCompiler::Jump hasCalledToNumber = m_jit.jump();
397     
398     // Finally, handle integers.
399     isInteger.link(&m_jit);
400     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
401     hasUnboxedDouble.link(&m_jit);
402     hasCalledToNumber.link(&m_jit);
403     
404     jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
405 }
406
407 void JITCodeGenerator::nonSpeculativeValueToInt32(Node& node)
408 {
409     ASSERT(!isInt32Constant(node.child1()));
410     
411     if (isKnownInteger(node.child1())) {
412         IntegerOperand op1(this, node.child1());
413         GPRTemporary result(this, op1);
414         m_jit.move(op1.gpr(), result.gpr());
415         integerResult(result.gpr(), m_compileIndex);
416         return;
417     }
418     
419     GenerationInfo& childInfo = m_generationInfo[at(node.child1()).virtualRegister()];
420     if (childInfo.isJSDouble()) {
421         DoubleOperand op1(this, node.child1());
422         GPRTemporary result(this);
423         FPRReg fpr = op1.fpr();
424         GPRReg gpr = result.gpr();
425         op1.use();
426         JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
427         
428         silentSpillAllRegisters(gpr);
429         
430         m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
431         appendCallWithExceptionCheck(toInt32);
432         m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
433         
434         silentFillAllRegisters(gpr);
435         
436         truncatedToInteger.link(&m_jit);
437         integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
438         return;
439     }
440     
441     JSValueOperand op1(this, node.child1());
442     GPRTemporary result(this, op1);
443     GPRReg jsValueGpr = op1.gpr();
444     GPRReg resultGPR = result.gpr();
445     op1.use();
446
447     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
448
449     // First handle non-integers
450     silentSpillAllRegisters(resultGPR);
451     callOperation(dfgConvertJSValueToInt32, resultGPR, jsValueGpr);
452     silentFillAllRegisters(resultGPR);
453     JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
454
455     // Then handle integers.
456     isInteger.link(&m_jit);
457     m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
458     hasCalledToInt32.link(&m_jit);
459     integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
460 }
461
462 void JITCodeGenerator::nonSpeculativeUInt32ToNumber(Node& node)
463 {
464     IntegerOperand op1(this, node.child1());
465     FPRTemporary boxer(this);
466     GPRTemporary result(this, op1);
467     
468     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
469     
470     m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
471     m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());
472     
473     boxDouble(boxer.fpr(), result.gpr());
474     
475     JITCompiler::Jump done = m_jit.jump();
476     
477     positive.link(&m_jit);
478     
479     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
480     
481     done.link(&m_jit);
482     
483     jsValueResult(result.gpr(), m_compileIndex);
484 }
485
486 void JITCodeGenerator::nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)
487 {
488     JSValueOperand regArg(this, regChild);
489     GPRReg regArgGPR = regArg.gpr();
490     GPRTemporary result(this);
491     GPRReg resultGPR = result.gpr();
492     FPRTemporary tmp1(this);
493     FPRTemporary tmp2(this);
494     FPRReg tmp1FPR = tmp1.fpr();
495     FPRReg tmp2FPR = tmp2.fpr();
496     
497     regArg.use();
498     use(immChild);
499
500     JITCompiler::Jump notInt;
501     
502     int32_t imm = valueOfInt32Constant(immChild);
503         
504     if (!isKnownInteger(regChild))
505         notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);
506     
507     JITCompiler::Jump overflow;
508     
509     switch (op) {
510     case ValueAdd:
511     case ArithAdd:
512         overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
513         break;
514         
515     case ArithSub:
516         overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
517         break;
518         
519     default:
520         ASSERT_NOT_REACHED();
521     }
522     
523     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
524         
525     JITCompiler::Jump done = m_jit.jump();
526     
527     overflow.link(&m_jit);
528     
529     JITCompiler::Jump notNumber;
530     
531     // first deal with overflow case
532     m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);
533     
534     // now deal with not-int case, if applicable
535     if (!isKnownInteger(regChild)) {
536         JITCompiler::Jump haveValue = m_jit.jump();
537         
538         notInt.link(&m_jit);
539         
540         if (!isKnownNumeric(regChild)) {
541             ASSERT(op == ValueAdd);
542             notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);
543         }
544         
545         m_jit.move(regArgGPR, resultGPR);
546         m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
547         m_jit.movePtrToDouble(resultGPR, tmp2FPR);
548         
549         haveValue.link(&m_jit);
550     }
551     
552     m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);
553     m_jit.movePtrToDouble(resultGPR, tmp1FPR);
554     switch (op) {
555     case ValueAdd:
556     case ArithAdd:
557         m_jit.addDouble(tmp1FPR, tmp2FPR);
558         break;
559         
560     case ArithSub:
561         m_jit.subDouble(tmp1FPR, tmp2FPR);
562         break;
563             
564     default:
565         ASSERT_NOT_REACHED();
566     }
567     
568     JITCompiler::Jump doneCaseConvertedToInt;
569     
570     if (op == ValueAdd) {
571         JITCompiler::JumpList failureCases;
572         m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);
573         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
574         
575         doneCaseConvertedToInt = m_jit.jump();
576         
577         failureCases.link(&m_jit);
578     }
579     
580     m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);
581     m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
582         
583     if (!isKnownNumeric(regChild)) {
584         ASSERT(notNumber.isSet());
585         ASSERT(op == ValueAdd);
586             
587         JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
588             
589         notNumber.link(&m_jit);
590             
591         silentSpillAllRegisters(resultGPR);
592         if (commute)
593             callOperation(operationValueAddNotNumber, resultGPR, MacroAssembler::Imm32(imm), regArgGPR);
594         else
595             callOperation(operationValueAddNotNumber, resultGPR, regArgGPR, MacroAssembler::Imm32(imm));
596         silentFillAllRegisters(resultGPR);
597             
598         doneCaseWasNumber.link(&m_jit);
599     }
600     
601     done.link(&m_jit);
602     if (doneCaseConvertedToInt.isSet())
603         doneCaseConvertedToInt.link(&m_jit);
604         
605     jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
606 }
607
608 void JITCodeGenerator::nonSpeculativeBasicArithOp(NodeType op, Node &node)
609 {
610     JSValueOperand arg1(this, node.child1());
611     JSValueOperand arg2(this, node.child2());
612     
613     FPRTemporary tmp1(this);
614     FPRTemporary tmp2(this);
615     FPRReg tmp1FPR = tmp1.fpr();
616     FPRReg tmp2FPR = tmp2.fpr();
617     
618     GPRTemporary result(this);
619
620     GPRReg arg1GPR = arg1.gpr();
621     GPRReg arg2GPR = arg2.gpr();
622     
623     GPRReg resultGPR = result.gpr();
624     
625     arg1.use();
626     arg2.use();
627     
628     JITCompiler::Jump child1NotInt;
629     JITCompiler::Jump child2NotInt;
630     JITCompiler::JumpList overflow;
631     
632     if (!isKnownInteger(node.child1()))
633         child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);
634     if (!isKnownInteger(node.child2()))
635         child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
636     
637     switch (op) {
638     case ValueAdd:
639     case ArithAdd: {
640         overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
641         break;
642     }
643         
644     case ArithSub: {
645         overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
646         break;
647     }
648         
649     case ArithMul: {
650         overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
651         overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
652         break;
653     }
654         
655     default:
656         ASSERT_NOT_REACHED();
657     }
658     
659     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
660         
661     JITCompiler::Jump done = m_jit.jump();
662     
663     JITCompiler::JumpList haveFPRArguments;
664
665     overflow.link(&m_jit);
666         
667     // both arguments are integers
668     m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
669     m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
670         
671     haveFPRArguments.append(m_jit.jump());
672         
673     JITCompiler::JumpList notNumbers;
674         
675     JITCompiler::Jump child2NotInt2;
676         
677     if (!isKnownInteger(node.child1())) {
678         child1NotInt.link(&m_jit);
679             
680         if (!isKnownNumeric(node.child1())) {
681             ASSERT(op == ValueAdd);
682             notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));
683         }
684             
685         m_jit.move(arg1GPR, resultGPR);
686         unboxDouble(resultGPR, tmp1FPR);
687             
688         // child1 is converted to a double; child2 may either be an int or
689         // a boxed double
690             
691         if (!isKnownInteger(node.child2())) {
692             if (isKnownNumeric(node.child2()))
693                 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
694             else {
695                 ASSERT(op == ValueAdd);
696                 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
697                 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
698                 child2NotInt2 = m_jit.jump();
699                 child2IsInt.link(&m_jit);
700             }
701         }
702             
703         // child 2 is definitely an integer
704         m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
705             
706         haveFPRArguments.append(m_jit.jump());
707     }
708         
709     if (!isKnownInteger(node.child2())) {
710         child2NotInt.link(&m_jit);
711             
712         if (!isKnownNumeric(node.child2())) {
713             ASSERT(op == ValueAdd);
714             notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
715         }
716             
717         // child1 is definitely an integer, and child 2 is definitely not
718             
719         m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
720             
721         if (child2NotInt2.isSet())
722             child2NotInt2.link(&m_jit);
723             
724         m_jit.move(arg2GPR, resultGPR);
725         unboxDouble(resultGPR, tmp2FPR);
726     }
727         
728     haveFPRArguments.link(&m_jit);
729         
730     switch (op) {
731     case ValueAdd:
732     case ArithAdd:
733         m_jit.addDouble(tmp2FPR, tmp1FPR);
734         break;
735             
736     case ArithSub:
737         m_jit.subDouble(tmp2FPR, tmp1FPR);
738         break;
739             
740     case ArithMul:
741         m_jit.mulDouble(tmp2FPR, tmp1FPR);
742         break;
743             
744     default:
745         ASSERT_NOT_REACHED();
746     }
747     
748     JITCompiler::Jump doneCaseConvertedToInt;
749     
750     if (op == ValueAdd) {
751         JITCompiler::JumpList failureCases;
752         m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);
753         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
754         
755         doneCaseConvertedToInt = m_jit.jump();
756         
757         failureCases.link(&m_jit);
758     }
759         
760     boxDouble(tmp1FPR, resultGPR);
761         
762     if (!notNumbers.empty()) {
763         ASSERT(op == ValueAdd);
764             
765         JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
766             
767         notNumbers.link(&m_jit);
768             
769         silentSpillAllRegisters(resultGPR);
770         callOperation(operationValueAddNotNumber, resultGPR, arg1GPR, arg2GPR);
771         silentFillAllRegisters(resultGPR);
772
773         doneCaseWasNumber.link(&m_jit);
774     }
775     
776     done.link(&m_jit);
777     if (doneCaseConvertedToInt.isSet())
778         doneCaseConvertedToInt.link(&m_jit);
779         
780     jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
781 }
782
783 JITCompiler::Call JITCodeGenerator::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, NodeType nodeType)
784 {
785     ASSERT(nodeType == GetById || nodeType == GetMethod);
786
787     JITCompiler::DataLabelPtr structureToCompare;
788     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
789     
790     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
791     JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
792     
793     JITCompiler::Jump done = m_jit.jump();
794
795     structureCheck.link(&m_jit);
796     
797     if (slowPathTarget.isSet())
798         slowPathTarget.link(&m_jit);
799     
800     JITCompiler::Label slowCase = m_jit.label();
801
802     silentSpillAllRegisters(resultGPR);
803     JITCompiler::Call functionCall = callOperation(nodeType == GetById ? operationGetByIdOptimize : operationGetMethodOptimize, resultGPR, baseGPR, identifier(identifierNumber));
804     silentFillAllRegisters(resultGPR);
805     
806     done.link(&m_jit);
807     
808     JITCompiler::Label doneLabel = m_jit.label();
809
810     int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
811     int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
812     int16_t callToLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, loadWithPatch));
813     int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
814     int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
815     
816     m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToLoad, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR));
817     
818     if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)
819         unlock(scratchGPR);
820     
821     return functionCall;
822 }
823
824 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
825 {
826     
827     JITCompiler::DataLabelPtr structureToCompare;
828     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
829
830     writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);
831
832     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
833     JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
834
835     JITCompiler::Jump done = m_jit.jump();
836
837     structureCheck.link(&m_jit);
838
839     if (slowPathTarget.isSet())
840         slowPathTarget.link(&m_jit);
841
842     JITCompiler::Label slowCase = m_jit.label();
843
844     silentSpillAllRegisters(InvalidGPRReg);
845     V_DFGOperation_EJCI optimizedCall;
846     if (m_jit.codeBlock()->isStrictMode()) {
847         if (putKind == Direct)
848             optimizedCall = operationPutByIdDirectStrictOptimize;
849         else
850             optimizedCall = operationPutByIdStrictOptimize;
851     } else {
852         if (putKind == Direct)
853             optimizedCall = operationPutByIdDirectNonStrictOptimize;
854         else
855             optimizedCall = operationPutByIdNonStrictOptimize;
856     }
857     JITCompiler::Call functionCall = callOperation(optimizedCall, valueGPR, baseGPR, identifier(identifierNumber));
858     silentFillAllRegisters(InvalidGPRReg);
859
860     done.link(&m_jit);
861     JITCompiler::Label doneLabel = m_jit.label();
862
863     int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
864     int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
865     int16_t callToStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, storeWithPatch));
866     int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
867     int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
868
869     m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR));
870 }
871
872 void JITCodeGenerator::cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
873 {
874     JITCompiler::Call slowCall;
875     JITCompiler::DataLabelPtr structToCompare, protoObj, protoStructToCompare, putFunction;
876     
877     JITCompiler::Jump wrongStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
878     protoObj = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
879     JITCompiler::Jump wrongProtoStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(resultGPR, JSCell::structureOffset()), protoStructToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
880     
881     putFunction = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
882     
883     JITCompiler::Jump done = m_jit.jump();
884     
885     wrongStructure.link(&m_jit);
886     wrongProtoStructure.link(&m_jit);
887     
888     slowCall = cachedGetById(baseGPR, resultGPR, scratchGPR, identifierNumber, slowPathTarget, GetMethod);
889     
890     done.link(&m_jit);
891     
892     m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction);
893 }
894
895 void JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
896 {
897     JSValueOperand arg(this, operand);
898     GPRReg argGPR = arg.gpr();
899     
900     GPRTemporary result(this, arg);
901     GPRReg resultGPR = result.gpr();
902     
903     JITCompiler::Jump notCell;
904     
905     if (!isKnownCell(operand))
906         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
907     
908     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
909     m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
910     
911     if (!isKnownCell(operand)) {
912         JITCompiler::Jump done = m_jit.jump();
913         
914         notCell.link(&m_jit);
915         
916         m_jit.move(argGPR, resultGPR);
917         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
918         m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
919         
920         done.link(&m_jit);
921     }
922     
923     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
924     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
925 }
926
927 void JITCodeGenerator::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)
928 {
929     Node& branchNode = at(branchNodeIndex);
930     BlockIndex taken = branchNode.takenBlockIndex();
931     BlockIndex notTaken = branchNode.notTakenBlockIndex();
932     
933     if (taken == (m_block + 1)) {
934         invert = !invert;
935         BlockIndex tmp = taken;
936         taken = notTaken;
937         notTaken = tmp;
938     }
939
940     JSValueOperand arg(this, operand);
941     GPRReg argGPR = arg.gpr();
942     
943     GPRTemporary result(this, arg);
944     GPRReg resultGPR = result.gpr();
945     
946     JITCompiler::Jump notCell;
947     
948     if (!isKnownCell(operand))
949         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
950     
951     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
952     addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);
953     
954     if (!isKnownCell(operand)) {
955         addBranch(m_jit.jump(), notTaken);
956         
957         notCell.link(&m_jit);
958         
959         m_jit.move(argGPR, resultGPR);
960         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
961         addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);
962     }
963     
964     if (notTaken != (m_block + 1))
965         addBranch(m_jit.jump(), notTaken);
966 }
967
968 bool JITCodeGenerator::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)
969 {
970     NodeIndex branchNodeIndex = detectPeepHoleBranch();
971     if (branchNodeIndex != NoNode) {
972         ASSERT(node.adjustedRefCount() == 1);
973         
974         nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
975     
976         use(node.child1());
977         use(node.child2());
978         m_compileIndex = branchNodeIndex;
979         
980         return true;
981     }
982     
983     nonSpeculativeNonPeepholeCompareNull(operand, invert);
984     
985     return false;
986 }
987
988 void JITCodeGenerator::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
989 {
990     Node& branchNode = at(branchNodeIndex);
991     BlockIndex taken = branchNode.takenBlockIndex();
992     BlockIndex notTaken = branchNode.notTakenBlockIndex();
993
994     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
995
996     // The branch instruction will branch to the taken block.
997     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
998     if (taken == (m_block + 1)) {
999         cond = JITCompiler::invert(cond);
1000         callResultCondition = JITCompiler::Zero;
1001         BlockIndex tmp = taken;
1002         taken = notTaken;
1003         notTaken = tmp;
1004     }
1005
1006     JSValueOperand arg1(this, node.child1());
1007     JSValueOperand arg2(this, node.child2());
1008     GPRReg arg1GPR = arg1.gpr();
1009     GPRReg arg2GPR = arg2.gpr();
1010     
1011     JITCompiler::JumpList slowPath;
1012     
1013     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
1014         GPRResult result(this);
1015         GPRReg resultGPR = result.gpr();
1016     
1017         arg1.use();
1018         arg2.use();
1019     
1020         flushRegisters();
1021         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1022
1023         addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
1024     } else {
1025         GPRTemporary result(this, arg2);
1026         GPRReg resultGPR = result.gpr();
1027     
1028         arg1.use();
1029         arg2.use();
1030     
1031         if (!isKnownInteger(node.child1()))
1032             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
1033         if (!isKnownInteger(node.child2()))
1034             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
1035     
1036         addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken);
1037     
1038         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
1039             addBranch(m_jit.jump(), notTaken);
1040     
1041             slowPath.link(&m_jit);
1042     
1043             silentSpillAllRegisters(resultGPR);
1044             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1045             silentFillAllRegisters(resultGPR);
1046         
1047             addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
1048         }
1049     }
1050
1051     if (notTaken != (m_block + 1))
1052         addBranch(m_jit.jump(), notTaken);
1053 }
1054
1055 void JITCodeGenerator::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
1056 {
1057     JSValueOperand arg1(this, node.child1());
1058     JSValueOperand arg2(this, node.child2());
1059     GPRReg arg1GPR = arg1.gpr();
1060     GPRReg arg2GPR = arg2.gpr();
1061     
1062     JITCompiler::JumpList slowPath;
1063     
1064     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
1065         GPRResult result(this);
1066         GPRReg resultGPR = result.gpr();
1067     
1068         arg1.use();
1069         arg2.use();
1070     
1071         flushRegisters();
1072         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1073         
1074         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1075         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1076     } else {
1077         GPRTemporary result(this, arg2);
1078         GPRReg resultGPR = result.gpr();
1079
1080         arg1.use();
1081         arg2.use();
1082     
1083         if (!isKnownInteger(node.child1()))
1084             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
1085         if (!isKnownInteger(node.child2()))
1086             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
1087     
1088         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
1089     
1090         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
1091             JITCompiler::Jump haveResult = m_jit.jump();
1092     
1093             slowPath.link(&m_jit);
1094         
1095             silentSpillAllRegisters(resultGPR);
1096             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1097             silentFillAllRegisters(resultGPR);
1098         
1099             m_jit.andPtr(TrustedImm32(1), resultGPR);
1100         
1101             haveResult.link(&m_jit);
1102         }
1103         
1104         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1105         
1106         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1107     }
1108 }
1109
1110 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
1111 {
1112     Node& branchNode = at(branchNodeIndex);
1113     BlockIndex taken = branchNode.takenBlockIndex();
1114     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1115
1116     // The branch instruction will branch to the taken block.
1117     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1118     if (taken == (m_block + 1)) {
1119         invert = !invert;
1120         BlockIndex tmp = taken;
1121         taken = notTaken;
1122         notTaken = tmp;
1123     }
1124     
1125     JSValueOperand arg1(this, node.child1());
1126     JSValueOperand arg2(this, node.child2());
1127     GPRReg arg1GPR = arg1.gpr();
1128     GPRReg arg2GPR = arg2.gpr();
1129     
1130     GPRTemporary result(this);
1131     GPRReg resultGPR = result.gpr();
1132     
1133     arg1.use();
1134     arg2.use();
1135     
1136     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1137         // see if we get lucky: if the arguments are cells and they reference the same
1138         // cell, then they must be strictly equal.
1139         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1140         
1141         silentSpillAllRegisters(resultGPR);
1142         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1143         silentFillAllRegisters(resultGPR);
1144         
1145         addBranch(m_jit.branchTest32(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
1146     } else {
1147         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1148         
1149         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1150         
1151         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1152         
1153         addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
1154         addBranch(m_jit.jump(), notTaken);
1155         
1156         twoCellsCase.link(&m_jit);
1157         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1158         
1159         numberCase.link(&m_jit);
1160         
1161         silentSpillAllRegisters(resultGPR);
1162         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1163         silentFillAllRegisters(resultGPR);
1164         
1165         addBranch(m_jit.branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
1166     }
1167     
1168     if (notTaken != (m_block + 1))
1169         addBranch(m_jit.jump(), notTaken);
1170 }
1171
1172 void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
1173 {
1174     JSValueOperand arg1(this, node.child1());
1175     JSValueOperand arg2(this, node.child2());
1176     GPRReg arg1GPR = arg1.gpr();
1177     GPRReg arg2GPR = arg2.gpr();
1178     
1179     GPRTemporary result(this);
1180     GPRReg resultGPR = result.gpr();
1181     
1182     arg1.use();
1183     arg2.use();
1184     
1185     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1186         // see if we get lucky: if the arguments are cells and they reference the same
1187         // cell, then they must be strictly equal.
1188         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1189         
1190         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1191         
1192         JITCompiler::Jump done = m_jit.jump();
1193
1194         notEqualCase.link(&m_jit);
1195         
1196         silentSpillAllRegisters(resultGPR);
1197         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1198         silentFillAllRegisters(resultGPR);
1199         
1200         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1201         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1202         
1203         done.link(&m_jit);
1204     } else {
1205         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1206         
1207         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1208         
1209         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1210         
1211         m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
1212         
1213         JITCompiler::Jump done1 = m_jit.jump();
1214         
1215         twoCellsCase.link(&m_jit);
1216         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1217         
1218         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1219         
1220         JITCompiler::Jump done2 = m_jit.jump();
1221         
1222         numberCase.link(&m_jit);
1223         notEqualCase.link(&m_jit);
1224         
1225         silentSpillAllRegisters(resultGPR);
1226         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1227         silentFillAllRegisters(resultGPR);
1228         
1229         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1230
1231         done1.link(&m_jit);
1232
1233         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1234         
1235         done2.link(&m_jit);
1236     }
1237     
1238     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1239 }
1240
1241 void JITCodeGenerator::emitCall(Node& node)
1242 {
1243     P_DFGOperation_E slowCallFunction;
1244     bool isCall;
1245     
1246     if (node.op == Call) {
1247         slowCallFunction = operationLinkCall;
1248         isCall = true;
1249     } else {
1250         ASSERT(node.op == Construct);
1251         slowCallFunction = operationLinkConstruct;
1252         isCall = false;
1253     }
1254     
1255     NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
1256     JSValueOperand callee(this, calleeNodeIndex);
1257     GPRReg calleeGPR = callee.gpr();
1258     use(calleeNodeIndex);
1259     
1260     // the call instruction's first child is either the function (normal call) or the
1261     // receiver (method call). subsequent children are the arguments.
1262     int numArgs = node.numChildren() - 1;
1263     
1264     // For constructors, the this argument is not passed but we have to make space
1265     // for it.
1266     int numPassedArgs = numArgs + (isCall ? 0 : 1);
1267     
1268     // amount of stuff (in units of sizeof(Register)) that we need to place at the
1269     // top of the JS stack.
1270     int callDataSize = 0;
1271
1272     // first there are the arguments
1273     callDataSize += numPassedArgs;
1274     
1275     // and then there is the call frame header
1276     callDataSize += RegisterFile::CallFrameHeaderSize;
1277     
1278     m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs))), addressOfCallData(RegisterFile::ArgumentCount));
1279     m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));
1280     
1281     for (int argIdx = 0; argIdx < numArgs; argIdx++) {
1282         NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
1283         JSValueOperand arg(this, argNodeIndex);
1284         GPRReg argGPR = arg.gpr();
1285         use(argNodeIndex);
1286         
1287         m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx + (isCall ? 0 : 1)));
1288     }
1289     
1290     m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
1291     
1292     flushRegisters();
1293     
1294     GPRResult result(this);
1295     GPRReg resultGPR = result.gpr();
1296
1297     JITCompiler::DataLabelPtr targetToCheck;
1298     JITCompiler::Jump slowPath;
1299     
1300     slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
1301     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
1302     m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
1303
1304     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1305     
1306     JITCompiler::Call fastCall = m_jit.nearCall();
1307     m_jit.notifyCall(fastCall, at(m_compileIndex).codeOrigin);
1308     
1309     JITCompiler::Jump done = m_jit.jump();
1310     
1311     slowPath.link(&m_jit);
1312     
1313     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1314     JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
1315     m_jit.move(Imm32(numPassedArgs), GPRInfo::regT1);
1316     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1317     m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
1318     
1319     done.link(&m_jit);
1320     
1321     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1322     
1323     jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
1324     
1325     m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, at(m_compileIndex).codeOrigin);
1326 }
1327
1328 #endif
1329
1330 } } // namespace JSC::DFG
1331
1332 #endif