initial import
[vuplus_webkit] / Source / JavaScriptCore / dfg / DFGJITCodeGenerator.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 "DFGNonSpeculativeJIT.h"
32 #include "DFGSpeculativeJIT.h"
33 #include "LinkBuffer.h"
34
35 namespace JSC { namespace DFG {
36
37 void JITCodeGenerator::clearGenerationInfo()
38 {
39     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
40         m_generationInfo[i] = GenerationInfo();
41     m_gprs = RegisterBank<GPRInfo>();
42     m_fprs = RegisterBank<FPRInfo>();
43 }
44
45 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
46 {
47     Node& node = m_jit.graph()[nodeIndex];
48     VirtualRegister virtualRegister = node.virtualRegister();
49     GenerationInfo& info = m_generationInfo[virtualRegister];
50
51     if (info.registerFormat() == DataFormatNone) {
52         GPRReg gpr = allocate();
53
54         if (node.isConstant()) {
55             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
56             if (isInt32Constant(nodeIndex)) {
57                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
58                 info.fillInteger(gpr);
59                 returnFormat = DataFormatInteger;
60                 return gpr;
61             }
62             if (isNumberConstant(nodeIndex)) {
63                 JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));
64                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
65             } else {
66                 ASSERT(isJSConstant(nodeIndex));
67                 JSValue jsValue = valueOfJSConstant(nodeIndex);
68                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
69             }
70         } else {
71             ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
72             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
73             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
74         }
75
76         // Since we statically know that we're filling an integer, and values
77         // in the RegisterFile are boxed, this must be DataFormatJSInteger.
78         // We will check this with a jitAssert below.
79         info.fillJSValue(gpr, DataFormatJSInteger);
80         unlock(gpr);
81     }
82
83     switch (info.registerFormat()) {
84     case DataFormatNone:
85         // Should have filled, above.
86     case DataFormatJSDouble:
87     case DataFormatDouble:
88     case DataFormatJS:
89     case DataFormatCell:
90     case DataFormatJSCell:
91     case DataFormatBoolean:
92     case DataFormatJSBoolean:
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 = m_jit.graph()[nodeIndex];
120     VirtualRegister virtualRegister = node.virtualRegister();
121     GenerationInfo& info = m_generationInfo[virtualRegister];
122
123     if (info.registerFormat() == DataFormatNone) {
124         GPRReg gpr = allocate();
125
126         if (node.isConstant()) {
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             ASSERT(spillFormat & DataFormatJS);
154             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
155             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
156             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
157             unlock(gpr);
158         }
159     }
160
161     switch (info.registerFormat()) {
162     case DataFormatNone:
163         // Should have filled, above.
164     case DataFormatCell:
165     case DataFormatJSCell:
166     case DataFormatBoolean:
167     case DataFormatJSBoolean:
168         // Should only be calling this function if we know this operand to be numeric.
169         ASSERT_NOT_REACHED();
170
171     case DataFormatJS: {
172         GPRReg jsValueGpr = info.gpr();
173         m_gprs.lock(jsValueGpr);
174         FPRReg fpr = fprAllocate();
175         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
176
177         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
178
179         m_jit.jitAssertIsJSDouble(jsValueGpr);
180
181         // First, if we get here we have a double encoded as a JSValue
182         m_jit.move(jsValueGpr, tempGpr);
183         unboxDouble(tempGpr, fpr);
184         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
185
186         // Finally, handle integers.
187         isInteger.link(&m_jit);
188         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
189         hasUnboxedDouble.link(&m_jit);
190
191         m_gprs.release(jsValueGpr);
192         m_gprs.unlock(jsValueGpr);
193         m_gprs.unlock(tempGpr);
194         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
195         info.fillDouble(fpr);
196         info.killSpilled();
197         return fpr;
198     }
199
200     case DataFormatJSInteger:
201     case DataFormatInteger: {
202         FPRReg fpr = fprAllocate();
203         GPRReg gpr = info.gpr();
204         m_gprs.lock(gpr);
205         m_jit.convertInt32ToDouble(gpr, fpr);
206         m_gprs.unlock(gpr);
207         return fpr;
208     }
209
210     // Unbox the double
211     case DataFormatJSDouble: {
212         GPRReg gpr = info.gpr();
213         FPRReg fpr = fprAllocate();
214         if (m_gprs.isLocked(gpr)) {
215             // Make sure we don't trample gpr if it is in use.
216             GPRReg temp = allocate();
217             m_jit.move(gpr, temp);
218             unboxDouble(temp, fpr);
219             unlock(temp);
220         } else
221             unboxDouble(gpr, fpr);
222
223         m_gprs.release(gpr);
224         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
225
226         info.fillDouble(fpr);
227         return fpr;
228     }
229
230     case DataFormatDouble: {
231         FPRReg fpr = info.fpr();
232         m_fprs.lock(fpr);
233         return fpr;
234     }
235     }
236
237     ASSERT_NOT_REACHED();
238     return InvalidFPRReg;
239 }
240
241 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
242 {
243     Node& node = m_jit.graph()[nodeIndex];
244     VirtualRegister virtualRegister = node.virtualRegister();
245     GenerationInfo& info = m_generationInfo[virtualRegister];
246
247     switch (info.registerFormat()) {
248     case DataFormatNone: {
249         GPRReg gpr = allocate();
250
251         if (node.isConstant()) {
252             if (isInt32Constant(nodeIndex)) {
253                 info.fillJSValue(gpr, DataFormatJSInteger);
254                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
255                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
256             } else if (isNumberConstant(nodeIndex)) {
257                 info.fillJSValue(gpr, DataFormatJSDouble);
258                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));
259                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
260             } else {
261                 ASSERT(isJSConstant(nodeIndex));
262                 JSValue jsValue = valueOfJSConstant(nodeIndex);
263                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
264                 info.fillJSValue(gpr, DataFormatJS);
265             }
266
267             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
268         } else {
269             DataFormat spillFormat = info.spillFormat();
270             ASSERT(spillFormat & DataFormatJS);
271             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
272             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
273             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
274         }
275         return gpr;
276     }
277
278     case DataFormatInteger: {
279         GPRReg gpr = info.gpr();
280         // If the register has already been locked we need to take a copy.
281         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
282         if (m_gprs.isLocked(gpr)) {
283             GPRReg result = allocate();
284             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
285             return result;
286         }
287         m_gprs.lock(gpr);
288         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
289         info.fillJSValue(gpr, DataFormatJSInteger);
290         return gpr;
291     }
292
293     case DataFormatDouble: {
294         FPRReg fpr = info.fpr();
295         GPRReg gpr = boxDouble(fpr);
296
297         // Update all info
298         info.fillJSValue(gpr, DataFormatJSDouble);
299         m_fprs.release(fpr);
300         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
301
302         return gpr;
303     }
304
305     case DataFormatCell:
306         // No retag required on JSVALUE64!
307     case DataFormatJS:
308     case DataFormatJSInteger:
309     case DataFormatJSDouble:
310     case DataFormatJSCell:
311     case DataFormatJSBoolean: {
312         GPRReg gpr = info.gpr();
313         m_gprs.lock(gpr);
314         return gpr;
315     }
316         
317     case DataFormatBoolean:
318         // this type currently never occurs
319         ASSERT_NOT_REACHED();
320     }
321
322     ASSERT_NOT_REACHED();
323     return InvalidGPRReg;
324 }
325
326 void JITCodeGenerator::useChildren(Node& node)
327 {
328     if (node.op & NodeHasVarArgs) {
329         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
330             use(m_jit.graph().m_varArgChildren[childIdx]);
331     } else {
332         NodeIndex child1 = node.child1();
333         if (child1 == NoNode) {
334             ASSERT(node.child2() == NoNode && node.child3() == NoNode);
335             return;
336         }
337         use(child1);
338         
339         NodeIndex child2 = node.child2();
340         if (child2 == NoNode) {
341             ASSERT(node.child3() == NoNode);
342             return;
343         }
344         use(child2);
345         
346         NodeIndex child3 = node.child3();
347         if (child3 == NoNode)
348             return;
349         use(child3);
350     }
351 }
352
353 bool JITCodeGenerator::isStrictInt32(NodeIndex nodeIndex)
354 {
355     if (isInt32Constant(nodeIndex))
356         return true;
357     
358     Node& node = m_jit.graph()[nodeIndex];
359     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
360     
361     return info.registerFormat() == DataFormatInteger;
362 }
363
364 bool JITCodeGenerator::isKnownInteger(NodeIndex nodeIndex)
365 {
366     if (isInt32Constant(nodeIndex))
367         return true;
368
369     Node& node = m_jit.graph()[nodeIndex];
370     
371     if (node.hasInt32Result())
372         return true;
373     
374     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
375
376     return info.isJSInteger();
377 }
378
379 bool JITCodeGenerator::isKnownNumeric(NodeIndex nodeIndex)
380 {
381     if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))
382         return true;
383
384     Node& node = m_jit.graph()[nodeIndex];
385     
386     if (node.hasNumberResult())
387         return true;
388     
389     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
390
391     return info.isJSInteger() || info.isJSDouble();
392 }
393
394 bool JITCodeGenerator::isKnownCell(NodeIndex nodeIndex)
395 {
396     return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();
397 }
398
399 bool JITCodeGenerator::isKnownNotInteger(NodeIndex nodeIndex)
400 {
401     Node& node = m_jit.graph()[nodeIndex];
402     VirtualRegister virtualRegister = node.virtualRegister();
403     GenerationInfo& info = m_generationInfo[virtualRegister];
404     
405     return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
406         || (node.isConstant() && !valueOfJSConstant(nodeIndex).isInt32());
407 }
408
409 bool JITCodeGenerator::isKnownNotNumber(NodeIndex nodeIndex)
410 {
411     Node& node = m_jit.graph()[nodeIndex];
412     VirtualRegister virtualRegister = node.virtualRegister();
413     GenerationInfo& info = m_generationInfo[virtualRegister];
414     
415     return (!info.isJSDouble() && !info.isJSInteger())
416         || (node.isConstant() && !isNumberConstant(nodeIndex));
417 }
418
419 bool JITCodeGenerator::isKnownBoolean(NodeIndex nodeIndex)
420 {
421     Node& node = m_jit.graph()[nodeIndex];
422     if (node.hasBooleanResult())
423         return true;
424     
425     if (isBooleanConstant(nodeIndex))
426         return true;
427     
428     VirtualRegister virtualRegister = node.virtualRegister();
429     GenerationInfo& info = m_generationInfo[virtualRegister];
430     
431     return info.isJSBoolean();
432 }
433
434 template<typename To, typename From>
435 inline To safeCast(From value)
436 {
437     To result = static_cast<To>(value);
438     ASSERT(result == value);
439     return result;
440 }
441
442 JITCompiler::Call JITCodeGenerator::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, NodeType nodeType)
443 {
444     JITCompiler::DataLabelPtr structureToCompare;
445     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
446     
447     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
448     JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
449     
450     JITCompiler::Jump done = m_jit.jump();
451
452     structureCheck.link(&m_jit);
453     
454     if (slowPathTarget.isSet())
455         slowPathTarget.link(&m_jit);
456     
457     JITCompiler::Label slowCase = m_jit.label();
458
459     silentSpillAllRegisters(resultGPR);
460     m_jit.move(baseGPR, GPRInfo::argumentGPR1);
461     m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR2);
462     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
463     JITCompiler::Call functionCall;
464     switch (nodeType) {
465     case GetById:
466         functionCall = appendCallWithExceptionCheck(operationGetByIdOptimize);
467         break;
468         
469     case GetMethod:
470         functionCall = appendCallWithExceptionCheck(operationGetMethodOptimize);
471         break;
472         
473     default:
474         ASSERT_NOT_REACHED();
475         return JITCompiler::Call();
476     }
477     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
478     silentFillAllRegisters(resultGPR);
479     
480     done.link(&m_jit);
481     
482     JITCompiler::Label doneLabel = m_jit.label();
483
484     int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
485     int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
486     int16_t callToLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, loadWithPatch));
487     int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
488     int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
489     
490     m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToLoad, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR));
491     
492     if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)
493         unlock(scratchGPR);
494     
495     return functionCall;
496 }
497
498 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch, WriteBarrierUseKind useKind)
499 {
500     UNUSED_PARAM(jit);
501     UNUSED_PARAM(owner);
502     UNUSED_PARAM(scratch);
503     UNUSED_PARAM(useKind);
504     ASSERT(owner != scratch);
505
506 #if ENABLE(WRITE_BARRIER_PROFILING)
507     JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
508 #endif
509 }
510
511 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
512 {
513     JITCompiler::DataLabelPtr structureToCompare;
514     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
515     
516     writeBarrier(m_jit, baseGPR, scratchGPR, WriteBarrierForPropertyAccess);
517
518     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
519     JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
520
521     JITCompiler::Jump done = m_jit.jump();
522
523     structureCheck.link(&m_jit);
524
525     if (slowPathTarget.isSet())
526         slowPathTarget.link(&m_jit);
527
528     JITCompiler::Label slowCase = m_jit.label();
529
530     silentSpillAllRegisters(InvalidGPRReg);
531     setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(valueGPR, baseGPR);
532     m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR3);
533     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
534     V_DFGOperation_EJJI optimizedCall;
535     if (m_jit.codeBlock()->isStrictMode()) {
536         if (putKind == Direct)
537             optimizedCall = operationPutByIdDirectStrictOptimize;
538         else
539             optimizedCall = operationPutByIdStrictOptimize;
540     } else {
541         if (putKind == Direct)
542             optimizedCall = operationPutByIdDirectNonStrictOptimize;
543         else
544             optimizedCall = operationPutByIdNonStrictOptimize;
545     }
546     JITCompiler::Call functionCall = appendCallWithExceptionCheck(optimizedCall);
547     silentFillAllRegisters(InvalidGPRReg);
548
549     done.link(&m_jit);
550     JITCompiler::Label doneLabel = m_jit.label();
551
552     int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));
553     int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));
554     int16_t callToStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, storeWithPatch));
555     int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));
556     int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));
557
558     m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR));
559 }
560
561 void JITCodeGenerator::cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
562 {
563     JITCompiler::Call slowCall;
564     JITCompiler::DataLabelPtr structToCompare, protoObj, protoStructToCompare, putFunction;
565     
566     JITCompiler::Jump wrongStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
567     protoObj = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
568     JITCompiler::Jump wrongProtoStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(resultGPR, JSCell::structureOffset()), protoStructToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
569     
570     putFunction = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);
571     
572     JITCompiler::Jump done = m_jit.jump();
573     
574     wrongStructure.link(&m_jit);
575     wrongProtoStructure.link(&m_jit);
576     
577     slowCall = cachedGetById(baseGPR, resultGPR, scratchGPR, identifierNumber, slowPathTarget, GetMethod);
578     
579     done.link(&m_jit);
580     
581     m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction);
582 }
583
584 void JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
585 {
586     JSValueOperand arg(this, operand);
587     GPRReg argGPR = arg.gpr();
588     
589     GPRTemporary result(this, arg);
590     GPRReg resultGPR = result.gpr();
591     
592     JITCompiler::Jump notCell;
593     
594     if (!isKnownCell(operand))
595         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
596     
597     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
598     m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
599     
600     if (!isKnownCell(operand)) {
601         JITCompiler::Jump done = m_jit.jump();
602         
603         notCell.link(&m_jit);
604         
605         m_jit.move(argGPR, resultGPR);
606         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
607         m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
608         
609         done.link(&m_jit);
610     }
611     
612     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
613     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
614 }
615
616 void JITCodeGenerator::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)
617 {
618     Node& branchNode = m_jit.graph()[branchNodeIndex];
619     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
620     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
621     
622     if (taken == (m_block + 1)) {
623         invert = !invert;
624         BlockIndex tmp = taken;
625         taken = notTaken;
626         notTaken = tmp;
627     }
628
629     JSValueOperand arg(this, operand);
630     GPRReg argGPR = arg.gpr();
631     
632     GPRTemporary result(this, arg);
633     GPRReg resultGPR = result.gpr();
634     
635     JITCompiler::Jump notCell;
636     
637     if (!isKnownCell(operand))
638         notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
639     
640     m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
641     addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);
642     
643     if (!isKnownCell(operand)) {
644         addBranch(m_jit.jump(), notTaken);
645         
646         notCell.link(&m_jit);
647         
648         m_jit.move(argGPR, resultGPR);
649         m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
650         addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);
651     }
652     
653     if (notTaken != (m_block + 1))
654         addBranch(m_jit.jump(), notTaken);
655 }
656
657 bool JITCodeGenerator::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)
658 {
659     NodeIndex branchNodeIndex = detectPeepHoleBranch();
660     if (branchNodeIndex != NoNode) {
661         ASSERT(node.adjustedRefCount() == 1);
662         
663         nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
664     
665         use(node.child1());
666         use(node.child2());
667         m_compileIndex = branchNodeIndex;
668         
669         return true;
670     }
671     
672     nonSpeculativeNonPeepholeCompareNull(operand, invert);
673     
674     return false;
675 }
676
677 void JITCodeGenerator::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)
678 {
679     Node& branchNode = m_jit.graph()[branchNodeIndex];
680     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
681     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
682
683     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
684
685     // The branch instruction will branch to the taken block.
686     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
687     if (taken == (m_block + 1)) {
688         cond = JITCompiler::invert(cond);
689         callResultCondition = JITCompiler::Zero;
690         BlockIndex tmp = taken;
691         taken = notTaken;
692         notTaken = tmp;
693     }
694
695     JSValueOperand arg1(this, node.child1());
696     JSValueOperand arg2(this, node.child2());
697     GPRReg arg1GPR = arg1.gpr();
698     GPRReg arg2GPR = arg2.gpr();
699     
700     JITCompiler::JumpList slowPath;
701     
702     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
703         GPRResult result(this);
704         GPRReg resultGPR = result.gpr();
705     
706         arg1.use();
707         arg2.use();
708     
709         flushRegisters();
710
711         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
712         addBranch(m_jit.branchTest8(callResultCondition, resultGPR), taken);
713     } else {
714         GPRTemporary result(this, arg2);
715         GPRReg resultGPR = result.gpr();
716     
717         arg1.use();
718         arg2.use();
719     
720         if (!isKnownInteger(node.child1()))
721             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
722         if (!isKnownInteger(node.child2()))
723             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
724     
725         addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken);
726     
727         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
728             addBranch(m_jit.jump(), notTaken);
729     
730             slowPath.link(&m_jit);
731     
732             silentSpillAllRegisters(resultGPR);
733             setupStubArguments(arg1GPR, arg2GPR);
734             m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
735             appendCallWithExceptionCheck(helperFunction);
736             m_jit.move(GPRInfo::returnValueGPR, resultGPR);
737             silentFillAllRegisters(resultGPR);
738         
739             addBranch(m_jit.branchTest8(callResultCondition, resultGPR), taken);
740         }
741     }
742
743     if (notTaken != (m_block + 1))
744         addBranch(m_jit.jump(), notTaken);
745 }
746
747 void JITCodeGenerator::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)
748 {
749     JSValueOperand arg1(this, node.child1());
750     JSValueOperand arg2(this, node.child2());
751     GPRReg arg1GPR = arg1.gpr();
752     GPRReg arg2GPR = arg2.gpr();
753     
754     JITCompiler::JumpList slowPath;
755     
756     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
757         GPRResult result(this);
758         GPRReg resultGPR = result.gpr();
759     
760         arg1.use();
761         arg2.use();
762     
763         flushRegisters();
764         
765         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
766         
767         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
768         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
769     } else {
770         GPRTemporary result(this, arg2);
771         GPRReg resultGPR = result.gpr();
772
773         arg1.use();
774         arg2.use();
775     
776         if (!isKnownInteger(node.child1()))
777             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
778         if (!isKnownInteger(node.child2()))
779             slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
780     
781         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
782     
783         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
784             JITCompiler::Jump haveResult = m_jit.jump();
785     
786             slowPath.link(&m_jit);
787         
788             silentSpillAllRegisters(resultGPR);
789             setupStubArguments(arg1GPR, arg2GPR);
790             m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
791             appendCallWithExceptionCheck(helperFunction);
792             m_jit.move(GPRInfo::returnValueGPR, resultGPR);
793             silentFillAllRegisters(resultGPR);
794         
795             m_jit.andPtr(TrustedImm32(1), resultGPR);
796         
797             haveResult.link(&m_jit);
798         }
799         
800         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
801         
802         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
803     }
804 }
805
806 bool JITCodeGenerator::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)
807 {
808     NodeIndex branchNodeIndex = detectPeepHoleBranch();
809     if (branchNodeIndex != NoNode) {
810         ASSERT(node.adjustedRefCount() == 1);
811         
812         nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
813     
814         m_compileIndex = branchNodeIndex;
815         
816         return true;
817     }
818     
819     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
820     
821     return false;
822 }
823
824 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
825 {
826     Node& branchNode = m_jit.graph()[branchNodeIndex];
827     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
828     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
829
830     // The branch instruction will branch to the taken block.
831     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
832     if (taken == (m_block + 1)) {
833         invert = !invert;
834         BlockIndex tmp = taken;
835         taken = notTaken;
836         notTaken = tmp;
837     }
838     
839     JSValueOperand arg1(this, node.child1());
840     JSValueOperand arg2(this, node.child2());
841     GPRReg arg1GPR = arg1.gpr();
842     GPRReg arg2GPR = arg2.gpr();
843     
844     GPRTemporary result(this);
845     GPRReg resultGPR = result.gpr();
846     
847     arg1.use();
848     arg2.use();
849     
850     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
851         // see if we get lucky: if the arguments are cells and they reference the same
852         // cell, then they must be strictly equal.
853         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
854         
855         silentSpillAllRegisters(resultGPR);
856         setupStubArguments(arg1GPR, arg2GPR);
857         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
858         appendCallWithExceptionCheck(operationCompareStrictEqCell);
859         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
860         silentFillAllRegisters(resultGPR);
861         
862         addBranch(m_jit.branchTest8(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
863     } else {
864         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
865         
866         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
867         
868         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
869         
870         addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
871         addBranch(m_jit.jump(), notTaken);
872         
873         twoCellsCase.link(&m_jit);
874         addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
875         
876         numberCase.link(&m_jit);
877         
878         silentSpillAllRegisters(resultGPR);
879         setupStubArguments(arg1GPR, arg2GPR);
880         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
881         appendCallWithExceptionCheck(operationCompareStrictEq);
882         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
883         silentFillAllRegisters(resultGPR);
884         
885         addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
886     }
887     
888     if (notTaken != (m_block + 1))
889         addBranch(m_jit.jump(), notTaken);
890 }
891
892 void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
893 {
894     JSValueOperand arg1(this, node.child1());
895     JSValueOperand arg2(this, node.child2());
896     GPRReg arg1GPR = arg1.gpr();
897     GPRReg arg2GPR = arg2.gpr();
898     
899     GPRTemporary result(this);
900     GPRReg resultGPR = result.gpr();
901     
902     arg1.use();
903     arg2.use();
904     
905     if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
906         // see if we get lucky: if the arguments are cells and they reference the same
907         // cell, then they must be strictly equal.
908         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
909         
910         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
911         
912         JITCompiler::Jump done = m_jit.jump();
913
914         notEqualCase.link(&m_jit);
915         
916         silentSpillAllRegisters(resultGPR);
917         setupStubArguments(arg1GPR, arg2GPR);
918         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
919         appendCallWithExceptionCheck(operationCompareStrictEqCell);
920         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
921         silentFillAllRegisters(resultGPR);
922         
923         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
924         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
925         
926         done.link(&m_jit);
927     } else {
928         m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
929         
930         JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
931         
932         JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
933         
934         m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
935         
936         JITCompiler::Jump done1 = m_jit.jump();
937         
938         twoCellsCase.link(&m_jit);
939         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
940         
941         m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
942         
943         JITCompiler::Jump done2 = m_jit.jump();
944         
945         numberCase.link(&m_jit);
946         notEqualCase.link(&m_jit);
947         
948         silentSpillAllRegisters(resultGPR);
949         setupStubArguments(arg1GPR, arg2GPR);
950         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
951         appendCallWithExceptionCheck(operationCompareStrictEq);
952         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
953         silentFillAllRegisters(resultGPR);
954         
955         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
956
957         done1.link(&m_jit);
958
959         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
960         
961         done2.link(&m_jit);
962     }
963     
964     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
965 }
966
967 bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)
968 {
969     if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))
970         return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);
971     
972     NodeIndex branchNodeIndex = detectPeepHoleBranch();
973     if (branchNodeIndex != NoNode) {
974         ASSERT(node.adjustedRefCount() == 1);
975         
976         nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
977     
978         m_compileIndex = branchNodeIndex;
979         
980         return true;
981     }
982     
983     nonSpeculativeNonPeepholeStrictEq(node, invert);
984     
985     return false;
986 }
987
988 void JITCodeGenerator::emitBranch(Node& node)
989 {
990     JSValueOperand value(this, node.child1());
991     GPRReg valueGPR = value.gpr();
992     
993     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
994     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
995     
996     if (isKnownBoolean(node.child1())) {
997         MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
998         
999         if (taken == (m_block + 1)) {
1000             condition = MacroAssembler::Zero;
1001             BlockIndex tmp = taken;
1002             taken = notTaken;
1003             notTaken = tmp;
1004         }
1005         
1006         addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken);
1007         if (notTaken != (m_block + 1))
1008             addBranch(m_jit.jump(), notTaken);
1009         
1010         noResult(m_compileIndex);
1011     } else {
1012         GPRTemporary result(this);
1013         GPRReg resultGPR = result.gpr();
1014         
1015         bool predictBoolean = isBooleanPrediction(m_jit.graph().getPrediction(m_jit.graph()[node.child1()]));
1016     
1017         if (predictBoolean) {
1018             addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
1019             addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
1020         }
1021         
1022         if (m_isSpeculative && predictBoolean) {
1023             speculationCheck(m_jit.jump());
1024             value.use();
1025         } else {
1026             addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
1027             addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken);
1028     
1029             if (!predictBoolean) {
1030                 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
1031                 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
1032             }
1033     
1034             value.use();
1035     
1036             silentSpillAllRegisters(resultGPR);
1037             m_jit.move(valueGPR, GPRInfo::argumentGPR1);
1038             m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1039             appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
1040             m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1041             silentFillAllRegisters(resultGPR);
1042     
1043             addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken);
1044             if (notTaken != (m_block + 1))
1045                 addBranch(m_jit.jump(), notTaken);
1046         }
1047         
1048         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1049     }
1050 }
1051
1052 void JITCodeGenerator::nonSpeculativeLogicalNot(Node& node)
1053 {
1054     JSValueOperand arg1(this, node.child1());
1055     GPRTemporary result(this);
1056     
1057     GPRReg arg1GPR = arg1.gpr();
1058     GPRReg resultGPR = result.gpr();
1059     
1060     arg1.use();
1061     
1062     m_jit.move(arg1GPR, resultGPR);
1063     m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1064     JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
1065     
1066     silentSpillAllRegisters(resultGPR);
1067     m_jit.move(arg1GPR, GPRInfo::argumentGPR1);
1068     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1069     appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
1070     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1071     silentFillAllRegisters(resultGPR);
1072     
1073     fastCase.link(&m_jit);
1074     
1075     m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1076     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1077 }
1078
1079 void JITCodeGenerator::emitCall(Node& node)
1080 {
1081     P_DFGOperation_E slowCallFunction;
1082     bool isCall;
1083     
1084     if (node.op == Call) {
1085         slowCallFunction = operationLinkCall;
1086         isCall = true;
1087     } else {
1088         ASSERT(node.op == Construct);
1089         slowCallFunction = operationLinkConstruct;
1090         isCall = false;
1091     }
1092     
1093     NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
1094     JSValueOperand callee(this, calleeNodeIndex);
1095     GPRReg calleeGPR = callee.gpr();
1096     use(calleeNodeIndex);
1097     
1098     // the call instruction's first child is either the function (normal call) or the
1099     // receiver (method call). subsequent children are the arguments.
1100     int numArgs = node.numChildren() - 1;
1101     
1102     // amount of stuff (in units of sizeof(Register)) that we need to place at the
1103     // top of the JS stack.
1104     int callDataSize = 0;
1105
1106     // first there are the arguments
1107     callDataSize += numArgs;
1108     
1109     // and then there is the call frame header
1110     callDataSize += RegisterFile::CallFrameHeaderSize;
1111     
1112     m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numArgs))), addressOfCallData(RegisterFile::ArgumentCount));
1113     m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));
1114     
1115     if (node.op == Construct)
1116         use(m_jit.graph().m_varArgChildren[node.firstChild() + 1]);
1117     
1118     for (int argIdx = (node.op == Call ? 0 : 1); argIdx < numArgs; argIdx++) {
1119         NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
1120         JSValueOperand arg(this, argNodeIndex);
1121         GPRReg argGPR = arg.gpr();
1122         use(argNodeIndex);
1123         
1124         m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx));
1125     }
1126     
1127     m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
1128     
1129     flushRegisters();
1130     
1131     GPRResult result(this);
1132     GPRReg resultGPR = result.gpr();
1133
1134     JITCompiler::DataLabelPtr targetToCheck;
1135     JITCompiler::Jump slowPath;
1136     
1137     slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
1138     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
1139     m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
1140
1141     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1142     
1143     JITCompiler::Call fastCall = m_jit.nearCall();
1144     m_jit.notifyCall(fastCall, m_jit.graph()[m_compileIndex].codeOrigin);
1145     
1146     JITCompiler::Jump done = m_jit.jump();
1147     
1148     slowPath.link(&m_jit);
1149     
1150     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1151     JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, m_jit.graph()[m_compileIndex].codeOrigin);
1152     m_jit.move(Imm32(numArgs), GPRInfo::regT1);
1153     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1154     m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), m_jit.graph()[m_compileIndex].codeOrigin);
1155     
1156     done.link(&m_jit);
1157     
1158     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1159     
1160     jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
1161     
1162     m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].codeOrigin);
1163 }
1164
1165 void JITCodeGenerator::speculationCheck(MacroAssembler::Jump jumpToFail)
1166 {
1167     ASSERT(m_isSpeculative);
1168     static_cast<SpeculativeJIT*>(this)->speculationCheck(jumpToFail);
1169 }
1170
1171 #ifndef NDEBUG
1172 static const char* dataFormatString(DataFormat format)
1173 {
1174     // These values correspond to the DataFormat enum.
1175     const char* strings[] = {
1176         "[  ]",
1177         "[ i]",
1178         "[ d]",
1179         "[ c]",
1180         "Err!",
1181         "Err!",
1182         "Err!",
1183         "Err!",
1184         "[J ]",
1185         "[Ji]",
1186         "[Jd]",
1187         "[Jc]",
1188         "Err!",
1189         "Err!",
1190         "Err!",
1191         "Err!",
1192     };
1193     return strings[format];
1194 }
1195
1196 void JITCodeGenerator::dump(const char* label)
1197 {
1198     if (label)
1199         fprintf(stderr, "<%s>\n", label);
1200
1201     fprintf(stderr, "  gprs:\n");
1202     m_gprs.dump();
1203     fprintf(stderr, "  fprs:\n");
1204     m_fprs.dump();
1205     fprintf(stderr, "  VirtualRegisters:\n");
1206     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1207         GenerationInfo& info = m_generationInfo[i];
1208         if (info.alive())
1209             fprintf(stderr, "    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
1210         else
1211             fprintf(stderr, "    % 3d:[__][__]", i);
1212         if (info.registerFormat() == DataFormatDouble)
1213             fprintf(stderr, ":fpr%d\n", info.fpr());
1214         else if (info.registerFormat() != DataFormatNone) {
1215             ASSERT(info.gpr() != InvalidGPRReg);
1216             fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));
1217         } else
1218             fprintf(stderr, "\n");
1219     }
1220     if (label)
1221         fprintf(stderr, "</%s>\n", label);
1222 }
1223 #endif
1224
1225
1226 #if ENABLE(DFG_CONSISTENCY_CHECK)
1227 void JITCodeGenerator::checkConsistency()
1228 {
1229     bool failed = false;
1230
1231     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
1232         if (iter.isLocked()) {
1233             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
1234             failed = true;
1235         }
1236     }
1237     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
1238         if (iter.isLocked()) {
1239             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
1240             failed = true;
1241         }
1242     }
1243
1244     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1245         VirtualRegister virtualRegister = (VirtualRegister)i;
1246         GenerationInfo& info = m_generationInfo[virtualRegister];
1247         if (!info.alive())
1248             continue;
1249         switch (info.registerFormat()) {
1250         case DataFormatNone:
1251             break;
1252         case DataFormatInteger:
1253         case DataFormatCell:
1254         case DataFormatJS:
1255         case DataFormatJSInteger:
1256         case DataFormatJSDouble:
1257         case DataFormatJSCell: {
1258             GPRReg gpr = info.gpr();
1259             ASSERT(gpr != InvalidGPRReg);
1260             if (m_gprs.name(gpr) != virtualRegister) {
1261                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
1262                 failed = true;
1263             }
1264             break;
1265         }
1266         case DataFormatDouble: {
1267             FPRReg fpr = info.fpr();
1268             ASSERT(fpr != InvalidFPRReg);
1269             if (m_fprs.name(fpr) != virtualRegister) {
1270                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
1271                 failed = true;
1272             }
1273             break;
1274         }
1275         }
1276     }
1277
1278     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
1279         VirtualRegister virtualRegister = iter.name();
1280         if (virtualRegister == InvalidVirtualRegister)
1281             continue;
1282
1283         GenerationInfo& info = m_generationInfo[virtualRegister];
1284         if (iter.regID() != info.gpr()) {
1285             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1286             failed = true;
1287         }
1288     }
1289
1290     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
1291         VirtualRegister virtualRegister = iter.name();
1292         if (virtualRegister == InvalidVirtualRegister)
1293             continue;
1294
1295         GenerationInfo& info = m_generationInfo[virtualRegister];
1296         if (iter.regID() != info.fpr()) {
1297             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1298             failed = true;
1299         }
1300     }
1301
1302     if (failed) {
1303         dump();
1304         CRASH();
1305     }
1306 }
1307 #endif
1308
1309 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
1310     : m_jit(jit)
1311     , m_gpr(InvalidGPRReg)
1312 {
1313     m_gpr = m_jit->allocate();
1314 }
1315
1316 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, GPRReg specific)
1317     : m_jit(jit)
1318     , m_gpr(InvalidGPRReg)
1319 {
1320     m_gpr = m_jit->allocate(specific);
1321 }
1322
1323 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)
1324     : m_jit(jit)
1325     , m_gpr(InvalidGPRReg)
1326 {
1327     if (m_jit->canReuse(op1.index()))
1328         m_gpr = m_jit->reuse(op1.gpr());
1329     else
1330         m_gpr = m_jit->allocate();
1331 }
1332
1333 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
1334     : m_jit(jit)
1335     , m_gpr(InvalidGPRReg)
1336 {
1337     if (m_jit->canReuse(op1.index()))
1338         m_gpr = m_jit->reuse(op1.gpr());
1339     else if (m_jit->canReuse(op2.index()))
1340         m_gpr = m_jit->reuse(op2.gpr());
1341     else
1342         m_gpr = m_jit->allocate();
1343 }
1344
1345 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)
1346     : m_jit(jit)
1347     , m_gpr(InvalidGPRReg)
1348 {
1349     if (m_jit->canReuse(op1.index()))
1350         m_gpr = m_jit->reuse(op1.gpr());
1351     else
1352         m_gpr = m_jit->allocate();
1353 }
1354
1355 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)
1356     : m_jit(jit)
1357     , m_gpr(InvalidGPRReg)
1358 {
1359     if (m_jit->canReuse(op1.index()))
1360         m_gpr = m_jit->reuse(op1.gpr());
1361     else if (m_jit->canReuse(op2.index()))
1362         m_gpr = m_jit->reuse(op2.gpr());
1363     else
1364         m_gpr = m_jit->allocate();
1365 }
1366
1367 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)
1368     : m_jit(jit)
1369     , m_gpr(InvalidGPRReg)
1370 {
1371     if (m_jit->canReuse(op1.index()))
1372         m_gpr = m_jit->reuse(op1.gpr());
1373     else
1374         m_gpr = m_jit->allocate();
1375 }
1376
1377 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateBooleanOperand& op1)
1378     : m_jit(jit)
1379     , m_gpr(InvalidGPRReg)
1380 {
1381     if (m_jit->canReuse(op1.index()))
1382         m_gpr = m_jit->reuse(op1.gpr());
1383     else
1384         m_gpr = m_jit->allocate();
1385 }
1386
1387 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)
1388     : m_jit(jit)
1389     , m_gpr(InvalidGPRReg)
1390 {
1391     if (m_jit->canReuse(op1.index()))
1392         m_gpr = m_jit->reuse(op1.gpr());
1393     else
1394         m_gpr = m_jit->allocate();
1395 }
1396
1397 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
1398     : m_jit(jit)
1399     , m_fpr(InvalidFPRReg)
1400 {
1401     m_fpr = m_jit->fprAllocate();
1402 }
1403
1404 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)
1405     : m_jit(jit)
1406     , m_fpr(InvalidFPRReg)
1407 {
1408     if (m_jit->canReuse(op1.index()))
1409         m_fpr = m_jit->reuse(op1.fpr());
1410     else
1411         m_fpr = m_jit->fprAllocate();
1412 }
1413
1414 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)
1415     : m_jit(jit)
1416     , m_fpr(InvalidFPRReg)
1417 {
1418     if (m_jit->canReuse(op1.index()))
1419         m_fpr = m_jit->reuse(op1.fpr());
1420     else if (m_jit->canReuse(op2.index()))
1421         m_fpr = m_jit->reuse(op2.fpr());
1422     else
1423         m_fpr = m_jit->fprAllocate();
1424 }
1425
1426 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1)
1427     : m_jit(jit)
1428     , m_fpr(InvalidFPRReg)
1429 {
1430     if (m_jit->canReuse(op1.index()))
1431         m_fpr = m_jit->reuse(op1.fpr());
1432     else
1433         m_fpr = m_jit->fprAllocate();
1434 }
1435
1436 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
1437     : m_jit(jit)
1438     , m_fpr(InvalidFPRReg)
1439 {
1440     if (m_jit->canReuse(op1.index()))
1441         m_fpr = m_jit->reuse(op1.fpr());
1442     else if (m_jit->canReuse(op2.index()))
1443         m_fpr = m_jit->reuse(op2.fpr());
1444     else
1445         m_fpr = m_jit->fprAllocate();
1446 }
1447
1448 } } // namespace JSC::DFG
1449
1450 #endif