Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 591393002: Made the detailed reason for deopts mandatory on ia32. Unified and improved things. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X64 7 #if V8_TARGET_ARCH_X64
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 // Check for (kMinInt / -1). 1285 // Check for (kMinInt / -1).
1286 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1286 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1287 __ cmpl(dividend, Immediate(kMinInt)); 1287 __ cmpl(dividend, Immediate(kMinInt));
1288 DeoptimizeIf(zero, instr, "overflow"); 1288 DeoptimizeIf(zero, instr, "overflow");
1289 } 1289 }
1290 // Deoptimize if remainder will not be 0. 1290 // Deoptimize if remainder will not be 0.
1291 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1291 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1292 divisor != 1 && divisor != -1) { 1292 divisor != 1 && divisor != -1) {
1293 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1293 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1294 __ testl(dividend, Immediate(mask)); 1294 __ testl(dividend, Immediate(mask));
1295 DeoptimizeIf(not_zero, instr, "remainder not zero"); 1295 DeoptimizeIf(not_zero, instr, "lost precision");
1296 } 1296 }
1297 __ Move(result, dividend); 1297 __ Move(result, dividend);
1298 int32_t shift = WhichPowerOf2Abs(divisor); 1298 int32_t shift = WhichPowerOf2Abs(divisor);
1299 if (shift > 0) { 1299 if (shift > 0) {
1300 // The arithmetic shift is always OK, the 'if' is an optimization only. 1300 // The arithmetic shift is always OK, the 'if' is an optimization only.
1301 if (shift > 1) __ sarl(result, Immediate(31)); 1301 if (shift > 1) __ sarl(result, Immediate(31));
1302 __ shrl(result, Immediate(32 - shift)); 1302 __ shrl(result, Immediate(32 - shift));
1303 __ addl(result, dividend); 1303 __ addl(result, dividend);
1304 __ sarl(result, Immediate(shift)); 1304 __ sarl(result, Immediate(shift));
1305 } 1305 }
(...skipping 18 matching lines...) Expand all
1324 DeoptimizeIf(zero, instr, "minus zero"); 1324 DeoptimizeIf(zero, instr, "minus zero");
1325 } 1325 }
1326 1326
1327 __ TruncatingDiv(dividend, Abs(divisor)); 1327 __ TruncatingDiv(dividend, Abs(divisor));
1328 if (divisor < 0) __ negl(rdx); 1328 if (divisor < 0) __ negl(rdx);
1329 1329
1330 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1330 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1331 __ movl(rax, rdx); 1331 __ movl(rax, rdx);
1332 __ imull(rax, rax, Immediate(divisor)); 1332 __ imull(rax, rax, Immediate(divisor));
1333 __ subl(rax, dividend); 1333 __ subl(rax, dividend);
1334 DeoptimizeIf(not_equal, instr, "remainder not zero"); 1334 DeoptimizeIf(not_equal, instr, "lost precision");
1335 } 1335 }
1336 } 1336 }
1337 1337
1338 1338
1339 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1339 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1340 void LCodeGen::DoDivI(LDivI* instr) { 1340 void LCodeGen::DoDivI(LDivI* instr) {
1341 HBinaryOperation* hdiv = instr->hydrogen(); 1341 HBinaryOperation* hdiv = instr->hydrogen();
1342 Register dividend = ToRegister(instr->dividend()); 1342 Register dividend = ToRegister(instr->dividend());
1343 Register divisor = ToRegister(instr->divisor()); 1343 Register divisor = ToRegister(instr->divisor());
1344 Register remainder = ToRegister(instr->temp()); 1344 Register remainder = ToRegister(instr->temp());
(...skipping 29 matching lines...) Expand all
1374 __ bind(&dividend_not_min_int); 1374 __ bind(&dividend_not_min_int);
1375 } 1375 }
1376 1376
1377 // Sign extend to rdx (= remainder). 1377 // Sign extend to rdx (= remainder).
1378 __ cdq(); 1378 __ cdq();
1379 __ idivl(divisor); 1379 __ idivl(divisor);
1380 1380
1381 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1381 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1382 // Deoptimize if remainder is not 0. 1382 // Deoptimize if remainder is not 0.
1383 __ testl(remainder, remainder); 1383 __ testl(remainder, remainder);
1384 DeoptimizeIf(not_zero, instr, "remainder not zero"); 1384 DeoptimizeIf(not_zero, instr, "lost precision");
1385 } 1385 }
1386 } 1386 }
1387 1387
1388 1388
1389 void LCodeGen::DoMulI(LMulI* instr) { 1389 void LCodeGen::DoMulI(LMulI* instr) {
1390 Register left = ToRegister(instr->left()); 1390 Register left = ToRegister(instr->left());
1391 LOperand* right = instr->right(); 1391 LOperand* right = instr->right();
1392 1392
1393 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1393 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1394 if (instr->hydrogen_value()->representation().IsSmi()) { 1394 if (instr->hydrogen_value()->representation().IsSmi()) {
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 case Token::ROR: 1602 case Token::ROR:
1603 __ rorl_cl(ToRegister(left)); 1603 __ rorl_cl(ToRegister(left));
1604 break; 1604 break;
1605 case Token::SAR: 1605 case Token::SAR:
1606 __ sarl_cl(ToRegister(left)); 1606 __ sarl_cl(ToRegister(left));
1607 break; 1607 break;
1608 case Token::SHR: 1608 case Token::SHR:
1609 __ shrl_cl(ToRegister(left)); 1609 __ shrl_cl(ToRegister(left));
1610 if (instr->can_deopt()) { 1610 if (instr->can_deopt()) {
1611 __ testl(ToRegister(left), ToRegister(left)); 1611 __ testl(ToRegister(left), ToRegister(left));
1612 DeoptimizeIf(negative, instr, "value to shift was negative"); 1612 DeoptimizeIf(negative, instr, "negative value");
1613 } 1613 }
1614 break; 1614 break;
1615 case Token::SHL: 1615 case Token::SHL:
1616 __ shll_cl(ToRegister(left)); 1616 __ shll_cl(ToRegister(left));
1617 break; 1617 break;
1618 default: 1618 default:
1619 UNREACHABLE(); 1619 UNREACHABLE();
1620 break; 1620 break;
1621 } 1621 }
1622 } else { 1622 } else {
1623 int32_t value = ToInteger32(LConstantOperand::cast(right)); 1623 int32_t value = ToInteger32(LConstantOperand::cast(right));
1624 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1624 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1625 switch (instr->op()) { 1625 switch (instr->op()) {
1626 case Token::ROR: 1626 case Token::ROR:
1627 if (shift_count != 0) { 1627 if (shift_count != 0) {
1628 __ rorl(ToRegister(left), Immediate(shift_count)); 1628 __ rorl(ToRegister(left), Immediate(shift_count));
1629 } 1629 }
1630 break; 1630 break;
1631 case Token::SAR: 1631 case Token::SAR:
1632 if (shift_count != 0) { 1632 if (shift_count != 0) {
1633 __ sarl(ToRegister(left), Immediate(shift_count)); 1633 __ sarl(ToRegister(left), Immediate(shift_count));
1634 } 1634 }
1635 break; 1635 break;
1636 case Token::SHR: 1636 case Token::SHR:
1637 if (shift_count != 0) { 1637 if (shift_count != 0) {
1638 __ shrl(ToRegister(left), Immediate(shift_count)); 1638 __ shrl(ToRegister(left), Immediate(shift_count));
1639 } else if (instr->can_deopt()) { 1639 } else if (instr->can_deopt()) {
1640 __ testl(ToRegister(left), ToRegister(left)); 1640 __ testl(ToRegister(left), ToRegister(left));
1641 DeoptimizeIf(negative, instr, "value to shift was negative"); 1641 DeoptimizeIf(negative, instr, "negative value");
1642 } 1642 }
1643 break; 1643 break;
1644 case Token::SHL: 1644 case Token::SHL:
1645 if (shift_count != 0) { 1645 if (shift_count != 0) {
1646 if (instr->hydrogen_value()->representation().IsSmi()) { 1646 if (instr->hydrogen_value()->representation().IsSmi()) {
1647 if (SmiValuesAre32Bits()) { 1647 if (SmiValuesAre32Bits()) {
1648 __ shlp(ToRegister(left), Immediate(shift_count)); 1648 __ shlp(ToRegister(left), Immediate(shift_count));
1649 } else { 1649 } else {
1650 DCHECK(SmiValuesAre31Bits()); 1650 DCHECK(SmiValuesAre31Bits());
1651 if (instr->can_deopt()) { 1651 if (instr->can_deopt()) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 1754
1755 void LCodeGen::DoDateField(LDateField* instr) { 1755 void LCodeGen::DoDateField(LDateField* instr) {
1756 Register object = ToRegister(instr->date()); 1756 Register object = ToRegister(instr->date());
1757 Register result = ToRegister(instr->result()); 1757 Register result = ToRegister(instr->result());
1758 Smi* index = instr->index(); 1758 Smi* index = instr->index();
1759 Label runtime, done, not_date_object; 1759 Label runtime, done, not_date_object;
1760 DCHECK(object.is(result)); 1760 DCHECK(object.is(result));
1761 DCHECK(object.is(rax)); 1761 DCHECK(object.is(rax));
1762 1762
1763 Condition cc = masm()->CheckSmi(object); 1763 Condition cc = masm()->CheckSmi(object);
1764 DeoptimizeIf(cc, instr, "not an object"); 1764 DeoptimizeIf(cc, instr, "Smi");
1765 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); 1765 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
1766 DeoptimizeIf(not_equal, instr, "not a date object"); 1766 DeoptimizeIf(not_equal, instr, "not a date object");
1767 1767
1768 if (index->value() == 0) { 1768 if (index->value() == 0) {
1769 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); 1769 __ movp(result, FieldOperand(object, JSDate::kValueOffset));
1770 } else { 1770 } else {
1771 if (index->value() < JSDate::kFirstUncachedField) { 1771 if (index->value() < JSDate::kFirstUncachedField) {
1772 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1772 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1773 Operand stamp_operand = __ ExternalOperand(stamp); 1773 Operand stamp_operand = __ ExternalOperand(stamp);
1774 __ movp(kScratchRegister, stamp_operand); 1774 __ movp(kScratchRegister, stamp_operand);
(...skipping 1606 matching lines...) Expand 10 before | Expand all | Expand 10 after
3381 } 3381 }
3382 3382
3383 // Normal function. Replace undefined or null with global receiver. 3383 // Normal function. Replace undefined or null with global receiver.
3384 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 3384 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
3385 __ j(equal, &global_object, Label::kNear); 3385 __ j(equal, &global_object, Label::kNear);
3386 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 3386 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
3387 __ j(equal, &global_object, Label::kNear); 3387 __ j(equal, &global_object, Label::kNear);
3388 3388
3389 // The receiver should be a JS object. 3389 // The receiver should be a JS object.
3390 Condition is_smi = __ CheckSmi(receiver); 3390 Condition is_smi = __ CheckSmi(receiver);
3391 DeoptimizeIf(is_smi, instr, "not an object"); 3391 DeoptimizeIf(is_smi, instr, "Smi");
3392 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 3392 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
3393 DeoptimizeIf(below, instr, "not a spec object"); 3393 DeoptimizeIf(below, instr, "not a JavaScript object");
3394 3394
3395 __ jmp(&receiver_ok, Label::kNear); 3395 __ jmp(&receiver_ok, Label::kNear);
3396 __ bind(&global_object); 3396 __ bind(&global_object);
3397 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3397 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
3398 __ movp(receiver, 3398 __ movp(receiver,
3399 Operand(receiver, 3399 Operand(receiver,
3400 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3400 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3401 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset)); 3401 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset));
3402 3402
3403 __ bind(&receiver_ok); 3403 __ bind(&receiver_ok);
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
3728 } 3728 }
3729 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3729 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3730 __ cvttsd2si(output_reg, xmm_scratch); 3730 __ cvttsd2si(output_reg, xmm_scratch);
3731 __ cmpl(output_reg, Immediate(0x1)); 3731 __ cmpl(output_reg, Immediate(0x1));
3732 DeoptimizeIf(overflow, instr, "overflow"); 3732 DeoptimizeIf(overflow, instr, "overflow");
3733 } else { 3733 } else {
3734 Label negative_sign, done; 3734 Label negative_sign, done;
3735 // Deoptimize on unordered. 3735 // Deoptimize on unordered.
3736 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3736 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3737 __ ucomisd(input_reg, xmm_scratch); 3737 __ ucomisd(input_reg, xmm_scratch);
3738 DeoptimizeIf(parity_even, instr, "unordered"); 3738 DeoptimizeIf(parity_even, instr, "NaN");
3739 __ j(below, &negative_sign, Label::kNear); 3739 __ j(below, &negative_sign, Label::kNear);
3740 3740
3741 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3741 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3742 // Check for negative zero. 3742 // Check for negative zero.
3743 Label positive_sign; 3743 Label positive_sign;
3744 __ j(above, &positive_sign, Label::kNear); 3744 __ j(above, &positive_sign, Label::kNear);
3745 __ movmskpd(output_reg, input_reg); 3745 __ movmskpd(output_reg, input_reg);
3746 __ testq(output_reg, Immediate(1)); 3746 __ testq(output_reg, Immediate(1));
3747 DeoptimizeIf(not_zero, instr, "minus zero"); 3747 DeoptimizeIf(not_zero, instr, "minus zero");
3748 __ Set(output_reg, 0); 3748 __ Set(output_reg, 0);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3785 __ movq(kScratchRegister, one_half); 3785 __ movq(kScratchRegister, one_half);
3786 __ movq(xmm_scratch, kScratchRegister); 3786 __ movq(xmm_scratch, kScratchRegister);
3787 __ ucomisd(xmm_scratch, input_reg); 3787 __ ucomisd(xmm_scratch, input_reg);
3788 __ j(above, &below_one_half, Label::kNear); 3788 __ j(above, &below_one_half, Label::kNear);
3789 3789
3790 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3790 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3791 __ addsd(xmm_scratch, input_reg); 3791 __ addsd(xmm_scratch, input_reg);
3792 __ cvttsd2si(output_reg, xmm_scratch); 3792 __ cvttsd2si(output_reg, xmm_scratch);
3793 // Overflow is signalled with minint. 3793 // Overflow is signalled with minint.
3794 __ cmpl(output_reg, Immediate(0x1)); 3794 __ cmpl(output_reg, Immediate(0x1));
3795 DeoptimizeIf(overflow, instr, "conversion overflow"); 3795 DeoptimizeIf(overflow, instr, "overflow");
3796 __ jmp(&done, dist); 3796 __ jmp(&done, dist);
3797 3797
3798 __ bind(&below_one_half); 3798 __ bind(&below_one_half);
3799 __ movq(kScratchRegister, minus_one_half); 3799 __ movq(kScratchRegister, minus_one_half);
3800 __ movq(xmm_scratch, kScratchRegister); 3800 __ movq(xmm_scratch, kScratchRegister);
3801 __ ucomisd(xmm_scratch, input_reg); 3801 __ ucomisd(xmm_scratch, input_reg);
3802 __ j(below_equal, &round_to_zero, Label::kNear); 3802 __ j(below_equal, &round_to_zero, Label::kNear);
3803 3803
3804 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3804 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3805 // compare and compensate. 3805 // compare and compensate.
3806 __ movq(input_temp, input_reg); // Do not alter input_reg. 3806 __ movq(input_temp, input_reg); // Do not alter input_reg.
3807 __ subsd(input_temp, xmm_scratch); 3807 __ subsd(input_temp, xmm_scratch);
3808 __ cvttsd2si(output_reg, input_temp); 3808 __ cvttsd2si(output_reg, input_temp);
3809 // Catch minint due to overflow, and to prevent overflow when compensating. 3809 // Catch minint due to overflow, and to prevent overflow when compensating.
3810 __ cmpl(output_reg, Immediate(0x1)); 3810 __ cmpl(output_reg, Immediate(0x1));
3811 DeoptimizeIf(overflow, instr, "conversion overflow"); 3811 DeoptimizeIf(overflow, instr, "overflow");
3812 3812
3813 __ Cvtlsi2sd(xmm_scratch, output_reg); 3813 __ Cvtlsi2sd(xmm_scratch, output_reg);
3814 __ ucomisd(xmm_scratch, input_temp); 3814 __ ucomisd(xmm_scratch, input_temp);
3815 __ j(equal, &done, dist); 3815 __ j(equal, &done, dist);
3816 __ subl(output_reg, Immediate(1)); 3816 __ subl(output_reg, Immediate(1));
3817 // No overflow because we already ruled out minint. 3817 // No overflow because we already ruled out minint.
3818 __ jmp(&done, dist); 3818 __ jmp(&done, dist);
3819 3819
3820 __ bind(&round_to_zero); 3820 __ bind(&round_to_zero);
3821 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3821 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
(...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after
4834 } 4834 }
4835 4835
4836 4836
4837 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4837 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4838 HChange* hchange = instr->hydrogen(); 4838 HChange* hchange = instr->hydrogen();
4839 Register input = ToRegister(instr->value()); 4839 Register input = ToRegister(instr->value());
4840 Register output = ToRegister(instr->result()); 4840 Register output = ToRegister(instr->result());
4841 if (hchange->CheckFlag(HValue::kCanOverflow) && 4841 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4842 hchange->value()->CheckFlag(HValue::kUint32)) { 4842 hchange->value()->CheckFlag(HValue::kUint32)) {
4843 Condition is_smi = __ CheckUInteger32ValidSmiValue(input); 4843 Condition is_smi = __ CheckUInteger32ValidSmiValue(input);
4844 DeoptimizeIf(NegateCondition(is_smi), instr, "not a smi"); 4844 DeoptimizeIf(NegateCondition(is_smi), instr, "overflow");
4845 } 4845 }
4846 __ Integer32ToSmi(output, input); 4846 __ Integer32ToSmi(output, input);
4847 if (hchange->CheckFlag(HValue::kCanOverflow) && 4847 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4848 !hchange->value()->CheckFlag(HValue::kUint32)) { 4848 !hchange->value()->CheckFlag(HValue::kUint32)) {
4849 DeoptimizeIf(overflow, instr, "overflow"); 4849 DeoptimizeIf(overflow, instr, "overflow");
4850 } 4850 }
4851 } 4851 }
4852 4852
4853 4853
4854 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4854 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4855 DCHECK(instr->value()->Equals(instr->result())); 4855 DCHECK(instr->value()->Equals(instr->result()));
4856 Register input = ToRegister(instr->value()); 4856 Register input = ToRegister(instr->value());
4857 if (instr->needs_check()) { 4857 if (instr->needs_check()) {
4858 Condition is_smi = __ CheckSmi(input); 4858 Condition is_smi = __ CheckSmi(input);
4859 DeoptimizeIf(NegateCondition(is_smi), instr, "not a smi"); 4859 DeoptimizeIf(NegateCondition(is_smi), instr, "not a Smi");
4860 } else { 4860 } else {
4861 __ AssertSmi(input); 4861 __ AssertSmi(input);
4862 } 4862 }
4863 __ SmiToInteger32(input, input); 4863 __ SmiToInteger32(input, input);
4864 } 4864 }
4865 4865
4866 4866
4867 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4867 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4868 XMMRegister result_reg, NumberUntagDMode mode) { 4868 XMMRegister result_reg, NumberUntagDMode mode) {
4869 bool can_convert_undefined_to_nan = 4869 bool can_convert_undefined_to_nan =
(...skipping 29 matching lines...) Expand all
4899 __ testq(kScratchRegister, Immediate(1)); 4899 __ testq(kScratchRegister, Immediate(1));
4900 DeoptimizeIf(not_zero, instr, "minus zero"); 4900 DeoptimizeIf(not_zero, instr, "minus zero");
4901 } 4901 }
4902 __ jmp(&done, Label::kNear); 4902 __ jmp(&done, Label::kNear);
4903 4903
4904 if (can_convert_undefined_to_nan) { 4904 if (can_convert_undefined_to_nan) {
4905 __ bind(&convert); 4905 __ bind(&convert);
4906 4906
4907 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. 4907 // Convert undefined (and hole) to NaN. Compute NaN as 0/0.
4908 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 4908 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
4909 DeoptimizeIf(not_equal, instr, "neither a heap number nor undefined"); 4909 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
4910 4910
4911 __ xorps(result_reg, result_reg); 4911 __ xorps(result_reg, result_reg);
4912 __ divsd(result_reg, result_reg); 4912 __ divsd(result_reg, result_reg);
4913 __ jmp(&done, Label::kNear); 4913 __ jmp(&done, Label::kNear);
4914 } 4914 }
4915 } else { 4915 } else {
4916 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4916 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4917 } 4917 }
4918 4918
4919 // Smi to XMM conversion 4919 // Smi to XMM conversion
(...skipping 26 matching lines...) Expand all
4946 __ jmp(done); 4946 __ jmp(done);
4947 4947
4948 __ bind(&check_bools); 4948 __ bind(&check_bools);
4949 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); 4949 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex);
4950 __ j(not_equal, &check_false, Label::kNear); 4950 __ j(not_equal, &check_false, Label::kNear);
4951 __ Set(input_reg, 1); 4951 __ Set(input_reg, 1);
4952 __ jmp(done); 4952 __ jmp(done);
4953 4953
4954 __ bind(&check_false); 4954 __ bind(&check_false);
4955 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); 4955 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
4956 DeoptimizeIf(not_equal, instr, "cannot truncate"); 4956 DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
4957 __ Set(input_reg, 0); 4957 __ Set(input_reg, 0);
4958 } else { 4958 } else {
4959 XMMRegister scratch = ToDoubleRegister(instr->temp()); 4959 XMMRegister scratch = ToDoubleRegister(instr->temp());
4960 DCHECK(!scratch.is(xmm0)); 4960 DCHECK(!scratch.is(xmm0));
4961 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 4961 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
4962 Heap::kHeapNumberMapRootIndex); 4962 Heap::kHeapNumberMapRootIndex);
4963 DeoptimizeIf(not_equal, instr, "not a heap number"); 4963 DeoptimizeIf(not_equal, instr, "not a heap number");
4964 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4964 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4965 __ cvttsd2si(input_reg, xmm0); 4965 __ cvttsd2si(input_reg, xmm0);
4966 __ Cvtlsi2sd(scratch, input_reg); 4966 __ Cvtlsi2sd(scratch, input_reg);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
5029 DCHECK(input->IsDoubleRegister()); 5029 DCHECK(input->IsDoubleRegister());
5030 LOperand* result = instr->result(); 5030 LOperand* result = instr->result();
5031 DCHECK(result->IsRegister()); 5031 DCHECK(result->IsRegister());
5032 5032
5033 XMMRegister input_reg = ToDoubleRegister(input); 5033 XMMRegister input_reg = ToDoubleRegister(input);
5034 Register result_reg = ToRegister(result); 5034 Register result_reg = ToRegister(result);
5035 5035
5036 if (instr->truncating()) { 5036 if (instr->truncating()) {
5037 __ TruncateDoubleToI(result_reg, input_reg); 5037 __ TruncateDoubleToI(result_reg, input_reg);
5038 } else { 5038 } else {
5039 Label bailout, done; 5039 Label lost_precision, is_nan, minus_zero, done;
5040 XMMRegister xmm_scratch = double_scratch0(); 5040 XMMRegister xmm_scratch = double_scratch0();
5041 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5041 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5042 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 5042 instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
5043 5043 &is_nan, &minus_zero,
5044 DeoptEveryNTimes() ? Label::kFar : Label::kNear);
5044 __ jmp(&done, Label::kNear); 5045 __ jmp(&done, Label::kNear);
5045 __ bind(&bailout); 5046 __ bind(&lost_precision);
5046 DeoptimizeIf(no_condition, instr, "conversion failed"); 5047 DeoptimizeIf(no_condition, instr, "lost precision");
5048 __ bind(&is_nan);
5049 DeoptimizeIf(no_condition, instr, "NaN");
5050 __ bind(&minus_zero);
5051 DeoptimizeIf(no_condition, instr, "minus zero");
5047 __ bind(&done); 5052 __ bind(&done);
5048 } 5053 }
5049 } 5054 }
5050 5055
5051 5056
5052 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5057 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5053 LOperand* input = instr->value(); 5058 LOperand* input = instr->value();
5054 DCHECK(input->IsDoubleRegister()); 5059 DCHECK(input->IsDoubleRegister());
5055 LOperand* result = instr->result(); 5060 LOperand* result = instr->result();
5056 DCHECK(result->IsRegister()); 5061 DCHECK(result->IsRegister());
5057 5062
5058 XMMRegister input_reg = ToDoubleRegister(input); 5063 XMMRegister input_reg = ToDoubleRegister(input);
5059 Register result_reg = ToRegister(result); 5064 Register result_reg = ToRegister(result);
5060 5065
5061 Label bailout, done; 5066 Label lost_precision, is_nan, minus_zero, done;
5062 XMMRegister xmm_scratch = double_scratch0(); 5067 XMMRegister xmm_scratch = double_scratch0();
5063 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5068 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5064 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 5069 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
5065 5070 &minus_zero, DeoptEveryNTimes() ? Label::kFar : Label::kNear);
5066 __ jmp(&done, Label::kNear); 5071 __ jmp(&done, Label::kNear);
5067 __ bind(&bailout); 5072 __ bind(&lost_precision);
5068 DeoptimizeIf(no_condition, instr, "conversion failed"); 5073 DeoptimizeIf(no_condition, instr, "lost precision");
5074 __ bind(&is_nan);
5075 DeoptimizeIf(no_condition, instr, "NaN");
5076 __ bind(&minus_zero);
5077 DeoptimizeIf(no_condition, instr, "minus zero");
5069 __ bind(&done); 5078 __ bind(&done);
5070
5071 __ Integer32ToSmi(result_reg, result_reg); 5079 __ Integer32ToSmi(result_reg, result_reg);
5072 DeoptimizeIf(overflow, instr, "overflow"); 5080 DeoptimizeIf(overflow, instr, "overflow");
5073 } 5081 }
5074 5082
5075 5083
5076 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5084 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5077 LOperand* input = instr->value(); 5085 LOperand* input = instr->value();
5078 Condition cc = masm()->CheckSmi(ToRegister(input)); 5086 Condition cc = masm()->CheckSmi(ToRegister(input));
5079 DeoptimizeIf(NegateCondition(cc), instr, "not a Smi"); 5087 DeoptimizeIf(NegateCondition(cc), instr, "not a Smi");
5080 } 5088 }
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
5238 __ JumpIfSmi(input_reg, &is_smi, dist); 5246 __ JumpIfSmi(input_reg, &is_smi, dist);
5239 5247
5240 // Check for heap number 5248 // Check for heap number
5241 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5249 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5242 factory()->heap_number_map()); 5250 factory()->heap_number_map());
5243 __ j(equal, &heap_number, Label::kNear); 5251 __ j(equal, &heap_number, Label::kNear);
5244 5252
5245 // Check for undefined. Undefined is converted to zero for clamping 5253 // Check for undefined. Undefined is converted to zero for clamping
5246 // conversions. 5254 // conversions.
5247 __ Cmp(input_reg, factory()->undefined_value()); 5255 __ Cmp(input_reg, factory()->undefined_value());
5248 DeoptimizeIf(not_equal, instr, "neither a heap number nor undefined"); 5256 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5249 __ xorl(input_reg, input_reg); 5257 __ xorl(input_reg, input_reg);
5250 __ jmp(&done, Label::kNear); 5258 __ jmp(&done, Label::kNear);
5251 5259
5252 // Heap number 5260 // Heap number
5253 __ bind(&heap_number); 5261 __ bind(&heap_number);
5254 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5262 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5255 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5263 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5256 __ jmp(&done, Label::kNear); 5264 __ jmp(&done, Label::kNear);
5257 5265
5258 // smi 5266 // smi
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
5746 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 5754 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
5747 __ jmp(&use_cache, Label::kNear); 5755 __ jmp(&use_cache, Label::kNear);
5748 5756
5749 // Get the set of properties to enumerate. 5757 // Get the set of properties to enumerate.
5750 __ bind(&call_runtime); 5758 __ bind(&call_runtime);
5751 __ Push(rax); 5759 __ Push(rax);
5752 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5760 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5753 5761
5754 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 5762 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
5755 Heap::kMetaMapRootIndex); 5763 Heap::kMetaMapRootIndex);
5756 DeoptimizeIf(not_equal, instr, "not a meta map"); 5764 DeoptimizeIf(not_equal, instr, "wrong map");
5757 __ bind(&use_cache); 5765 __ bind(&use_cache);
5758 } 5766 }
5759 5767
5760 5768
5761 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5769 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5762 Register map = ToRegister(instr->map()); 5770 Register map = ToRegister(instr->map());
5763 Register result = ToRegister(instr->result()); 5771 Register result = ToRegister(instr->result());
5764 Label load_cache, done; 5772 Label load_cache, done;
5765 __ EnumLength(result, map); 5773 __ EnumLength(result, map);
5766 __ Cmp(result, Smi::FromInt(0)); 5774 __ Cmp(result, Smi::FromInt(0));
5767 __ j(not_equal, &load_cache, Label::kNear); 5775 __ j(not_equal, &load_cache, Label::kNear);
5768 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); 5776 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex);
5769 __ jmp(&done, Label::kNear); 5777 __ jmp(&done, Label::kNear);
5770 __ bind(&load_cache); 5778 __ bind(&load_cache);
5771 __ LoadInstanceDescriptors(map, result); 5779 __ LoadInstanceDescriptors(map, result);
5772 __ movp(result, 5780 __ movp(result,
5773 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5781 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5774 __ movp(result, 5782 __ movp(result,
5775 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5783 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5776 __ bind(&done); 5784 __ bind(&done);
5777 Condition cc = masm()->CheckSmi(result); 5785 Condition cc = masm()->CheckSmi(result);
5778 DeoptimizeIf(cc, instr, "Smi"); 5786 DeoptimizeIf(cc, instr, "no cache");
5779 } 5787 }
5780 5788
5781 5789
5782 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5790 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5783 Register object = ToRegister(instr->value()); 5791 Register object = ToRegister(instr->value());
5784 __ cmpp(ToRegister(instr->map()), 5792 __ cmpp(ToRegister(instr->map()),
5785 FieldOperand(object, HeapObject::kMapOffset)); 5793 FieldOperand(object, HeapObject::kMapOffset));
5786 DeoptimizeIf(not_equal, instr, "wrong map"); 5794 DeoptimizeIf(not_equal, instr, "wrong map");
5787 } 5795 }
5788 5796
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
5871 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5879 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5872 RecordSafepoint(Safepoint::kNoLazyDeopt); 5880 RecordSafepoint(Safepoint::kNoLazyDeopt);
5873 } 5881 }
5874 5882
5875 5883
5876 #undef __ 5884 #undef __
5877 5885
5878 } } // namespace v8::internal 5886 } } // namespace v8::internal
5879 5887
5880 #endif // V8_TARGET_ARCH_X64 5888 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698