2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGSpeculativeJIT.h"
29 #include "JSByteArray.h"
33 namespace JSC { namespace DFG {
37 GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
39 Node& node = at(nodeIndex);
40 VirtualRegister virtualRegister = node.virtualRegister();
41 GenerationInfo& info = m_generationInfo[virtualRegister];
43 if (info.registerFormat() == DataFormatNone) {
44 GPRReg gpr = allocate();
46 if (node.hasConstant()) {
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;
54 if (isNumberConstant(nodeIndex)) {
55 JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));
56 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
58 ASSERT(isJSConstant(nodeIndex));
59 JSValue jsValue = valueOfJSConstant(nodeIndex);
60 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
62 } else if (info.spillFormat() == DataFormatInteger) {
63 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
64 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
65 // Tag it, since fillInteger() is used when we want a boxed integer.
66 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
68 ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
69 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
70 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
73 // Since we statically know that we're filling an integer, and values
74 // in the RegisterFile are boxed, this must be DataFormatJSInteger.
75 // We will check this with a jitAssert below.
76 info.fillJSValue(gpr, DataFormatJSInteger);
80 switch (info.registerFormat()) {
82 // Should have filled, above.
83 case DataFormatJSDouble:
84 case DataFormatDouble:
87 case DataFormatJSCell:
88 case DataFormatBoolean:
89 case DataFormatJSBoolean:
90 case DataFormatStorage:
91 // Should only be calling this function if we know this operand to be integer.
94 case DataFormatJSInteger: {
95 GPRReg gpr = info.gpr();
97 m_jit.jitAssertIsJSInt32(gpr);
98 returnFormat = DataFormatJSInteger;
102 case DataFormatInteger: {
103 GPRReg gpr = info.gpr();
105 m_jit.jitAssertIsInt32(gpr);
106 returnFormat = DataFormatInteger;
111 ASSERT_NOT_REACHED();
112 return InvalidGPRReg;
115 FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
117 Node& node = at(nodeIndex);
118 VirtualRegister virtualRegister = node.virtualRegister();
119 GenerationInfo& info = m_generationInfo[virtualRegister];
121 if (info.registerFormat() == DataFormatNone) {
122 if (node.hasConstant()) {
123 GPRReg gpr = allocate();
125 if (isInt32Constant(nodeIndex)) {
126 // FIXME: should not be reachable?
127 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
128 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
129 info.fillInteger(gpr);
131 } else if (isNumberConstant(nodeIndex)) {
132 FPRReg fpr = fprAllocate();
133 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
134 m_jit.movePtrToDouble(gpr, fpr);
137 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
138 info.fillDouble(fpr);
141 // FIXME: should not be reachable?
142 ASSERT(isJSConstant(nodeIndex));
143 JSValue jsValue = valueOfJSConstant(nodeIndex);
144 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
145 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
146 info.fillJSValue(gpr, DataFormatJS);
150 DataFormat spillFormat = info.spillFormat();
151 switch (spillFormat) {
152 case DataFormatDouble: {
153 FPRReg fpr = fprAllocate();
154 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
155 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
156 info.fillDouble(fpr);
160 case DataFormatInteger: {
161 GPRReg gpr = allocate();
163 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
164 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
165 info.fillInteger(gpr);
171 GPRReg gpr = allocate();
173 ASSERT(spillFormat & DataFormatJS);
174 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
175 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
176 info.fillJSValue(gpr, spillFormat);
183 switch (info.registerFormat()) {
185 // Should have filled, above.
187 case DataFormatJSCell:
188 case DataFormatBoolean:
189 case DataFormatJSBoolean:
190 case DataFormatStorage:
191 // Should only be calling this function if we know this operand to be numeric.
192 ASSERT_NOT_REACHED();
195 GPRReg jsValueGpr = info.gpr();
196 m_gprs.lock(jsValueGpr);
197 FPRReg fpr = fprAllocate();
198 GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
200 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
202 m_jit.jitAssertIsJSDouble(jsValueGpr);
204 // First, if we get here we have a double encoded as a JSValue
205 m_jit.move(jsValueGpr, tempGpr);
206 unboxDouble(tempGpr, fpr);
207 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
209 // Finally, handle integers.
210 isInteger.link(&m_jit);
211 m_jit.convertInt32ToDouble(jsValueGpr, fpr);
212 hasUnboxedDouble.link(&m_jit);
214 m_gprs.release(jsValueGpr);
215 m_gprs.unlock(jsValueGpr);
216 m_gprs.unlock(tempGpr);
217 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
218 info.fillDouble(fpr);
223 case DataFormatJSInteger:
224 case DataFormatInteger: {
225 FPRReg fpr = fprAllocate();
226 GPRReg gpr = info.gpr();
228 m_jit.convertInt32ToDouble(gpr, fpr);
234 case DataFormatJSDouble: {
235 GPRReg gpr = info.gpr();
236 FPRReg fpr = fprAllocate();
237 if (m_gprs.isLocked(gpr)) {
238 // Make sure we don't trample gpr if it is in use.
239 GPRReg temp = allocate();
240 m_jit.move(gpr, temp);
241 unboxDouble(temp, fpr);
244 unboxDouble(gpr, fpr);
247 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
249 info.fillDouble(fpr);
253 case DataFormatDouble: {
254 FPRReg fpr = info.fpr();
260 ASSERT_NOT_REACHED();
261 return InvalidFPRReg;
264 GPRReg SpeculativeJIT::fillJSValue(NodeIndex nodeIndex)
266 Node& node = at(nodeIndex);
267 VirtualRegister virtualRegister = node.virtualRegister();
268 GenerationInfo& info = m_generationInfo[virtualRegister];
270 switch (info.registerFormat()) {
271 case DataFormatNone: {
272 GPRReg gpr = allocate();
274 if (node.hasConstant()) {
275 if (isInt32Constant(nodeIndex)) {
276 info.fillJSValue(gpr, DataFormatJSInteger);
277 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
278 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
279 } else if (isNumberConstant(nodeIndex)) {
280 info.fillJSValue(gpr, DataFormatJSDouble);
281 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));
282 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
284 ASSERT(isJSConstant(nodeIndex));
285 JSValue jsValue = valueOfJSConstant(nodeIndex);
286 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
287 info.fillJSValue(gpr, DataFormatJS);
290 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
292 DataFormat spillFormat = info.spillFormat();
293 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
294 if (spillFormat == DataFormatInteger) {
295 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
296 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
297 spillFormat = DataFormatJSInteger;
299 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
300 if (spillFormat == DataFormatDouble) {
301 // Need to box the double, since we want a JSValue.
302 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
303 spillFormat = DataFormatJSDouble;
305 ASSERT(spillFormat & DataFormatJS);
307 info.fillJSValue(gpr, spillFormat);
312 case DataFormatInteger: {
313 GPRReg gpr = info.gpr();
314 // If the register has already been locked we need to take a copy.
315 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
316 if (m_gprs.isLocked(gpr)) {
317 GPRReg result = allocate();
318 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
322 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
323 info.fillJSValue(gpr, DataFormatJSInteger);
327 case DataFormatDouble: {
328 FPRReg fpr = info.fpr();
329 GPRReg gpr = boxDouble(fpr);
332 info.fillJSValue(gpr, DataFormatJSDouble);
334 m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
340 // No retag required on JSVALUE64!
342 case DataFormatJSInteger:
343 case DataFormatJSDouble:
344 case DataFormatJSCell:
345 case DataFormatJSBoolean: {
346 GPRReg gpr = info.gpr();
351 case DataFormatBoolean:
352 case DataFormatStorage:
353 // this type currently never occurs
354 ASSERT_NOT_REACHED();
357 ASSERT_NOT_REACHED();
358 return InvalidGPRReg;
361 void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node)
363 if (isKnownNumeric(node.child1())) {
364 JSValueOperand op1(this, node.child1());
365 GPRTemporary result(this, op1);
366 m_jit.move(op1.gpr(), result.gpr());
367 jsValueResult(result.gpr(), m_compileIndex);
371 JSValueOperand op1(this, node.child1());
372 GPRTemporary result(this);
374 ASSERT(!isInt32Constant(node.child1()));
375 ASSERT(!isNumberConstant(node.child1()));
377 GPRReg jsValueGpr = op1.gpr();
378 GPRReg gpr = result.gpr();
381 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
382 JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
384 // First, if we get here we have a double encoded as a JSValue
385 m_jit.move(jsValueGpr, gpr);
386 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
388 // Next handle cells (& other JS immediates)
389 nonNumeric.link(&m_jit);
390 silentSpillAllRegisters(gpr);
391 callOperation(dfgConvertJSValueToNumber, FPRInfo::returnValueFPR, jsValueGpr);
392 boxDouble(FPRInfo::returnValueFPR, gpr);
393 silentFillAllRegisters(gpr);
394 JITCompiler::Jump hasCalledToNumber = m_jit.jump();
396 // Finally, handle integers.
397 isInteger.link(&m_jit);
398 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
399 hasUnboxedDouble.link(&m_jit);
400 hasCalledToNumber.link(&m_jit);
402 jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
405 void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node)
407 ASSERT(!isInt32Constant(node.child1()));
409 if (isKnownInteger(node.child1())) {
410 IntegerOperand op1(this, node.child1());
411 GPRTemporary result(this, op1);
412 m_jit.move(op1.gpr(), result.gpr());
413 integerResult(result.gpr(), m_compileIndex);
417 GenerationInfo& childInfo = m_generationInfo[at(node.child1()).virtualRegister()];
418 if (childInfo.isJSDouble()) {
419 DoubleOperand op1(this, node.child1());
420 GPRTemporary result(this);
421 FPRReg fpr = op1.fpr();
422 GPRReg gpr = result.gpr();
424 JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
426 silentSpillAllRegisters(gpr);
427 callOperation(toInt32, gpr, fpr);
428 silentFillAllRegisters(gpr);
430 truncatedToInteger.link(&m_jit);
431 integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
435 JSValueOperand op1(this, node.child1());
436 GPRTemporary result(this, op1);
437 GPRReg jsValueGpr = op1.gpr();
438 GPRReg resultGPR = result.gpr();
441 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
443 // First handle non-integers
444 silentSpillAllRegisters(resultGPR);
445 callOperation(dfgConvertJSValueToInt32, resultGPR, jsValueGpr);
446 silentFillAllRegisters(resultGPR);
447 JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
449 // Then handle integers.
450 isInteger.link(&m_jit);
451 m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
452 hasCalledToInt32.link(&m_jit);
453 integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
456 void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
458 IntegerOperand op1(this, node.child1());
459 FPRTemporary boxer(this);
460 GPRTemporary result(this, op1);
462 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
464 m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
465 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());
467 boxDouble(boxer.fpr(), result.gpr());
469 JITCompiler::Jump done = m_jit.jump();
471 positive.link(&m_jit);
473 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
477 jsValueResult(result.gpr(), m_compileIndex);
480 void SpeculativeJIT::nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)
482 JSValueOperand regArg(this, regChild);
483 GPRReg regArgGPR = regArg.gpr();
484 GPRTemporary result(this);
485 GPRReg resultGPR = result.gpr();
486 FPRTemporary tmp1(this);
487 FPRTemporary tmp2(this);
488 FPRReg tmp1FPR = tmp1.fpr();
489 FPRReg tmp2FPR = tmp2.fpr();
494 JITCompiler::Jump notInt;
496 int32_t imm = valueOfInt32Constant(immChild);
498 if (!isKnownInteger(regChild))
499 notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);
501 JITCompiler::Jump overflow;
506 overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
510 overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
514 ASSERT_NOT_REACHED();
517 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
519 JITCompiler::Jump done = m_jit.jump();
521 overflow.link(&m_jit);
523 JITCompiler::Jump notNumber;
525 // first deal with overflow case
526 m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);
528 // now deal with not-int case, if applicable
529 if (!isKnownInteger(regChild)) {
530 JITCompiler::Jump haveValue = m_jit.jump();
534 if (!isKnownNumeric(regChild)) {
535 ASSERT(op == ValueAdd);
536 notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);
539 m_jit.move(regArgGPR, resultGPR);
540 m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
541 m_jit.movePtrToDouble(resultGPR, tmp2FPR);
543 haveValue.link(&m_jit);
546 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);
547 m_jit.movePtrToDouble(resultGPR, tmp1FPR);
551 m_jit.addDouble(tmp1FPR, tmp2FPR);
555 m_jit.subDouble(tmp1FPR, tmp2FPR);
559 ASSERT_NOT_REACHED();
562 JITCompiler::Jump doneCaseConvertedToInt;
564 if (op == ValueAdd) {
565 JITCompiler::JumpList failureCases;
566 m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);
567 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
569 doneCaseConvertedToInt = m_jit.jump();
571 failureCases.link(&m_jit);
574 m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);
575 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
577 if (!isKnownNumeric(regChild)) {
578 ASSERT(notNumber.isSet());
579 ASSERT(op == ValueAdd);
581 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
583 notNumber.link(&m_jit);
585 silentSpillAllRegisters(resultGPR);
587 callOperation(operationValueAddNotNumber, resultGPR, MacroAssembler::Imm32(imm), regArgGPR);
589 callOperation(operationValueAddNotNumber, resultGPR, regArgGPR, MacroAssembler::Imm32(imm));
590 silentFillAllRegisters(resultGPR);
592 doneCaseWasNumber.link(&m_jit);
596 if (doneCaseConvertedToInt.isSet())
597 doneCaseConvertedToInt.link(&m_jit);
599 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
602 void SpeculativeJIT::nonSpeculativeBasicArithOp(NodeType op, Node &node)
604 JSValueOperand arg1(this, node.child1());
605 JSValueOperand arg2(this, node.child2());
607 FPRTemporary tmp1(this);
608 FPRTemporary tmp2(this);
609 FPRReg tmp1FPR = tmp1.fpr();
610 FPRReg tmp2FPR = tmp2.fpr();
612 GPRTemporary result(this);
614 GPRReg arg1GPR = arg1.gpr();
615 GPRReg arg2GPR = arg2.gpr();
617 GPRReg resultGPR = result.gpr();
622 JITCompiler::Jump child1NotInt;
623 JITCompiler::Jump child2NotInt;
624 JITCompiler::JumpList overflow;
626 if (!isKnownInteger(node.child1()))
627 child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);
628 if (!isKnownInteger(node.child2()))
629 child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
634 overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
639 overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
644 overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
645 overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
650 ASSERT_NOT_REACHED();
653 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
655 JITCompiler::Jump done = m_jit.jump();
657 JITCompiler::JumpList haveFPRArguments;
659 overflow.link(&m_jit);
661 // both arguments are integers
662 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
663 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
665 haveFPRArguments.append(m_jit.jump());
667 JITCompiler::JumpList notNumbers;
669 JITCompiler::Jump child2NotInt2;
671 if (!isKnownInteger(node.child1())) {
672 child1NotInt.link(&m_jit);
674 if (!isKnownNumeric(node.child1())) {
675 ASSERT(op == ValueAdd);
676 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));
679 m_jit.move(arg1GPR, resultGPR);
680 unboxDouble(resultGPR, tmp1FPR);
682 // child1 is converted to a double; child2 may either be an int or
685 if (!isKnownInteger(node.child2())) {
686 if (isKnownNumeric(node.child2()))
687 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
689 ASSERT(op == ValueAdd);
690 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
691 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
692 child2NotInt2 = m_jit.jump();
693 child2IsInt.link(&m_jit);
697 // child 2 is definitely an integer
698 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
700 haveFPRArguments.append(m_jit.jump());
703 if (!isKnownInteger(node.child2())) {
704 child2NotInt.link(&m_jit);
706 if (!isKnownNumeric(node.child2())) {
707 ASSERT(op == ValueAdd);
708 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
711 // child1 is definitely an integer, and child 2 is definitely not
713 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
715 if (child2NotInt2.isSet())
716 child2NotInt2.link(&m_jit);
718 m_jit.move(arg2GPR, resultGPR);
719 unboxDouble(resultGPR, tmp2FPR);
722 haveFPRArguments.link(&m_jit);
727 m_jit.addDouble(tmp2FPR, tmp1FPR);
731 m_jit.subDouble(tmp2FPR, tmp1FPR);
735 m_jit.mulDouble(tmp2FPR, tmp1FPR);
739 ASSERT_NOT_REACHED();
742 JITCompiler::Jump doneCaseConvertedToInt;
744 if (op == ValueAdd) {
745 JITCompiler::JumpList failureCases;
746 m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);
747 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
749 doneCaseConvertedToInt = m_jit.jump();
751 failureCases.link(&m_jit);
754 boxDouble(tmp1FPR, resultGPR);
756 if (!notNumbers.empty()) {
757 ASSERT(op == ValueAdd);
759 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
761 notNumbers.link(&m_jit);
763 silentSpillAllRegisters(resultGPR);
764 callOperation(operationValueAddNotNumber, resultGPR, arg1GPR, arg2GPR);
765 silentFillAllRegisters(resultGPR);
767 doneCaseWasNumber.link(&m_jit);
771 if (doneCaseConvertedToInt.isSet())
772 doneCaseConvertedToInt.link(&m_jit);
774 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
777 JITCompiler::Call SpeculativeJIT::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)
779 JITCompiler::DataLabelPtr structureToCompare;
780 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
782 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
783 JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
785 JITCompiler::Jump done = m_jit.jump();
787 structureCheck.link(&m_jit);
789 if (slowPathTarget.isSet())
790 slowPathTarget.link(&m_jit);
792 JITCompiler::Label slowCase = m_jit.label();
794 silentSpillAllRegisters(resultGPR);
795 JITCompiler::Call functionCall = callOperation(operationGetByIdOptimize, resultGPR, baseGPR, identifier(identifierNumber));
796 silentFillAllRegisters(resultGPR);
800 JITCompiler::Label doneLabel = m_jit.label();
802 m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, loadWithPatch, slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR)));
804 if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)
810 void SpeculativeJIT::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
813 JITCompiler::DataLabelPtr structureToCompare;
814 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
816 writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);
818 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
819 JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
821 JITCompiler::Jump done = m_jit.jump();
823 structureCheck.link(&m_jit);
825 if (slowPathTarget.isSet())
826 slowPathTarget.link(&m_jit);
828 JITCompiler::Label slowCase = m_jit.label();
830 silentSpillAllRegisters(InvalidGPRReg);
831 V_DFGOperation_EJCI optimizedCall;
832 if (m_jit.strictModeFor(at(m_compileIndex).codeOrigin)) {
833 if (putKind == Direct)
834 optimizedCall = operationPutByIdDirectStrictOptimize;
836 optimizedCall = operationPutByIdStrictOptimize;
838 if (putKind == Direct)
839 optimizedCall = operationPutByIdDirectNonStrictOptimize;
841 optimizedCall = operationPutByIdNonStrictOptimize;
843 JITCompiler::Call functionCall = callOperation(optimizedCall, valueGPR, baseGPR, identifier(identifierNumber));
844 silentFillAllRegisters(InvalidGPRReg);
847 JITCompiler::Label doneLabel = m_jit.label();
849 m_jit.addPropertyAccess(PropertyAccessRecord(structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR)));
852 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
854 JSValueOperand arg(this, operand);
855 GPRReg argGPR = arg.gpr();
857 GPRTemporary result(this, arg);
858 GPRReg resultGPR = result.gpr();
860 JITCompiler::Jump notCell;
862 if (!isKnownCell(operand))
863 notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
865 m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
866 m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
868 if (!isKnownCell(operand)) {
869 JITCompiler::Jump done = m_jit.jump();
871 notCell.link(&m_jit);
873 m_jit.move(argGPR, resultGPR);
874 m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
875 m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
880 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
881 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
884 void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)
886 Node& branchNode = at(branchNodeIndex);
887 BlockIndex taken = branchNode.takenBlockIndex();
888 BlockIndex notTaken = branchNode.notTakenBlockIndex();
890 if (taken == (m_block + 1)) {
892 BlockIndex tmp = taken;
897 JSValueOperand arg(this, operand);
898 GPRReg argGPR = arg.gpr();
900 GPRTemporary result(this, arg);
901 GPRReg resultGPR = result.gpr();
903 JITCompiler::Jump notCell;
905 if (!isKnownCell(operand))
906 notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
908 m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
909 addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);
911 if (!isKnownCell(operand)) {
912 addBranch(m_jit.jump(), notTaken);
914 notCell.link(&m_jit);
916 m_jit.move(argGPR, resultGPR);
917 m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
918 addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);
921 if (notTaken != (m_block + 1))
922 addBranch(m_jit.jump(), notTaken);
925 bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)
927 NodeIndex branchNodeIndex = detectPeepHoleBranch();
928 if (branchNodeIndex != NoNode) {
929 ASSERT(node.adjustedRefCount() == 1);
931 nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
935 m_compileIndex = branchNodeIndex;
940 nonSpeculativeNonPeepholeCompareNull(operand, invert);
945 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
947 Node& branchNode = at(branchNodeIndex);
948 BlockIndex taken = branchNode.takenBlockIndex();
949 BlockIndex notTaken = branchNode.notTakenBlockIndex();
951 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
953 // The branch instruction will branch to the taken block.
954 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
955 if (taken == (m_block + 1)) {
956 cond = JITCompiler::invert(cond);
957 callResultCondition = JITCompiler::Zero;
958 BlockIndex tmp = taken;
963 JSValueOperand arg1(this, node.child1());
964 JSValueOperand arg2(this, node.child2());
965 GPRReg arg1GPR = arg1.gpr();
966 GPRReg arg2GPR = arg2.gpr();
968 JITCompiler::JumpList slowPath;
970 if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
971 GPRResult result(this);
972 GPRReg resultGPR = result.gpr();
978 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
980 addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
982 GPRTemporary result(this, arg2);
983 GPRReg resultGPR = result.gpr();
988 if (!isKnownInteger(node.child1()))
989 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
990 if (!isKnownInteger(node.child2()))
991 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
993 addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken);
995 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
996 addBranch(m_jit.jump(), notTaken);
998 slowPath.link(&m_jit);
1000 silentSpillAllRegisters(resultGPR);
1001 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1002 silentFillAllRegisters(resultGPR);
1004 addBranch(m_jit.branchTest32(callResultCondition, resultGPR), taken);
1008 if (notTaken != (m_block + 1))
1009 addBranch(m_jit.jump(), notTaken);
1012 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
1014 JSValueOperand arg1(this, node.child1());
1015 JSValueOperand arg2(this, node.child2());
1016 GPRReg arg1GPR = arg1.gpr();
1017 GPRReg arg2GPR = arg2.gpr();
1019 JITCompiler::JumpList slowPath;
1021 if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {
1022 GPRResult result(this);
1023 GPRReg resultGPR = result.gpr();
1029 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1031 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1032 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1034 GPRTemporary result(this, arg2);
1035 GPRReg resultGPR = result.gpr();
1040 if (!isKnownInteger(node.child1()))
1041 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
1042 if (!isKnownInteger(node.child2()))
1043 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
1045 m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
1047 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
1048 JITCompiler::Jump haveResult = m_jit.jump();
1050 slowPath.link(&m_jit);
1052 silentSpillAllRegisters(resultGPR);
1053 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
1054 silentFillAllRegisters(resultGPR);
1056 m_jit.andPtr(TrustedImm32(1), resultGPR);
1058 haveResult.link(&m_jit);
1061 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1063 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1067 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
1069 Node& branchNode = at(branchNodeIndex);
1070 BlockIndex taken = branchNode.takenBlockIndex();
1071 BlockIndex notTaken = branchNode.notTakenBlockIndex();
1073 // The branch instruction will branch to the taken block.
1074 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1075 if (taken == (m_block + 1)) {
1077 BlockIndex tmp = taken;
1082 JSValueOperand arg1(this, node.child1());
1083 JSValueOperand arg2(this, node.child2());
1084 GPRReg arg1GPR = arg1.gpr();
1085 GPRReg arg2GPR = arg2.gpr();
1087 GPRTemporary result(this);
1088 GPRReg resultGPR = result.gpr();
1093 if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1094 // see if we get lucky: if the arguments are cells and they reference the same
1095 // cell, then they must be strictly equal.
1096 addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1098 silentSpillAllRegisters(resultGPR);
1099 callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1100 silentFillAllRegisters(resultGPR);
1102 addBranch(m_jit.branchTest32(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
1104 m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1106 JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1108 JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1110 addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
1111 addBranch(m_jit.jump(), notTaken);
1113 twoCellsCase.link(&m_jit);
1114 addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
1116 numberCase.link(&m_jit);
1118 silentSpillAllRegisters(resultGPR);
1119 callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1120 silentFillAllRegisters(resultGPR);
1122 addBranch(m_jit.branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
1125 if (notTaken != (m_block + 1))
1126 addBranch(m_jit.jump(), notTaken);
1129 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
1131 JSValueOperand arg1(this, node.child1());
1132 JSValueOperand arg2(this, node.child2());
1133 GPRReg arg1GPR = arg1.gpr();
1134 GPRReg arg2GPR = arg2.gpr();
1136 GPRTemporary result(this);
1137 GPRReg resultGPR = result.gpr();
1142 if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
1143 // see if we get lucky: if the arguments are cells and they reference the same
1144 // cell, then they must be strictly equal.
1145 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1147 m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1149 JITCompiler::Jump done = m_jit.jump();
1151 notEqualCase.link(&m_jit);
1153 silentSpillAllRegisters(resultGPR);
1154 callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
1155 silentFillAllRegisters(resultGPR);
1157 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1158 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1162 m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
1164 JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
1166 JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
1168 m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
1170 JITCompiler::Jump done1 = m_jit.jump();
1172 twoCellsCase.link(&m_jit);
1173 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
1175 m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
1177 JITCompiler::Jump done2 = m_jit.jump();
1179 numberCase.link(&m_jit);
1180 notEqualCase.link(&m_jit);
1182 silentSpillAllRegisters(resultGPR);
1183 callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
1184 silentFillAllRegisters(resultGPR);
1186 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
1190 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
1195 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1198 void SpeculativeJIT::emitCall(Node& node)
1200 P_DFGOperation_E slowCallFunction;
1202 if (node.op == Call)
1203 slowCallFunction = operationLinkCall;
1205 ASSERT(node.op == Construct);
1206 slowCallFunction = operationLinkConstruct;
1209 // For constructors, the this argument is not passed but we have to make space
1211 int dummyThisArgument = node.op == Call ? 0 : 1;
1213 CallLinkInfo::CallType callType = node.op == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
1215 NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
1216 JSValueOperand callee(this, calleeNodeIndex);
1217 GPRReg calleeGPR = callee.gpr();
1218 use(calleeNodeIndex);
1220 // the call instruction's first child is either the function (normal call) or the
1221 // receiver (method call). subsequent children are the arguments.
1222 int numArgs = node.numChildren() - 1;
1224 int numPassedArgs = numArgs + dummyThisArgument;
1226 // amount of stuff (in units of sizeof(Register)) that we need to place at the
1227 // top of the JS stack.
1228 int callDataSize = 0;
1230 // first there are the arguments
1231 callDataSize += numPassedArgs;
1233 // and then there is the call frame header
1234 callDataSize += RegisterFile::CallFrameHeaderSize;
1236 m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs))), addressOfCallData(RegisterFile::ArgumentCount));
1237 m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));
1239 for (int argIdx = 0; argIdx < numArgs; argIdx++) {
1240 NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];
1241 JSValueOperand arg(this, argNodeIndex);
1242 GPRReg argGPR = arg.gpr();
1245 m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx + dummyThisArgument));
1248 m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
1252 GPRResult result(this);
1253 GPRReg resultGPR = result.gpr();
1255 JITCompiler::DataLabelPtr targetToCheck;
1256 JITCompiler::Jump slowPath;
1258 slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
1259 m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
1260 m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
1262 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1264 JITCompiler::Call fastCall = m_jit.nearCall();
1265 m_jit.notifyCall(fastCall, at(m_compileIndex).codeOrigin);
1267 JITCompiler::Jump done = m_jit.jump();
1269 slowPath.link(&m_jit);
1271 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1272 JITCompiler::Call slowCall = m_jit.addFastExceptionCheck(m_jit.appendCall(slowCallFunction), at(m_compileIndex).codeOrigin);
1273 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1274 m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), at(m_compileIndex).codeOrigin);
1278 m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1280 jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
1282 m_jit.addJSCall(fastCall, slowCall, targetToCheck, callType, at(m_compileIndex).codeOrigin);
1285 template<bool strict>
1286 GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
1288 #if DFG_ENABLE(DEBUG_VERBOSE)
1289 fprintf(stderr, "SpecInt@%d ", nodeIndex);
1291 Node& node = at(nodeIndex);
1292 VirtualRegister virtualRegister = node.virtualRegister();
1293 GenerationInfo& info = m_generationInfo[virtualRegister];
1295 switch (info.registerFormat()) {
1296 case DataFormatNone: {
1297 if ((node.hasConstant() && !isInt32Constant(nodeIndex)) || info.spillFormat() == DataFormatDouble) {
1298 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1299 returnFormat = DataFormatInteger;
1303 GPRReg gpr = allocate();
1305 if (node.hasConstant()) {
1306 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1307 ASSERT(isInt32Constant(nodeIndex));
1308 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
1309 info.fillInteger(gpr);
1310 returnFormat = DataFormatInteger;
1314 DataFormat spillFormat = info.spillFormat();
1316 ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
1318 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1320 if (spillFormat == DataFormatJSInteger || spillFormat == DataFormatInteger) {
1321 // If we know this was spilled as an integer we can fill without checking.
1323 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1324 info.fillInteger(gpr);
1325 returnFormat = DataFormatInteger;
1328 if (spillFormat == DataFormatInteger) {
1329 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1330 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
1332 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
1333 info.fillJSValue(gpr, DataFormatJSInteger);
1334 returnFormat = DataFormatJSInteger;
1337 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
1339 // Fill as JSValue, and fall through.
1340 info.fillJSValue(gpr, DataFormatJSInteger);
1344 case DataFormatJS: {
1345 // Check the value is an integer.
1346 GPRReg gpr = info.gpr();
1348 speculationCheck(JSValueRegs(gpr), nodeIndex, m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1349 info.fillJSValue(gpr, DataFormatJSInteger);
1350 // If !strict we're done, return.
1352 returnFormat = DataFormatJSInteger;
1355 // else fall through & handle as DataFormatJSInteger.
1359 case DataFormatJSInteger: {
1360 // In a strict fill we need to strip off the value tag.
1362 GPRReg gpr = info.gpr();
1364 // If the register has already been locked we need to take a copy.
1365 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
1366 if (m_gprs.isLocked(gpr))
1367 result = allocate();
1370 info.fillInteger(gpr);
1373 m_jit.zeroExtend32ToPtr(gpr, result);
1374 returnFormat = DataFormatInteger;
1378 GPRReg gpr = info.gpr();
1380 returnFormat = DataFormatJSInteger;
1384 case DataFormatInteger: {
1385 GPRReg gpr = info.gpr();
1387 returnFormat = DataFormatInteger;
1391 case DataFormatDouble:
1392 case DataFormatCell:
1393 case DataFormatBoolean:
1394 case DataFormatJSDouble:
1395 case DataFormatJSCell:
1396 case DataFormatJSBoolean: {
1397 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1398 returnFormat = DataFormatInteger;
1402 case DataFormatStorage:
1403 ASSERT_NOT_REACHED();
1406 ASSERT_NOT_REACHED();
1407 return InvalidGPRReg;
1410 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
1412 return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
1415 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
1417 DataFormat mustBeDataFormatInteger;
1418 GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
1419 ASSERT(mustBeDataFormatInteger == DataFormatInteger);
1423 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
1425 #if DFG_ENABLE(DEBUG_VERBOSE)
1426 fprintf(stderr, "SpecDouble@%d ", nodeIndex);
1428 Node& node = at(nodeIndex);
1429 VirtualRegister virtualRegister = node.virtualRegister();
1430 GenerationInfo& info = m_generationInfo[virtualRegister];
1432 if (info.registerFormat() == DataFormatNone) {
1433 if (node.hasConstant()) {
1434 GPRReg gpr = allocate();
1436 if (isInt32Constant(nodeIndex)) {
1437 FPRReg fpr = fprAllocate();
1438 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
1439 m_jit.movePtrToDouble(gpr, fpr);
1442 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1443 info.fillDouble(fpr);
1446 if (isNumberConstant(nodeIndex)) {
1447 FPRReg fpr = fprAllocate();
1448 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
1449 m_jit.movePtrToDouble(gpr, fpr);
1452 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1453 info.fillDouble(fpr);
1456 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1457 return fprAllocate();
1460 DataFormat spillFormat = info.spillFormat();
1461 switch (spillFormat) {
1462 case DataFormatDouble: {
1463 FPRReg fpr = fprAllocate();
1464 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1465 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1466 info.fillDouble(fpr);
1470 case DataFormatInteger: {
1471 GPRReg gpr = allocate();
1473 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1474 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1475 info.fillInteger(gpr);
1481 GPRReg gpr = allocate();
1483 ASSERT(spillFormat & DataFormatJS);
1484 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1485 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
1486 info.fillJSValue(gpr, spillFormat);
1492 switch (info.registerFormat()) {
1493 case DataFormatNone: // Should have filled, above.
1494 case DataFormatBoolean: // This type never occurs.
1495 case DataFormatStorage:
1496 ASSERT_NOT_REACHED();
1498 case DataFormatCell:
1499 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1500 return fprAllocate();
1502 case DataFormatJSCell:
1504 case DataFormatJSBoolean: {
1505 GPRReg jsValueGpr = info.gpr();
1506 m_gprs.lock(jsValueGpr);
1507 FPRReg fpr = fprAllocate();
1508 GPRReg tempGpr = allocate();
1510 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
1512 speculationCheck(JSValueRegs(jsValueGpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
1514 // First, if we get here we have a double encoded as a JSValue
1515 m_jit.move(jsValueGpr, tempGpr);
1516 unboxDouble(tempGpr, fpr);
1517 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
1519 // Finally, handle integers.
1520 isInteger.link(&m_jit);
1521 m_jit.convertInt32ToDouble(jsValueGpr, fpr);
1522 hasUnboxedDouble.link(&m_jit);
1524 m_gprs.release(jsValueGpr);
1525 m_gprs.unlock(jsValueGpr);
1526 m_gprs.unlock(tempGpr);
1527 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1528 info.fillDouble(fpr);
1533 case DataFormatJSInteger:
1534 case DataFormatInteger: {
1535 FPRReg fpr = fprAllocate();
1536 GPRReg gpr = info.gpr();
1538 m_jit.convertInt32ToDouble(gpr, fpr);
1544 case DataFormatJSDouble: {
1545 GPRReg gpr = info.gpr();
1546 FPRReg fpr = fprAllocate();
1547 if (m_gprs.isLocked(gpr)) {
1548 // Make sure we don't trample gpr if it is in use.
1549 GPRReg temp = allocate();
1550 m_jit.move(gpr, temp);
1551 unboxDouble(temp, fpr);
1554 unboxDouble(gpr, fpr);
1556 m_gprs.release(gpr);
1557 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1559 info.fillDouble(fpr);
1563 case DataFormatDouble: {
1564 FPRReg fpr = info.fpr();
1570 ASSERT_NOT_REACHED();
1571 return InvalidFPRReg;
1574 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
1576 #if DFG_ENABLE(DEBUG_VERBOSE)
1577 fprintf(stderr, "SpecCell@%d ", nodeIndex);
1579 Node& node = at(nodeIndex);
1580 VirtualRegister virtualRegister = node.virtualRegister();
1581 GenerationInfo& info = m_generationInfo[virtualRegister];
1583 switch (info.registerFormat()) {
1584 case DataFormatNone: {
1585 if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
1586 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1590 GPRReg gpr = allocate();
1592 if (node.hasConstant()) {
1593 JSValue jsValue = valueOfJSConstant(nodeIndex);
1594 if (jsValue.isCell()) {
1595 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1596 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
1597 info.fillJSValue(gpr, DataFormatJSCell);
1600 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1603 ASSERT(info.spillFormat() & DataFormatJS);
1604 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1605 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
1607 info.fillJSValue(gpr, DataFormatJS);
1608 if (info.spillFormat() != DataFormatJSCell)
1609 speculationCheck(JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
1610 info.fillJSValue(gpr, DataFormatJSCell);
1614 case DataFormatCell:
1615 case DataFormatJSCell: {
1616 GPRReg gpr = info.gpr();
1621 case DataFormatJS: {
1622 GPRReg gpr = info.gpr();
1624 speculationCheck(JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
1625 info.fillJSValue(gpr, DataFormatJSCell);
1629 case DataFormatJSInteger:
1630 case DataFormatInteger:
1631 case DataFormatJSDouble:
1632 case DataFormatDouble:
1633 case DataFormatJSBoolean:
1634 case DataFormatBoolean: {
1635 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1639 case DataFormatStorage:
1640 ASSERT_NOT_REACHED();
1643 ASSERT_NOT_REACHED();
1644 return InvalidGPRReg;
1647 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
1649 #if DFG_ENABLE(DEBUG_VERBOSE)
1650 fprintf(stderr, "SpecBool@%d ", nodeIndex);
1652 Node& node = at(nodeIndex);
1653 VirtualRegister virtualRegister = node.virtualRegister();
1654 GenerationInfo& info = m_generationInfo[virtualRegister];
1656 switch (info.registerFormat()) {
1657 case DataFormatNone: {
1658 if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
1659 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1663 GPRReg gpr = allocate();
1665 if (node.hasConstant()) {
1666 JSValue jsValue = valueOfJSConstant(nodeIndex);
1667 if (jsValue.isBoolean()) {
1668 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1669 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
1670 info.fillJSValue(gpr, DataFormatJSBoolean);
1673 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1676 ASSERT(info.spillFormat() & DataFormatJS);
1677 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1678 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
1680 info.fillJSValue(gpr, DataFormatJS);
1681 if (info.spillFormat() != DataFormatJSBoolean) {
1682 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1683 speculationCheck(JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1684 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1686 info.fillJSValue(gpr, DataFormatJSBoolean);
1690 case DataFormatBoolean:
1691 case DataFormatJSBoolean: {
1692 GPRReg gpr = info.gpr();
1697 case DataFormatJS: {
1698 GPRReg gpr = info.gpr();
1700 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1701 speculationCheck(JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1702 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1703 info.fillJSValue(gpr, DataFormatJSBoolean);
1707 case DataFormatJSInteger:
1708 case DataFormatInteger:
1709 case DataFormatJSDouble:
1710 case DataFormatDouble:
1711 case DataFormatJSCell:
1712 case DataFormatCell: {
1713 terminateSpeculativeExecution(JSValueRegs(), NoNode);
1717 case DataFormatStorage:
1718 ASSERT_NOT_REACHED();
1721 ASSERT_NOT_REACHED();
1722 return InvalidGPRReg;
1725 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
1727 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
1729 JITCompiler::Jump notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
1731 m_jit.move(value, tmp);
1732 unboxDouble(tmp, result);
1734 JITCompiler::Jump done = m_jit.jump();
1736 isInteger.link(&m_jit);
1738 m_jit.convertInt32ToDouble(value, result);
1745 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck)
1747 SpeculateCellOperand op1(this, node.child1());
1748 SpeculateCellOperand op2(this, node.child2());
1749 GPRTemporary result(this, op1);
1751 GPRReg op1GPR = op1.gpr();
1752 GPRReg op2GPR = op2.gpr();
1753 GPRReg resultGPR = result.gpr();
1755 if (!predictionCheck(m_state.forNode(node.child1()).m_type))
1756 speculationCheck(JSValueRegs(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
1757 if (!predictionCheck(m_state.forNode(node.child2()).m_type))
1758 speculationCheck(JSValueRegs(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
1760 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
1761 m_jit.move(Imm32(ValueTrue), resultGPR);
1762 MacroAssembler::Jump done = m_jit.jump();
1763 falseCase.link(&m_jit);
1764 m_jit.move(Imm32(ValueFalse), resultGPR);
1767 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
1770 // Returns true if the compare is fused with a subsequent branch.
1771 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
1773 if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
1776 if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
1777 SpeculateIntegerOperand op1(this, node.child1());
1778 SpeculateIntegerOperand op2(this, node.child2());
1779 GPRTemporary result(this, op1, op2);
1781 m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1783 // If we add a DataFormatBool, we should use it here.
1784 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1785 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1786 } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
1787 SpeculateDoubleOperand op1(this, node.child1());
1788 SpeculateDoubleOperand op2(this, node.child2());
1789 GPRTemporary result(this);
1791 m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1792 MacroAssembler::Jump trueCase = m_jit.branchDouble(doubleCondition, op1.fpr(), op2.fpr());
1793 m_jit.xorPtr(Imm32(true), result.gpr());
1794 trueCase.link(&m_jit);
1796 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1797 } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
1798 compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
1799 else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
1800 compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
1802 nonSpeculativeNonPeepholeCompare(node, condition, operation);
1807 void SpeculativeJIT::compileValueAdd(Node& node)
1809 JSValueOperand op1(this, node.child1());
1810 JSValueOperand op2(this, node.child2());
1812 GPRReg op1GPR = op1.gpr();
1813 GPRReg op2GPR = op2.gpr();
1817 GPRResult result(this);
1818 if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
1819 callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
1821 callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
1823 jsValueResult(result.gpr(), m_compileIndex);
1826 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr, bool needSpeculationCheck)
1828 JSValueOperand value(this, nodeIndex);
1829 GPRTemporary result(this);
1830 GPRReg valueGPR = value.gpr();
1831 GPRReg resultGPR = result.gpr();
1833 MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
1834 if (needSpeculationCheck)
1835 speculationCheck(JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
1836 m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1837 MacroAssembler::Jump done = m_jit.jump();
1839 notCell.link(&m_jit);
1841 if (needSpeculationCheck) {
1842 m_jit.move(valueGPR, resultGPR);
1843 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1844 speculationCheck(JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
1846 m_jit.move(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1850 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
1853 void SpeculativeJIT::compileLogicalNot(Node& node)
1855 if (isKnownBoolean(node.child1())) {
1856 SpeculateBooleanOperand value(this, node.child1());
1857 GPRTemporary result(this, value);
1859 m_jit.move(value.gpr(), result.gpr());
1860 m_jit.xorPtr(TrustedImm32(true), result.gpr());
1862 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1865 if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
1866 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1869 if (at(node.child1()).shouldSpeculateArrayOrOther()) {
1870 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1873 if (at(node.child1()).shouldSpeculateInteger()) {
1874 SpeculateIntegerOperand value(this, node.child1());
1875 GPRTemporary result(this, value);
1876 m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1877 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1878 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1881 if (at(node.child1()).shouldSpeculateNumber()) {
1882 SpeculateDoubleOperand value(this, node.child1());
1883 FPRTemporary scratch(this);
1884 GPRTemporary result(this);
1885 m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1886 MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1887 m_jit.xor32(Imm32(true), result.gpr());
1888 nonZero.link(&m_jit);
1889 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1893 PredictedType prediction = m_jit.getPrediction(node.child1());
1894 if (isBooleanPrediction(prediction) || !prediction) {
1895 JSValueOperand value(this, node.child1());
1896 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1898 m_jit.move(value.gpr(), result.gpr());
1899 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1900 speculationCheck(JSValueRegs(value.gpr()), node.child1(), m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1901 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1903 // If we add a DataFormatBool, we should use it here.
1904 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1908 JSValueOperand arg1(this, node.child1());
1909 GPRTemporary result(this);
1911 GPRReg arg1GPR = arg1.gpr();
1912 GPRReg resultGPR = result.gpr();
1916 m_jit.move(arg1GPR, resultGPR);
1917 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1918 JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
1920 silentSpillAllRegisters(resultGPR);
1921 callOperation(dfgConvertJSValueToBoolean, resultGPR, arg1GPR);
1922 silentFillAllRegisters(resultGPR);
1924 fastCase.link(&m_jit);
1926 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1927 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1930 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck)
1932 JSValueOperand value(this, nodeIndex);
1933 GPRTemporary scratch(this);
1934 GPRReg valueGPR = value.gpr();
1935 GPRReg scratchGPR = scratch.gpr();
1937 MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
1938 if (needSpeculationCheck)
1939 speculationCheck(JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
1940 addBranch(m_jit.jump(), taken);
1942 notCell.link(&m_jit);
1944 if (needSpeculationCheck) {
1945 m_jit.move(valueGPR, scratchGPR);
1946 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
1947 speculationCheck(JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
1949 if (notTaken != (m_block + 1))
1950 addBranch(m_jit.jump(), notTaken);
1952 noResult(m_compileIndex);
1955 void SpeculativeJIT::emitBranch(Node& node)
1957 JSValueOperand value(this, node.child1());
1958 GPRReg valueGPR = value.gpr();
1960 BlockIndex taken = node.takenBlockIndex();
1961 BlockIndex notTaken = node.notTakenBlockIndex();
1963 if (isKnownBoolean(node.child1())) {
1964 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1966 if (taken == (m_block + 1)) {
1967 condition = MacroAssembler::Zero;
1968 BlockIndex tmp = taken;
1973 addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken);
1974 if (notTaken != (m_block + 1))
1975 addBranch(m_jit.jump(), notTaken);
1977 noResult(m_compileIndex);
1978 } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
1979 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1980 } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
1981 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1982 } else if (at(node.child1()).shouldSpeculateNumber()) {
1983 if (at(node.child1()).shouldSpeculateInteger()) {
1984 bool invert = false;
1986 if (taken == (m_block + 1)) {
1988 BlockIndex tmp = taken;
1993 SpeculateIntegerOperand value(this, node.child1());
1994 addBranch(m_jit.branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr()), taken);
1996 SpeculateDoubleOperand value(this, node.child1());
1997 FPRTemporary scratch(this);
1998 addBranch(m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr()), taken);
2001 if (notTaken != (m_block + 1))
2002 addBranch(m_jit.jump(), notTaken);
2004 noResult(m_compileIndex);
2006 GPRTemporary result(this);
2007 GPRReg resultGPR = result.gpr();
2009 bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
2011 if (predictBoolean) {
2012 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
2013 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
2015 speculationCheck(JSValueRegs(valueGPR), node.child1(), m_jit.jump());
2018 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
2019 addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken);
2021 if (!predictBoolean) {
2022 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
2023 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
2028 silentSpillAllRegisters(resultGPR);
2029 callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR);
2030 silentFillAllRegisters(resultGPR);
2032 addBranch(m_jit.branchTest32(MacroAssembler::NonZero, resultGPR), taken);
2033 if (notTaken != (m_block + 1))
2034 addBranch(m_jit.jump(), notTaken);
2037 noResult(m_compileIndex, UseChildrenCalledExplicitly);
2041 void SpeculativeJIT::compile(Node& node)
2043 NodeType op = node.op;
2047 initConstantInfo(m_compileIndex);
2050 case WeakJSConstant:
2051 m_jit.addWeakReference(node.weakConstant());
2052 initConstantInfo(m_compileIndex);
2056 PredictedType prediction = node.variableAccessData()->prediction();
2057 AbstractValue& value = block()->valuesAtHead.operand(node.local());
2059 // If we have no prediction for this local, then don't attempt to compile.
2060 if (prediction == PredictNone || value.isClear()) {
2061 terminateSpeculativeExecution(JSValueRegs(), NoNode);
2065 GPRTemporary result(this);
2066 if (isInt32Prediction(value.m_type)) {
2067 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2069 // Like integerResult, but don't useChildren - our children are phi nodes,
2070 // and don't represent values within this dataflow with virtual registers.
2071 VirtualRegister virtualRegister = node.virtualRegister();
2072 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2073 m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
2077 m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
2079 // Like jsValueResult, but don't useChildren - our children are phi nodes,
2080 // and don't represent values within this dataflow with virtual registers.
2081 VirtualRegister virtualRegister = node.virtualRegister();
2082 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2085 if (isCellPrediction(value.m_type))
2086 format = DataFormatJSCell;
2087 else if (isBooleanPrediction(value.m_type))
2088 format = DataFormatJSBoolean;
2090 format = DataFormatJS;
2092 m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
2097 // SetLocal doubles as a hint as to where a node will be stored and
2098 // as a speculation point. So before we speculate make sure that we
2099 // know where the child of this node needs to go in the virtual
2101 compileMovHint(node);
2103 // As far as OSR is concerned, we're on the bytecode index corresponding
2104 // to the *next* instruction, since we've already "executed" the
2105 // SetLocal and whatever other DFG Nodes are associated with the same
2106 // bytecode index as the SetLocal.
2107 ASSERT(m_codeOriginForOSR == node.codeOrigin);
2108 Node& nextNode = at(m_compileIndex + 1);
2110 // Oddly, it's possible for the bytecode index for the next node to be
2111 // equal to ours. This will happen for op_post_inc. And, even more oddly,
2112 // this is just fine. Ordinarily, this wouldn't be fine, since if the
2113 // next node failed OSR then we'd be OSR-ing with this SetLocal's local
2114 // variable already set even though from the standpoint of the old JIT,
2115 // this SetLocal should not have executed. But for op_post_inc, it's just
2116 // fine, because this SetLocal's local (i.e. the LHS in a x = y++
2117 // statement) would be dead anyway - so the fact that DFG would have
2118 // already made the assignment, and baked it into the register file during
2119 // OSR exit, would not be visible to the old JIT in any way.
2120 m_codeOriginForOSR = nextNode.codeOrigin;
2122 PredictedType predictedType = node.variableAccessData()->prediction();
2123 if (isInt32Prediction(predictedType)) {
2124 SpeculateIntegerOperand value(this, node.child1());
2125 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
2126 noResult(m_compileIndex);
2127 } else if (isArrayPrediction(predictedType)) {
2128 SpeculateCellOperand cell(this, node.child1());
2129 GPRReg cellGPR = cell.gpr();
2130 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2131 speculationCheck(JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
2132 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
2133 noResult(m_compileIndex);
2134 } else if (isByteArrayPrediction(predictedType)) {
2135 SpeculateCellOperand cell(this, node.child1());
2136 GPRReg cellGPR = cell.gpr();
2137 if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
2138 speculationCheck(JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
2139 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
2140 noResult(m_compileIndex);
2141 } else if (isBooleanPrediction(predictedType)) {
2142 SpeculateBooleanOperand boolean(this, node.child1());
2143 m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
2144 noResult(m_compileIndex);
2146 JSValueOperand value(this, node.child1());
2147 m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
2148 noResult(m_compileIndex);
2151 // Indicate that it's no longer necessary to retrieve the value of
2152 // this bytecode variable from registers or other locations in the register file.
2153 valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType);
2158 // This is a no-op; it just marks the fact that the argument is being used.
2159 // But it may be profitable to use this as a hook to run speculation checks
2160 // on arguments, thereby allowing us to trivially eliminate such checks if
2161 // the argument is not used.
2167 if (isInt32Constant(node.child1())) {
2168 SpeculateIntegerOperand op2(this, node.child2());
2169 GPRTemporary result(this, op2);
2171 bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
2173 integerResult(result.gpr(), m_compileIndex);
2174 } else if (isInt32Constant(node.child2())) {
2175 SpeculateIntegerOperand op1(this, node.child1());
2176 GPRTemporary result(this, op1);
2178 bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
2180 integerResult(result.gpr(), m_compileIndex);
2182 SpeculateIntegerOperand op1(this, node.child1());
2183 SpeculateIntegerOperand op2(this, node.child2());
2184 GPRTemporary result(this, op1, op2);
2186 GPRReg reg1 = op1.gpr();
2187 GPRReg reg2 = op2.gpr();
2188 bitOp(op, reg1, reg2, result.gpr());
2190 integerResult(result.gpr(), m_compileIndex);
2197 if (isInt32Constant(node.child2())) {
2198 SpeculateIntegerOperand op1(this, node.child1());
2199 GPRTemporary result(this, op1);
2201 shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
2203 integerResult(result.gpr(), m_compileIndex);
2205 // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
2206 SpeculateIntegerOperand op1(this, node.child1());
2207 SpeculateIntegerOperand op2(this, node.child2());
2208 GPRTemporary result(this, op1);
2210 GPRReg reg1 = op1.gpr();
2211 GPRReg reg2 = op2.gpr();
2212 shiftOp(op, reg1, reg2, result.gpr());
2214 integerResult(result.gpr(), m_compileIndex);
2218 case UInt32ToNumber: {
2219 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
2220 // We know that this sometimes produces doubles. So produce a double every
2221 // time. This at least allows subsequent code to not have weird conditionals.
2223 IntegerOperand op1(this, node.child1());
2224 FPRTemporary result(this);
2226 GPRReg inputGPR = op1.gpr();
2227 FPRReg outputFPR = result.fpr();
2229 m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2231 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2232 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);
2233 positive.link(&m_jit);
2235 doubleResult(outputFPR, m_compileIndex);
2239 IntegerOperand op1(this, node.child1());
2240 GPRTemporary result(this, op1);
2242 // Test the operand is positive.
2243 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
2245 m_jit.move(op1.gpr(), result.gpr());
2246 integerResult(result.gpr(), m_compileIndex, op1.format());
2250 case ValueToInt32: {
2251 compileValueToInt32(node);
2255 case ValueToNumber: {
2256 if (at(node.child1()).shouldNotSpeculateInteger()) {
2257 SpeculateDoubleOperand op1(this, node.child1());
2258 FPRTemporary result(this, op1);
2259 m_jit.moveDouble(op1.fpr(), result.fpr());
2260 doubleResult(result.fpr(), m_compileIndex);
2264 SpeculateIntegerOperand op1(this, node.child1());
2265 GPRTemporary result(this, op1);
2266 m_jit.move(op1.gpr(), result.gpr());
2267 integerResult(result.gpr(), m_compileIndex, op1.format());
2271 case ValueToDouble: {
2272 SpeculateDoubleOperand op1(this, node.child1());
2273 FPRTemporary result(this, op1);
2274 m_jit.moveDouble(op1.fpr(), result.fpr());
2275 doubleResult(result.fpr(), m_compileIndex);
2281 if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2282 if (isInt32Constant(node.child1())) {
2283 int32_t imm1 = valueOfInt32Constant(node.child1());
2284 SpeculateIntegerOperand op2(this, node.child2());
2285 GPRTemporary result(this);
2287 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2288 m_jit.move(op2.gpr(), result.gpr());
2289 m_jit.add32(Imm32(imm1), result.gpr());
2291 speculationCheck(JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
2293 integerResult(result.gpr(), m_compileIndex);
2297 if (isInt32Constant(node.child2())) {
2298 SpeculateIntegerOperand op1(this, node.child1());
2299 int32_t imm2 = valueOfInt32Constant(node.child2());
2300 GPRTemporary result(this);
2302 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2303 m_jit.move(op1.gpr(), result.gpr());
2304 m_jit.add32(Imm32(imm2), result.gpr());
2306 speculationCheck(JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2308 integerResult(result.gpr(), m_compileIndex);
2312 SpeculateIntegerOperand op1(this, node.child1());
2313 SpeculateIntegerOperand op2(this, node.child2());
2314 GPRTemporary result(this, op1, op2);
2316 GPRReg gpr1 = op1.gpr();
2317 GPRReg gpr2 = op2.gpr();
2318 GPRReg gprResult = result.gpr();
2320 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2321 if (gpr1 == gprResult)
2322 m_jit.add32(gpr2, gprResult);
2324 m_jit.move(gpr2, gprResult);
2325 m_jit.add32(gpr1, gprResult);
2328 MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
2330 if (gpr1 == gprResult)
2331 speculationCheck(JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
2332 else if (gpr2 == gprResult)
2333 speculationCheck(JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
2335 speculationCheck(JSValueRegs(), NoNode, check);
2338 integerResult(gprResult, m_compileIndex);
2342 if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2343 SpeculateDoubleOperand op1(this, node.child1());
2344 SpeculateDoubleOperand op2(this, node.child2());
2345 FPRTemporary result(this, op1, op2);
2347 FPRReg reg1 = op1.fpr();
2348 FPRReg reg2 = op2.fpr();
2349 m_jit.addDouble(reg1, reg2, result.fpr());
2351 doubleResult(result.fpr(), m_compileIndex);
2355 ASSERT(op == ValueAdd);
2356 compileValueAdd(node);
2361 if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2362 if (isInt32Constant(node.child2())) {
2363 SpeculateIntegerOperand op1(this, node.child1());
2364 int32_t imm2 = valueOfInt32Constant(node.child2());
2365 GPRTemporary result(this);
2367 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2368 m_jit.move(op1.gpr(), result.gpr());
2369 m_jit.sub32(Imm32(imm2), result.gpr());
2371 speculationCheck(JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2373 integerResult(result.gpr(), m_compileIndex);
2377 SpeculateIntegerOperand op1(this, node.child1());
2378 SpeculateIntegerOperand op2(this, node.child2());
2379 GPRTemporary result(this);
2381 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2382 m_jit.move(op1.gpr(), result.gpr());
2383 m_jit.sub32(op2.gpr(), result.gpr());
2385 speculationCheck(JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
2387 integerResult(result.gpr(), m_compileIndex);
2391 SpeculateDoubleOperand op1(this, node.child1());
2392 SpeculateDoubleOperand op2(this, node.child2());
2393 FPRTemporary result(this, op1);
2395 FPRReg reg1 = op1.fpr();
2396 FPRReg reg2 = op2.fpr();
2397 m_jit.subDouble(reg1, reg2, result.fpr());
2399 doubleResult(result.fpr(), m_compileIndex);
2404 compileArithMul(node);
2409 if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2410 SpeculateIntegerOperand op1(this, node.child1());
2411 SpeculateIntegerOperand op2(this, node.child2());
2412 GPRTemporary eax(this, X86Registers::eax);
2413 GPRTemporary edx(this, X86Registers::edx);
2414 GPRReg op1GPR = op1.gpr();
2415 GPRReg op2GPR = op2.gpr();
2417 speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
2419 // If the user cares about negative zero, then speculate that we're not about
2420 // to produce negative zero.
2421 if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
2422 MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
2423 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
2424 numeratorNonZero.link(&m_jit);
2427 GPRReg temp2 = InvalidGPRReg;
2428 if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
2430 m_jit.move(op2GPR, temp2);
2434 m_jit.move(op1GPR, eax.gpr());
2435 m_jit.assembler().cdq();
2436 m_jit.assembler().idivl_r(op2GPR);
2438 if (temp2 != InvalidGPRReg)
2441 // Check that there was no remainder. If there had been, then we'd be obligated to
2442 // produce a double result instead.
2443 speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
2445 integerResult(eax.gpr(), m_compileIndex);
2449 SpeculateDoubleOperand op1(this, node.child1());
2450 SpeculateDoubleOperand op2(this, node.child2());
2451 FPRTemporary result(this, op1);
2453 FPRReg reg1 = op1.fpr();
2454 FPRReg reg2 = op2.fpr();
2455 m_jit.divDouble(reg1, reg2, result.fpr());
2457 doubleResult(result.fpr(), m_compileIndex);
2462 compileArithMod(node);
2467 if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
2468 SpeculateIntegerOperand op1(this, node.child1());
2469 GPRTemporary result(this, op1);
2470 GPRTemporary scratch(this);
2472 m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2473 m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2474 m_jit.add32(scratch.gpr(), result.gpr());
2475 m_jit.xor32(scratch.gpr(), result.gpr());
2476 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2477 integerResult(result.gpr(), m_compileIndex);
2481 SpeculateDoubleOperand op1(this, node.child1());
2482 FPRTemporary result(this);
2484 m_jit.absDouble(op1.fpr(), result.fpr());
2485 doubleResult(result.fpr(), m_compileIndex);
2491 if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2492 SpeculateStrictInt32Operand op1(this, node.child1());
2493 SpeculateStrictInt32Operand op2(this, node.child2());
2494 GPRTemporary result(this, op1);
2496 MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2497 m_jit.move(op2.gpr(), result.gpr());
2498 if (op1.gpr() != result.gpr()) {
2499 MacroAssembler::Jump done = m_jit.jump();
2500 op1Less.link(&m_jit);
2501 m_jit.move(op1.gpr(), result.gpr());
2504 op1Less.link(&m_jit);
2506 integerResult(result.gpr(), m_compileIndex);
2510 SpeculateDoubleOperand op1(this, node.child1());
2511 SpeculateDoubleOperand op2(this, node.child2());
2512 FPRTemporary result(this, op1);
2514 MacroAssembler::JumpList done;
2516 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
2518 // op2 is eather the lesser one or one of then is NaN
2519 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
2521 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding
2522 // op1 + op2 and putting it into result.
2523 m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
2524 done.append(m_jit.jump());
2526 op2Less.link(&m_jit);
2527 m_jit.moveDouble(op2.fpr(), result.fpr());
2529 if (op1.fpr() != result.fpr()) {
2530 done.append(m_jit.jump());
2532 op1Less.link(&m_jit);
2533 m_jit.moveDouble(op1.fpr(), result.fpr());
2535 op1Less.link(&m_jit);
2539 doubleResult(result.fpr(), m_compileIndex);
2544 SpeculateDoubleOperand op1(this, node.child1());
2545 FPRTemporary result(this, op1);
2547 m_jit.sqrtDouble(op1.fpr(), result.fpr());
2549 doubleResult(result.fpr(), m_compileIndex);
2554 compileLogicalNot(node);
2558 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2563 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2567 case CompareGreater:
2568 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2572 case CompareGreaterEq:
2573 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2578 if (isNullConstant(node.child1())) {
2579 if (nonSpeculativeCompareNull(node, node.child2()))
2583 if (isNullConstant(node.child2())) {
2584 if (nonSpeculativeCompareNull(node, node.child1()))
2588 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2592 case CompareStrictEq:
2593 if (nonSpeculativeStrictEq(node))
2597 case StringCharCodeAt: {
2598 compileGetCharCodeAt(node);
2602 case StringCharAt: {
2603 // Relies on StringCharAt node having same basic layout as GetByVal
2604 compileGetByValOnString(node);
2609 PredictedType basePrediction = at(node.child2()).prediction();
2610 if (!(basePrediction & PredictInt32) && basePrediction) {
2611 JSValueOperand base(this, node.child1());
2612 JSValueOperand property(this, node.child2());
2613 GPRReg baseGPR = base.gpr();
2614 GPRReg propertyGPR = property.gpr();
2617 GPRResult result(this);
2618 callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2620 jsValueResult(result.gpr(), m_compileIndex);
2624 if (at(node.child1()).prediction() == PredictString) {
2625 compileGetByValOnString(node);
2631 if (at(node.child1()).shouldSpeculateByteArray()) {
2632 compileGetByValOnByteArray(node);
2638 ASSERT(node.child3() == NoNode);
2639 SpeculateCellOperand base(this, node.child1());
2640 SpeculateStrictInt32Operand property(this, node.child2());
2641 GPRTemporary storage(this);
2643 GPRReg baseReg = base.gpr();
2644 GPRReg propertyReg = property.gpr();
2645 GPRReg storageReg = storage.gpr();
2650 // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
2651 // an access with offset JSArray::storageOffset() is valid for all JSCells!
2652 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2654 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
2655 // If we have predicted the base to be type array, we can skip the check.
2656 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2657 speculationCheck(JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
2658 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
2660 // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
2661 // the storage pointer - especially if there happens to be another register free right now. If we do so,
2662 // then we'll need to allocate a new temporary for result.
2663 GPRTemporary& result = storage;
2664 m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2665 speculationCheck(JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
2667 jsValueResult(result.gpr(), m_compileIndex);
2672 PredictedType basePrediction = at(node.child2()).prediction();
2673 if (!(basePrediction & PredictInt32) && basePrediction) {
2674 JSValueOperand arg1(this, node.child1());
2675 JSValueOperand arg2(this, node.child2());
2676 JSValueOperand arg3(this, node.child3());
2677 GPRReg arg1GPR = arg1.gpr();
2678 GPRReg arg2GPR = arg2.gpr();
2679 GPRReg arg3GPR = arg3.gpr();
2682 callOperation(m_jit.strictModeFor(node.codeOrigin) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2684 noResult(m_compileIndex);
2688 SpeculateCellOperand base(this, node.child1());
2689 SpeculateStrictInt32Operand property(this, node.child2());
2690 if (at(node.child1()).shouldSpeculateByteArray()) {
2691 compilePutByValForByteArray(base.gpr(), property.gpr(), node);
2695 JSValueOperand value(this, node.child3());
2696 GPRTemporary scratch(this);
2698 // Map base, property & value into registers, allocate a scratch register.
2699 GPRReg baseReg = base.gpr();
2700 GPRReg propertyReg = property.gpr();
2701 GPRReg valueReg = value.gpr();
2702 GPRReg scratchReg = scratch.gpr();
2707 writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
2709 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
2710 // If we have predicted the base to be type array, we can skip the check.
2711 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2712 speculationCheck(JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
2718 MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
2720 // Code to handle put beyond array bounds.
2721 silentSpillAllRegisters(scratchReg);
2722 callOperation(operationPutByValBeyondArrayBounds, baseReg, propertyReg, valueReg);
2723 silentFillAllRegisters(scratchReg);
2724 JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
2726 withinArrayBounds.link(&m_jit);
2728 // Get the array storage.
2729 GPRReg storageReg = scratchReg;
2730 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2732 // Check if we're writing to a hole; if so increment m_numValuesInVector.
2733 MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2734 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2736 // If we're writing to a hole we might be growing the array;
2737 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2738 m_jit.add32(TrustedImm32(1), propertyReg);
2739 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2740 m_jit.sub32(TrustedImm32(1), propertyReg);
2742 lengthDoesNotNeedUpdate.link(&m_jit);
2743 notHoleValue.link(&m_jit);
2745 // Store the value to the array.
2746 m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2748 wasBeyondArrayBounds.link(&m_jit);
2750 noResult(m_compileIndex, UseChildrenCalledExplicitly);
2754 case PutByValAlias: {
2755 PredictedType basePrediction = at(node.child2()).prediction();
2756 ASSERT_UNUSED(basePrediction, (basePrediction & PredictInt32) || !basePrediction);
2758 SpeculateCellOperand base(this, node.child1());
2759 SpeculateStrictInt32Operand property(this, node.child2());
2760 if (at(node.child1()).shouldSpeculateByteArray()) {
2761 compilePutByValForByteArray(base.gpr(), property.gpr(), node);
2765 JSValueOperand value(this, node.child3());
2766 GPRTemporary scratch(this);
2768 GPRReg baseReg = base.gpr();
2769 GPRReg scratchReg = scratch.gpr();
2771 writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
2773 // Get the array storage.
2774 GPRReg storageReg = scratchReg;
2775 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2777 // Store the value to the array.
2778 GPRReg propertyReg = property.gpr();
2779 GPRReg valueReg = value.gpr();
2780 m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2782 noResult(m_compileIndex);
2787 SpeculateCellOperand base(this, node.child1());
2788 JSValueOperand value(this, node.child2());
2789 GPRTemporary storage(this);
2790 GPRTemporary storageLength(this);
2792 GPRReg baseGPR = base.gpr();
2793 GPRReg valueGPR = value.gpr();
2794 GPRReg storageGPR = storage.gpr();
2795 GPRReg storageLengthGPR = storageLength.gpr();
2797 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
2799 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2800 speculationCheck(JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
2802 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
2803 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
2805 // Refuse to handle bizarre lengths.
2806 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
2808 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
2810 m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2812 m_jit.add32(Imm32(1), storageLengthGPR);
2813 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2814 m_jit.add32(Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2815 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
2817 MacroAssembler::Jump done = m_jit.jump();
2819 slowPath.link(&m_jit);
2821 silentSpillAllRegisters(storageLengthGPR);
2822 callOperation(operationArrayPush, storageLengthGPR, valueGPR, baseGPR);
2823 silentFillAllRegisters(storageLengthGPR);
2827 jsValueResult(storageLengthGPR, m_compileIndex);
2832 SpeculateCellOperand base(this, node.child1());
2833 GPRTemporary value(this);
2834 GPRTemporary storage(this);
2835 GPRTemporary storageLength(this);
2837 GPRReg baseGPR = base.gpr();
2838 GPRReg valueGPR = value.gpr();
2839 GPRReg storageGPR = storage.gpr();
2840 GPRReg storageLengthGPR = storageLength.gpr();
2842 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2843 speculationCheck(JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
2845 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
2846 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
2848 MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
2850 m_jit.sub32(Imm32(1), storageLengthGPR);
2852 MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
2854 m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
2856 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2858 MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
2860 m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2861 m_jit.sub32(MacroAssembler::Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2863 MacroAssembler::JumpList done;
2865 done.append(m_jit.jump());
2867 holeCase.link(&m_jit);
2868 emptyArrayCase.link(&m_jit);
2869 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR);
2870 done.append(m_jit.jump());
2872 slowCase.link(&m_jit);
2874 silentSpillAllRegisters(valueGPR);
2875 callOperation(operationArrayPop, valueGPR, baseGPR);
2876 silentFillAllRegisters(valueGPR);
2880 jsValueResult(valueGPR, m_compileIndex);
2885 BlockIndex taken = node.takenBlockIndex();
2886 if (taken != (m_block + 1))
2887 addBranch(m_jit.jump(), taken);
2888 noResult(m_compileIndex);
2893 if (isStrictInt32(node.child1()) || at(node.child1()).shouldSpeculateInteger()) {
2894 SpeculateIntegerOperand op(this, node.child1());
2896 BlockIndex taken = node.takenBlockIndex();
2897 BlockIndex notTaken = node.notTakenBlockIndex();
2899 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2901 if (taken == (m_block + 1)) {
2902 condition = MacroAssembler::Zero;
2903 BlockIndex tmp = taken;
2908 addBranch(m_jit.branchTest32(condition, op.gpr()), taken);
2909 if (notTaken != (m_block + 1))
2910 addBranch(m_jit.jump(), notTaken);
2912 noResult(m_compileIndex);
2919 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
2920 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2921 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2923 #if DFG_ENABLE(SUCCESS_STATS)
2924 static SamplingCounter counter("SpeculativeJIT");
2925 m_jit.emitCount(counter);
2928 // Return the result in returnValueGPR.
2929 JSValueOperand op1(this, node.child1());
2930 m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
2932 // Grab the return address.
2933 m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
2934 // Restore our caller's "r".
2935 m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
2937 m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
2940 noResult(m_compileIndex);
2945 case ThrowReferenceError: {
2946 // We expect that throw statements are rare and are intended to exit the code block
2947 // anyway, so we just OSR back to the old JIT for now.
2948 terminateSpeculativeExecution(JSValueRegs(), NoNode);
2953 if (at(node.child1()).shouldSpeculateInteger()) {
2954 // It's really profitable to speculate integer, since it's really cheap,
2955 // it means we don't have to do any real work, and we emit a lot less code.
2957 SpeculateIntegerOperand op1(this, node.child1());
2958 GPRTemporary result(this, op1);
2960 m_jit.move(op1.gpr(), result.gpr());
2961 if (op1.format() == DataFormatInteger)
2962 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, result.gpr());
2964 jsValueResult(result.gpr(), m_compileIndex);
2968 // FIXME: Add string speculation here.
2970 bool wasPrimitive = isKnownNumeric(node.child1()) || isKnownBoolean(node.child1());
2972 JSValueOperand op1(this, node.child1());
2973 GPRTemporary result(this, op1);
2975 GPRReg op1GPR = op1.gpr();
2976 GPRReg resultGPR = result.gpr();
2981 m_jit.move(op1GPR, resultGPR);
2983 MacroAssembler::JumpList alreadyPrimitive;
2985 alreadyPrimitive.append(m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister));
2986 alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
2988 silentSpillAllRegisters(resultGPR);
2989 callOperation(operationToPrimitive, resultGPR, op1GPR);
2990 silentFillAllRegisters(resultGPR);
2992 MacroAssembler::Jump done = m_jit.jump();
2994 alreadyPrimitive.link(&m_jit);
2995 m_jit.move(op1GPR, resultGPR);
3000 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3006 // We really don't want to grow the register file just to do a StrCat or NewArray.
3007 // Say we have 50 functions on the stack that all have a StrCat in them that has
3008 // upwards of 10 operands. In the DFG this would mean that each one gets
3009 // some random virtual register, and then to do the StrCat we'd need a second
3010 // span of 10 operands just to have somewhere to copy the 10 operands to, where
3011 // they'd be contiguous and we could easily tell the C code how to find them.
3012 // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
3013 // way, those 50 functions will share the same scratchBuffer for offloading their
3014 // StrCat operands. It's about as good as we can do, unless we start doing
3015 // virtual register coalescing to ensure that operands to StrCat get spilled
3016 // in exactly the place where StrCat wants them, or else have the StrCat
3017 // refer to those operands' SetLocal instructions to force them to spill in
3018 // the right place. Basically, any way you cut it, the current approach
3019 // probably has the best balance of performance and sensibility in the sense
3020 // that it does not increase the complexity of the DFG JIT just to make StrCat
3023 EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * node.numChildren()));
3025 for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3026 JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
3027 GPRReg opGPR = operand.gpr();
3030 m_jit.storePtr(opGPR, buffer + operandIdx);
3035 GPRResult result(this);
3037 callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), buffer, node.numChildren());
3039 cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
3043 case NewArrayBuffer: {
3045 GPRResult result(this);
3047 callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
3049 cellResult(result.gpr(), m_compileIndex);
3055 GPRResult result(this);
3057 callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
3059 cellResult(result.gpr(), m_compileIndex);
3064 if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
3065 SpeculateCellOperand thisValue(this, node.child1());
3066 GPRTemporary result(this, thisValue);
3067 m_jit.move(thisValue.gpr(), result.gpr());
3068 cellResult(result.gpr(), m_compileIndex);
3072 if (isOtherPrediction(at(node.child1()).prediction())) {
3073 JSValueOperand thisValue(this, node.child1());
3074 GPRTemporary scratch(this, thisValue);
3075 GPRReg thisValueGPR = thisValue.gpr();
3076 GPRReg scratchGPR = scratch.gpr();
3078 if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
3079 m_jit.move(thisValueGPR, scratchGPR);
3080 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
3081 speculationCheck(JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
3084 m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), scratchGPR);
3085 cellResult(scratchGPR, m_compileIndex);
3089 if (isObjectPrediction(at(node.child1()).prediction())) {
3090 SpeculateCellOperand thisValue(this, node.child1());
3091 GPRTemporary result(this, thisValue);
3092 GPRReg thisValueGPR = thisValue.gpr();
3093 GPRReg resultGPR = result.gpr();
3095 if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
3096 speculationCheck(JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
3098 m_jit.move(thisValueGPR, resultGPR);
3100 cellResult(resultGPR, m_compileIndex);
3104 JSValueOperand thisValue(this, node.child1());
3105 GPRReg thisValueGPR = thisValue.gpr();
3109 GPRResult result(this);
3110 callOperation(operationConvertThis, result.gpr(), thisValueGPR);
3112 cellResult(result.gpr(), m_compileIndex);
3117 // Note that there is not so much profit to speculate here. The only things we
3118 // speculate on are (1) that it's a cell, since that eliminates cell checks
3119 // later if the proto is reused, and (2) if we have a FinalObject prediction
3120 // then we speculate because we want to get recompiled if it isn't (since
3121 // otherwise we'd start taking slow path a lot).
3123 SpeculateCellOperand proto(this, node.child1());
3124 GPRTemporary result(this);
3125 GPRTemporary scratch(this);
3127 GPRReg protoGPR = proto.gpr();
3128 GPRReg resultGPR = result.gpr();
3129 GPRReg scratchGPR = scratch.gpr();
3133 MacroAssembler::JumpList slowPath;
3135 // Need to verify that the prototype is an object. If we have reason to believe
3136 // that it's a FinalObject then we speculate on that directly. Otherwise we
3137 // do the slow (structure-based) check.
3138 if (at(node.child1()).shouldSpeculateFinalObject()) {
3139 if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
3140 speculationCheck(JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
3142 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
3143 slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
3146 // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
3147 // use to refer to that prototype). If the inheritorID is not set, go to slow path.
3148 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
3149 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
3151 emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
3153 MacroAssembler::Jump done = m_jit.jump();
3155 slowPath.link(&m_jit);
3157 silentSpillAllRegisters(resultGPR);
3158 if (node.codeOrigin.inlineCallFrame)
3159 callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
3161 callOperation(operationCreateThis, resultGPR, protoGPR);
3162 silentFillAllRegisters(resultGPR);
3166 cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3171 GPRTemporary result(this);
3172 GPRTemporary scratch(this);
3174 GPRReg resultGPR = result.gpr();
3175 GPRReg scratchGPR = scratch.gpr();
3177 MacroAssembler::JumpList slowPath;
3179 emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
3181 MacroAssembler::Jump done = m_jit.jump();
3183 slowPath.link(&m_jit);
3185 silentSpillAllRegisters(resultGPR);
3186 callOperation(operationNewObject, resultGPR);
3187 silentFillAllRegisters(resultGPR);
3191 cellResult(resultGPR, m_compileIndex);
3196 GPRTemporary result(this);
3197 m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
3198 cellResult(result.gpr(), m_compileIndex);
3202 case GetScopeChain: {
3203 GPRTemporary result(this);
3204 GPRReg resultGPR = result.gpr();
3206 m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
3207 bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
3208 int skip = node.scopeChainDepth();
3209 ASSERT(skip || !checkTopLevel);
3210 if (checkTopLevel && skip--) {
3211 JITCompiler::Jump activationNotCreated;
3213 activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
3214 m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
3215 activationNotCreated.link(&m_jit);
3218 m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
3220 m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
3222 cellResult(resultGPR, m_compileIndex);
3225 case GetScopedVar: {
3226 SpeculateCellOperand scopeChain(this, node.child1());
3227 GPRTemporary result(this);
3228 GPRReg resultGPR = result.gpr();
3229 m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR);
3230 m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
3231 jsValueResult(resultGPR, m_compileIndex);
3234 case PutScopedVar: {
3235 SpeculateCellOperand scopeChain(this, node.child1());
3236 GPRTemporary scratchRegister(this);
3237 GPRReg scratchGPR = scratchRegister.gpr();
3238 m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
3239 JSValueOperand value(this, node.child2());
3240 m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register)));
3241 writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
3242 noResult(m_compileIndex);
3246 if (!node.prediction()) {
3247 terminateSpeculativeExecution(JSValueRegs(), NoNode);
3251 if (isCellPrediction(at(node.child1()).prediction())) {
3252 SpeculateCellOperand base(this, node.child1());
3253 GPRTemporary result(this, base);
3255 GPRReg baseGPR = base.gpr();
3256 GPRReg resultGPR = result.gpr();
3259 if (resultGPR == baseGPR)
3260 scratchGPR = tryAllocate();
3262 scratchGPR = resultGPR;
3266 cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
3268 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3272 JSValueOperand base(this, node.child1());
3273 GPRTemporary result(this, base);
3275 GPRReg baseGPR = base.gpr();
3276 GPRReg resultGPR = result.gpr();
3279 if (resultGPR == baseGPR)
3280 scratchGPR = tryAllocate();
3282 scratchGPR = resultGPR;
3286 JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
3288 cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
3290 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3295 case GetArrayLength: {
3296 SpeculateCellOperand base(this, node.child1());
3297 GPRTemporary result(this);
3299 GPRReg baseGPR = base.gpr();
3300 GPRReg resultGPR = result.gpr();
3302 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
3303 speculationCheck(JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
3305 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
3306 m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
3308 speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
3310 integerResult(resultGPR, m_compileIndex);
3314 case GetStringLength: {
3315 SpeculateCellOperand base(this, node.child1());
3316 GPRTemporary result(this);
3318 GPRReg baseGPR = base.gpr();
3319 GPRReg resultGPR = result.gpr();
3321 if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
3322 speculationCheck(JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
3324 m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
3326 integerResult(resultGPR, m_compileIndex);
3330 case GetByteArrayLength: {
3331 SpeculateCellOperand base(this, node.child1());
3332 GPRTemporary result(this);
3334 GPRReg baseGPR = base.gpr();
3335 GPRReg resultGPR = result.gpr();
3337 if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
3338 speculationCheck(JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
3340 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR);
3341 m_jit.load32(MacroAssembler::Address(baseGPR, ByteArray::offsetOfSize()), resultGPR);
3343 integerResult(resultGPR, m_compileIndex);
3347 case CheckFunction: {
3348 SpeculateCellOperand function(this, node.child1());
3349 speculationCheck(JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node.function()));
3350 noResult(m_compileIndex);
3353 case CheckStructure: {
3354 if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
3355 noResult(m_compileIndex);
3359 SpeculateCellOperand base(this, node.child1());
3361 ASSERT(node.structureSet().size());
3363 if (node.structureSet().size() == 1)
3364 speculationCheck(JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0]));
3366 GPRTemporary structure(this);
3368 m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
3370 JITCompiler::JumpList done;
3372 for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
3373 done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i]));
3375 speculationCheck(JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()));
3380 noResult(m_compileIndex);
3384 case PutStructure: {
3385 SpeculateCellOperand base(this, node.child1());
3386 GPRReg baseGPR = base.gpr();
3388 m_jit.addWeakReferenceTransition(
3389 node.codeOrigin.codeOriginOwner(),
3390 node.structureTransitionData().previousStructure,
3391 node.structureTransitionData().newStructure);
3393 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3394 // Must always emit this write barrier as the structure transition itself requires it
3395 writeBarrier(baseGPR, node.structureTransitionData().newStructure, WriteBarrierForGenericAccess);
3398 m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
3400 noResult(m_compileIndex);
3404 case GetPropertyStorage: {
3405 SpeculateCellOperand base(this, node.child1());
3406 GPRTemporary result(this, base);
3408 GPRReg baseGPR = base.gpr();
3409 GPRReg resultGPR = result.gpr();
3411 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
3413 storageResult(resultGPR, m_compileIndex);
3418 StorageOperand storage(this, node.child1());
3419 GPRTemporary result(this, storage);
3421 GPRReg storageGPR = storage.gpr();
3422 GPRReg resultGPR = result.gpr();
3424 StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
3426 m_jit.loadPtr(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)), resultGPR);
3428 jsValueResult(resultGPR, m_compileIndex);
3433 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3434 SpeculateCellOperand base(this, node.child1());
3436 StorageOperand storage(this, node.child2());
3437 JSValueOperand value(this, node.child3());
3439 GPRReg storageGPR = storage.gpr();
3440 GPRReg valueGPR = value.gpr();
3442 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3443 writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess);
3446 StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
3448 m_jit.storePtr(valueGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)));
3450 noResult(m_compileIndex);
3455 SpeculateCellOperand base(this, node.child1());
3456 JSValueOperand value(this, node.child2());
3457 GPRTemporary scratch(this);
3459 GPRReg baseGPR = base.gpr();
3460 GPRReg valueGPR = value.gpr();
3461 GPRReg scratchGPR = scratch.gpr();
3466 cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
3468 noResult(m_compileIndex, UseChildrenCalledExplicitly);
3472 case PutByIdDirect: {
3473 SpeculateCellOperand base(this, node.child1());
3474 JSValueOperand value(this, node.child2());
3475 GPRTemporary scratch(this);
3477 GPRReg baseGPR = base.gpr();
3478 GPRReg valueGPR = value.gpr();
3479 GPRReg scratchGPR = scratch.gpr();
3484 cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
3486 noResult(m_compileIndex, UseChildrenCalledExplicitly);
3490 case GetGlobalVar: {
3491 GPRTemporary result(this);
3493 JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
3494 m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
3495 m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
3497 jsValueResult(result.gpr(), m_compileIndex);
3501 case PutGlobalVar: {
3502 JSValueOperand value(this, node.child1());
3503 GPRTemporary globalObject(this);
3504 GPRTemporary scratch(this);
3506 GPRReg globalObjectReg = globalObject.gpr();
3507 GPRReg scratchReg = scratch.gpr();
3509 m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
3511 writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
3513 m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
3514 m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
3516 noResult(m_compileIndex);
3520 case CheckHasInstance: {
3521 SpeculateCellOperand base(this, node.child1());
3522 GPRTemporary structure(this);
3524 // Speculate that base 'ImplementsDefaultHasInstance'.
3525 m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
3526 speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
3528 noResult(m_compileIndex);
3533 compileInstanceOf(node);
3539 ASSERT_NOT_REACHED();
3542 #if ENABLE(DEBUG_WITH_BREAKPOINT)
3545 ASSERT_NOT_REACHED();
3556 GPRResult result(this);
3557 callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
3558 jsValueResult(result.gpr(), m_compileIndex);
3564 GPRResult result(this);
3565 callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
3566 jsValueResult(result.gpr(), m_compileIndex);
3570 case ResolveBaseStrictPut: {
3572 GPRResult result(this);
3573 callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
3574 jsValueResult(result.gpr(), m_compileIndex);
3578 case ResolveGlobal: {
3579 GPRTemporary globalObject(this);
3580 GPRTemporary resolveInfo(this);
3581 GPRTemporary result(this);
3583 GPRReg globalObjectGPR = globalObject.gpr();
3584 GPRReg resolveInfoGPR = resolveInfo.gpr();
3585 GPRReg resultGPR = result.gpr();
3587 ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()];
3588 GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex));
3590 // Check Structure of global object
3591 m_jit.move(JITCompiler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectGPR);
3592 m_jit.move(JITCompiler::TrustedImmPtr(resolveInfoAddress), resolveInfoGPR);
3593 m_jit.loadPtr(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), resultGPR);
3594 JITCompiler::Jump structuresMatch = m_jit.branchPtr(JITCompiler::Equal, resultGPR, JITCompiler::Address(globalObjectGPR, JSCell::structureOffset()));
3596 silentSpillAllRegisters(resultGPR);
3597 callOperation(operationResolveGlobal, resultGPR, resolveInfoGPR, &m_jit.codeBlock()->identifier(data.identifierNumber));
3598 silentFillAllRegisters(resultGPR);
3600 JITCompiler::Jump wasSlow = m_jit.jump();
3603 structuresMatch.link(&m_jit);
3604 m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
3605 m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
3606 m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr), resultGPR);
3608 wasSlow.link(&m_jit);
3610 jsValueResult(resultGPR, m_compileIndex);
3614 case ForceOSRExit: {
3615 terminateSpeculativeExecution(JSValueRegs(), NoNode);
3621 noResult(m_compileIndex);
3625 ASSERT_NOT_REACHED();
3629 if (node.hasResult() && node.mustGenerate())
3630 use(m_compileIndex);
3635 } } // namespace JSC::DFG