]>
Commit | Line | Data |
---|---|---|
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 | ||
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 |