Towards 8 Bit Strings: Templatize JSC::Parser class by Lexer type
[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     m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, loadWithPatch, slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR)));
811     
812     if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)
813         unlock(scratchGPR);
814     
815     return functionCall;
816 }
817
818 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
819 {
820     
821     JITCompiler::DataLabelPtr structureToCompare;
822     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
823
824     writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);
825
826     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
827     JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
828
829     JITCompiler::Jump done = m_jit.jump();
830
831     structureCheck.link(&m_jit);
832
833     if (slowPathTarget.isSet())
834         slowPathTarget.link(&m_jit);
835
836     JITCompiler::Label slowCase = m_jit.label();
837
838     silentSpillAllRegisters(InvalidGPRReg);
839     V_DFGOperation_EJCI optimizedCall;
840     if (m_jit.codeBlock()->isStrictMode()) {
841         if (putKind == Direct)
842             optimizedCall = operationPutByIdDirectStrictOptimize;
843         else
844             optimizedCall = operationPutByIdStrictOptimize;
845     } else {
846         if (putKind == Direct)
847             optimizedCall = operationPutByIdDirectNonStrictOptimize;
848         else
849             optimizedCall = operationPutByIdNonStrictOptimize;
850     }
851     JITCompiler::Call functionCall = callOperation(optimizedCall, valueGPR, baseGPR, identifier(identifierNumber));
852     silentFillAllRegisters(InvalidGPRReg);
853
854     done.link(&m_jit);
855     JITCompiler::Label doneLabel = m_jit.label();
856
857     m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR)));
858 }
859
860 void JITCodeGenerator::cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
861 {
862     JITCompiler::Call slowCall;
863     JITCompiler::DataLabelPtr structToCompare, protoObj, protoStructToCompare, putFunction;
864     
865     JITCompiler::Jump wrongStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
866     protoObj = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
867     JITCompiler::Jump wrongProtoStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(resultGPR, JSCell::structureOffset()), protoStructToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
868     
869     putFunction = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
870     
871     JITCompiler::Jump done = m_jit.jump();
872     
873     wrongStructure.link(&m_jit);
874     wrongProtoStructure.link(&m_jit);
875     
876     slowCall = cachedGetById(baseGPR, resultGPR, scratchGPR, identifierNumber, slowPathTarget, GetMethod);
877     
878     done.link(&m_jit);
879     
880     m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction);
881 }
882
883 void JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
884 {
885     JSValueOperand arg(this, operand);
886     GPRReg argGPR = arg.gpr();
887     
888     GPRTemporary result(this, arg);
889     GPRReg resultGPR = result.gpr();
890     
891     JITCompiler::Jump notCell;
892     
893     if (!isKnownCell(operand))
894         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
895     
896     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
897     m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
898     
899     if (!isKnownCell(operand)) {
900         JITCompiler::Jump done = m_jit.jump();
901         
902         notCell.link(&m_jit);
903         
904         m_jit.move(argGPR, resultGPR);
905         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
906         m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
907         
908         done.link(&m_jit);
909     }
910     
911     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
912     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
913 }
914
915 void JITCodeGenerator::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)
916 {
917     Node& branchNode = at(branchNodeIndex);
918     BlockIndex taken = branchNode.takenBlockIndex();
919     BlockIndex notTaken = branchNode.notTakenBlockIndex();
920     
921     if (taken == (m_block + 1)) {
922         invert = !invert;
923         BlockIndex tmp = taken;
924         taken = notTaken;
925         notTaken = tmp;
926     }
927
928     JSValueOperand arg(this, operand);
929     GPRReg argGPR = arg.gpr();
930     
931     GPRTemporary result(this, arg);
932     GPRReg resultGPR = result.gpr();
933     
934     JITCompiler::Jump notCell;
935     
936     if (!isKnownCell(operand))
937         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
938     
939     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
940     addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);
941     
942     if (!isKnownCell(operand)) {
943         addBranch(m_jit.jump(), notTaken);
944         
945         notCell.link(&m_jit);
946         
947         m_jit.move(argGPR, resultGPR);
948         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
949         addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);
950     }
951     
952     if (notTaken != (m_block + 1))
953         addBranch(m_jit.jump(), notTaken);
954 }
955
956 bool JITCodeGenerator::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)
957 {
958     NodeIndex branchNodeIndex = detectPeepHoleBranch();
959     if (branchNodeIndex != NoNode) {
960         ASSERT(node.adjustedRefCount() == 1);
961         
962         nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
963     
964         use(node.child1());
965         use(node.child2());
966         m_compileIndex = branchNodeIndex;
967         
968         return true;
969     }
970     
971     nonSpeculativeNonPeepholeCompareNull(operand, invert);
972     
973     return false;
974 }
975
976 void JITCodeGenerator::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
977 {
978     Node& branchNode = at(branchNodeIndex);
979     BlockIndex taken = branchNode.takenBlockIndex();
980     BlockIndex notTaken = branchNode.notTakenBlockIndex();
981
982     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
983
984     // The branch instruction will branch to the taken block.
985     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
986     if (taken == (m_block + 1)) {
987         cond = JITCompiler::invert(cond);
988         callResultCondition = JITCompiler::Zero;
989         BlockIndex tmp = taken;
990         taken = notTaken;
991         notTaken = tmp;
992     }
993
994     JSValueOperand arg1(this, node.child1());
995     JSValueOperand arg2(this, node.child2());
996     GPRReg arg1GPR = arg1.gpr();
997     GPRReg arg2GPR = arg2.gpr();
998     
999     JITCompiler::JumpList slowPath;
1000     
1001     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
1002         GPRResult result(this);
1003         GPRReg resultGPR = result.gpr();
1004     
1005         arg1.use();
1006         arg2.use();
1007     
1008         flushRegisters();
1009         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1010
1011         addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
1012     } else {
1013         GPRTemporary result(this, arg2);
1014         GPRReg resultGPR = result.gpr();
1015     
1016         arg1.use();
1017         arg2.use();
1018     
1019         if (!isKnownInteger(node.child1()))
1020             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
1021         if (!isKnownInteger(node.child2()))
1022             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
1023     
1024         addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken);
1025     
1026         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
1027             addBranch(m_jit.jump(), notTaken);
1028     
1029             slowPath.link(&m_jit);
1030     
1031             silentSpillAllRegisters(resultGPR);
1032             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1033             silentFillAllRegisters(resultGPR);
1034         
1035             addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
1036         }
1037     }
1038
1039     if (notTaken != (m_block + 1))
1040         addBranch(m_jit.jump(), notTaken);
1041 }
1042
1043 void JITCodeGenerator::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
1044 {
1045     JSValueOperand arg1(this, node.child1());
1046     JSValueOperand arg2(this, node.child2());
1047     GPRReg arg1GPR = arg1.gpr();
1048     GPRReg arg2GPR = arg2.gpr();
1049     
1050     JITCompiler::JumpList slowPath;
1051     
1052     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
1053         GPRResult result(this);
1054         GPRReg resultGPR = result.gpr();
1055     
1056         arg1.use();
1057         arg2.use();
1058     
1059         flushRegisters();
1060         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1061         
1062         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1063         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1064     } else {
1065         GPRTemporary result(this, arg2);
1066         GPRReg resultGPR = result.gpr();
1067
1068         arg1.use();
1069         arg2.use();
1070     
1071         if (!isKnownInteger(node.child1()))
1072             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
1073         if (!isKnownInteger(node.child2()))
1074             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
1075     
1076         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
1077     
1078         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
1079             JITCompiler::Jump haveResult = m_jit.jump();
1080     
1081             slowPath.link(&m_jit);
1082         
1083             silentSpillAllRegisters(resultGPR);
1084             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1085             silentFillAllRegisters(resultGPR);
1086         
1087             m_jit.andPtr(TrustedImm32(1), resultGPR);
1088         
1089             haveResult.link(&m_jit);
1090         }
1091         
1092         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1093         
1094         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1095     }
1096 }
1097
1098 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
1099 {
1100     Node& branchNode = at(branchNodeIndex);
1101     BlockIndex taken = branchNode.takenBlockIndex();
1102     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1103
1104     // The branch instruction will branch to the taken block.
1105     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1106     if (taken == (m_block + 1)) {
1107         invert = !invert;
1108         BlockIndex tmp = taken;
1109         taken = notTaken;
1110         notTaken = tmp;
1111     }
1112     
1113     JSValueOperand arg1(this, node.child1());
1114     JSValueOperand arg2(this, node.child2());
1115     GPRReg arg1GPR = arg1.gpr();
1116     GPRReg arg2GPR = arg2.gpr();
1117     
1118     GPRTemporary result(this);
1119     GPRReg resultGPR = result.gpr();
1120     
1121     arg1.use();
1122     arg2.use();
1123     
1124     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1125         // see if we get lucky: if the arguments are cells and they reference the same
1126         // cell, then they must be strictly equal.
1127         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1128         
1129         silentSpillAllRegisters(resultGPR);
1130         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1131         silentFillAllRegisters(resultGPR);
1132         
1133         addBranch(m_jit.branchTest32(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
1134     } else {
1135         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1136         
1137         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1138         
1139         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1140         
1141         addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
1142         addBranch(m_jit.jump(), notTaken);
1143         
1144         twoCellsCase.link(&m_jit);
1145         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1146         
1147         numberCase.link(&m_jit);
1148         
1149         silentSpillAllRegisters(resultGPR);
1150         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1151         silentFillAllRegisters(resultGPR);
1152         
1153         addBranch(m_jit.branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
1154     }
1155     
1156     if (notTaken != (m_block + 1))
1157         addBranch(m_jit.jump(), notTaken);
1158 }
1159
1160 void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
1161 {
1162     JSValueOperand arg1(this, node.child1());
1163     JSValueOperand arg2(this, node.child2());
1164     GPRReg arg1GPR = arg1.gpr();
1165     GPRReg arg2GPR = arg2.gpr();
1166     
1167     GPRTemporary result(this);
1168     GPRReg resultGPR = result.gpr();
1169     
1170     arg1.use();
1171     arg2.use();
1172     
1173     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1174         // see if we get lucky: if the arguments are cells and they reference the same
1175         // cell, then they must be strictly equal.
1176         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1177         
1178         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1179         
1180         JITCompiler::Jump done = m_jit.jump();
1181
1182         notEqualCase.link(&m_jit);
1183         
1184         silentSpillAllRegisters(resultGPR);
1185         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1186         silentFillAllRegisters(resultGPR);
1187         
1188         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1189         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1190         
1191         done.link(&m_jit);
1192     } else {
1193         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1194         
1195         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1196         
1197         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1198         
1199         m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
1200         
1201         JITCompiler::Jump done1 = m_jit.jump();
1202         
1203         twoCellsCase.link(&m_jit);
1204         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1205         
1206         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1207         
1208         JITCompiler::Jump done2 = m_jit.jump();
1209         
1210         numberCase.link(&m_jit);
1211         notEqualCase.link(&m_jit);
1212         
1213         silentSpillAllRegisters(resultGPR);
1214         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1215         silentFillAllRegisters(resultGPR);
1216         
1217         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1218
1219         done1.link(&m_jit);
1220
1221         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1222         
1223         done2.link(&m_jit);
1224     }
1225     
1226     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1227 }
1228
1229 void JITCodeGenerator::emitCall(Node& node)
1230 {
1231     P_DFGOperation_E slowCallFunction;
1232     bool isCall;
1233     
1234     if (node.op == Call) {
1235         slowCallFunction = operationLinkCall;
1236         isCall = true;
1237     } else {
1238         ASSERT(node.op == Construct);
1239         slowCallFunction = operationLinkConstruct;
1240         isCall = false;
1241     }
1242     
1243     NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
1244     JSValueOperand callee(this, calleeNodeIndex);
1245     GPRReg calleeGPR = callee.gpr();
1246     use(calleeNodeIndex);
1247     
1248     // the call instruction's first child is either the function (normal call) or the
1249     // receiver (method call). subsequent children are the arguments.
1250     int numArgs = node.numChildren() - 1;
1251     
1252     // For constructors, the this argument is not passed but we have to make space
1253     // for it.
1254     int numPassedArgs = numArgs + (isCall ? 0 : 1);
1255     
1256     // amount of stuff (in units of sizeof(Register)) that we need to place at the
1257     // top of the JS stack.
1258     int callDataSize = 0;
1259
1260     // first there are the arguments
1261     callDataSize += numPassedArgs;
1262     
1263     // and then there is the call frame header
1264     callDataSize += RegisterFile::CallFrameHeaderSize;
1265     
1266     m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs))), addressOfCallData(RegisterFile::ArgumentCount));
1267     m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));
1268     
1269     for (int argIdx = 0; argIdx < numArgs; argIdx++) {
1270         NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
1271         JSValueOperand arg(this, argNodeIndex);
1272         GPRReg argGPR = arg.gpr();
1273         use(argNodeIndex);
1274         
1275         m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx + (isCall ? 0 : 1)));
1276     }
1277     
1278     m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
1279     
1280     flushRegisters();
1281     
1282     GPRResult result(this);
1283     GPRReg resultGPR = result.gpr();
1284
1285     JITCompiler::DataLabelPtr targetToCheck;
1286     JITCompiler::Jump slowPath;
1287     
1288     slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
1289     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
1290     m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
1291
1292     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1293     
1294     JITCompiler::Call fastCall = m_jit.nearCall();
1295     m_jit.notifyCall(fastCall, at(m_compileIndex).codeOrigin);
1296     
1297     JITCompiler::Jump done = m_jit.jump();
1298     
1299     slowPath.link(&m_jit);
1300     
1301     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1302     JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
1303     m_jit.move(Imm32(numPassedArgs), GPRInfo::regT1);
1304     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1305     m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
1306     
1307     done.link(&m_jit);
1308     
1309     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1310     
1311     jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
1312     
1313     m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, at(m_compileIndex).codeOrigin);
1314 }
1315
1316 #endif
1317
1318 } } // namespace JSC::DFG
1319
1320 #endif