OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 | 778 |
779 void LCodeGen::DoModI(LModI* instr) { | 779 void LCodeGen::DoModI(LModI* instr) { |
780 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 780 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
781 Register dividend = ToRegister(instr->InputAt(0)); | 781 Register dividend = ToRegister(instr->InputAt(0)); |
782 | 782 |
783 int32_t divisor = | 783 int32_t divisor = |
784 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 784 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
785 | 785 |
786 if (divisor < 0) divisor = -divisor; | 786 if (divisor < 0) divisor = -divisor; |
787 | 787 |
788 NearLabel positive_dividend, done; | 788 Label positive_dividend, done; |
789 __ testl(dividend, dividend); | 789 __ testl(dividend, dividend); |
790 __ j(not_sign, &positive_dividend); | 790 __ j(not_sign, &positive_dividend, Label::kNear); |
791 __ negl(dividend); | 791 __ negl(dividend); |
792 __ andl(dividend, Immediate(divisor - 1)); | 792 __ andl(dividend, Immediate(divisor - 1)); |
793 __ negl(dividend); | 793 __ negl(dividend); |
794 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 794 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
795 __ j(not_zero, &done); | 795 __ j(not_zero, &done, Label::kNear); |
796 DeoptimizeIf(no_condition, instr->environment()); | 796 DeoptimizeIf(no_condition, instr->environment()); |
797 } | 797 } |
798 __ bind(&positive_dividend); | 798 __ bind(&positive_dividend); |
799 __ andl(dividend, Immediate(divisor - 1)); | 799 __ andl(dividend, Immediate(divisor - 1)); |
800 __ bind(&done); | 800 __ bind(&done); |
801 } else { | 801 } else { |
802 NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 802 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
803 Register left_reg = ToRegister(instr->InputAt(0)); | 803 Register left_reg = ToRegister(instr->InputAt(0)); |
804 Register right_reg = ToRegister(instr->InputAt(1)); | 804 Register right_reg = ToRegister(instr->InputAt(1)); |
805 Register result_reg = ToRegister(instr->result()); | 805 Register result_reg = ToRegister(instr->result()); |
806 | 806 |
807 ASSERT(left_reg.is(rax)); | 807 ASSERT(left_reg.is(rax)); |
808 ASSERT(result_reg.is(rdx)); | 808 ASSERT(result_reg.is(rdx)); |
809 ASSERT(!right_reg.is(rax)); | 809 ASSERT(!right_reg.is(rax)); |
810 ASSERT(!right_reg.is(rdx)); | 810 ASSERT(!right_reg.is(rdx)); |
811 | 811 |
812 // Check for x % 0. | 812 // Check for x % 0. |
813 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 813 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
814 __ testl(right_reg, right_reg); | 814 __ testl(right_reg, right_reg); |
815 DeoptimizeIf(zero, instr->environment()); | 815 DeoptimizeIf(zero, instr->environment()); |
816 } | 816 } |
817 | 817 |
818 __ testl(left_reg, left_reg); | 818 __ testl(left_reg, left_reg); |
819 __ j(zero, &remainder_eq_dividend); | 819 __ j(zero, &remainder_eq_dividend, Label::kNear); |
820 __ j(sign, &slow); | 820 __ j(sign, &slow, Label::kNear); |
821 | 821 |
822 __ testl(right_reg, right_reg); | 822 __ testl(right_reg, right_reg); |
823 __ j(not_sign, &both_positive); | 823 __ j(not_sign, &both_positive, Label::kNear); |
824 // The sign of the divisor doesn't matter. | 824 // The sign of the divisor doesn't matter. |
825 __ neg(right_reg); | 825 __ neg(right_reg); |
826 | 826 |
827 __ bind(&both_positive); | 827 __ bind(&both_positive); |
828 // If the dividend is smaller than the nonnegative | 828 // If the dividend is smaller than the nonnegative |
829 // divisor, the dividend is the result. | 829 // divisor, the dividend is the result. |
830 __ cmpl(left_reg, right_reg); | 830 __ cmpl(left_reg, right_reg); |
831 __ j(less, &remainder_eq_dividend); | 831 __ j(less, &remainder_eq_dividend, Label::kNear); |
832 | 832 |
833 // Check if the divisor is a PowerOfTwo integer. | 833 // Check if the divisor is a PowerOfTwo integer. |
834 Register scratch = ToRegister(instr->TempAt(0)); | 834 Register scratch = ToRegister(instr->TempAt(0)); |
835 __ movl(scratch, right_reg); | 835 __ movl(scratch, right_reg); |
836 __ subl(scratch, Immediate(1)); | 836 __ subl(scratch, Immediate(1)); |
837 __ testl(scratch, right_reg); | 837 __ testl(scratch, right_reg); |
838 __ j(not_zero, &do_subtraction); | 838 __ j(not_zero, &do_subtraction, Label::kNear); |
839 __ andl(left_reg, scratch); | 839 __ andl(left_reg, scratch); |
840 __ jmp(&remainder_eq_dividend); | 840 __ jmp(&remainder_eq_dividend, Label::kNear); |
841 | 841 |
842 __ bind(&do_subtraction); | 842 __ bind(&do_subtraction); |
843 const int kUnfolds = 3; | 843 const int kUnfolds = 3; |
844 // Try a few subtractions of the dividend. | 844 // Try a few subtractions of the dividend. |
845 __ movl(scratch, left_reg); | 845 __ movl(scratch, left_reg); |
846 for (int i = 0; i < kUnfolds; i++) { | 846 for (int i = 0; i < kUnfolds; i++) { |
847 // Reduce the dividend by the divisor. | 847 // Reduce the dividend by the divisor. |
848 __ subl(left_reg, right_reg); | 848 __ subl(left_reg, right_reg); |
849 // Check if the dividend is less than the divisor. | 849 // Check if the dividend is less than the divisor. |
850 __ cmpl(left_reg, right_reg); | 850 __ cmpl(left_reg, right_reg); |
851 __ j(less, &remainder_eq_dividend); | 851 __ j(less, &remainder_eq_dividend, Label::kNear); |
852 } | 852 } |
853 __ movl(left_reg, scratch); | 853 __ movl(left_reg, scratch); |
854 | 854 |
855 // Slow case, using idiv instruction. | 855 // Slow case, using idiv instruction. |
856 __ bind(&slow); | 856 __ bind(&slow); |
857 // Sign extend eax to edx. | 857 // Sign extend eax to edx. |
858 // (We are using only the low 32 bits of the values.) | 858 // (We are using only the low 32 bits of the values.) |
859 __ cdq(); | 859 __ cdq(); |
860 | 860 |
861 // Check for (0 % -x) that will produce negative zero. | 861 // Check for (0 % -x) that will produce negative zero. |
862 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 862 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
863 NearLabel positive_left; | 863 Label positive_left; |
864 NearLabel done; | 864 Label done; |
865 __ testl(left_reg, left_reg); | 865 __ testl(left_reg, left_reg); |
866 __ j(not_sign, &positive_left); | 866 __ j(not_sign, &positive_left, Label::kNear); |
867 __ idivl(right_reg); | 867 __ idivl(right_reg); |
868 | 868 |
869 // Test the remainder for 0, because then the result would be -0. | 869 // Test the remainder for 0, because then the result would be -0. |
870 __ testl(result_reg, result_reg); | 870 __ testl(result_reg, result_reg); |
871 __ j(not_zero, &done); | 871 __ j(not_zero, &done, Label::kNear); |
872 | 872 |
873 DeoptimizeIf(no_condition, instr->environment()); | 873 DeoptimizeIf(no_condition, instr->environment()); |
874 __ bind(&positive_left); | 874 __ bind(&positive_left); |
875 __ idivl(right_reg); | 875 __ idivl(right_reg); |
876 __ bind(&done); | 876 __ bind(&done); |
877 } else { | 877 } else { |
878 __ idivl(right_reg); | 878 __ idivl(right_reg); |
879 } | 879 } |
880 __ jmp(&done); | 880 __ jmp(&done, Label::kNear); |
881 | 881 |
882 __ bind(&remainder_eq_dividend); | 882 __ bind(&remainder_eq_dividend); |
883 __ movl(result_reg, left_reg); | 883 __ movl(result_reg, left_reg); |
884 | 884 |
885 __ bind(&done); | 885 __ bind(&done); |
886 } | 886 } |
887 } | 887 } |
888 | 888 |
889 | 889 |
890 void LCodeGen::DoDivI(LDivI* instr) { | 890 void LCodeGen::DoDivI(LDivI* instr) { |
891 LOperand* right = instr->InputAt(1); | 891 LOperand* right = instr->InputAt(1); |
892 ASSERT(ToRegister(instr->result()).is(rax)); | 892 ASSERT(ToRegister(instr->result()).is(rax)); |
893 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 893 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
894 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); | 894 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); |
895 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); | 895 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); |
896 | 896 |
897 Register left_reg = rax; | 897 Register left_reg = rax; |
898 | 898 |
899 // Check for x / 0. | 899 // Check for x / 0. |
900 Register right_reg = ToRegister(right); | 900 Register right_reg = ToRegister(right); |
901 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 901 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
902 __ testl(right_reg, right_reg); | 902 __ testl(right_reg, right_reg); |
903 DeoptimizeIf(zero, instr->environment()); | 903 DeoptimizeIf(zero, instr->environment()); |
904 } | 904 } |
905 | 905 |
906 // Check for (0 / -x) that will produce negative zero. | 906 // Check for (0 / -x) that will produce negative zero. |
907 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 907 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
908 NearLabel left_not_zero; | 908 Label left_not_zero; |
909 __ testl(left_reg, left_reg); | 909 __ testl(left_reg, left_reg); |
910 __ j(not_zero, &left_not_zero); | 910 __ j(not_zero, &left_not_zero, Label::kNear); |
911 __ testl(right_reg, right_reg); | 911 __ testl(right_reg, right_reg); |
912 DeoptimizeIf(sign, instr->environment()); | 912 DeoptimizeIf(sign, instr->environment()); |
913 __ bind(&left_not_zero); | 913 __ bind(&left_not_zero); |
914 } | 914 } |
915 | 915 |
916 // Check for (-kMinInt / -1). | 916 // Check for (-kMinInt / -1). |
917 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 917 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
918 NearLabel left_not_min_int; | 918 Label left_not_min_int; |
919 __ cmpl(left_reg, Immediate(kMinInt)); | 919 __ cmpl(left_reg, Immediate(kMinInt)); |
920 __ j(not_zero, &left_not_min_int); | 920 __ j(not_zero, &left_not_min_int, Label::kNear); |
921 __ cmpl(right_reg, Immediate(-1)); | 921 __ cmpl(right_reg, Immediate(-1)); |
922 DeoptimizeIf(zero, instr->environment()); | 922 DeoptimizeIf(zero, instr->environment()); |
923 __ bind(&left_not_min_int); | 923 __ bind(&left_not_min_int); |
924 } | 924 } |
925 | 925 |
926 // Sign extend to rdx. | 926 // Sign extend to rdx. |
927 __ cdq(); | 927 __ cdq(); |
928 __ idivl(right_reg); | 928 __ idivl(right_reg); |
929 | 929 |
930 // Deoptimize if remainder is not 0. | 930 // Deoptimize if remainder is not 0. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 } else { | 989 } else { |
990 __ imull(left, ToRegister(right)); | 990 __ imull(left, ToRegister(right)); |
991 } | 991 } |
992 | 992 |
993 if (can_overflow) { | 993 if (can_overflow) { |
994 DeoptimizeIf(overflow, instr->environment()); | 994 DeoptimizeIf(overflow, instr->environment()); |
995 } | 995 } |
996 | 996 |
997 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 997 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
998 // Bail out if the result is supposed to be negative zero. | 998 // Bail out if the result is supposed to be negative zero. |
999 NearLabel done; | 999 Label done; |
1000 __ testl(left, left); | 1000 __ testl(left, left); |
1001 __ j(not_zero, &done); | 1001 __ j(not_zero, &done, Label::kNear); |
1002 if (right->IsConstantOperand()) { | 1002 if (right->IsConstantOperand()) { |
1003 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { | 1003 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
1004 DeoptimizeIf(no_condition, instr->environment()); | 1004 DeoptimizeIf(no_condition, instr->environment()); |
1005 } | 1005 } |
1006 } else if (right->IsStackSlot()) { | 1006 } else if (right->IsStackSlot()) { |
1007 __ or_(kScratchRegister, ToOperand(right)); | 1007 __ or_(kScratchRegister, ToOperand(right)); |
1008 DeoptimizeIf(sign, instr->environment()); | 1008 DeoptimizeIf(sign, instr->environment()); |
1009 } else { | 1009 } else { |
1010 // Test the non-zero operand for negative sign. | 1010 // Test the non-zero operand for negative sign. |
1011 __ or_(kScratchRegister, ToRegister(right)); | 1011 __ or_(kScratchRegister, ToRegister(right)); |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 __ j(equal, false_label); | 1360 __ j(equal, false_label); |
1361 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1361 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1362 __ j(equal, true_label); | 1362 __ j(equal, true_label); |
1363 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1363 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
1364 __ j(equal, false_label); | 1364 __ j(equal, false_label); |
1365 __ Cmp(reg, Smi::FromInt(0)); | 1365 __ Cmp(reg, Smi::FromInt(0)); |
1366 __ j(equal, false_label); | 1366 __ j(equal, false_label); |
1367 __ JumpIfSmi(reg, true_label); | 1367 __ JumpIfSmi(reg, true_label); |
1368 | 1368 |
1369 // Test for double values. Plus/minus zero and NaN are false. | 1369 // Test for double values. Plus/minus zero and NaN are false. |
1370 NearLabel call_stub; | 1370 Label call_stub; |
1371 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), | 1371 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), |
1372 Heap::kHeapNumberMapRootIndex); | 1372 Heap::kHeapNumberMapRootIndex); |
1373 __ j(not_equal, &call_stub); | 1373 __ j(not_equal, &call_stub, Label::kNear); |
1374 | 1374 |
1375 // HeapNumber => false iff +0, -0, or NaN. These three cases set the | 1375 // HeapNumber => false iff +0, -0, or NaN. These three cases set the |
1376 // zero flag when compared to zero using ucomisd. | 1376 // zero flag when compared to zero using ucomisd. |
1377 __ xorps(xmm0, xmm0); | 1377 __ xorps(xmm0, xmm0); |
1378 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 1378 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
1379 __ j(zero, false_label); | 1379 __ j(zero, false_label); |
1380 __ jmp(true_label); | 1380 __ jmp(true_label); |
1381 | 1381 |
1382 // The conversion stub doesn't cause garbage collections so it's | 1382 // The conversion stub doesn't cause garbage collections so it's |
1383 // safe to not record a safepoint after the call. | 1383 // safe to not record a safepoint after the call. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1477 __ cmpl(ToRegister(left), ToOperand(right)); | 1477 __ cmpl(ToRegister(left), ToOperand(right)); |
1478 } | 1478 } |
1479 } | 1479 } |
1480 | 1480 |
1481 | 1481 |
1482 void LCodeGen::DoCmpID(LCmpID* instr) { | 1482 void LCodeGen::DoCmpID(LCmpID* instr) { |
1483 LOperand* left = instr->InputAt(0); | 1483 LOperand* left = instr->InputAt(0); |
1484 LOperand* right = instr->InputAt(1); | 1484 LOperand* right = instr->InputAt(1); |
1485 LOperand* result = instr->result(); | 1485 LOperand* result = instr->result(); |
1486 | 1486 |
1487 NearLabel unordered; | 1487 Label unordered; |
1488 if (instr->is_double()) { | 1488 if (instr->is_double()) { |
1489 // Don't base result on EFLAGS when a NaN is involved. Instead | 1489 // Don't base result on EFLAGS when a NaN is involved. Instead |
1490 // jump to the unordered case, which produces a false value. | 1490 // jump to the unordered case, which produces a false value. |
1491 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1491 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1492 __ j(parity_even, &unordered); | 1492 __ j(parity_even, &unordered, Label::kNear); |
1493 } else { | 1493 } else { |
1494 EmitCmpI(left, right); | 1494 EmitCmpI(left, right); |
1495 } | 1495 } |
1496 | 1496 |
1497 NearLabel done; | 1497 Label done; |
1498 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1498 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1499 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex); | 1499 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex); |
1500 __ j(cc, &done); | 1500 __ j(cc, &done, Label::kNear); |
1501 | 1501 |
1502 __ bind(&unordered); | 1502 __ bind(&unordered); |
1503 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex); | 1503 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex); |
1504 __ bind(&done); | 1504 __ bind(&done); |
1505 } | 1505 } |
1506 | 1506 |
1507 | 1507 |
1508 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1508 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1509 LOperand* left = instr->InputAt(0); | 1509 LOperand* left = instr->InputAt(0); |
1510 LOperand* right = instr->InputAt(1); | 1510 LOperand* right = instr->InputAt(1); |
(...skipping 12 matching lines...) Expand all Loading... |
1523 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1523 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1524 EmitBranch(true_block, false_block, cc); | 1524 EmitBranch(true_block, false_block, cc); |
1525 } | 1525 } |
1526 | 1526 |
1527 | 1527 |
1528 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1528 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
1529 Register left = ToRegister(instr->InputAt(0)); | 1529 Register left = ToRegister(instr->InputAt(0)); |
1530 Register right = ToRegister(instr->InputAt(1)); | 1530 Register right = ToRegister(instr->InputAt(1)); |
1531 Register result = ToRegister(instr->result()); | 1531 Register result = ToRegister(instr->result()); |
1532 | 1532 |
1533 NearLabel different, done; | 1533 Label different, done; |
1534 __ cmpq(left, right); | 1534 __ cmpq(left, right); |
1535 __ j(not_equal, &different); | 1535 __ j(not_equal, &different, Label::kNear); |
1536 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1536 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
1537 __ jmp(&done); | 1537 __ jmp(&done, Label::kNear); |
1538 __ bind(&different); | 1538 __ bind(&different); |
1539 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1539 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1540 __ bind(&done); | 1540 __ bind(&done); |
1541 } | 1541 } |
1542 | 1542 |
1543 | 1543 |
1544 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1544 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
1545 Register left = ToRegister(instr->InputAt(0)); | 1545 Register left = ToRegister(instr->InputAt(0)); |
1546 Register right = ToRegister(instr->InputAt(1)); | 1546 Register right = ToRegister(instr->InputAt(1)); |
1547 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1547 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 13 matching lines...) Expand all Loading... |
1561 // Consider adding other type and representation tests too. | 1561 // Consider adding other type and representation tests too. |
1562 if (instr->hydrogen()->value()->type().IsSmi()) { | 1562 if (instr->hydrogen()->value()->type().IsSmi()) { |
1563 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1563 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1564 return; | 1564 return; |
1565 } | 1565 } |
1566 | 1566 |
1567 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1567 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
1568 if (instr->is_strict()) { | 1568 if (instr->is_strict()) { |
1569 ASSERT(Heap::kTrueValueRootIndex >= 0); | 1569 ASSERT(Heap::kTrueValueRootIndex >= 0); |
1570 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | 1570 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
1571 NearLabel load; | 1571 Label load; |
1572 __ j(equal, &load); | 1572 __ j(equal, &load, Label::kNear); |
1573 __ Set(result, Heap::kFalseValueRootIndex); | 1573 __ Set(result, Heap::kFalseValueRootIndex); |
1574 __ bind(&load); | 1574 __ bind(&load); |
1575 __ LoadRootIndexed(result, result, 0); | 1575 __ LoadRootIndexed(result, result, 0); |
1576 } else { | 1576 } else { |
1577 NearLabel true_value, false_value, done; | 1577 NearLabel false_value; |
1578 __ j(equal, &true_value); | 1578 Label true_value, done; |
| 1579 __ j(equal, &true_value, Label::kNear); |
1579 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1580 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
1580 __ j(equal, &true_value); | 1581 __ j(equal, &true_value, Label::kNear); |
1581 __ JumpIfSmi(reg, &false_value); | 1582 __ JumpIfSmi(reg, &false_value); |
1582 // Check for undetectable objects by looking in the bit field in | 1583 // Check for undetectable objects by looking in the bit field in |
1583 // the map. The object has already been smi checked. | 1584 // the map. The object has already been smi checked. |
1584 Register scratch = result; | 1585 Register scratch = result; |
1585 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1586 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1586 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1587 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
1587 Immediate(1 << Map::kIsUndetectable)); | 1588 Immediate(1 << Map::kIsUndetectable)); |
1588 __ j(not_zero, &true_value); | 1589 __ j(not_zero, &true_value, Label::kNear); |
1589 __ bind(&false_value); | 1590 __ bind(&false_value); |
1590 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1591 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1591 __ jmp(&done); | 1592 __ jmp(&done, Label::kNear); |
1592 __ bind(&true_value); | 1593 __ bind(&true_value); |
1593 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1594 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
1594 __ bind(&done); | 1595 __ bind(&done); |
1595 } | 1596 } |
1596 } | 1597 } |
1597 | 1598 |
1598 | 1599 |
1599 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1600 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1600 Register reg = ToRegister(instr->InputAt(0)); | 1601 Register reg = ToRegister(instr->InputAt(0)); |
1601 | 1602 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 return equal; | 1743 return equal; |
1743 } | 1744 } |
1744 | 1745 |
1745 | 1746 |
1746 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1747 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
1747 Register input = ToRegister(instr->InputAt(0)); | 1748 Register input = ToRegister(instr->InputAt(0)); |
1748 Register result = ToRegister(instr->result()); | 1749 Register result = ToRegister(instr->result()); |
1749 | 1750 |
1750 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1751 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1751 __ testl(input, Immediate(kSmiTagMask)); | 1752 __ testl(input, Immediate(kSmiTagMask)); |
1752 NearLabel done, is_false; | 1753 Label done, is_false; |
1753 __ j(zero, &is_false); | 1754 __ j(zero, &is_false); |
1754 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | 1755 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
1755 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); | 1756 __ j(NegateCondition(BranchCondition(instr->hydrogen())), |
| 1757 &is_false, Label::kNear); |
1756 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1758 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
1757 __ jmp(&done); | 1759 __ jmp(&done, Label::kNear); |
1758 __ bind(&is_false); | 1760 __ bind(&is_false); |
1759 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1761 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1760 __ bind(&done); | 1762 __ bind(&done); |
1761 } | 1763 } |
1762 | 1764 |
1763 | 1765 |
1764 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1766 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1765 Register input = ToRegister(instr->InputAt(0)); | 1767 Register input = ToRegister(instr->InputAt(0)); |
1766 | 1768 |
1767 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1769 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 23 matching lines...) Expand all Loading... |
1791 | 1793 |
1792 | 1794 |
1793 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1795 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
1794 Register input = ToRegister(instr->InputAt(0)); | 1796 Register input = ToRegister(instr->InputAt(0)); |
1795 Register result = ToRegister(instr->result()); | 1797 Register result = ToRegister(instr->result()); |
1796 | 1798 |
1797 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1799 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1798 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1800 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
1799 __ testl(FieldOperand(input, String::kHashFieldOffset), | 1801 __ testl(FieldOperand(input, String::kHashFieldOffset), |
1800 Immediate(String::kContainsCachedArrayIndexMask)); | 1802 Immediate(String::kContainsCachedArrayIndexMask)); |
1801 NearLabel done; | 1803 Label done; |
1802 __ j(zero, &done); | 1804 __ j(zero, &done, Label::kNear); |
1803 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1805 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1804 __ bind(&done); | 1806 __ bind(&done); |
1805 } | 1807 } |
1806 | 1808 |
1807 | 1809 |
1808 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1810 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1809 LHasCachedArrayIndexAndBranch* instr) { | 1811 LHasCachedArrayIndexAndBranch* instr) { |
1810 Register input = ToRegister(instr->InputAt(0)); | 1812 Register input = ToRegister(instr->InputAt(0)); |
1811 | 1813 |
1812 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1814 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1871 // End with the answer in the z flag. | 1873 // End with the answer in the z flag. |
1872 } | 1874 } |
1873 | 1875 |
1874 | 1876 |
1875 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1877 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1876 Register input = ToRegister(instr->InputAt(0)); | 1878 Register input = ToRegister(instr->InputAt(0)); |
1877 Register result = ToRegister(instr->result()); | 1879 Register result = ToRegister(instr->result()); |
1878 ASSERT(input.is(result)); | 1880 ASSERT(input.is(result)); |
1879 Register temp = ToRegister(instr->TempAt(0)); | 1881 Register temp = ToRegister(instr->TempAt(0)); |
1880 Handle<String> class_name = instr->hydrogen()->class_name(); | 1882 Handle<String> class_name = instr->hydrogen()->class_name(); |
1881 NearLabel done; | 1883 Label done; |
1882 Label is_true, is_false; | 1884 Label is_true, is_false; |
1883 | 1885 |
1884 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); | 1886 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); |
1885 | 1887 |
1886 __ j(not_equal, &is_false); | 1888 __ j(not_equal, &is_false); |
1887 | 1889 |
1888 __ bind(&is_true); | 1890 __ bind(&is_true); |
1889 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1891 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
1890 __ jmp(&done); | 1892 __ jmp(&done, Label::kNear); |
1891 | 1893 |
1892 __ bind(&is_false); | 1894 __ bind(&is_false); |
1893 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1895 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
1894 __ bind(&done); | 1896 __ bind(&done); |
1895 } | 1897 } |
1896 | 1898 |
1897 | 1899 |
1898 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1900 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1899 Register input = ToRegister(instr->InputAt(0)); | 1901 Register input = ToRegister(instr->InputAt(0)); |
1900 Register temp = ToRegister(instr->TempAt(0)); | 1902 Register temp = ToRegister(instr->TempAt(0)); |
(...skipping 19 matching lines...) Expand all Loading... |
1920 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1922 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
1921 EmitBranch(true_block, false_block, equal); | 1923 EmitBranch(true_block, false_block, equal); |
1922 } | 1924 } |
1923 | 1925 |
1924 | 1926 |
1925 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1927 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1926 InstanceofStub stub(InstanceofStub::kNoFlags); | 1928 InstanceofStub stub(InstanceofStub::kNoFlags); |
1927 __ push(ToRegister(instr->InputAt(0))); | 1929 __ push(ToRegister(instr->InputAt(0))); |
1928 __ push(ToRegister(instr->InputAt(1))); | 1930 __ push(ToRegister(instr->InputAt(1))); |
1929 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1931 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1930 NearLabel true_value, done; | 1932 Label true_value, done; |
1931 __ testq(rax, rax); | 1933 __ testq(rax, rax); |
1932 __ j(zero, &true_value); | 1934 __ j(zero, &true_value, Label::kNear); |
1933 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 1935 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
1934 __ jmp(&done); | 1936 __ jmp(&done, Label::kNear); |
1935 __ bind(&true_value); | 1937 __ bind(&true_value); |
1936 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 1938 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
1937 __ bind(&done); | 1939 __ bind(&done); |
1938 } | 1940 } |
1939 | 1941 |
1940 | 1942 |
1941 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1943 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
1942 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1944 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1943 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1945 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1944 | 1946 |
(...skipping 29 matching lines...) Expand all Loading... |
1974 | 1976 |
1975 Label done, false_result; | 1977 Label done, false_result; |
1976 Register object = ToRegister(instr->InputAt(0)); | 1978 Register object = ToRegister(instr->InputAt(0)); |
1977 | 1979 |
1978 // A Smi is not an instance of anything. | 1980 // A Smi is not an instance of anything. |
1979 __ JumpIfSmi(object, &false_result); | 1981 __ JumpIfSmi(object, &false_result); |
1980 | 1982 |
1981 // This is the inlined call site instanceof cache. The two occurences of the | 1983 // This is the inlined call site instanceof cache. The two occurences of the |
1982 // hole value will be patched to the last map/result pair generated by the | 1984 // hole value will be patched to the last map/result pair generated by the |
1983 // instanceof stub. | 1985 // instanceof stub. |
1984 NearLabel cache_miss; | 1986 Label cache_miss; |
1985 // Use a temp register to avoid memory operands with variable lengths. | 1987 // Use a temp register to avoid memory operands with variable lengths. |
1986 Register map = ToRegister(instr->TempAt(0)); | 1988 Register map = ToRegister(instr->TempAt(0)); |
1987 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 1989 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
1988 __ bind(deferred->map_check()); // Label for calculating code patching. | 1990 __ bind(deferred->map_check()); // Label for calculating code patching. |
1989 __ movq(kScratchRegister, factory()->the_hole_value(), | 1991 __ movq(kScratchRegister, factory()->the_hole_value(), |
1990 RelocInfo::EMBEDDED_OBJECT); | 1992 RelocInfo::EMBEDDED_OBJECT); |
1991 __ cmpq(map, kScratchRegister); // Patched to cached map. | 1993 __ cmpq(map, kScratchRegister); // Patched to cached map. |
1992 __ j(not_equal, &cache_miss); | 1994 __ j(not_equal, &cache_miss, Label::kNear); |
1993 // Patched to load either true or false. | 1995 // Patched to load either true or false. |
1994 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 1996 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
1995 #ifdef DEBUG | 1997 #ifdef DEBUG |
1996 // Check that the code size between patch label and patch sites is invariant. | 1998 // Check that the code size between patch label and patch sites is invariant. |
1997 Label end_of_patched_code; | 1999 Label end_of_patched_code; |
1998 __ bind(&end_of_patched_code); | 2000 __ bind(&end_of_patched_code); |
1999 ASSERT(true); | 2001 ASSERT(true); |
2000 #endif | 2002 #endif |
2001 __ jmp(&done); | 2003 __ jmp(&done); |
2002 | 2004 |
2003 // The inlined call site cache did not match. Check for null and string | 2005 // The inlined call site cache did not match. Check for null and string |
2004 // before calling the deferred code. | 2006 // before calling the deferred code. |
2005 __ bind(&cache_miss); // Null is not an instance of anything. | 2007 __ bind(&cache_miss); // Null is not an instance of anything. |
2006 __ CompareRoot(object, Heap::kNullValueRootIndex); | 2008 __ CompareRoot(object, Heap::kNullValueRootIndex); |
2007 __ j(equal, &false_result); | 2009 __ j(equal, &false_result, Label::kNear); |
2008 | 2010 |
2009 // String values are not instances of anything. | 2011 // String values are not instances of anything. |
2010 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); | 2012 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); |
2011 | 2013 |
2012 __ bind(&false_result); | 2014 __ bind(&false_result); |
2013 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2015 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2014 | 2016 |
2015 __ bind(deferred->exit()); | 2017 __ bind(deferred->exit()); |
2016 __ bind(&done); | 2018 __ bind(&done); |
2017 } | 2019 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2064 void LCodeGen::DoCmpT(LCmpT* instr) { | 2066 void LCodeGen::DoCmpT(LCmpT* instr) { |
2065 Token::Value op = instr->op(); | 2067 Token::Value op = instr->op(); |
2066 | 2068 |
2067 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2069 Handle<Code> ic = CompareIC::GetUninitialized(op); |
2068 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2070 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2069 | 2071 |
2070 Condition condition = TokenToCondition(op, false); | 2072 Condition condition = TokenToCondition(op, false); |
2071 if (op == Token::GT || op == Token::LTE) { | 2073 if (op == Token::GT || op == Token::LTE) { |
2072 condition = ReverseCondition(condition); | 2074 condition = ReverseCondition(condition); |
2073 } | 2075 } |
2074 NearLabel true_value, done; | 2076 Label true_value, done; |
2075 __ testq(rax, rax); | 2077 __ testq(rax, rax); |
2076 __ j(condition, &true_value); | 2078 __ j(condition, &true_value, Label::kNear); |
2077 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2079 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2078 __ jmp(&done); | 2080 __ jmp(&done, Label::kNear); |
2079 __ bind(&true_value); | 2081 __ bind(&true_value); |
2080 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2082 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
2081 __ bind(&done); | 2083 __ bind(&done); |
2082 } | 2084 } |
2083 | 2085 |
2084 | 2086 |
2085 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { | 2087 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
2086 Token::Value op = instr->op(); | 2088 Token::Value op = instr->op(); |
2087 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2089 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2088 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2090 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2241 | 2243 |
2242 int map_count = instr->hydrogen()->types()->length(); | 2244 int map_count = instr->hydrogen()->types()->length(); |
2243 Handle<String> name = instr->hydrogen()->name(); | 2245 Handle<String> name = instr->hydrogen()->name(); |
2244 | 2246 |
2245 if (map_count == 0) { | 2247 if (map_count == 0) { |
2246 ASSERT(instr->hydrogen()->need_generic()); | 2248 ASSERT(instr->hydrogen()->need_generic()); |
2247 __ Move(rcx, instr->hydrogen()->name()); | 2249 __ Move(rcx, instr->hydrogen()->name()); |
2248 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2250 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2249 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2251 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2250 } else { | 2252 } else { |
2251 NearLabel done; | 2253 Label done; |
2252 for (int i = 0; i < map_count - 1; ++i) { | 2254 for (int i = 0; i < map_count - 1; ++i) { |
2253 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2255 Handle<Map> map = instr->hydrogen()->types()->at(i); |
2254 NearLabel next; | 2256 Label next; |
2255 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2257 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2256 __ j(not_equal, &next); | 2258 __ j(not_equal, &next, Label::kNear); |
2257 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2259 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2258 __ jmp(&done); | 2260 __ jmp(&done, Label::kNear); |
2259 __ bind(&next); | 2261 __ bind(&next); |
2260 } | 2262 } |
2261 Handle<Map> map = instr->hydrogen()->types()->last(); | 2263 Handle<Map> map = instr->hydrogen()->types()->last(); |
2262 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2264 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2263 if (instr->hydrogen()->need_generic()) { | 2265 if (instr->hydrogen()->need_generic()) { |
2264 NearLabel generic; | 2266 Label generic; |
2265 __ j(not_equal, &generic); | 2267 __ j(not_equal, &generic, Label::kNear); |
2266 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2268 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2267 __ jmp(&done); | 2269 __ jmp(&done, Label::kNear); |
2268 __ bind(&generic); | 2270 __ bind(&generic); |
2269 __ Move(rcx, instr->hydrogen()->name()); | 2271 __ Move(rcx, instr->hydrogen()->name()); |
2270 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2272 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2271 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2273 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2272 } else { | 2274 } else { |
2273 DeoptimizeIf(not_equal, instr->environment()); | 2275 DeoptimizeIf(not_equal, instr->environment()); |
2274 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2276 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2275 } | 2277 } |
2276 __ bind(&done); | 2278 __ bind(&done); |
2277 } | 2279 } |
(...skipping 12 matching lines...) Expand all Loading... |
2290 | 2292 |
2291 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2293 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
2292 Register function = ToRegister(instr->function()); | 2294 Register function = ToRegister(instr->function()); |
2293 Register result = ToRegister(instr->result()); | 2295 Register result = ToRegister(instr->result()); |
2294 | 2296 |
2295 // Check that the function really is a function. | 2297 // Check that the function really is a function. |
2296 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2298 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
2297 DeoptimizeIf(not_equal, instr->environment()); | 2299 DeoptimizeIf(not_equal, instr->environment()); |
2298 | 2300 |
2299 // Check whether the function has an instance prototype. | 2301 // Check whether the function has an instance prototype. |
2300 NearLabel non_instance; | 2302 Label non_instance; |
2301 __ testb(FieldOperand(result, Map::kBitFieldOffset), | 2303 __ testb(FieldOperand(result, Map::kBitFieldOffset), |
2302 Immediate(1 << Map::kHasNonInstancePrototype)); | 2304 Immediate(1 << Map::kHasNonInstancePrototype)); |
2303 __ j(not_zero, &non_instance); | 2305 __ j(not_zero, &non_instance, Label::kNear); |
2304 | 2306 |
2305 // Get the prototype or initial map from the function. | 2307 // Get the prototype or initial map from the function. |
2306 __ movq(result, | 2308 __ movq(result, |
2307 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2309 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
2308 | 2310 |
2309 // Check that the function has a prototype or an initial map. | 2311 // Check that the function has a prototype or an initial map. |
2310 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2312 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
2311 DeoptimizeIf(equal, instr->environment()); | 2313 DeoptimizeIf(equal, instr->environment()); |
2312 | 2314 |
2313 // If the function does not have an initial map, we're done. | 2315 // If the function does not have an initial map, we're done. |
2314 NearLabel done; | 2316 Label done; |
2315 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); | 2317 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); |
2316 __ j(not_equal, &done); | 2318 __ j(not_equal, &done, Label::kNear); |
2317 | 2319 |
2318 // Get the prototype from the initial map. | 2320 // Get the prototype from the initial map. |
2319 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); | 2321 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); |
2320 __ jmp(&done); | 2322 __ jmp(&done, Label::kNear); |
2321 | 2323 |
2322 // Non-instance prototype: Fetch prototype from constructor field | 2324 // Non-instance prototype: Fetch prototype from constructor field |
2323 // in the function's map. | 2325 // in the function's map. |
2324 __ bind(&non_instance); | 2326 __ bind(&non_instance); |
2325 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); | 2327 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); |
2326 | 2328 |
2327 // All done. | 2329 // All done. |
2328 __ bind(&done); | 2330 __ bind(&done); |
2329 } | 2331 } |
2330 | 2332 |
2331 | 2333 |
2332 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2334 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2333 Register result = ToRegister(instr->result()); | 2335 Register result = ToRegister(instr->result()); |
2334 Register input = ToRegister(instr->InputAt(0)); | 2336 Register input = ToRegister(instr->InputAt(0)); |
2335 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); | 2337 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); |
2336 if (FLAG_debug_code) { | 2338 if (FLAG_debug_code) { |
2337 NearLabel done; | 2339 Label done; |
2338 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2340 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2339 Heap::kFixedArrayMapRootIndex); | 2341 Heap::kFixedArrayMapRootIndex); |
2340 __ j(equal, &done); | 2342 __ j(equal, &done, Label::kNear); |
2341 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2343 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2342 Heap::kFixedCOWArrayMapRootIndex); | 2344 Heap::kFixedCOWArrayMapRootIndex); |
2343 __ j(equal, &done); | 2345 __ j(equal, &done, Label::kNear); |
2344 Register temp((result.is(rax)) ? rbx : rax); | 2346 Register temp((result.is(rax)) ? rbx : rax); |
2345 __ push(temp); | 2347 __ push(temp); |
2346 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2348 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2347 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 2349 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
2348 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); | 2350 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); |
2349 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); | 2351 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); |
2350 __ pop(temp); | 2352 __ pop(temp); |
2351 __ Check(below, "Check for fast elements failed."); | 2353 __ Check(below, "Check for fast elements failed."); |
2352 __ bind(&done); | 2354 __ bind(&done); |
2353 } | 2355 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2453 | 2455 |
2454 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2456 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2455 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2457 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2456 } | 2458 } |
2457 | 2459 |
2458 | 2460 |
2459 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2461 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
2460 Register result = ToRegister(instr->result()); | 2462 Register result = ToRegister(instr->result()); |
2461 | 2463 |
2462 // Check for arguments adapter frame. | 2464 // Check for arguments adapter frame. |
2463 NearLabel done, adapted; | 2465 Label done, adapted; |
2464 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2466 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2465 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), | 2467 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), |
2466 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2468 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
2467 __ j(equal, &adapted); | 2469 __ j(equal, &adapted, Label::kNear); |
2468 | 2470 |
2469 // No arguments adaptor frame. | 2471 // No arguments adaptor frame. |
2470 __ movq(result, rbp); | 2472 __ movq(result, rbp); |
2471 __ jmp(&done); | 2473 __ jmp(&done, Label::kNear); |
2472 | 2474 |
2473 // Arguments adaptor frame present. | 2475 // Arguments adaptor frame present. |
2474 __ bind(&adapted); | 2476 __ bind(&adapted); |
2475 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2477 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2476 | 2478 |
2477 // Result is the frame pointer for the frame if not adapted and for the real | 2479 // Result is the frame pointer for the frame if not adapted and for the real |
2478 // frame below the adaptor frame if adapted. | 2480 // frame below the adaptor frame if adapted. |
2479 __ bind(&done); | 2481 __ bind(&done); |
2480 } | 2482 } |
2481 | 2483 |
2482 | 2484 |
2483 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2485 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2484 Register result = ToRegister(instr->result()); | 2486 Register result = ToRegister(instr->result()); |
2485 | 2487 |
2486 NearLabel done; | 2488 Label done; |
2487 | 2489 |
2488 // If no arguments adaptor frame the number of arguments is fixed. | 2490 // If no arguments adaptor frame the number of arguments is fixed. |
2489 if (instr->InputAt(0)->IsRegister()) { | 2491 if (instr->InputAt(0)->IsRegister()) { |
2490 __ cmpq(rbp, ToRegister(instr->InputAt(0))); | 2492 __ cmpq(rbp, ToRegister(instr->InputAt(0))); |
2491 } else { | 2493 } else { |
2492 __ cmpq(rbp, ToOperand(instr->InputAt(0))); | 2494 __ cmpq(rbp, ToOperand(instr->InputAt(0))); |
2493 } | 2495 } |
2494 __ movl(result, Immediate(scope()->num_parameters())); | 2496 __ movl(result, Immediate(scope()->num_parameters())); |
2495 __ j(equal, &done); | 2497 __ j(equal, &done, Label::kNear); |
2496 | 2498 |
2497 // Arguments adaptor frame present. Get argument length from there. | 2499 // Arguments adaptor frame present. Get argument length from there. |
2498 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2500 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2499 __ SmiToInteger32(result, | 2501 __ SmiToInteger32(result, |
2500 Operand(result, | 2502 Operand(result, |
2501 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2503 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2502 | 2504 |
2503 // Argument length is in result register. | 2505 // Argument length is in result register. |
2504 __ bind(&done); | 2506 __ bind(&done); |
2505 } | 2507 } |
2506 | 2508 |
2507 | 2509 |
2508 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 2510 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
2509 Register receiver = ToRegister(instr->receiver()); | 2511 Register receiver = ToRegister(instr->receiver()); |
2510 Register function = ToRegister(instr->function()); | 2512 Register function = ToRegister(instr->function()); |
2511 Register length = ToRegister(instr->length()); | 2513 Register length = ToRegister(instr->length()); |
2512 Register elements = ToRegister(instr->elements()); | 2514 Register elements = ToRegister(instr->elements()); |
2513 ASSERT(receiver.is(rax)); // Used for parameter count. | 2515 ASSERT(receiver.is(rax)); // Used for parameter count. |
2514 ASSERT(function.is(rdi)); // Required by InvokeFunction. | 2516 ASSERT(function.is(rdi)); // Required by InvokeFunction. |
2515 ASSERT(ToRegister(instr->result()).is(rax)); | 2517 ASSERT(ToRegister(instr->result()).is(rax)); |
2516 | 2518 |
2517 // If the receiver is null or undefined, we have to pass the global object | 2519 // If the receiver is null or undefined, we have to pass the global object |
2518 // as a receiver. | 2520 // as a receiver. |
2519 NearLabel global_object, receiver_ok; | 2521 Label global_object, receiver_ok; |
2520 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 2522 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
2521 __ j(equal, &global_object); | 2523 __ j(equal, &global_object, Label::kNear); |
2522 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 2524 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
2523 __ j(equal, &global_object); | 2525 __ j(equal, &global_object, Label::kNear); |
2524 | 2526 |
2525 // The receiver should be a JS object. | 2527 // The receiver should be a JS object. |
2526 Condition is_smi = __ CheckSmi(receiver); | 2528 Condition is_smi = __ CheckSmi(receiver); |
2527 DeoptimizeIf(is_smi, instr->environment()); | 2529 DeoptimizeIf(is_smi, instr->environment()); |
2528 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); | 2530 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); |
2529 DeoptimizeIf(below, instr->environment()); | 2531 DeoptimizeIf(below, instr->environment()); |
2530 __ jmp(&receiver_ok); | 2532 __ jmp(&receiver_ok, Label::kNear); |
2531 | 2533 |
2532 __ bind(&global_object); | 2534 __ bind(&global_object); |
2533 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2535 // TODO(kmillikin): We have a hydrogen value for the global object. See |
2534 // if it's better to use it than to explicitly fetch it from the context | 2536 // if it's better to use it than to explicitly fetch it from the context |
2535 // here. | 2537 // here. |
2536 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2538 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2537 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2539 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
2538 __ bind(&receiver_ok); | 2540 __ bind(&receiver_ok); |
2539 | 2541 |
2540 // Copy the arguments to this function possibly from the | 2542 // Copy the arguments to this function possibly from the |
2541 // adaptor frame below it. | 2543 // adaptor frame below it. |
2542 const uint32_t kArgumentsLimit = 1 * KB; | 2544 const uint32_t kArgumentsLimit = 1 * KB; |
2543 __ cmpq(length, Immediate(kArgumentsLimit)); | 2545 __ cmpq(length, Immediate(kArgumentsLimit)); |
2544 DeoptimizeIf(above, instr->environment()); | 2546 DeoptimizeIf(above, instr->environment()); |
2545 | 2547 |
2546 __ push(receiver); | 2548 __ push(receiver); |
2547 __ movq(receiver, length); | 2549 __ movq(receiver, length); |
2548 | 2550 |
2549 // Loop through the arguments pushing them onto the execution | 2551 // Loop through the arguments pushing them onto the execution |
2550 // stack. | 2552 // stack. |
2551 NearLabel invoke, loop; | 2553 Label invoke, loop; |
2552 // length is a small non-negative integer, due to the test above. | 2554 // length is a small non-negative integer, due to the test above. |
2553 __ testl(length, length); | 2555 __ testl(length, length); |
2554 __ j(zero, &invoke); | 2556 __ j(zero, &invoke, Label::kNear); |
2555 __ bind(&loop); | 2557 __ bind(&loop); |
2556 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 2558 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); |
2557 __ decl(length); | 2559 __ decl(length); |
2558 __ j(not_zero, &loop); | 2560 __ j(not_zero, &loop); |
2559 | 2561 |
2560 // Invoke the function. | 2562 // Invoke the function. |
2561 __ bind(&invoke); | 2563 __ bind(&invoke); |
2562 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 2564 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
2563 LPointerMap* pointers = instr->pointer_map(); | 2565 LPointerMap* pointers = instr->pointer_map(); |
2564 LEnvironment* env = instr->deoptimization_environment(); | 2566 LEnvironment* env = instr->deoptimization_environment(); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2791 | 2793 |
2792 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2794 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
2793 const XMMRegister xmm_scratch = xmm0; | 2795 const XMMRegister xmm_scratch = xmm0; |
2794 Register output_reg = ToRegister(instr->result()); | 2796 Register output_reg = ToRegister(instr->result()); |
2795 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2797 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2796 | 2798 |
2797 Label done; | 2799 Label done; |
2798 // xmm_scratch = 0.5 | 2800 // xmm_scratch = 0.5 |
2799 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); | 2801 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
2800 __ movq(xmm_scratch, kScratchRegister); | 2802 __ movq(xmm_scratch, kScratchRegister); |
2801 NearLabel below_half; | 2803 Label below_half; |
2802 __ ucomisd(xmm_scratch, input_reg); | 2804 __ ucomisd(xmm_scratch, input_reg); |
2803 __ j(above, &below_half); // If input_reg is NaN, this doesn't jump. | 2805 // If input_reg is NaN, this doesn't jump. |
| 2806 __ j(above, &below_half, Label::kNear); |
2804 // input = input + 0.5 | 2807 // input = input + 0.5 |
2805 // This addition might give a result that isn't the correct for | 2808 // This addition might give a result that isn't the correct for |
2806 // rounding, due to loss of precision, but only for a number that's | 2809 // rounding, due to loss of precision, but only for a number that's |
2807 // so big that the conversion below will overflow anyway. | 2810 // so big that the conversion below will overflow anyway. |
2808 __ addsd(input_reg, xmm_scratch); | 2811 __ addsd(input_reg, xmm_scratch); |
2809 // Compute Math.floor(input). | 2812 // Compute Math.floor(input). |
2810 // Use truncating instruction (OK because input is positive). | 2813 // Use truncating instruction (OK because input is positive). |
2811 __ cvttsd2si(output_reg, input_reg); | 2814 __ cvttsd2si(output_reg, input_reg); |
2812 // Overflow is signalled with minint. | 2815 // Overflow is signalled with minint. |
2813 __ cmpl(output_reg, Immediate(0x80000000)); | 2816 __ cmpl(output_reg, Immediate(0x80000000)); |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3100 __ cvtsd2ss(value, value); | 3103 __ cvtsd2ss(value, value); |
3101 __ movss(Operand(external_pointer, key, times_4, 0), value); | 3104 __ movss(Operand(external_pointer, key, times_4, 0), value); |
3102 } else if (array_type == kExternalDoubleArray) { | 3105 } else if (array_type == kExternalDoubleArray) { |
3103 __ movsd(Operand(external_pointer, key, times_8, 0), | 3106 __ movsd(Operand(external_pointer, key, times_8, 0), |
3104 ToDoubleRegister(instr->value())); | 3107 ToDoubleRegister(instr->value())); |
3105 } else { | 3108 } else { |
3106 Register value(ToRegister(instr->value())); | 3109 Register value(ToRegister(instr->value())); |
3107 switch (array_type) { | 3110 switch (array_type) { |
3108 case kExternalPixelArray: | 3111 case kExternalPixelArray: |
3109 { // Clamp the value to [0..255]. | 3112 { // Clamp the value to [0..255]. |
3110 NearLabel done; | 3113 Label done; |
3111 __ testl(value, Immediate(0xFFFFFF00)); | 3114 __ testl(value, Immediate(0xFFFFFF00)); |
3112 __ j(zero, &done); | 3115 __ j(zero, &done, Label::kNear); |
3113 __ setcc(negative, value); // 1 if negative, 0 if positive. | 3116 __ setcc(negative, value); // 1 if negative, 0 if positive. |
3114 __ decb(value); // 0 if negative, 255 if positive. | 3117 __ decb(value); // 0 if negative, 255 if positive. |
3115 __ bind(&done); | 3118 __ bind(&done); |
3116 __ movb(Operand(external_pointer, key, times_1, 0), value); | 3119 __ movb(Operand(external_pointer, key, times_1, 0), value); |
3117 } | 3120 } |
3118 break; | 3121 break; |
3119 case kExternalByteArray: | 3122 case kExternalByteArray: |
3120 case kExternalUnsignedByteArray: | 3123 case kExternalUnsignedByteArray: |
3121 __ movb(Operand(external_pointer, key, times_1, 0), value); | 3124 __ movb(Operand(external_pointer, key, times_1, 0), value); |
3122 break; | 3125 break; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3225 return; | 3228 return; |
3226 } | 3229 } |
3227 } else { | 3230 } else { |
3228 index = ToRegister(instr->index()); | 3231 index = ToRegister(instr->index()); |
3229 } | 3232 } |
3230 Register result = ToRegister(instr->result()); | 3233 Register result = ToRegister(instr->result()); |
3231 | 3234 |
3232 DeferredStringCharCodeAt* deferred = | 3235 DeferredStringCharCodeAt* deferred = |
3233 new DeferredStringCharCodeAt(this, instr); | 3236 new DeferredStringCharCodeAt(this, instr); |
3234 | 3237 |
3235 NearLabel flat_string, ascii_string, done; | 3238 Label flat_string, ascii_string, done; |
3236 | 3239 |
3237 // Fetch the instance type of the receiver into result register. | 3240 // Fetch the instance type of the receiver into result register. |
3238 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 3241 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
3239 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3242 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
3240 | 3243 |
3241 // We need special handling for non-sequential strings. | 3244 // We need special handling for non-sequential strings. |
3242 STATIC_ASSERT(kSeqStringTag == 0); | 3245 STATIC_ASSERT(kSeqStringTag == 0); |
3243 __ testb(result, Immediate(kStringRepresentationMask)); | 3246 __ testb(result, Immediate(kStringRepresentationMask)); |
3244 __ j(zero, &flat_string); | 3247 __ j(zero, &flat_string, Label::kNear); |
3245 | 3248 |
3246 // Handle cons strings and go to deferred code for the rest. | 3249 // Handle cons strings and go to deferred code for the rest. |
3247 __ testb(result, Immediate(kIsConsStringMask)); | 3250 __ testb(result, Immediate(kIsConsStringMask)); |
3248 __ j(zero, deferred->entry()); | 3251 __ j(zero, deferred->entry()); |
3249 | 3252 |
3250 // ConsString. | 3253 // ConsString. |
3251 // Check whether the right hand side is the empty string (i.e. if | 3254 // Check whether the right hand side is the empty string (i.e. if |
3252 // this is really a flat string in a cons string). If that is not | 3255 // this is really a flat string in a cons string). If that is not |
3253 // the case we would rather go to the runtime system now to flatten | 3256 // the case we would rather go to the runtime system now to flatten |
3254 // the string. | 3257 // the string. |
3255 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), | 3258 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), |
3256 Heap::kEmptyStringRootIndex); | 3259 Heap::kEmptyStringRootIndex); |
3257 __ j(not_equal, deferred->entry()); | 3260 __ j(not_equal, deferred->entry()); |
3258 // Get the first of the two strings and load its instance type. | 3261 // Get the first of the two strings and load its instance type. |
3259 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); | 3262 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); |
3260 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 3263 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
3261 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3264 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
3262 // If the first cons component is also non-flat, then go to runtime. | 3265 // If the first cons component is also non-flat, then go to runtime. |
3263 STATIC_ASSERT(kSeqStringTag == 0); | 3266 STATIC_ASSERT(kSeqStringTag == 0); |
3264 __ testb(result, Immediate(kStringRepresentationMask)); | 3267 __ testb(result, Immediate(kStringRepresentationMask)); |
3265 __ j(not_zero, deferred->entry()); | 3268 __ j(not_zero, deferred->entry()); |
3266 | 3269 |
3267 // Check for ASCII or two-byte string. | 3270 // Check for ASCII or two-byte string. |
3268 __ bind(&flat_string); | 3271 __ bind(&flat_string); |
3269 STATIC_ASSERT(kAsciiStringTag != 0); | 3272 STATIC_ASSERT(kAsciiStringTag != 0); |
3270 __ testb(result, Immediate(kStringEncodingMask)); | 3273 __ testb(result, Immediate(kStringEncodingMask)); |
3271 __ j(not_zero, &ascii_string); | 3274 __ j(not_zero, &ascii_string, Label::kNear); |
3272 | 3275 |
3273 // Two-byte string. | 3276 // Two-byte string. |
3274 // Load the two-byte character code into the result register. | 3277 // Load the two-byte character code into the result register. |
3275 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 3278 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
3276 if (instr->index()->IsConstantOperand()) { | 3279 if (instr->index()->IsConstantOperand()) { |
3277 __ movzxwl(result, | 3280 __ movzxwl(result, |
3278 FieldOperand(string, | 3281 FieldOperand(string, |
3279 SeqTwoByteString::kHeaderSize + | 3282 SeqTwoByteString::kHeaderSize + |
3280 (kUC16Size * const_index))); | 3283 (kUC16Size * const_index))); |
3281 } else { | 3284 } else { |
3282 __ movzxwl(result, FieldOperand(string, | 3285 __ movzxwl(result, FieldOperand(string, |
3283 index, | 3286 index, |
3284 times_2, | 3287 times_2, |
3285 SeqTwoByteString::kHeaderSize)); | 3288 SeqTwoByteString::kHeaderSize)); |
3286 } | 3289 } |
3287 __ jmp(&done); | 3290 __ jmp(&done, Label::kNear); |
3288 | 3291 |
3289 // ASCII string. | 3292 // ASCII string. |
3290 // Load the byte into the result register. | 3293 // Load the byte into the result register. |
3291 __ bind(&ascii_string); | 3294 __ bind(&ascii_string); |
3292 if (instr->index()->IsConstantOperand()) { | 3295 if (instr->index()->IsConstantOperand()) { |
3293 __ movzxbl(result, FieldOperand(string, | 3296 __ movzxbl(result, FieldOperand(string, |
3294 SeqAsciiString::kHeaderSize + const_index)); | 3297 SeqAsciiString::kHeaderSize + const_index)); |
3295 } else { | 3298 } else { |
3296 __ movzxbl(result, FieldOperand(string, | 3299 __ movzxbl(result, FieldOperand(string, |
3297 index, | 3300 index, |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3467 Condition is_smi = __ CheckSmi(input); | 3470 Condition is_smi = __ CheckSmi(input); |
3468 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 3471 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
3469 } | 3472 } |
3470 __ SmiToInteger32(input, input); | 3473 __ SmiToInteger32(input, input); |
3471 } | 3474 } |
3472 | 3475 |
3473 | 3476 |
3474 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3477 void LCodeGen::EmitNumberUntagD(Register input_reg, |
3475 XMMRegister result_reg, | 3478 XMMRegister result_reg, |
3476 LEnvironment* env) { | 3479 LEnvironment* env) { |
3477 NearLabel load_smi, heap_number, done; | 3480 NearLabel load_smi; |
| 3481 Label heap_number, done; |
3478 | 3482 |
3479 // Smi check. | 3483 // Smi check. |
3480 __ JumpIfSmi(input_reg, &load_smi); | 3484 __ JumpIfSmi(input_reg, &load_smi); |
3481 | 3485 |
3482 // Heap number map check. | 3486 // Heap number map check. |
3483 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3487 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3484 Heap::kHeapNumberMapRootIndex); | 3488 Heap::kHeapNumberMapRootIndex); |
3485 __ j(equal, &heap_number); | 3489 __ j(equal, &heap_number, Label::kNear); |
3486 | 3490 |
3487 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 3491 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
3488 DeoptimizeIf(not_equal, env); | 3492 DeoptimizeIf(not_equal, env); |
3489 | 3493 |
3490 // Convert undefined to NaN. Compute NaN as 0/0. | 3494 // Convert undefined to NaN. Compute NaN as 0/0. |
3491 __ xorps(result_reg, result_reg); | 3495 __ xorps(result_reg, result_reg); |
3492 __ divsd(result_reg, result_reg); | 3496 __ divsd(result_reg, result_reg); |
3493 __ jmp(&done); | 3497 __ jmp(&done, Label::kNear); |
3494 | 3498 |
3495 // Heap number to XMM conversion. | 3499 // Heap number to XMM conversion. |
3496 __ bind(&heap_number); | 3500 __ bind(&heap_number); |
3497 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3501 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3498 __ jmp(&done); | 3502 __ jmp(&done, Label::kNear); |
3499 | 3503 |
3500 // Smi to XMM conversion | 3504 // Smi to XMM conversion |
3501 __ bind(&load_smi); | 3505 __ bind(&load_smi); |
3502 __ SmiToInteger32(kScratchRegister, input_reg); | 3506 __ SmiToInteger32(kScratchRegister, input_reg); |
3503 __ cvtlsi2sd(result_reg, kScratchRegister); | 3507 __ cvtlsi2sd(result_reg, kScratchRegister); |
3504 __ bind(&done); | 3508 __ bind(&done); |
3505 } | 3509 } |
3506 | 3510 |
3507 | 3511 |
3508 class DeferredTaggedToI: public LDeferredCode { | 3512 class DeferredTaggedToI: public LDeferredCode { |
3509 public: | 3513 public: |
3510 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3514 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
3511 : LDeferredCode(codegen), instr_(instr) { } | 3515 : LDeferredCode(codegen), instr_(instr) { } |
3512 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3516 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
3513 private: | 3517 private: |
3514 LTaggedToI* instr_; | 3518 LTaggedToI* instr_; |
3515 }; | 3519 }; |
3516 | 3520 |
3517 | 3521 |
3518 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3522 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
3519 NearLabel done, heap_number; | 3523 Label done, heap_number; |
3520 Register input_reg = ToRegister(instr->InputAt(0)); | 3524 Register input_reg = ToRegister(instr->InputAt(0)); |
3521 | 3525 |
3522 // Heap number map check. | 3526 // Heap number map check. |
3523 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3527 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3524 Heap::kHeapNumberMapRootIndex); | 3528 Heap::kHeapNumberMapRootIndex); |
3525 | 3529 |
3526 if (instr->truncating()) { | 3530 if (instr->truncating()) { |
3527 __ j(equal, &heap_number); | 3531 __ j(equal, &heap_number, Label::kNear); |
3528 // Check for undefined. Undefined is converted to zero for truncating | 3532 // Check for undefined. Undefined is converted to zero for truncating |
3529 // conversions. | 3533 // conversions. |
3530 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 3534 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
3531 DeoptimizeIf(not_equal, instr->environment()); | 3535 DeoptimizeIf(not_equal, instr->environment()); |
3532 __ Set(input_reg, 0); | 3536 __ Set(input_reg, 0); |
3533 __ jmp(&done); | 3537 __ jmp(&done, Label::kNear); |
3534 | 3538 |
3535 __ bind(&heap_number); | 3539 __ bind(&heap_number); |
3536 | 3540 |
3537 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3541 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3538 __ cvttsd2siq(input_reg, xmm0); | 3542 __ cvttsd2siq(input_reg, xmm0); |
3539 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | 3543 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
3540 __ cmpq(input_reg, kScratchRegister); | 3544 __ cmpq(input_reg, kScratchRegister); |
3541 DeoptimizeIf(equal, instr->environment()); | 3545 DeoptimizeIf(equal, instr->environment()); |
3542 } else { | 3546 } else { |
3543 // Deoptimize if we don't have a heap number. | 3547 // Deoptimize if we don't have a heap number. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3604 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); | 3608 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); |
3605 __ cmpq(result_reg, kScratchRegister); | 3609 __ cmpq(result_reg, kScratchRegister); |
3606 DeoptimizeIf(equal, instr->environment()); | 3610 DeoptimizeIf(equal, instr->environment()); |
3607 } else { | 3611 } else { |
3608 __ cvttsd2si(result_reg, input_reg); | 3612 __ cvttsd2si(result_reg, input_reg); |
3609 __ cvtlsi2sd(xmm0, result_reg); | 3613 __ cvtlsi2sd(xmm0, result_reg); |
3610 __ ucomisd(xmm0, input_reg); | 3614 __ ucomisd(xmm0, input_reg); |
3611 DeoptimizeIf(not_equal, instr->environment()); | 3615 DeoptimizeIf(not_equal, instr->environment()); |
3612 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3616 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
3613 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3617 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3614 NearLabel done; | 3618 Label done; |
3615 // The integer converted back is equal to the original. We | 3619 // The integer converted back is equal to the original. We |
3616 // only have to test if we got -0 as an input. | 3620 // only have to test if we got -0 as an input. |
3617 __ testl(result_reg, result_reg); | 3621 __ testl(result_reg, result_reg); |
3618 __ j(not_zero, &done); | 3622 __ j(not_zero, &done, Label::kNear); |
3619 __ movmskpd(result_reg, input_reg); | 3623 __ movmskpd(result_reg, input_reg); |
3620 // Bit 0 contains the sign of the double in input_reg. | 3624 // Bit 0 contains the sign of the double in input_reg. |
3621 // If input was positive, we are ok and return 0, otherwise | 3625 // If input was positive, we are ok and return 0, otherwise |
3622 // deoptimize. | 3626 // deoptimize. |
3623 __ andl(result_reg, Immediate(1)); | 3627 __ andl(result_reg, Immediate(1)); |
3624 DeoptimizeIf(not_zero, instr->environment()); | 3628 DeoptimizeIf(not_zero, instr->environment()); |
3625 __ bind(&done); | 3629 __ bind(&done); |
3626 } | 3630 } |
3627 } | 3631 } |
3628 } | 3632 } |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3776 | 3780 |
3777 | 3781 |
3778 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 3782 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
3779 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 3783 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
3780 __ push(rax); | 3784 __ push(rax); |
3781 CallRuntime(Runtime::kToFastProperties, 1, instr); | 3785 CallRuntime(Runtime::kToFastProperties, 1, instr); |
3782 } | 3786 } |
3783 | 3787 |
3784 | 3788 |
3785 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 3789 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
3786 NearLabel materialized; | 3790 Label materialized; |
3787 // Registers will be used as follows: | 3791 // Registers will be used as follows: |
3788 // rdi = JS function. | 3792 // rdi = JS function. |
3789 // rcx = literals array. | 3793 // rcx = literals array. |
3790 // rbx = regexp literal. | 3794 // rbx = regexp literal. |
3791 // rax = regexp literal clone. | 3795 // rax = regexp literal clone. |
3792 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3796 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3793 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 3797 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
3794 int literal_offset = FixedArray::kHeaderSize + | 3798 int literal_offset = FixedArray::kHeaderSize + |
3795 instr->hydrogen()->literal_index() * kPointerSize; | 3799 instr->hydrogen()->literal_index() * kPointerSize; |
3796 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 3800 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
3797 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 3801 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
3798 __ j(not_equal, &materialized); | 3802 __ j(not_equal, &materialized, Label::kNear); |
3799 | 3803 |
3800 // Create regexp literal using runtime function | 3804 // Create regexp literal using runtime function |
3801 // Result will be in rax. | 3805 // Result will be in rax. |
3802 __ push(rcx); | 3806 __ push(rcx); |
3803 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 3807 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
3804 __ Push(instr->hydrogen()->pattern()); | 3808 __ Push(instr->hydrogen()->pattern()); |
3805 __ Push(instr->hydrogen()->flags()); | 3809 __ Push(instr->hydrogen()->flags()); |
3806 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 3810 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
3807 __ movq(rbx, rax); | 3811 __ movq(rbx, rax); |
3808 | 3812 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3860 EmitPushTaggedOperand(input); | 3864 EmitPushTaggedOperand(input); |
3861 CallRuntime(Runtime::kTypeof, 1, instr); | 3865 CallRuntime(Runtime::kTypeof, 1, instr); |
3862 } | 3866 } |
3863 | 3867 |
3864 | 3868 |
3865 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3869 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
3866 Register input = ToRegister(instr->InputAt(0)); | 3870 Register input = ToRegister(instr->InputAt(0)); |
3867 Register result = ToRegister(instr->result()); | 3871 Register result = ToRegister(instr->result()); |
3868 Label true_label; | 3872 Label true_label; |
3869 Label false_label; | 3873 Label false_label; |
3870 NearLabel done; | 3874 Label done; |
3871 | 3875 |
3872 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3876 Condition final_branch_condition = EmitTypeofIs(&true_label, |
3873 &false_label, | 3877 &false_label, |
3874 input, | 3878 input, |
3875 instr->type_literal()); | 3879 instr->type_literal()); |
3876 __ j(final_branch_condition, &true_label); | 3880 __ j(final_branch_condition, &true_label); |
3877 __ bind(&false_label); | 3881 __ bind(&false_label); |
3878 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 3882 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
3879 __ jmp(&done); | 3883 __ jmp(&done, Label::kNear); |
3880 | 3884 |
3881 __ bind(&true_label); | 3885 __ bind(&true_label); |
3882 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 3886 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
3883 | 3887 |
3884 __ bind(&done); | 3888 __ bind(&done); |
3885 } | 3889 } |
3886 | 3890 |
3887 | 3891 |
3888 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 3892 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
3889 ASSERT(!operand->IsDoubleRegister()); | 3893 ASSERT(!operand->IsDoubleRegister()); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3971 final_branch_condition = never; | 3975 final_branch_condition = never; |
3972 __ jmp(false_label); | 3976 __ jmp(false_label); |
3973 } | 3977 } |
3974 | 3978 |
3975 return final_branch_condition; | 3979 return final_branch_condition; |
3976 } | 3980 } |
3977 | 3981 |
3978 | 3982 |
3979 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | 3983 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
3980 Register result = ToRegister(instr->result()); | 3984 Register result = ToRegister(instr->result()); |
3981 NearLabel true_label; | 3985 Label true_label; |
3982 NearLabel false_label; | 3986 Label done; |
3983 NearLabel done; | |
3984 | 3987 |
3985 EmitIsConstructCall(result); | 3988 EmitIsConstructCall(result); |
3986 __ j(equal, &true_label); | 3989 __ j(equal, &true_label, Label::kNear); |
3987 | 3990 |
3988 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 3991 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
3989 __ jmp(&done); | 3992 __ jmp(&done, Label::kNear); |
3990 | 3993 |
3991 __ bind(&true_label); | 3994 __ bind(&true_label); |
3992 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 3995 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
3993 | 3996 |
3994 | 3997 |
3995 __ bind(&done); | 3998 __ bind(&done); |
3996 } | 3999 } |
3997 | 4000 |
3998 | 4001 |
3999 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4002 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4000 Register temp = ToRegister(instr->TempAt(0)); | 4003 Register temp = ToRegister(instr->TempAt(0)); |
4001 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4004 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4002 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4005 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4003 | 4006 |
4004 EmitIsConstructCall(temp); | 4007 EmitIsConstructCall(temp); |
4005 EmitBranch(true_block, false_block, equal); | 4008 EmitBranch(true_block, false_block, equal); |
4006 } | 4009 } |
4007 | 4010 |
4008 | 4011 |
4009 void LCodeGen::EmitIsConstructCall(Register temp) { | 4012 void LCodeGen::EmitIsConstructCall(Register temp) { |
4010 // Get the frame pointer for the calling frame. | 4013 // Get the frame pointer for the calling frame. |
4011 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 4014 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
4012 | 4015 |
4013 // Skip the arguments adaptor frame if it exists. | 4016 // Skip the arguments adaptor frame if it exists. |
4014 NearLabel check_frame_marker; | 4017 Label check_frame_marker; |
4015 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 4018 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
4016 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 4019 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
4017 __ j(not_equal, &check_frame_marker); | 4020 __ j(not_equal, &check_frame_marker, Label::kNear); |
4018 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 4021 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
4019 | 4022 |
4020 // Check the marker in the calling frame. | 4023 // Check the marker in the calling frame. |
4021 __ bind(&check_frame_marker); | 4024 __ bind(&check_frame_marker); |
4022 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 4025 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
4023 Smi::FromInt(StackFrame::CONSTRUCT)); | 4026 Smi::FromInt(StackFrame::CONSTRUCT)); |
4024 } | 4027 } |
4025 | 4028 |
4026 | 4029 |
4027 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 4030 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4071 // builtin) | 4074 // builtin) |
4072 SafepointGenerator safepoint_generator(this, | 4075 SafepointGenerator safepoint_generator(this, |
4073 pointers, | 4076 pointers, |
4074 env->deoptimization_index()); | 4077 env->deoptimization_index()); |
4075 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4078 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4076 } | 4079 } |
4077 | 4080 |
4078 | 4081 |
4079 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4082 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
4080 // Perform stack overflow check. | 4083 // Perform stack overflow check. |
4081 NearLabel done; | 4084 Label done; |
4082 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 4085 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
4083 __ j(above_equal, &done); | 4086 __ j(above_equal, &done, Label::kNear); |
4084 | 4087 |
4085 StackCheckStub stub; | 4088 StackCheckStub stub; |
4086 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4089 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4087 __ bind(&done); | 4090 __ bind(&done); |
4088 } | 4091 } |
4089 | 4092 |
4090 | 4093 |
4091 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 4094 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
4092 // This is a pseudo-instruction that ensures that the environment here is | 4095 // This is a pseudo-instruction that ensures that the environment here is |
4093 // properly registered for deoptimization and records the assembler's PC | 4096 // properly registered for deoptimization and records the assembler's PC |
4094 // offset. | 4097 // offset. |
4095 LEnvironment* environment = instr->environment(); | 4098 LEnvironment* environment = instr->environment(); |
4096 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), | 4099 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), |
4097 instr->SpilledDoubleRegisterArray()); | 4100 instr->SpilledDoubleRegisterArray()); |
4098 | 4101 |
4099 // If the environment were already registered, we would have no way of | 4102 // If the environment were already registered, we would have no way of |
4100 // backpatching it with the spill slot operands. | 4103 // backpatching it with the spill slot operands. |
4101 ASSERT(!environment->HasBeenRegistered()); | 4104 ASSERT(!environment->HasBeenRegistered()); |
4102 RegisterEnvironmentForDeoptimization(environment); | 4105 RegisterEnvironmentForDeoptimization(environment); |
4103 ASSERT(osr_pc_offset_ == -1); | 4106 ASSERT(osr_pc_offset_ == -1); |
4104 osr_pc_offset_ = masm()->pc_offset(); | 4107 osr_pc_offset_ = masm()->pc_offset(); |
4105 } | 4108 } |
4106 | 4109 |
4107 #undef __ | 4110 #undef __ |
4108 | 4111 |
4109 } } // namespace v8::internal | 4112 } } // namespace v8::internal |
4110 | 4113 |
4111 #endif // V8_TARGET_ARCH_X64 | 4114 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |