https://bugs.webkit.org/show_bug.cgi?id=63218
[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         m_jit.convertInt32ToDouble(gpr, fpr);
194         m_gprs.unlock(gpr);
195         return fpr;
196     }
197
198     // Unbox the double
199     case DataFormatJSDouble: {
200         GPRReg gpr = info.gpr();
201         FPRReg fpr = unboxDouble(gpr);
202
203         m_gprs.release(gpr);
204         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
205
206         info.fillDouble(fpr);
207         return fpr;
208     }
209
210     case DataFormatDouble: {
211         FPRReg fpr = info.fpr();
212         m_fprs.lock(fpr);
213         return fpr;
214     }
215     }
216
217     ASSERT_NOT_REACHED();
218     return InvalidFPRReg;
219 }
220
221 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
222 {
223     Node& node = m_jit.graph()[nodeIndex];
224     VirtualRegister virtualRegister = node.virtualRegister();
225     GenerationInfo& info = m_generationInfo[virtualRegister];
226
227     switch (info.registerFormat()) {
228     case DataFormatNone: {
229         GPRReg gpr = allocate();
230
231         if (node.isConstant()) {
232             if (isInt32Constant(nodeIndex)) {
233                 info.fillJSValue(gpr, DataFormatJSInteger);
234                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
235                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
236             } else if (isDoubleConstant(nodeIndex)) {
237                 info.fillJSValue(gpr, DataFormatJSDouble);
238                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex));
239                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
240             } else {
241                 ASSERT(isJSConstant(nodeIndex));
242                 JSValue jsValue = valueOfJSConstant(nodeIndex);
243                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
244                 info.fillJSValue(gpr, DataFormatJS);
245             }
246
247             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
248         } else {
249             DataFormat spillFormat = info.spillFormat();
250             ASSERT(spillFormat & DataFormatJS);
251             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
252             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
253             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
254         }
255         return gpr;
256     }
257
258     case DataFormatInteger: {
259         GPRReg gpr = info.gpr();
260         // If the register has already been locked we need to take a copy.
261         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
262         if (m_gprs.isLocked(gpr)) {
263             GPRReg result = allocate();
264             m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
265             return result;
266         }
267         m_gprs.lock(gpr);
268         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
269         info.fillJSValue(gpr, DataFormatJSInteger);
270         return gpr;
271     }
272
273     case DataFormatDouble: {
274         FPRReg fpr = info.fpr();
275         GPRReg gpr = boxDouble(fpr);
276
277         // Update all info
278         info.fillJSValue(gpr, DataFormatJSDouble);
279         m_fprs.release(fpr);
280         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
281
282         return gpr;
283     }
284
285     case DataFormatCell:
286         // No retag required on JSVALUE64!
287     case DataFormatJS:
288     case DataFormatJSInteger:
289     case DataFormatJSDouble:
290     case DataFormatJSCell: {
291         GPRReg gpr = info.gpr();
292         m_gprs.lock(gpr);
293         return gpr;
294     }
295     }
296
297     ASSERT_NOT_REACHED();
298     return InvalidGPRReg;
299 }
300
301 void JITCodeGenerator::useChildren(Node& node)
302 {
303     NodeIndex child1 = node.child1;
304     if (child1 == NoNode) {
305         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
306         return;
307     }
308     use(child1);
309
310     NodeIndex child2 = node.child2;
311     if (child2 == NoNode) {
312         ASSERT(node.child3 == NoNode);
313         return;
314     }
315     use(child2);
316
317     NodeIndex child3 = node.child3;
318     if (child3 == NoNode)
319         return;
320     use(child3);
321 }
322
323 #ifndef NDEBUG
324 static const char* dataFormatString(DataFormat format)
325 {
326     // These values correspond to the DataFormat enum.
327     const char* strings[] = {
328         "[  ]",
329         "[ i]",
330         "[ d]",
331         "[ c]",
332         "Err!",
333         "Err!",
334         "Err!",
335         "Err!",
336         "[J ]",
337         "[Ji]",
338         "[Jd]",
339         "[Jc]",
340         "Err!",
341         "Err!",
342         "Err!",
343         "Err!",
344     };
345     return strings[format];
346 }
347
348 void JITCodeGenerator::dump(const char* label)
349 {
350     if (label)
351         fprintf(stderr, "<%s>\n", label);
352
353     fprintf(stderr, "  gprs:\n");
354     m_gprs.dump();
355     fprintf(stderr, "  fprs:\n");
356     m_fprs.dump();
357     fprintf(stderr, "  VirtualRegisters:\n");
358     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
359         GenerationInfo& info = m_generationInfo[i];
360         if (info.alive())
361             fprintf(stderr, "    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
362         else
363             fprintf(stderr, "    % 3d:[__][__]", i);
364         if (info.registerFormat() == DataFormatDouble)
365             fprintf(stderr, ":fpr%d\n", info.fpr());
366         else if (info.registerFormat() != DataFormatNone) {
367             ASSERT(info.gpr() != InvalidGPRReg);
368             fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));
369         } else
370             fprintf(stderr, "\n");
371     }
372     if (label)
373         fprintf(stderr, "</%s>\n", label);
374 }
375 #endif
376
377
378 #if DFG_CONSISTENCY_CHECK
379 void JITCodeGenerator::checkConsistency()
380 {
381     bool failed = false;
382
383     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
384         if (iter.isLocked()) {
385             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
386             failed = true;
387         }
388     }
389     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
390         if (iter.isLocked()) {
391             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
392             failed = true;
393         }
394     }
395
396     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
397         VirtualRegister virtualRegister = (VirtualRegister)i;
398         GenerationInfo& info = m_generationInfo[virtualRegister];
399         if (!info.alive())
400             continue;
401         switch (info.registerFormat()) {
402         case DataFormatNone:
403             break;
404         case DataFormatInteger:
405         case DataFormatCell:
406         case DataFormatJS:
407         case DataFormatJSInteger:
408         case DataFormatJSDouble:
409         case DataFormatJSCell: {
410             GPRReg gpr = info.gpr();
411             ASSERT(gpr != InvalidGPRReg);
412             if (m_gprs.name(gpr) != virtualRegister) {
413                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
414                 failed = true;
415             }
416             break;
417         }
418         case DataFormatDouble: {
419             FPRReg fpr = info.fpr();
420             ASSERT(fpr != InvalidFPRReg);
421             if (m_fprs.name(fpr) != virtualRegister) {
422                 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
423                 failed = true;
424             }
425             break;
426         }
427         }
428     }
429
430     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
431         VirtualRegister virtualRegister = iter.name();
432         if (virtualRegister == InvalidVirtualRegister)
433             continue;
434
435         GenerationInfo& info = m_generationInfo[virtualRegister];
436         if (iter.regID() != info.gpr()) {
437             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
438             failed = true;
439         }
440     }
441
442     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
443         VirtualRegister virtualRegister = iter.name();
444         if (virtualRegister == InvalidVirtualRegister)
445             continue;
446
447         GenerationInfo& info = m_generationInfo[virtualRegister];
448         if (iter.regID() != info.fpr()) {
449             fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
450             failed = true;
451         }
452     }
453
454     if (failed) {
455         dump();
456         CRASH();
457     }
458 }
459 #endif
460
461 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
462     : m_jit(jit)
463     , m_gpr(InvalidGPRReg)
464 {
465     m_gpr = m_jit->allocate();
466 }
467
468 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)
469     : m_jit(jit)
470     , m_gpr(InvalidGPRReg)
471 {
472     if (m_jit->canReuse(op1.index()))
473         m_gpr = m_jit->reuse(op1.gpr());
474     else
475         m_gpr = m_jit->allocate();
476 }
477
478 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
479     : m_jit(jit)
480     , m_gpr(InvalidGPRReg)
481 {
482     if (m_jit->canReuse(op1.index()))
483         m_gpr = m_jit->reuse(op1.gpr());
484     else if (m_jit->canReuse(op2.index()))
485         m_gpr = m_jit->reuse(op2.gpr());
486     else
487         m_gpr = m_jit->allocate();
488 }
489
490 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)
491     : m_jit(jit)
492     , m_gpr(InvalidGPRReg)
493 {
494     if (m_jit->canReuse(op1.index()))
495         m_gpr = m_jit->reuse(op1.gpr());
496     else
497         m_gpr = m_jit->allocate();
498 }
499
500 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)
501     : m_jit(jit)
502     , m_gpr(InvalidGPRReg)
503 {
504     if (m_jit->canReuse(op1.index()))
505         m_gpr = m_jit->reuse(op1.gpr());
506     else if (m_jit->canReuse(op2.index()))
507         m_gpr = m_jit->reuse(op2.gpr());
508     else
509         m_gpr = m_jit->allocate();
510 }
511
512 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)
513     : m_jit(jit)
514     , m_gpr(InvalidGPRReg)
515 {
516     if (m_jit->canReuse(op1.index()))
517         m_gpr = m_jit->reuse(op1.gpr());
518     else
519         m_gpr = m_jit->allocate();
520 }
521
522 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)
523     : m_jit(jit)
524     , m_gpr(InvalidGPRReg)
525 {
526     if (m_jit->canReuse(op1.index()))
527         m_gpr = m_jit->reuse(op1.gpr());
528     else
529         m_gpr = m_jit->allocate();
530 }
531
532 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
533     : m_jit(jit)
534     , m_fpr(InvalidFPRReg)
535 {
536     m_fpr = m_jit->fprAllocate();
537 }
538
539 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)
540     : m_jit(jit)
541     , m_fpr(InvalidFPRReg)
542 {
543     if (m_jit->canReuse(op1.index()))
544         m_fpr = m_jit->reuse(op1.fpr());
545     else
546         m_fpr = m_jit->fprAllocate();
547 }
548
549 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)
550     : m_jit(jit)
551     , m_fpr(InvalidFPRReg)
552 {
553     if (m_jit->canReuse(op1.index()))
554         m_fpr = m_jit->reuse(op1.fpr());
555     else if (m_jit->canReuse(op2.index()))
556         m_fpr = m_jit->reuse(op2.fpr());
557     else
558         m_fpr = m_jit->fprAllocate();
559 }
560
561 } } // namespace JSC::DFG
562
563 #endif