]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGJITCodeGenerator.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / dfg / DFGJITCodeGenerator.cpp
CommitLineData
14957cd0
A
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
35namespace JSC { namespace DFG {
36
37GPRReg 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
107FPRReg 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
226GPRReg 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
306void 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
329static 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
353void 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
384void 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
466GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
467 : m_jit(jit)
468 , m_gpr(InvalidGPRReg)
469{
470 m_gpr = m_jit->allocate();
471}
472
473GPRTemporary::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
483GPRTemporary::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
495GPRTemporary::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
505GPRTemporary::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
517GPRTemporary::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
527GPRTemporary::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
537FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
538 : m_jit(jit)
539 , m_fpr(InvalidFPRReg)
540{
541 m_fpr = m_jit->fprAllocate();
542}
543
544FPRTemporary::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
554FPRTemporary::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