781edbb3d08ad70daf74d6f688d32afb43f6b1be
[WebKit-https.git] / 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 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
38 {
39     Node& node = m_jit.graph()[nodeIndex];
40     VirtualRegister virtualRegister = node.virtualRegister();
41     GenerationInfo& info = m_generationInfo[virtualRegister];
42
43     if (info.registerFormat() == DataFormatNone) {
44         GPRReg gpr = allocate();
45
46         if (node.isConstant()) {
47             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
48             if (isInt32Constant(nodeIndex)) {
49                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
50                 info.fillInteger(gpr);
51                 returnFormat = DataFormatInteger;
52                 return gpr;
53             }
54             if (isDoubleConstant(nodeIndex)) {
55                 JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex));
56                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
57             } else {
58                 ASSERT(isJSConstant(nodeIndex));
59                 JSValue jsValue = valueOfJSConstant(nodeIndex);
60                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
61             }
62         } else {
63             ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
64             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
65             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
66         }
67
68         // Since we statically know that we're filling an integer, and values
69         // in the RegisterFile are boxed, this must be DataFormatJSInteger.
70         // We will check this with a jitAssert below.
71         info.fillJSValue(gpr, DataFormatJSInteger);
72         unlock(gpr);
73     }
74
75     switch (info.registerFormat()) {
76     case DataFormatNone:
77         // Should have filled, above.
78     case DataFormatJSDouble:
79     case DataFormatDouble:
80     case DataFormatJS:
81     case DataFormatCell:
82     case DataFormatJSCell:
83         // Should only be calling this function if we know this operand to be integer.
84         ASSERT_NOT_REACHED();
85
86     case DataFormatJSInteger: {
87         GPRReg gpr = info.gpr();
88         m_gprs.lock(gpr);
89         m_jit.jitAssertIsJSInt32(gpr);
90         returnFormat = DataFormatJSInteger;
91         return gpr;
92     }
93
94     case DataFormatInteger: {
95         GPRReg gpr = info.gpr();
96         m_gprs.lock(gpr);
97         m_jit.jitAssertIsInt32(gpr);
98         returnFormat = DataFormatInteger;
99         return gpr;
100     }
101     }
102
103     ASSERT_NOT_REACHED();
104     return InvalidGPRReg;
105 }
106
107 FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
108 {
109     Node& node = m_jit.graph()[nodeIndex];
110     VirtualRegister virtualRegister = node.virtualRegister();
111     GenerationInfo& info = m_generationInfo[virtualRegister];
112
113     if (info.registerFormat() == DataFormatNone) {
114         GPRReg gpr = allocate();
115
116         if (node.isConstant()) {
117             if (isInt32Constant(nodeIndex)) {
118                 // FIXME: should not be reachable?
119                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
120                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
121                 info.fillInteger(gpr);
122                 unlock(gpr);
123             } else if (isDoubleConstant(nodeIndex)) {
124                 FPRReg fpr = fprAllocate();
125                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
126                 m_jit.movePtrToDouble(gpr, fpr);
127                 unlock(gpr);
128
129                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
130                 info.fillDouble(fpr);
131                 return fpr;
132             } else {
133                 // FIXME: should not be reachable?
134                 ASSERT(isJSConstant(nodeIndex));
135                 JSValue jsValue = valueOfJSConstant(nodeIndex);
136                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
137                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
138                 info.fillJSValue(gpr, DataFormatJS);
139                 unlock(gpr);
140             }
141         } else {
142             DataFormat spillFormat = info.spillFormat();
143             ASSERT(spillFormat & DataFormatJS);
144             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
145             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
146             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
147             unlock(gpr);
148         }
149     }
150
151     switch (info.registerFormat()) {
152     case DataFormatNone:
153         // Should have filled, above.
154     case DataFormatCell:
155     case DataFormatJSCell:
156         // Should only be calling this function if we know this operand to be numeric.
157         ASSERT_NOT_REACHED();
158
159     case DataFormatJS: {
160         GPRReg jsValueGpr = info.gpr();
161         m_gprs.lock(jsValueGpr);
162         FPRReg fpr = fprAllocate();
163         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
164
165         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
166
167         m_jit.jitAssertIsJSDouble(jsValueGpr);
168
169         // First, if we get here we have a double encoded as a JSValue
170         m_jit.move(jsValueGpr, tempGpr);
171         m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
172         m_jit.movePtrToDouble(tempGpr, fpr);
173         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
174
175         // Finally, handle integers.
176         isInteger.link(&m_jit);
177         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
178         hasUnboxedDouble.link(&m_jit);
179
180         m_gprs.release(jsValueGpr);
181         m_gprs.unlock(jsValueGpr);
182         m_gprs.unlock(tempGpr);
183         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
184         info.fillDouble(fpr);
185         return fpr;
186     }
187
188     case DataFormatJSInteger:
189     case DataFormatInteger: {
190         FPRReg fpr = fprAllocate();
191         GPRReg gpr = info.gpr();
192         m_gprs.lock(gpr);
193
194         m_jit.convertInt32ToDouble(gpr, fpr);
195
196         m_gprs.release(gpr);
197         m_gprs.unlock(gpr);
198         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
199         info.fillDouble(fpr);
200         return fpr;
201     }
202
203     // Unbox the double
204     case DataFormatJSDouble: {
205         GPRReg gpr = info.gpr();
206         FPRReg fpr = unboxDouble(gpr);
207
208         m_gprs.release(gpr);
209         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
210
211         info.fillDouble(fpr);
212         return fpr;
213     }
214
215     case DataFormatDouble: {
216         FPRReg fpr = info.fpr();
217         m_fprs.lock(fpr);
218         return fpr;
219     }
220     }
221
222     ASSERT_NOT_REACHED();
223     return InvalidFPRReg;
224 }
225
226 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
227 {
228     Node& node = m_jit.graph()[nodeIndex];
229     VirtualRegister virtualRegister = node.virtualRegister();
230     GenerationInfo& info = m_generationInfo[virtualRegister];
231
232     switch (info.registerFormat()) {
233     case DataFormatNone: {
234         GPRReg gpr = allocate();
235
236         if (node.isConstant()) {
237             if (isInt32Constant(nodeIndex)) {
238                 info.fillJSValue(gpr, DataFormatJSInteger);
239                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
240                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
241             } else if (isDoubleConstant(nodeIndex)) {
242                 info.fillJSValue(gpr, DataFormatJSDouble);
243                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex));
244                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
245             } else {
246                 ASSERT(isJSConstant(nodeIndex));
247                 JSValue jsValue = valueOfJSConstant(nodeIndex);
248                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
249                 info.fillJSValue(gpr, DataFormatJS);
250             }
251
252             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
253         } else {
254             DataFormat spillFormat = info.spillFormat();
255             ASSERT(spillFormat & DataFormatJS);
256             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
257             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
258             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
259         }
260         return gpr;
261     }
262
263     case DataFormatInteger: {
264         GPRReg gpr = info.gpr();
265         // If the register has already been locked we need to take a copy.
266         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
267         if (m_gprs.isLocked(gpr)) {
268             GPRReg result = allocate();
269             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
270             return result;
271         }
272         m_gprs.lock(gpr);
273         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
274         info.fillJSValue(gpr, DataFormatJSInteger);
275         return gpr;
276     }
277
278     case DataFormatDouble: {
279         FPRReg fpr = info.fpr();
280         GPRReg gpr = boxDouble(fpr);
281
282         // Update all info
283         info.fillJSValue(gpr, DataFormatJSDouble);
284         m_fprs.release(fpr);
285         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
286
287         return gpr;
288     }
289
290     case DataFormatCell:
291         // No retag required on JSVALUE64!
292     case DataFormatJS:
293     case DataFormatJSInteger:
294     case DataFormatJSDouble:
295     case DataFormatJSCell: {
296         GPRReg gpr = info.gpr();
297         m_gprs.lock(gpr);
298         return gpr;
299     }
300     }
301
302     ASSERT_NOT_REACHED();
303     return InvalidGPRReg;
304 }
305
306 void JITCodeGenerator::useChildren(Node& node)
307 {
308     NodeIndex child1 = node.child1;
309     if (child1 == NoNode) {
310         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
311         return;
312     }
313     use(child1);
314
315     NodeIndex child2 = node.child2;
316     if (child2 == NoNode) {
317         ASSERT(node.child3 == NoNode);
318         return;
319     }
320     use(child2);
321
322     NodeIndex child3 = node.child3;
323     if (child3 == NoNode)
324         return;
325     use(child3);
326 }
327
328 #ifndef NDEBUG
329 static const char* dataFormatString(DataFormat format)
330 {
331     // These values correspond to the DataFormat enum.
332     const char* strings[] = {
333         "[  ]",
334         "[ i]",
335         "[ d]",
336         "[ c]",
337         "Err!",
338         "Err!",
339         "Err!",
340         "Err!",
341         "[J ]",
342         "[Ji]",
343         "[Jd]",
344         "[Jc]",
345         "Err!",
346         "Err!",
347         "Err!",
348         "Err!",
349     };
350     return strings[format];
351 }
352
353 void JITCodeGenerator::dump(const char* label)
354 {
355     if (label)
356         fprintf(stderr, "<%s>\n", label);
357
358     fprintf(stderr, "  gprs:\n");
359     m_gprs.dump();
360     fprintf(stderr, "  fprs:\n");
361     m_fprs.dump();
362     fprintf(stderr, "  VirtualRegisters:\n");
363     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
364         GenerationInfo& info = m_generationInfo[i];
365         if (info.alive())
366             fprintf(stderr, "    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
367         else
368             fprintf(stderr, "    % 3d:[__][__]", i);
369         if (info.registerFormat() == DataFormatDouble)
370             fprintf(stderr, ":fpr%d\n", info.fpr());
371         else if (info.registerFormat() != DataFormatNone) {
372             ASSERT(info.gpr() != InvalidGPRReg);
373             fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));
374         } else
375             fprintf(stderr, "\n");
376     }
377     if (label)
378         fprintf(stderr, "</%s>\n", label);
379 }
380 #endif
381
382
383 #if DFG_CONSISTENCY_CHECK
384 void JITCodeGenerator::checkConsistency()
385 {
386     bool failed = false;
387
388     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
389         if (iter.isLocked()) {
390             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
391             failed = true;
392         }
393     }
394     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
395         if (iter.isLocked()) {
396             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
397             failed = true;
398         }
399     }
400
401     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
402         VirtualRegister virtualRegister = (VirtualRegister)i;
403         GenerationInfo& info = m_generationInfo[virtualRegister];
404         if (!info.alive())
405             continue;
406         switch (info.registerFormat()) {
407         case DataFormatNone:
408             break;
409         case DataFormatInteger:
410         case DataFormatCell:
411         case DataFormatJS:
412         case DataFormatJSInteger:
413         case DataFormatJSDouble:
414         case DataFormatJSCell: {
415             GPRReg gpr = info.gpr();
416             ASSERT(gpr != InvalidGPRReg);
417             if (m_gprs.name(gpr) != virtualRegister) {
418                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
419                 failed = true;
420             }
421             break;
422         }
423         case DataFormatDouble: {
424             FPRReg fpr = info.fpr();
425             ASSERT(fpr != InvalidFPRReg);
426             if (m_fprs.name(fpr) != virtualRegister) {
427                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
428                 failed = true;
429             }
430             break;
431         }
432         }
433     }
434
435     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
436         VirtualRegister virtualRegister = iter.name();
437         if (virtualRegister == InvalidVirtualRegister)
438             continue;
439
440         GenerationInfo& info = m_generationInfo[virtualRegister];
441         if (iter.regID() != info.gpr()) {
442             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
443             failed = true;
444         }
445     }
446
447     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
448         VirtualRegister virtualRegister = iter.name();
449         if (virtualRegister == InvalidVirtualRegister)
450             continue;
451
452         GenerationInfo& info = m_generationInfo[virtualRegister];
453         if (iter.regID() != info.fpr()) {
454             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
455             failed = true;
456         }
457     }
458
459     if (failed) {
460         dump();
461         CRASH();
462     }
463 }
464 #endif
465
466 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
467     : m_jit(jit)
468     , m_gpr(InvalidGPRReg)
469 {
470     m_gpr = m_jit->allocate();
471 }
472
473 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)
474     : m_jit(jit)
475     , m_gpr(InvalidGPRReg)
476 {
477     if (m_jit->canReuse(op1.index()))
478         m_gpr = m_jit->reuse(op1.gpr());
479     else
480         m_gpr = m_jit->allocate();
481 }
482
483 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
484     : m_jit(jit)
485     , m_gpr(InvalidGPRReg)
486 {
487     if (m_jit->canReuse(op1.index()))
488         m_gpr = m_jit->reuse(op1.gpr());
489     else if (m_jit->canReuse(op2.index()))
490         m_gpr = m_jit->reuse(op2.gpr());
491     else
492         m_gpr = m_jit->allocate();
493 }
494
495 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)
496     : m_jit(jit)
497     , m_gpr(InvalidGPRReg)
498 {
499     if (m_jit->canReuse(op1.index()))
500         m_gpr = m_jit->reuse(op1.gpr());
501     else
502         m_gpr = m_jit->allocate();
503 }
504
505 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)
506     : m_jit(jit)
507     , m_gpr(InvalidGPRReg)
508 {
509     if (m_jit->canReuse(op1.index()))
510         m_gpr = m_jit->reuse(op1.gpr());
511     else if (m_jit->canReuse(op2.index()))
512         m_gpr = m_jit->reuse(op2.gpr());
513     else
514         m_gpr = m_jit->allocate();
515 }
516
517 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)
518     : m_jit(jit)
519     , m_gpr(InvalidGPRReg)
520 {
521     if (m_jit->canReuse(op1.index()))
522         m_gpr = m_jit->reuse(op1.gpr());
523     else
524         m_gpr = m_jit->allocate();
525 }
526
527 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)
528     : m_jit(jit)
529     , m_gpr(InvalidGPRReg)
530 {
531     if (m_jit->canReuse(op1.index()))
532         m_gpr = m_jit->reuse(op1.gpr());
533     else
534         m_gpr = m_jit->allocate();
535 }
536
537 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
538     : m_jit(jit)
539     , m_fpr(InvalidFPRReg)
540 {
541     m_fpr = m_jit->fprAllocate();
542 }
543
544 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)
545     : m_jit(jit)
546     , m_fpr(InvalidFPRReg)
547 {
548     if (m_jit->canReuse(op1.index()))
549         m_fpr = m_jit->reuse(op1.fpr());
550     else
551         m_fpr = m_jit->fprAllocate();
552 }
553
554 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)
555     : m_jit(jit)
556     , m_fpr(InvalidFPRReg)
557 {
558     if (m_jit->canReuse(op1.index()))
559         m_fpr = m_jit->reuse(op1.fpr());
560     else if (m_jit->canReuse(op2.index()))
561         m_fpr = m_jit->reuse(op2.fpr());
562     else
563         m_fpr = m_jit->fprAllocate();
564 }
565
566 } } // namespace JSC::DFG
567
568 #endif