| 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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 void LCodeGen::RecordSafepoint( | 633 void LCodeGen::RecordSafepoint( |
| 634 LPointerMap* pointers, | 634 LPointerMap* pointers, |
| 635 Safepoint::Kind kind, | 635 Safepoint::Kind kind, |
| 636 int arguments, | 636 int arguments, |
| 637 int deoptimization_index) { | 637 int deoptimization_index) { |
| 638 ASSERT(kind == expected_safepoint_kind_); | 638 ASSERT(kind == expected_safepoint_kind_); |
| 639 | 639 |
| 640 const ZoneList<LOperand*>* operands = pointers->operands(); | 640 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); |
| 641 | 641 |
| 642 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 642 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 643 kind, arguments, deoptimization_index); | 643 kind, arguments, deoptimization_index); |
| 644 for (int i = 0; i < operands->length(); i++) { | 644 for (int i = 0; i < operands->length(); i++) { |
| 645 LOperand* pointer = operands->at(i); | 645 LOperand* pointer = operands->at(i); |
| 646 if (pointer->IsStackSlot()) { | 646 if (pointer->IsStackSlot()) { |
| 647 safepoint.DefinePointerSlot(pointer->index()); | 647 safepoint.DefinePointerSlot(pointer->index()); |
| 648 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 648 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 649 safepoint.DefinePointerRegister(ToRegister(pointer)); | 649 safepoint.DefinePointerRegister(ToRegister(pointer)); |
| 650 } | 650 } |
| (...skipping 127 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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 Register result = ToRegister(instr->result()); | 1196 Register result = ToRegister(instr->result()); |
| 1197 Register array = ToRegister(instr->InputAt(0)); | 1197 Register array = ToRegister(instr->InputAt(0)); |
| 1198 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset)); | 1198 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset)); |
| 1199 } | 1199 } |
| 1200 | 1200 |
| 1201 | 1201 |
| 1202 void LCodeGen::DoValueOf(LValueOf* instr) { | 1202 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1203 Register input = ToRegister(instr->InputAt(0)); | 1203 Register input = ToRegister(instr->InputAt(0)); |
| 1204 Register result = ToRegister(instr->result()); | 1204 Register result = ToRegister(instr->result()); |
| 1205 ASSERT(input.is(result)); | 1205 ASSERT(input.is(result)); |
| 1206 NearLabel done; | 1206 Label done; |
| 1207 // If the object is a smi return the object. | 1207 // If the object is a smi return the object. |
| 1208 __ JumpIfSmi(input, &done); | 1208 __ JumpIfSmi(input, &done, Label::kNear); |
| 1209 | 1209 |
| 1210 // If the object is not a value type, return the object. | 1210 // If the object is not a value type, return the object. |
| 1211 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); | 1211 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); |
| 1212 __ j(not_equal, &done); | 1212 __ j(not_equal, &done, Label::kNear); |
| 1213 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); | 1213 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); |
| 1214 | 1214 |
| 1215 __ bind(&done); | 1215 __ bind(&done); |
| 1216 } | 1216 } |
| 1217 | 1217 |
| 1218 | 1218 |
| 1219 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1219 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1220 LOperand* input = instr->InputAt(0); | 1220 LOperand* input = instr->InputAt(0); |
| 1221 ASSERT(input->Equals(instr->result())); | 1221 ASSERT(input->Equals(instr->result())); |
| 1222 __ not_(ToRegister(input)); | 1222 __ not_(ToRegister(input)); |
| (...skipping 137 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()); |
| 1548 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1548 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1549 | 1549 |
| 1550 __ cmpq(left, right); | 1550 __ cmpq(left, right); |
| 1551 EmitBranch(true_block, false_block, equal); | 1551 EmitBranch(true_block, false_block, equal); |
| 1552 } | 1552 } |
| 1553 | 1553 |
| 1554 | 1554 |
| 1555 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) { |
| 1556 Register left = ToRegister(instr->InputAt(0)); |
| 1557 Register right = ToRegister(instr->InputAt(1)); |
| 1558 Register result = ToRegister(instr->result()); |
| 1559 |
| 1560 Label done; |
| 1561 __ cmpq(left, right); |
| 1562 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1563 __ j(not_equal, &done, Label::kNear); |
| 1564 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1565 __ bind(&done); |
| 1566 } |
| 1567 |
| 1568 |
| 1569 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) { |
| 1570 Register left = ToRegister(instr->InputAt(0)); |
| 1571 Register right = ToRegister(instr->InputAt(1)); |
| 1572 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1573 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1574 |
| 1575 __ cmpq(left, right); |
| 1576 EmitBranch(true_block, false_block, equal); |
| 1577 } |
| 1578 |
| 1579 |
| 1555 void LCodeGen::DoIsNull(LIsNull* instr) { | 1580 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1556 Register reg = ToRegister(instr->InputAt(0)); | 1581 Register reg = ToRegister(instr->InputAt(0)); |
| 1557 Register result = ToRegister(instr->result()); | 1582 Register result = ToRegister(instr->result()); |
| 1558 | 1583 |
| 1559 // If the expression is known to be a smi, then it's | 1584 // If the expression is known to be a smi, then it's |
| 1560 // definitely not null. Materialize false. | 1585 // definitely not null. Materialize false. |
| 1561 // Consider adding other type and representation tests too. | 1586 // Consider adding other type and representation tests too. |
| 1562 if (instr->hydrogen()->value()->type().IsSmi()) { | 1587 if (instr->hydrogen()->value()->type().IsSmi()) { |
| 1563 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1588 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1564 return; | 1589 return; |
| 1565 } | 1590 } |
| 1566 | 1591 |
| 1567 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1592 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1568 if (instr->is_strict()) { | 1593 if (instr->is_strict()) { |
| 1569 ASSERT(Heap::kTrueValueRootIndex >= 0); | 1594 ASSERT(Heap::kTrueValueRootIndex >= 0); |
| 1570 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | 1595 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
| 1571 NearLabel load; | 1596 Label load; |
| 1572 __ j(equal, &load); | 1597 __ j(equal, &load, Label::kNear); |
| 1573 __ Set(result, Heap::kFalseValueRootIndex); | 1598 __ Set(result, Heap::kFalseValueRootIndex); |
| 1574 __ bind(&load); | 1599 __ bind(&load); |
| 1575 __ LoadRootIndexed(result, result, 0); | 1600 __ LoadRootIndexed(result, result, 0); |
| 1576 } else { | 1601 } else { |
| 1577 NearLabel true_value, false_value, done; | 1602 Label false_value, true_value, done; |
| 1578 __ j(equal, &true_value); | 1603 __ j(equal, &true_value, Label::kNear); |
| 1579 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1604 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1580 __ j(equal, &true_value); | 1605 __ j(equal, &true_value, Label::kNear); |
| 1581 __ JumpIfSmi(reg, &false_value); | 1606 __ JumpIfSmi(reg, &false_value, Label::kNear); |
| 1582 // Check for undetectable objects by looking in the bit field in | 1607 // Check for undetectable objects by looking in the bit field in |
| 1583 // the map. The object has already been smi checked. | 1608 // the map. The object has already been smi checked. |
| 1584 Register scratch = result; | 1609 Register scratch = result; |
| 1585 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1610 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1586 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1611 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
| 1587 Immediate(1 << Map::kIsUndetectable)); | 1612 Immediate(1 << Map::kIsUndetectable)); |
| 1588 __ j(not_zero, &true_value); | 1613 __ j(not_zero, &true_value, Label::kNear); |
| 1589 __ bind(&false_value); | 1614 __ bind(&false_value); |
| 1590 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1615 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1591 __ jmp(&done); | 1616 __ jmp(&done, Label::kNear); |
| 1592 __ bind(&true_value); | 1617 __ bind(&true_value); |
| 1593 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1618 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1594 __ bind(&done); | 1619 __ bind(&done); |
| 1595 } | 1620 } |
| 1596 } | 1621 } |
| 1597 | 1622 |
| 1598 | 1623 |
| 1599 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1624 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1600 Register reg = ToRegister(instr->InputAt(0)); | 1625 Register reg = ToRegister(instr->InputAt(0)); |
| 1601 | 1626 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1716 Register input = ToRegister(instr->InputAt(0)); | 1741 Register input = ToRegister(instr->InputAt(0)); |
| 1717 is_smi = masm()->CheckSmi(input); | 1742 is_smi = masm()->CheckSmi(input); |
| 1718 } else { | 1743 } else { |
| 1719 Operand input = ToOperand(instr->InputAt(0)); | 1744 Operand input = ToOperand(instr->InputAt(0)); |
| 1720 is_smi = masm()->CheckSmi(input); | 1745 is_smi = masm()->CheckSmi(input); |
| 1721 } | 1746 } |
| 1722 EmitBranch(true_block, false_block, is_smi); | 1747 EmitBranch(true_block, false_block, is_smi); |
| 1723 } | 1748 } |
| 1724 | 1749 |
| 1725 | 1750 |
| 1751 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) { |
| 1752 Register input = ToRegister(instr->InputAt(0)); |
| 1753 Register result = ToRegister(instr->result()); |
| 1754 |
| 1755 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1756 Label false_label, done; |
| 1757 __ JumpIfSmi(input, &false_label); |
| 1758 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); |
| 1759 __ testb(FieldOperand(result, Map::kBitFieldOffset), |
| 1760 Immediate(1 << Map::kIsUndetectable)); |
| 1761 __ j(zero, &false_label); |
| 1762 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1763 __ jmp(&done); |
| 1764 __ bind(&false_label); |
| 1765 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1766 __ bind(&done); |
| 1767 } |
| 1768 |
| 1769 |
| 1770 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 1771 Register input = ToRegister(instr->InputAt(0)); |
| 1772 Register temp = ToRegister(instr->TempAt(0)); |
| 1773 |
| 1774 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1775 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1776 |
| 1777 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
| 1778 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 1779 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
| 1780 Immediate(1 << Map::kIsUndetectable)); |
| 1781 EmitBranch(true_block, false_block, not_zero); |
| 1782 } |
| 1783 |
| 1784 |
| 1726 static InstanceType TestType(HHasInstanceType* instr) { | 1785 static InstanceType TestType(HHasInstanceType* instr) { |
| 1727 InstanceType from = instr->from(); | 1786 InstanceType from = instr->from(); |
| 1728 InstanceType to = instr->to(); | 1787 InstanceType to = instr->to(); |
| 1729 if (from == FIRST_TYPE) return to; | 1788 if (from == FIRST_TYPE) return to; |
| 1730 ASSERT(from == to || to == LAST_TYPE); | 1789 ASSERT(from == to || to == LAST_TYPE); |
| 1731 return from; | 1790 return from; |
| 1732 } | 1791 } |
| 1733 | 1792 |
| 1734 | 1793 |
| 1735 static Condition BranchCondition(HHasInstanceType* instr) { | 1794 static Condition BranchCondition(HHasInstanceType* instr) { |
| 1736 InstanceType from = instr->from(); | 1795 InstanceType from = instr->from(); |
| 1737 InstanceType to = instr->to(); | 1796 InstanceType to = instr->to(); |
| 1738 if (from == to) return equal; | 1797 if (from == to) return equal; |
| 1739 if (to == LAST_TYPE) return above_equal; | 1798 if (to == LAST_TYPE) return above_equal; |
| 1740 if (from == FIRST_TYPE) return below_equal; | 1799 if (from == FIRST_TYPE) return below_equal; |
| 1741 UNREACHABLE(); | 1800 UNREACHABLE(); |
| 1742 return equal; | 1801 return equal; |
| 1743 } | 1802 } |
| 1744 | 1803 |
| 1745 | 1804 |
| 1746 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1805 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1747 Register input = ToRegister(instr->InputAt(0)); | 1806 Register input = ToRegister(instr->InputAt(0)); |
| 1748 Register result = ToRegister(instr->result()); | 1807 Register result = ToRegister(instr->result()); |
| 1749 | 1808 |
| 1750 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1809 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1751 __ testl(input, Immediate(kSmiTagMask)); | 1810 __ testl(input, Immediate(kSmiTagMask)); |
| 1752 NearLabel done, is_false; | 1811 Label done, is_false; |
| 1753 __ j(zero, &is_false); | 1812 __ j(zero, &is_false); |
| 1754 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | 1813 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
| 1755 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); | 1814 __ j(NegateCondition(BranchCondition(instr->hydrogen())), |
| 1815 &is_false, Label::kNear); |
| 1756 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1816 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1757 __ jmp(&done); | 1817 __ jmp(&done, Label::kNear); |
| 1758 __ bind(&is_false); | 1818 __ bind(&is_false); |
| 1759 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1819 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1760 __ bind(&done); | 1820 __ bind(&done); |
| 1761 } | 1821 } |
| 1762 | 1822 |
| 1763 | 1823 |
| 1764 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1824 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1765 Register input = ToRegister(instr->InputAt(0)); | 1825 Register input = ToRegister(instr->InputAt(0)); |
| 1766 | 1826 |
| 1767 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1827 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1791 | 1851 |
| 1792 | 1852 |
| 1793 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1853 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1794 Register input = ToRegister(instr->InputAt(0)); | 1854 Register input = ToRegister(instr->InputAt(0)); |
| 1795 Register result = ToRegister(instr->result()); | 1855 Register result = ToRegister(instr->result()); |
| 1796 | 1856 |
| 1797 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1857 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1798 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1858 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1799 __ testl(FieldOperand(input, String::kHashFieldOffset), | 1859 __ testl(FieldOperand(input, String::kHashFieldOffset), |
| 1800 Immediate(String::kContainsCachedArrayIndexMask)); | 1860 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1801 NearLabel done; | 1861 Label done; |
| 1802 __ j(zero, &done); | 1862 __ j(zero, &done, Label::kNear); |
| 1803 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1863 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1804 __ bind(&done); | 1864 __ bind(&done); |
| 1805 } | 1865 } |
| 1806 | 1866 |
| 1807 | 1867 |
| 1808 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1868 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1809 LHasCachedArrayIndexAndBranch* instr) { | 1869 LHasCachedArrayIndexAndBranch* instr) { |
| 1810 Register input = ToRegister(instr->InputAt(0)); | 1870 Register input = ToRegister(instr->InputAt(0)); |
| 1811 | 1871 |
| 1812 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1872 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. | 1931 // End with the answer in the z flag. |
| 1872 } | 1932 } |
| 1873 | 1933 |
| 1874 | 1934 |
| 1875 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1935 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
| 1876 Register input = ToRegister(instr->InputAt(0)); | 1936 Register input = ToRegister(instr->InputAt(0)); |
| 1877 Register result = ToRegister(instr->result()); | 1937 Register result = ToRegister(instr->result()); |
| 1878 ASSERT(input.is(result)); | 1938 ASSERT(input.is(result)); |
| 1879 Register temp = ToRegister(instr->TempAt(0)); | 1939 Register temp = ToRegister(instr->TempAt(0)); |
| 1880 Handle<String> class_name = instr->hydrogen()->class_name(); | 1940 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1881 NearLabel done; | 1941 Label done; |
| 1882 Label is_true, is_false; | 1942 Label is_true, is_false; |
| 1883 | 1943 |
| 1884 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); | 1944 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); |
| 1885 | 1945 |
| 1886 __ j(not_equal, &is_false); | 1946 __ j(not_equal, &is_false); |
| 1887 | 1947 |
| 1888 __ bind(&is_true); | 1948 __ bind(&is_true); |
| 1889 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1949 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1890 __ jmp(&done); | 1950 __ jmp(&done, Label::kNear); |
| 1891 | 1951 |
| 1892 __ bind(&is_false); | 1952 __ bind(&is_false); |
| 1893 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1953 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1894 __ bind(&done); | 1954 __ bind(&done); |
| 1895 } | 1955 } |
| 1896 | 1956 |
| 1897 | 1957 |
| 1898 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1958 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1899 Register input = ToRegister(instr->InputAt(0)); | 1959 Register input = ToRegister(instr->InputAt(0)); |
| 1900 Register temp = ToRegister(instr->TempAt(0)); | 1960 Register temp = ToRegister(instr->TempAt(0)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1920 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1980 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1921 EmitBranch(true_block, false_block, equal); | 1981 EmitBranch(true_block, false_block, equal); |
| 1922 } | 1982 } |
| 1923 | 1983 |
| 1924 | 1984 |
| 1925 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1985 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1926 InstanceofStub stub(InstanceofStub::kNoFlags); | 1986 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 1927 __ push(ToRegister(instr->InputAt(0))); | 1987 __ push(ToRegister(instr->InputAt(0))); |
| 1928 __ push(ToRegister(instr->InputAt(1))); | 1988 __ push(ToRegister(instr->InputAt(1))); |
| 1929 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1989 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1930 NearLabel true_value, done; | 1990 Label true_value, done; |
| 1931 __ testq(rax, rax); | 1991 __ testq(rax, rax); |
| 1932 __ j(zero, &true_value); | 1992 __ j(zero, &true_value, Label::kNear); |
| 1933 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 1993 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 1934 __ jmp(&done); | 1994 __ jmp(&done, Label::kNear); |
| 1935 __ bind(&true_value); | 1995 __ bind(&true_value); |
| 1936 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 1996 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 1937 __ bind(&done); | 1997 __ bind(&done); |
| 1938 } | 1998 } |
| 1939 | 1999 |
| 1940 | 2000 |
| 1941 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 2001 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1942 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2002 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1943 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2003 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1944 | 2004 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1974 | 2034 |
| 1975 Label done, false_result; | 2035 Label done, false_result; |
| 1976 Register object = ToRegister(instr->InputAt(0)); | 2036 Register object = ToRegister(instr->InputAt(0)); |
| 1977 | 2037 |
| 1978 // A Smi is not an instance of anything. | 2038 // A Smi is not an instance of anything. |
| 1979 __ JumpIfSmi(object, &false_result); | 2039 __ JumpIfSmi(object, &false_result); |
| 1980 | 2040 |
| 1981 // This is the inlined call site instanceof cache. The two occurences of the | 2041 // 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 | 2042 // hole value will be patched to the last map/result pair generated by the |
| 1983 // instanceof stub. | 2043 // instanceof stub. |
| 1984 NearLabel cache_miss; | 2044 Label cache_miss; |
| 1985 // Use a temp register to avoid memory operands with variable lengths. | 2045 // Use a temp register to avoid memory operands with variable lengths. |
| 1986 Register map = ToRegister(instr->TempAt(0)); | 2046 Register map = ToRegister(instr->TempAt(0)); |
| 1987 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 2047 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1988 __ bind(deferred->map_check()); // Label for calculating code patching. | 2048 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1989 __ movq(kScratchRegister, factory()->the_hole_value(), | 2049 __ movq(kScratchRegister, factory()->the_hole_value(), |
| 1990 RelocInfo::EMBEDDED_OBJECT); | 2050 RelocInfo::EMBEDDED_OBJECT); |
| 1991 __ cmpq(map, kScratchRegister); // Patched to cached map. | 2051 __ cmpq(map, kScratchRegister); // Patched to cached map. |
| 1992 __ j(not_equal, &cache_miss); | 2052 __ j(not_equal, &cache_miss, Label::kNear); |
| 1993 // Patched to load either true or false. | 2053 // Patched to load either true or false. |
| 1994 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2054 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
| 1995 #ifdef DEBUG | 2055 #ifdef DEBUG |
| 1996 // Check that the code size between patch label and patch sites is invariant. | 2056 // Check that the code size between patch label and patch sites is invariant. |
| 1997 Label end_of_patched_code; | 2057 Label end_of_patched_code; |
| 1998 __ bind(&end_of_patched_code); | 2058 __ bind(&end_of_patched_code); |
| 1999 ASSERT(true); | 2059 ASSERT(true); |
| 2000 #endif | 2060 #endif |
| 2001 __ jmp(&done); | 2061 __ jmp(&done); |
| 2002 | 2062 |
| 2003 // The inlined call site cache did not match. Check for null and string | 2063 // The inlined call site cache did not match. Check for null and string |
| 2004 // before calling the deferred code. | 2064 // before calling the deferred code. |
| 2005 __ bind(&cache_miss); // Null is not an instance of anything. | 2065 __ bind(&cache_miss); // Null is not an instance of anything. |
| 2006 __ CompareRoot(object, Heap::kNullValueRootIndex); | 2066 __ CompareRoot(object, Heap::kNullValueRootIndex); |
| 2007 __ j(equal, &false_result); | 2067 __ j(equal, &false_result, Label::kNear); |
| 2008 | 2068 |
| 2009 // String values are not instances of anything. | 2069 // String values are not instances of anything. |
| 2010 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); | 2070 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); |
| 2011 | 2071 |
| 2012 __ bind(&false_result); | 2072 __ bind(&false_result); |
| 2013 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2073 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2014 | 2074 |
| 2015 __ bind(deferred->exit()); | 2075 __ bind(deferred->exit()); |
| 2016 __ bind(&done); | 2076 __ bind(&done); |
| 2017 } | 2077 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2064 void LCodeGen::DoCmpT(LCmpT* instr) { | 2124 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2065 Token::Value op = instr->op(); | 2125 Token::Value op = instr->op(); |
| 2066 | 2126 |
| 2067 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2127 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 2068 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2128 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2069 | 2129 |
| 2070 Condition condition = TokenToCondition(op, false); | 2130 Condition condition = TokenToCondition(op, false); |
| 2071 if (op == Token::GT || op == Token::LTE) { | 2131 if (op == Token::GT || op == Token::LTE) { |
| 2072 condition = ReverseCondition(condition); | 2132 condition = ReverseCondition(condition); |
| 2073 } | 2133 } |
| 2074 NearLabel true_value, done; | 2134 Label true_value, done; |
| 2075 __ testq(rax, rax); | 2135 __ testq(rax, rax); |
| 2076 __ j(condition, &true_value); | 2136 __ j(condition, &true_value, Label::kNear); |
| 2077 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2137 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2078 __ jmp(&done); | 2138 __ jmp(&done, Label::kNear); |
| 2079 __ bind(&true_value); | 2139 __ bind(&true_value); |
| 2080 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2140 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 2081 __ bind(&done); | 2141 __ bind(&done); |
| 2082 } | 2142 } |
| 2083 | 2143 |
| 2084 | 2144 |
| 2085 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { | 2145 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
| 2086 Token::Value op = instr->op(); | 2146 Token::Value op = instr->op(); |
| 2087 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2147 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2088 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2148 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 | 2301 |
| 2242 int map_count = instr->hydrogen()->types()->length(); | 2302 int map_count = instr->hydrogen()->types()->length(); |
| 2243 Handle<String> name = instr->hydrogen()->name(); | 2303 Handle<String> name = instr->hydrogen()->name(); |
| 2244 | 2304 |
| 2245 if (map_count == 0) { | 2305 if (map_count == 0) { |
| 2246 ASSERT(instr->hydrogen()->need_generic()); | 2306 ASSERT(instr->hydrogen()->need_generic()); |
| 2247 __ Move(rcx, instr->hydrogen()->name()); | 2307 __ Move(rcx, instr->hydrogen()->name()); |
| 2248 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2308 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2249 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2309 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2250 } else { | 2310 } else { |
| 2251 NearLabel done; | 2311 Label done; |
| 2252 for (int i = 0; i < map_count - 1; ++i) { | 2312 for (int i = 0; i < map_count - 1; ++i) { |
| 2253 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2313 Handle<Map> map = instr->hydrogen()->types()->at(i); |
| 2254 NearLabel next; | 2314 Label next; |
| 2255 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2315 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2256 __ j(not_equal, &next); | 2316 __ j(not_equal, &next, Label::kNear); |
| 2257 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2317 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2258 __ jmp(&done); | 2318 __ jmp(&done, Label::kNear); |
| 2259 __ bind(&next); | 2319 __ bind(&next); |
| 2260 } | 2320 } |
| 2261 Handle<Map> map = instr->hydrogen()->types()->last(); | 2321 Handle<Map> map = instr->hydrogen()->types()->last(); |
| 2262 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2322 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2263 if (instr->hydrogen()->need_generic()) { | 2323 if (instr->hydrogen()->need_generic()) { |
| 2264 NearLabel generic; | 2324 Label generic; |
| 2265 __ j(not_equal, &generic); | 2325 __ j(not_equal, &generic, Label::kNear); |
| 2266 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2326 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2267 __ jmp(&done); | 2327 __ jmp(&done, Label::kNear); |
| 2268 __ bind(&generic); | 2328 __ bind(&generic); |
| 2269 __ Move(rcx, instr->hydrogen()->name()); | 2329 __ Move(rcx, instr->hydrogen()->name()); |
| 2270 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2330 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2271 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2331 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2272 } else { | 2332 } else { |
| 2273 DeoptimizeIf(not_equal, instr->environment()); | 2333 DeoptimizeIf(not_equal, instr->environment()); |
| 2274 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2334 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2275 } | 2335 } |
| 2276 __ bind(&done); | 2336 __ bind(&done); |
| 2277 } | 2337 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2290 | 2350 |
| 2291 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2351 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 2292 Register function = ToRegister(instr->function()); | 2352 Register function = ToRegister(instr->function()); |
| 2293 Register result = ToRegister(instr->result()); | 2353 Register result = ToRegister(instr->result()); |
| 2294 | 2354 |
| 2295 // Check that the function really is a function. | 2355 // Check that the function really is a function. |
| 2296 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2356 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
| 2297 DeoptimizeIf(not_equal, instr->environment()); | 2357 DeoptimizeIf(not_equal, instr->environment()); |
| 2298 | 2358 |
| 2299 // Check whether the function has an instance prototype. | 2359 // Check whether the function has an instance prototype. |
| 2300 NearLabel non_instance; | 2360 Label non_instance; |
| 2301 __ testb(FieldOperand(result, Map::kBitFieldOffset), | 2361 __ testb(FieldOperand(result, Map::kBitFieldOffset), |
| 2302 Immediate(1 << Map::kHasNonInstancePrototype)); | 2362 Immediate(1 << Map::kHasNonInstancePrototype)); |
| 2303 __ j(not_zero, &non_instance); | 2363 __ j(not_zero, &non_instance, Label::kNear); |
| 2304 | 2364 |
| 2305 // Get the prototype or initial map from the function. | 2365 // Get the prototype or initial map from the function. |
| 2306 __ movq(result, | 2366 __ movq(result, |
| 2307 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2367 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2308 | 2368 |
| 2309 // Check that the function has a prototype or an initial map. | 2369 // Check that the function has a prototype or an initial map. |
| 2310 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2370 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2311 DeoptimizeIf(equal, instr->environment()); | 2371 DeoptimizeIf(equal, instr->environment()); |
| 2312 | 2372 |
| 2313 // If the function does not have an initial map, we're done. | 2373 // If the function does not have an initial map, we're done. |
| 2314 NearLabel done; | 2374 Label done; |
| 2315 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); | 2375 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); |
| 2316 __ j(not_equal, &done); | 2376 __ j(not_equal, &done, Label::kNear); |
| 2317 | 2377 |
| 2318 // Get the prototype from the initial map. | 2378 // Get the prototype from the initial map. |
| 2319 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); | 2379 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); |
| 2320 __ jmp(&done); | 2380 __ jmp(&done, Label::kNear); |
| 2321 | 2381 |
| 2322 // Non-instance prototype: Fetch prototype from constructor field | 2382 // Non-instance prototype: Fetch prototype from constructor field |
| 2323 // in the function's map. | 2383 // in the function's map. |
| 2324 __ bind(&non_instance); | 2384 __ bind(&non_instance); |
| 2325 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); | 2385 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); |
| 2326 | 2386 |
| 2327 // All done. | 2387 // All done. |
| 2328 __ bind(&done); | 2388 __ bind(&done); |
| 2329 } | 2389 } |
| 2330 | 2390 |
| 2331 | 2391 |
| 2332 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2392 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2333 Register result = ToRegister(instr->result()); | 2393 Register result = ToRegister(instr->result()); |
| 2334 Register input = ToRegister(instr->InputAt(0)); | 2394 Register input = ToRegister(instr->InputAt(0)); |
| 2335 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); | 2395 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); |
| 2336 if (FLAG_debug_code) { | 2396 if (FLAG_debug_code) { |
| 2337 NearLabel done; | 2397 Label done; |
| 2338 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2398 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
| 2339 Heap::kFixedArrayMapRootIndex); | 2399 Heap::kFixedArrayMapRootIndex); |
| 2340 __ j(equal, &done); | 2400 __ j(equal, &done, Label::kNear); |
| 2341 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2401 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
| 2342 Heap::kFixedCOWArrayMapRootIndex); | 2402 Heap::kFixedCOWArrayMapRootIndex); |
| 2343 __ j(equal, &done); | 2403 __ j(equal, &done, Label::kNear); |
| 2344 Register temp((result.is(rax)) ? rbx : rax); | 2404 Register temp((result.is(rax)) ? rbx : rax); |
| 2345 __ push(temp); | 2405 __ push(temp); |
| 2346 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2406 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); |
| 2347 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 2407 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 2348 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); | 2408 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); |
| 2349 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); | 2409 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); |
| 2350 __ pop(temp); | 2410 __ pop(temp); |
| 2351 __ Check(below, "Check for fast elements failed."); | 2411 __ Check(below, "Check for fast elements failed."); |
| 2352 __ bind(&done); | 2412 __ bind(&done); |
| 2353 } | 2413 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2387 Register result = ToRegister(instr->result()); | 2447 Register result = ToRegister(instr->result()); |
| 2388 ASSERT(result.is(elements)); | 2448 ASSERT(result.is(elements)); |
| 2389 | 2449 |
| 2390 // Load the result. | 2450 // Load the result. |
| 2391 __ movq(result, FieldOperand(elements, | 2451 __ movq(result, FieldOperand(elements, |
| 2392 key, | 2452 key, |
| 2393 times_pointer_size, | 2453 times_pointer_size, |
| 2394 FixedArray::kHeaderSize)); | 2454 FixedArray::kHeaderSize)); |
| 2395 | 2455 |
| 2396 // Check for the hole value. | 2456 // Check for the hole value. |
| 2397 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2457 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2398 DeoptimizeIf(equal, instr->environment()); | 2458 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2459 DeoptimizeIf(equal, instr->environment()); |
| 2460 } |
| 2461 } |
| 2462 |
| 2463 |
| 2464 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer, |
| 2465 LOperand* key, |
| 2466 ExternalArrayType array_type) { |
| 2467 Register external_pointer_reg = ToRegister(external_pointer); |
| 2468 int shift_size = ExternalArrayTypeToShiftSize(array_type); |
| 2469 if (key->IsConstantOperand()) { |
| 2470 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
| 2471 if (constant_value & 0xF0000000) { |
| 2472 Abort("array index constant value too big"); |
| 2473 } |
| 2474 return Operand(external_pointer_reg, constant_value * (1 << shift_size)); |
| 2475 } else { |
| 2476 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 2477 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0); |
| 2478 } |
| 2399 } | 2479 } |
| 2400 | 2480 |
| 2401 | 2481 |
| 2402 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2482 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2403 LLoadKeyedSpecializedArrayElement* instr) { | 2483 LLoadKeyedSpecializedArrayElement* instr) { |
| 2404 Register external_pointer = ToRegister(instr->external_pointer()); | |
| 2405 Register key = ToRegister(instr->key()); | |
| 2406 ExternalArrayType array_type = instr->array_type(); | 2484 ExternalArrayType array_type = instr->array_type(); |
| 2485 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), |
| 2486 instr->key(), array_type)); |
| 2407 if (array_type == kExternalFloatArray) { | 2487 if (array_type == kExternalFloatArray) { |
| 2408 XMMRegister result(ToDoubleRegister(instr->result())); | 2488 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2409 __ movss(result, Operand(external_pointer, key, times_4, 0)); | 2489 __ movss(result, operand); |
| 2410 __ cvtss2sd(result, result); | 2490 __ cvtss2sd(result, result); |
| 2411 } else if (array_type == kExternalDoubleArray) { | 2491 } else if (array_type == kExternalDoubleArray) { |
| 2412 __ movsd(ToDoubleRegister(instr->result()), | 2492 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 2413 Operand(external_pointer, key, times_8, 0)); | |
| 2414 } else { | 2493 } else { |
| 2415 Register result(ToRegister(instr->result())); | 2494 Register result(ToRegister(instr->result())); |
| 2416 switch (array_type) { | 2495 switch (array_type) { |
| 2417 case kExternalByteArray: | 2496 case kExternalByteArray: |
| 2418 __ movsxbq(result, Operand(external_pointer, key, times_1, 0)); | 2497 __ movsxbq(result, operand); |
| 2419 break; | 2498 break; |
| 2420 case kExternalUnsignedByteArray: | 2499 case kExternalUnsignedByteArray: |
| 2421 case kExternalPixelArray: | 2500 case kExternalPixelArray: |
| 2422 __ movzxbq(result, Operand(external_pointer, key, times_1, 0)); | 2501 __ movzxbq(result, operand); |
| 2423 break; | 2502 break; |
| 2424 case kExternalShortArray: | 2503 case kExternalShortArray: |
| 2425 __ movsxwq(result, Operand(external_pointer, key, times_2, 0)); | 2504 __ movsxwq(result, operand); |
| 2426 break; | 2505 break; |
| 2427 case kExternalUnsignedShortArray: | 2506 case kExternalUnsignedShortArray: |
| 2428 __ movzxwq(result, Operand(external_pointer, key, times_2, 0)); | 2507 __ movzxwq(result, operand); |
| 2429 break; | 2508 break; |
| 2430 case kExternalIntArray: | 2509 case kExternalIntArray: |
| 2431 __ movsxlq(result, Operand(external_pointer, key, times_4, 0)); | 2510 __ movsxlq(result, operand); |
| 2432 break; | 2511 break; |
| 2433 case kExternalUnsignedIntArray: | 2512 case kExternalUnsignedIntArray: |
| 2434 __ movl(result, Operand(external_pointer, key, times_4, 0)); | 2513 __ movl(result, operand); |
| 2435 __ testl(result, result); | 2514 __ testl(result, result); |
| 2436 // TODO(danno): we could be more clever here, perhaps having a special | 2515 // TODO(danno): we could be more clever here, perhaps having a special |
| 2437 // version of the stub that detects if the overflow case actually | 2516 // version of the stub that detects if the overflow case actually |
| 2438 // happens, and generate code that returns a double rather than int. | 2517 // happens, and generate code that returns a double rather than int. |
| 2439 DeoptimizeIf(negative, instr->environment()); | 2518 DeoptimizeIf(negative, instr->environment()); |
| 2440 break; | 2519 break; |
| 2441 case kExternalFloatArray: | 2520 case kExternalFloatArray: |
| 2442 case kExternalDoubleArray: | 2521 case kExternalDoubleArray: |
| 2443 UNREACHABLE(); | 2522 UNREACHABLE(); |
| 2444 break; | 2523 break; |
| 2445 } | 2524 } |
| 2446 } | 2525 } |
| 2447 } | 2526 } |
| 2448 | 2527 |
| 2449 | 2528 |
| 2450 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2529 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 2451 ASSERT(ToRegister(instr->object()).is(rdx)); | 2530 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 2452 ASSERT(ToRegister(instr->key()).is(rax)); | 2531 ASSERT(ToRegister(instr->key()).is(rax)); |
| 2453 | 2532 |
| 2454 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2533 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2455 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2534 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2456 } | 2535 } |
| 2457 | 2536 |
| 2458 | 2537 |
| 2459 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2538 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 2460 Register result = ToRegister(instr->result()); | 2539 Register result = ToRegister(instr->result()); |
| 2461 | 2540 |
| 2462 // Check for arguments adapter frame. | 2541 // Check for arguments adapter frame. |
| 2463 NearLabel done, adapted; | 2542 Label done, adapted; |
| 2464 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2543 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2465 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), | 2544 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), |
| 2466 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2545 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2467 __ j(equal, &adapted); | 2546 __ j(equal, &adapted, Label::kNear); |
| 2468 | 2547 |
| 2469 // No arguments adaptor frame. | 2548 // No arguments adaptor frame. |
| 2470 __ movq(result, rbp); | 2549 __ movq(result, rbp); |
| 2471 __ jmp(&done); | 2550 __ jmp(&done, Label::kNear); |
| 2472 | 2551 |
| 2473 // Arguments adaptor frame present. | 2552 // Arguments adaptor frame present. |
| 2474 __ bind(&adapted); | 2553 __ bind(&adapted); |
| 2475 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2554 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2476 | 2555 |
| 2477 // Result is the frame pointer for the frame if not adapted and for the real | 2556 // Result is the frame pointer for the frame if not adapted and for the real |
| 2478 // frame below the adaptor frame if adapted. | 2557 // frame below the adaptor frame if adapted. |
| 2479 __ bind(&done); | 2558 __ bind(&done); |
| 2480 } | 2559 } |
| 2481 | 2560 |
| 2482 | 2561 |
| 2483 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2562 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2484 Register result = ToRegister(instr->result()); | 2563 Register result = ToRegister(instr->result()); |
| 2485 | 2564 |
| 2486 NearLabel done; | 2565 Label done; |
| 2487 | 2566 |
| 2488 // If no arguments adaptor frame the number of arguments is fixed. | 2567 // If no arguments adaptor frame the number of arguments is fixed. |
| 2489 if (instr->InputAt(0)->IsRegister()) { | 2568 if (instr->InputAt(0)->IsRegister()) { |
| 2490 __ cmpq(rbp, ToRegister(instr->InputAt(0))); | 2569 __ cmpq(rbp, ToRegister(instr->InputAt(0))); |
| 2491 } else { | 2570 } else { |
| 2492 __ cmpq(rbp, ToOperand(instr->InputAt(0))); | 2571 __ cmpq(rbp, ToOperand(instr->InputAt(0))); |
| 2493 } | 2572 } |
| 2494 __ movl(result, Immediate(scope()->num_parameters())); | 2573 __ movl(result, Immediate(scope()->num_parameters())); |
| 2495 __ j(equal, &done); | 2574 __ j(equal, &done, Label::kNear); |
| 2496 | 2575 |
| 2497 // Arguments adaptor frame present. Get argument length from there. | 2576 // Arguments adaptor frame present. Get argument length from there. |
| 2498 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2577 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2499 __ SmiToInteger32(result, | 2578 __ SmiToInteger32(result, |
| 2500 Operand(result, | 2579 Operand(result, |
| 2501 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2580 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2502 | 2581 |
| 2503 // Argument length is in result register. | 2582 // Argument length is in result register. |
| 2504 __ bind(&done); | 2583 __ bind(&done); |
| 2505 } | 2584 } |
| 2506 | 2585 |
| 2507 | 2586 |
| 2508 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 2587 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 2509 Register receiver = ToRegister(instr->receiver()); | 2588 Register receiver = ToRegister(instr->receiver()); |
| 2510 Register function = ToRegister(instr->function()); | 2589 Register function = ToRegister(instr->function()); |
| 2511 Register length = ToRegister(instr->length()); | 2590 Register length = ToRegister(instr->length()); |
| 2512 Register elements = ToRegister(instr->elements()); | 2591 Register elements = ToRegister(instr->elements()); |
| 2513 ASSERT(receiver.is(rax)); // Used for parameter count. | 2592 ASSERT(receiver.is(rax)); // Used for parameter count. |
| 2514 ASSERT(function.is(rdi)); // Required by InvokeFunction. | 2593 ASSERT(function.is(rdi)); // Required by InvokeFunction. |
| 2515 ASSERT(ToRegister(instr->result()).is(rax)); | 2594 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2516 | 2595 |
| 2517 // If the receiver is null or undefined, we have to pass the global object | 2596 // If the receiver is null or undefined, we have to pass the global object |
| 2518 // as a receiver. | 2597 // as a receiver. |
| 2519 NearLabel global_object, receiver_ok; | 2598 Label global_object, receiver_ok; |
| 2520 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 2599 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 2521 __ j(equal, &global_object); | 2600 __ j(equal, &global_object, Label::kNear); |
| 2522 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 2601 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
| 2523 __ j(equal, &global_object); | 2602 __ j(equal, &global_object, Label::kNear); |
| 2524 | 2603 |
| 2525 // The receiver should be a JS object. | 2604 // The receiver should be a JS object. |
| 2526 Condition is_smi = __ CheckSmi(receiver); | 2605 Condition is_smi = __ CheckSmi(receiver); |
| 2527 DeoptimizeIf(is_smi, instr->environment()); | 2606 DeoptimizeIf(is_smi, instr->environment()); |
| 2528 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); | 2607 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); |
| 2529 DeoptimizeIf(below, instr->environment()); | 2608 DeoptimizeIf(below, instr->environment()); |
| 2530 __ jmp(&receiver_ok); | 2609 __ jmp(&receiver_ok, Label::kNear); |
| 2531 | 2610 |
| 2532 __ bind(&global_object); | 2611 __ bind(&global_object); |
| 2533 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2612 // 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 | 2613 // if it's better to use it than to explicitly fetch it from the context |
| 2535 // here. | 2614 // here. |
| 2536 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2615 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2537 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2616 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
| 2538 __ bind(&receiver_ok); | 2617 __ bind(&receiver_ok); |
| 2539 | 2618 |
| 2540 // Copy the arguments to this function possibly from the | 2619 // Copy the arguments to this function possibly from the |
| 2541 // adaptor frame below it. | 2620 // adaptor frame below it. |
| 2542 const uint32_t kArgumentsLimit = 1 * KB; | 2621 const uint32_t kArgumentsLimit = 1 * KB; |
| 2543 __ cmpq(length, Immediate(kArgumentsLimit)); | 2622 __ cmpq(length, Immediate(kArgumentsLimit)); |
| 2544 DeoptimizeIf(above, instr->environment()); | 2623 DeoptimizeIf(above, instr->environment()); |
| 2545 | 2624 |
| 2546 __ push(receiver); | 2625 __ push(receiver); |
| 2547 __ movq(receiver, length); | 2626 __ movq(receiver, length); |
| 2548 | 2627 |
| 2549 // Loop through the arguments pushing them onto the execution | 2628 // Loop through the arguments pushing them onto the execution |
| 2550 // stack. | 2629 // stack. |
| 2551 NearLabel invoke, loop; | 2630 Label invoke, loop; |
| 2552 // length is a small non-negative integer, due to the test above. | 2631 // length is a small non-negative integer, due to the test above. |
| 2553 __ testl(length, length); | 2632 __ testl(length, length); |
| 2554 __ j(zero, &invoke); | 2633 __ j(zero, &invoke, Label::kNear); |
| 2555 __ bind(&loop); | 2634 __ bind(&loop); |
| 2556 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 2635 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); |
| 2557 __ decl(length); | 2636 __ decl(length); |
| 2558 __ j(not_zero, &loop); | 2637 __ j(not_zero, &loop); |
| 2559 | 2638 |
| 2560 // Invoke the function. | 2639 // Invoke the function. |
| 2561 __ bind(&invoke); | 2640 __ bind(&invoke); |
| 2562 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 2641 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
| 2563 LPointerMap* pointers = instr->pointer_map(); | 2642 LPointerMap* pointers = instr->pointer_map(); |
| 2564 LEnvironment* env = instr->deoptimization_environment(); | 2643 LEnvironment* env = instr->deoptimization_environment(); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2791 | 2870 |
| 2792 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2871 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2793 const XMMRegister xmm_scratch = xmm0; | 2872 const XMMRegister xmm_scratch = xmm0; |
| 2794 Register output_reg = ToRegister(instr->result()); | 2873 Register output_reg = ToRegister(instr->result()); |
| 2795 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2874 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2796 | 2875 |
| 2797 Label done; | 2876 Label done; |
| 2798 // xmm_scratch = 0.5 | 2877 // xmm_scratch = 0.5 |
| 2799 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); | 2878 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
| 2800 __ movq(xmm_scratch, kScratchRegister); | 2879 __ movq(xmm_scratch, kScratchRegister); |
| 2801 NearLabel below_half; | 2880 Label below_half; |
| 2802 __ ucomisd(xmm_scratch, input_reg); | 2881 __ ucomisd(xmm_scratch, input_reg); |
| 2803 __ j(above, &below_half); // If input_reg is NaN, this doesn't jump. | 2882 // If input_reg is NaN, this doesn't jump. |
| 2883 __ j(above, &below_half, Label::kNear); |
| 2804 // input = input + 0.5 | 2884 // input = input + 0.5 |
| 2805 // This addition might give a result that isn't the correct for | 2885 // 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 | 2886 // rounding, due to loss of precision, but only for a number that's |
| 2807 // so big that the conversion below will overflow anyway. | 2887 // so big that the conversion below will overflow anyway. |
| 2808 __ addsd(input_reg, xmm_scratch); | 2888 __ addsd(input_reg, xmm_scratch); |
| 2809 // Compute Math.floor(input). | 2889 // Compute Math.floor(input). |
| 2810 // Use truncating instruction (OK because input is positive). | 2890 // Use truncating instruction (OK because input is positive). |
| 2811 __ cvttsd2si(output_reg, input_reg); | 2891 __ cvttsd2si(output_reg, input_reg); |
| 2812 // Overflow is signalled with minint. | 2892 // Overflow is signalled with minint. |
| 2813 __ cmpl(output_reg, Immediate(0x80000000)); | 2893 __ cmpl(output_reg, Immediate(0x80000000)); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3085 __ Move(rcx, instr->hydrogen()->name()); | 3165 __ Move(rcx, instr->hydrogen()->name()); |
| 3086 Handle<Code> ic = instr->strict_mode() | 3166 Handle<Code> ic = instr->strict_mode() |
| 3087 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3167 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3088 : isolate()->builtins()->StoreIC_Initialize(); | 3168 : isolate()->builtins()->StoreIC_Initialize(); |
| 3089 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3169 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3090 } | 3170 } |
| 3091 | 3171 |
| 3092 | 3172 |
| 3093 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3173 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 3094 LStoreKeyedSpecializedArrayElement* instr) { | 3174 LStoreKeyedSpecializedArrayElement* instr) { |
| 3095 Register external_pointer = ToRegister(instr->external_pointer()); | |
| 3096 Register key = ToRegister(instr->key()); | |
| 3097 ExternalArrayType array_type = instr->array_type(); | 3175 ExternalArrayType array_type = instr->array_type(); |
| 3176 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), |
| 3177 instr->key(), array_type)); |
| 3098 if (array_type == kExternalFloatArray) { | 3178 if (array_type == kExternalFloatArray) { |
| 3099 XMMRegister value(ToDoubleRegister(instr->value())); | 3179 XMMRegister value(ToDoubleRegister(instr->value())); |
| 3100 __ cvtsd2ss(value, value); | 3180 __ cvtsd2ss(value, value); |
| 3101 __ movss(Operand(external_pointer, key, times_4, 0), value); | 3181 __ movss(operand, value); |
| 3102 } else if (array_type == kExternalDoubleArray) { | 3182 } else if (array_type == kExternalDoubleArray) { |
| 3103 __ movsd(Operand(external_pointer, key, times_8, 0), | 3183 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 3104 ToDoubleRegister(instr->value())); | |
| 3105 } else { | 3184 } else { |
| 3106 Register value(ToRegister(instr->value())); | 3185 Register value(ToRegister(instr->value())); |
| 3107 switch (array_type) { | 3186 switch (array_type) { |
| 3108 case kExternalPixelArray: | 3187 case kExternalPixelArray: |
| 3109 { // Clamp the value to [0..255]. | |
| 3110 NearLabel done; | |
| 3111 __ testl(value, Immediate(0xFFFFFF00)); | |
| 3112 __ j(zero, &done); | |
| 3113 __ setcc(negative, value); // 1 if negative, 0 if positive. | |
| 3114 __ decb(value); // 0 if negative, 255 if positive. | |
| 3115 __ bind(&done); | |
| 3116 __ movb(Operand(external_pointer, key, times_1, 0), value); | |
| 3117 } | |
| 3118 break; | |
| 3119 case kExternalByteArray: | 3188 case kExternalByteArray: |
| 3120 case kExternalUnsignedByteArray: | 3189 case kExternalUnsignedByteArray: |
| 3121 __ movb(Operand(external_pointer, key, times_1, 0), value); | 3190 __ movb(operand, value); |
| 3122 break; | 3191 break; |
| 3123 case kExternalShortArray: | 3192 case kExternalShortArray: |
| 3124 case kExternalUnsignedShortArray: | 3193 case kExternalUnsignedShortArray: |
| 3125 __ movw(Operand(external_pointer, key, times_2, 0), value); | 3194 __ movw(operand, value); |
| 3126 break; | 3195 break; |
| 3127 case kExternalIntArray: | 3196 case kExternalIntArray: |
| 3128 case kExternalUnsignedIntArray: | 3197 case kExternalUnsignedIntArray: |
| 3129 __ movl(Operand(external_pointer, key, times_4, 0), value); | 3198 __ movl(operand, value); |
| 3130 break; | 3199 break; |
| 3131 case kExternalFloatArray: | 3200 case kExternalFloatArray: |
| 3132 case kExternalDoubleArray: | 3201 case kExternalDoubleArray: |
| 3133 UNREACHABLE(); | 3202 UNREACHABLE(); |
| 3134 break; | 3203 break; |
| 3135 } | 3204 } |
| 3136 } | 3205 } |
| 3137 } | 3206 } |
| 3138 | 3207 |
| 3139 | 3208 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3225 return; | 3294 return; |
| 3226 } | 3295 } |
| 3227 } else { | 3296 } else { |
| 3228 index = ToRegister(instr->index()); | 3297 index = ToRegister(instr->index()); |
| 3229 } | 3298 } |
| 3230 Register result = ToRegister(instr->result()); | 3299 Register result = ToRegister(instr->result()); |
| 3231 | 3300 |
| 3232 DeferredStringCharCodeAt* deferred = | 3301 DeferredStringCharCodeAt* deferred = |
| 3233 new DeferredStringCharCodeAt(this, instr); | 3302 new DeferredStringCharCodeAt(this, instr); |
| 3234 | 3303 |
| 3235 NearLabel flat_string, ascii_string, done; | 3304 Label flat_string, ascii_string, done; |
| 3236 | 3305 |
| 3237 // Fetch the instance type of the receiver into result register. | 3306 // Fetch the instance type of the receiver into result register. |
| 3238 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 3307 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 3239 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3308 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 3240 | 3309 |
| 3241 // We need special handling for non-sequential strings. | 3310 // We need special handling for non-sequential strings. |
| 3242 STATIC_ASSERT(kSeqStringTag == 0); | 3311 STATIC_ASSERT(kSeqStringTag == 0); |
| 3243 __ testb(result, Immediate(kStringRepresentationMask)); | 3312 __ testb(result, Immediate(kStringRepresentationMask)); |
| 3244 __ j(zero, &flat_string); | 3313 __ j(zero, &flat_string, Label::kNear); |
| 3245 | 3314 |
| 3246 // Handle cons strings and go to deferred code for the rest. | 3315 // Handle cons strings and go to deferred code for the rest. |
| 3247 __ testb(result, Immediate(kIsConsStringMask)); | 3316 __ testb(result, Immediate(kIsConsStringMask)); |
| 3248 __ j(zero, deferred->entry()); | 3317 __ j(zero, deferred->entry()); |
| 3249 | 3318 |
| 3250 // ConsString. | 3319 // ConsString. |
| 3251 // Check whether the right hand side is the empty string (i.e. if | 3320 // 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 | 3321 // 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 | 3322 // the case we would rather go to the runtime system now to flatten |
| 3254 // the string. | 3323 // the string. |
| 3255 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), | 3324 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), |
| 3256 Heap::kEmptyStringRootIndex); | 3325 Heap::kEmptyStringRootIndex); |
| 3257 __ j(not_equal, deferred->entry()); | 3326 __ j(not_equal, deferred->entry()); |
| 3258 // Get the first of the two strings and load its instance type. | 3327 // Get the first of the two strings and load its instance type. |
| 3259 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); | 3328 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); |
| 3260 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 3329 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 3261 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3330 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 3262 // If the first cons component is also non-flat, then go to runtime. | 3331 // If the first cons component is also non-flat, then go to runtime. |
| 3263 STATIC_ASSERT(kSeqStringTag == 0); | 3332 STATIC_ASSERT(kSeqStringTag == 0); |
| 3264 __ testb(result, Immediate(kStringRepresentationMask)); | 3333 __ testb(result, Immediate(kStringRepresentationMask)); |
| 3265 __ j(not_zero, deferred->entry()); | 3334 __ j(not_zero, deferred->entry()); |
| 3266 | 3335 |
| 3267 // Check for ASCII or two-byte string. | 3336 // Check for ASCII or two-byte string. |
| 3268 __ bind(&flat_string); | 3337 __ bind(&flat_string); |
| 3269 STATIC_ASSERT(kAsciiStringTag != 0); | 3338 STATIC_ASSERT(kAsciiStringTag != 0); |
| 3270 __ testb(result, Immediate(kStringEncodingMask)); | 3339 __ testb(result, Immediate(kStringEncodingMask)); |
| 3271 __ j(not_zero, &ascii_string); | 3340 __ j(not_zero, &ascii_string, Label::kNear); |
| 3272 | 3341 |
| 3273 // Two-byte string. | 3342 // Two-byte string. |
| 3274 // Load the two-byte character code into the result register. | 3343 // Load the two-byte character code into the result register. |
| 3275 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 3344 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 3276 if (instr->index()->IsConstantOperand()) { | 3345 if (instr->index()->IsConstantOperand()) { |
| 3277 __ movzxwl(result, | 3346 __ movzxwl(result, |
| 3278 FieldOperand(string, | 3347 FieldOperand(string, |
| 3279 SeqTwoByteString::kHeaderSize + | 3348 SeqTwoByteString::kHeaderSize + |
| 3280 (kUC16Size * const_index))); | 3349 (kUC16Size * const_index))); |
| 3281 } else { | 3350 } else { |
| 3282 __ movzxwl(result, FieldOperand(string, | 3351 __ movzxwl(result, FieldOperand(string, |
| 3283 index, | 3352 index, |
| 3284 times_2, | 3353 times_2, |
| 3285 SeqTwoByteString::kHeaderSize)); | 3354 SeqTwoByteString::kHeaderSize)); |
| 3286 } | 3355 } |
| 3287 __ jmp(&done); | 3356 __ jmp(&done, Label::kNear); |
| 3288 | 3357 |
| 3289 // ASCII string. | 3358 // ASCII string. |
| 3290 // Load the byte into the result register. | 3359 // Load the byte into the result register. |
| 3291 __ bind(&ascii_string); | 3360 __ bind(&ascii_string); |
| 3292 if (instr->index()->IsConstantOperand()) { | 3361 if (instr->index()->IsConstantOperand()) { |
| 3293 __ movzxbl(result, FieldOperand(string, | 3362 __ movzxbl(result, FieldOperand(string, |
| 3294 SeqAsciiString::kHeaderSize + const_index)); | 3363 SeqAsciiString::kHeaderSize + const_index)); |
| 3295 } else { | 3364 } else { |
| 3296 __ movzxbl(result, FieldOperand(string, | 3365 __ movzxbl(result, FieldOperand(string, |
| 3297 index, | 3366 index, |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3467 Condition is_smi = __ CheckSmi(input); | 3536 Condition is_smi = __ CheckSmi(input); |
| 3468 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 3537 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
| 3469 } | 3538 } |
| 3470 __ SmiToInteger32(input, input); | 3539 __ SmiToInteger32(input, input); |
| 3471 } | 3540 } |
| 3472 | 3541 |
| 3473 | 3542 |
| 3474 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3543 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 3475 XMMRegister result_reg, | 3544 XMMRegister result_reg, |
| 3476 LEnvironment* env) { | 3545 LEnvironment* env) { |
| 3477 NearLabel load_smi, heap_number, done; | 3546 Label load_smi, heap_number, done; |
| 3478 | 3547 |
| 3479 // Smi check. | 3548 // Smi check. |
| 3480 __ JumpIfSmi(input_reg, &load_smi); | 3549 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 3481 | 3550 |
| 3482 // Heap number map check. | 3551 // Heap number map check. |
| 3483 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3552 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3484 Heap::kHeapNumberMapRootIndex); | 3553 Heap::kHeapNumberMapRootIndex); |
| 3485 __ j(equal, &heap_number); | 3554 __ j(equal, &heap_number, Label::kNear); |
| 3486 | 3555 |
| 3487 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 3556 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 3488 DeoptimizeIf(not_equal, env); | 3557 DeoptimizeIf(not_equal, env); |
| 3489 | 3558 |
| 3490 // Convert undefined to NaN. Compute NaN as 0/0. | 3559 // Convert undefined to NaN. Compute NaN as 0/0. |
| 3491 __ xorps(result_reg, result_reg); | 3560 __ xorps(result_reg, result_reg); |
| 3492 __ divsd(result_reg, result_reg); | 3561 __ divsd(result_reg, result_reg); |
| 3493 __ jmp(&done); | 3562 __ jmp(&done, Label::kNear); |
| 3494 | 3563 |
| 3495 // Heap number to XMM conversion. | 3564 // Heap number to XMM conversion. |
| 3496 __ bind(&heap_number); | 3565 __ bind(&heap_number); |
| 3497 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3566 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3498 __ jmp(&done); | 3567 __ jmp(&done, Label::kNear); |
| 3499 | 3568 |
| 3500 // Smi to XMM conversion | 3569 // Smi to XMM conversion |
| 3501 __ bind(&load_smi); | 3570 __ bind(&load_smi); |
| 3502 __ SmiToInteger32(kScratchRegister, input_reg); | 3571 __ SmiToInteger32(kScratchRegister, input_reg); |
| 3503 __ cvtlsi2sd(result_reg, kScratchRegister); | 3572 __ cvtlsi2sd(result_reg, kScratchRegister); |
| 3504 __ bind(&done); | 3573 __ bind(&done); |
| 3505 } | 3574 } |
| 3506 | 3575 |
| 3507 | 3576 |
| 3508 class DeferredTaggedToI: public LDeferredCode { | 3577 class DeferredTaggedToI: public LDeferredCode { |
| 3509 public: | 3578 public: |
| 3510 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3579 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 3511 : LDeferredCode(codegen), instr_(instr) { } | 3580 : LDeferredCode(codegen), instr_(instr) { } |
| 3512 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3581 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 3513 private: | 3582 private: |
| 3514 LTaggedToI* instr_; | 3583 LTaggedToI* instr_; |
| 3515 }; | 3584 }; |
| 3516 | 3585 |
| 3517 | 3586 |
| 3518 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3587 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 3519 NearLabel done, heap_number; | 3588 Label done, heap_number; |
| 3520 Register input_reg = ToRegister(instr->InputAt(0)); | 3589 Register input_reg = ToRegister(instr->InputAt(0)); |
| 3521 | 3590 |
| 3522 // Heap number map check. | 3591 // Heap number map check. |
| 3523 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3592 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3524 Heap::kHeapNumberMapRootIndex); | 3593 Heap::kHeapNumberMapRootIndex); |
| 3525 | 3594 |
| 3526 if (instr->truncating()) { | 3595 if (instr->truncating()) { |
| 3527 __ j(equal, &heap_number); | 3596 __ j(equal, &heap_number, Label::kNear); |
| 3528 // Check for undefined. Undefined is converted to zero for truncating | 3597 // Check for undefined. Undefined is converted to zero for truncating |
| 3529 // conversions. | 3598 // conversions. |
| 3530 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 3599 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 3531 DeoptimizeIf(not_equal, instr->environment()); | 3600 DeoptimizeIf(not_equal, instr->environment()); |
| 3532 __ Set(input_reg, 0); | 3601 __ Set(input_reg, 0); |
| 3533 __ jmp(&done); | 3602 __ jmp(&done, Label::kNear); |
| 3534 | 3603 |
| 3535 __ bind(&heap_number); | 3604 __ bind(&heap_number); |
| 3536 | 3605 |
| 3537 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3606 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3538 __ cvttsd2siq(input_reg, xmm0); | 3607 __ cvttsd2siq(input_reg, xmm0); |
| 3539 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | 3608 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
| 3540 __ cmpq(input_reg, kScratchRegister); | 3609 __ cmpq(input_reg, kScratchRegister); |
| 3541 DeoptimizeIf(equal, instr->environment()); | 3610 DeoptimizeIf(equal, instr->environment()); |
| 3542 } else { | 3611 } else { |
| 3543 // Deoptimize if we don't have a heap number. | 3612 // 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); | 3673 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); |
| 3605 __ cmpq(result_reg, kScratchRegister); | 3674 __ cmpq(result_reg, kScratchRegister); |
| 3606 DeoptimizeIf(equal, instr->environment()); | 3675 DeoptimizeIf(equal, instr->environment()); |
| 3607 } else { | 3676 } else { |
| 3608 __ cvttsd2si(result_reg, input_reg); | 3677 __ cvttsd2si(result_reg, input_reg); |
| 3609 __ cvtlsi2sd(xmm0, result_reg); | 3678 __ cvtlsi2sd(xmm0, result_reg); |
| 3610 __ ucomisd(xmm0, input_reg); | 3679 __ ucomisd(xmm0, input_reg); |
| 3611 DeoptimizeIf(not_equal, instr->environment()); | 3680 DeoptimizeIf(not_equal, instr->environment()); |
| 3612 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3681 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 3613 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3682 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3614 NearLabel done; | 3683 Label done; |
| 3615 // The integer converted back is equal to the original. We | 3684 // The integer converted back is equal to the original. We |
| 3616 // only have to test if we got -0 as an input. | 3685 // only have to test if we got -0 as an input. |
| 3617 __ testl(result_reg, result_reg); | 3686 __ testl(result_reg, result_reg); |
| 3618 __ j(not_zero, &done); | 3687 __ j(not_zero, &done, Label::kNear); |
| 3619 __ movmskpd(result_reg, input_reg); | 3688 __ movmskpd(result_reg, input_reg); |
| 3620 // Bit 0 contains the sign of the double in input_reg. | 3689 // Bit 0 contains the sign of the double in input_reg. |
| 3621 // If input was positive, we are ok and return 0, otherwise | 3690 // If input was positive, we are ok and return 0, otherwise |
| 3622 // deoptimize. | 3691 // deoptimize. |
| 3623 __ andl(result_reg, Immediate(1)); | 3692 __ andl(result_reg, Immediate(1)); |
| 3624 DeoptimizeIf(not_zero, instr->environment()); | 3693 DeoptimizeIf(not_zero, instr->environment()); |
| 3625 __ bind(&done); | 3694 __ bind(&done); |
| 3626 } | 3695 } |
| 3627 } | 3696 } |
| 3628 } | 3697 } |
| 3629 | 3698 |
| 3630 | 3699 |
| 3631 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3700 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 3632 LOperand* input = instr->InputAt(0); | 3701 LOperand* input = instr->InputAt(0); |
| 3633 Condition cc = masm()->CheckSmi(ToRegister(input)); | 3702 Condition cc = masm()->CheckSmi(ToRegister(input)); |
| 3634 DeoptimizeIf(NegateCondition(cc), instr->environment()); | 3703 DeoptimizeIf(NegateCondition(cc), instr->environment()); |
| 3635 } | 3704 } |
| 3636 | 3705 |
| 3637 | 3706 |
| 3638 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 3707 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 3639 LOperand* input = instr->InputAt(0); | 3708 LOperand* input = instr->InputAt(0); |
| 3640 Condition cc = masm()->CheckSmi(ToRegister(input)); | 3709 Condition cc = masm()->CheckSmi(ToRegister(input)); |
| 3641 DeoptimizeIf(cc, instr->environment()); | 3710 DeoptimizeIf(cc, instr->environment()); |
| 3642 } | 3711 } |
| 3643 | 3712 |
| 3644 | 3713 |
| 3645 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3714 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 3646 Register input = ToRegister(instr->InputAt(0)); | 3715 Register input = ToRegister(instr->InputAt(0)); |
| 3647 InstanceType first = instr->hydrogen()->first(); | |
| 3648 InstanceType last = instr->hydrogen()->last(); | |
| 3649 | 3716 |
| 3650 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 3717 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
| 3651 | 3718 |
| 3652 // If there is only one type in the interval check for equality. | 3719 if (instr->hydrogen()->is_interval_check()) { |
| 3653 if (first == last) { | 3720 InstanceType first; |
| 3721 InstanceType last; |
| 3722 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 3723 |
| 3654 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 3724 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
| 3655 Immediate(static_cast<int8_t>(first))); | 3725 Immediate(static_cast<int8_t>(first))); |
| 3656 DeoptimizeIf(not_equal, instr->environment()); | 3726 |
| 3657 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { | 3727 // If there is only one type in the interval check for equality. |
| 3658 // String has a dedicated bit in instance type. | 3728 if (first == last) { |
| 3659 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 3729 DeoptimizeIf(not_equal, instr->environment()); |
| 3660 Immediate(kIsNotStringMask)); | 3730 } else { |
| 3661 DeoptimizeIf(not_zero, instr->environment()); | 3731 DeoptimizeIf(below, instr->environment()); |
| 3732 // Omit check for the last type. |
| 3733 if (last != LAST_TYPE) { |
| 3734 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
| 3735 Immediate(static_cast<int8_t>(last))); |
| 3736 DeoptimizeIf(above, instr->environment()); |
| 3737 } |
| 3738 } |
| 3662 } else { | 3739 } else { |
| 3663 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 3740 uint8_t mask; |
| 3664 Immediate(static_cast<int8_t>(first))); | 3741 uint8_t tag; |
| 3665 DeoptimizeIf(below, instr->environment()); | 3742 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 3666 // Omit check for the last type. | 3743 |
| 3667 if (last != LAST_TYPE) { | 3744 if (IsPowerOf2(mask)) { |
| 3668 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 3745 ASSERT(tag == 0 || IsPowerOf2(tag)); |
| 3669 Immediate(static_cast<int8_t>(last))); | 3746 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
| 3670 DeoptimizeIf(above, instr->environment()); | 3747 Immediate(mask)); |
| 3748 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); |
| 3749 } else { |
| 3750 __ movzxbl(kScratchRegister, |
| 3751 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
| 3752 __ andb(kScratchRegister, Immediate(mask)); |
| 3753 __ cmpb(kScratchRegister, Immediate(tag)); |
| 3754 DeoptimizeIf(not_equal, instr->environment()); |
| 3671 } | 3755 } |
| 3672 } | 3756 } |
| 3673 } | 3757 } |
| 3674 | 3758 |
| 3675 | 3759 |
| 3676 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3760 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 3677 ASSERT(instr->InputAt(0)->IsRegister()); | 3761 ASSERT(instr->InputAt(0)->IsRegister()); |
| 3678 Register reg = ToRegister(instr->InputAt(0)); | 3762 Register reg = ToRegister(instr->InputAt(0)); |
| 3679 __ Cmp(reg, instr->hydrogen()->target()); | 3763 __ Cmp(reg, instr->hydrogen()->target()); |
| 3680 DeoptimizeIf(not_equal, instr->environment()); | 3764 DeoptimizeIf(not_equal, instr->environment()); |
| 3681 } | 3765 } |
| 3682 | 3766 |
| 3683 | 3767 |
| 3684 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3768 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 3685 LOperand* input = instr->InputAt(0); | 3769 LOperand* input = instr->InputAt(0); |
| 3686 ASSERT(input->IsRegister()); | 3770 ASSERT(input->IsRegister()); |
| 3687 Register reg = ToRegister(input); | 3771 Register reg = ToRegister(input); |
| 3688 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3772 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3689 instr->hydrogen()->map()); | 3773 instr->hydrogen()->map()); |
| 3690 DeoptimizeIf(not_equal, instr->environment()); | 3774 DeoptimizeIf(not_equal, instr->environment()); |
| 3691 } | 3775 } |
| 3692 | 3776 |
| 3693 | 3777 |
| 3778 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 3779 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 3780 Register result_reg = ToRegister(instr->result()); |
| 3781 Register temp_reg = ToRegister(instr->TempAt(0)); |
| 3782 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); |
| 3783 } |
| 3784 |
| 3785 |
| 3786 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 3787 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 3788 Register value_reg = ToRegister(instr->result()); |
| 3789 __ ClampUint8(value_reg); |
| 3790 } |
| 3791 |
| 3792 |
| 3793 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 3794 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 3795 Register input_reg = ToRegister(instr->unclamped()); |
| 3796 Register temp_reg = ToRegister(instr->TempAt(0)); |
| 3797 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1)); |
| 3798 Label is_smi, done, heap_number; |
| 3799 |
| 3800 __ JumpIfSmi(input_reg, &is_smi); |
| 3801 |
| 3802 // Check for heap number |
| 3803 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3804 factory()->heap_number_map()); |
| 3805 __ j(equal, &heap_number, Label::kNear); |
| 3806 |
| 3807 // Check for undefined. Undefined is converted to zero for clamping |
| 3808 // conversions. |
| 3809 __ Cmp(input_reg, factory()->undefined_value()); |
| 3810 DeoptimizeIf(not_equal, instr->environment()); |
| 3811 __ movq(input_reg, Immediate(0)); |
| 3812 __ jmp(&done, Label::kNear); |
| 3813 |
| 3814 // Heap number |
| 3815 __ bind(&heap_number); |
| 3816 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3817 __ ClampDoubleToUint8(xmm0, temp_xmm_reg, input_reg, temp_reg); |
| 3818 __ jmp(&done, Label::kNear); |
| 3819 |
| 3820 // smi |
| 3821 __ bind(&is_smi); |
| 3822 __ SmiToInteger32(input_reg, input_reg); |
| 3823 __ ClampUint8(input_reg); |
| 3824 |
| 3825 __ bind(&done); |
| 3826 } |
| 3827 |
| 3828 |
| 3694 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { | 3829 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { |
| 3695 if (heap()->InNewSpace(*object)) { | 3830 if (heap()->InNewSpace(*object)) { |
| 3696 Handle<JSGlobalPropertyCell> cell = | 3831 Handle<JSGlobalPropertyCell> cell = |
| 3697 factory()->NewJSGlobalPropertyCell(object); | 3832 factory()->NewJSGlobalPropertyCell(object); |
| 3698 __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 3833 __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
| 3699 __ movq(result, Operand(result, 0)); | 3834 __ movq(result, Operand(result, 0)); |
| 3700 } else { | 3835 } else { |
| 3701 __ Move(result, object); | 3836 __ Move(result, object); |
| 3702 } | 3837 } |
| 3703 } | 3838 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3776 | 3911 |
| 3777 | 3912 |
| 3778 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 3913 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 3779 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 3914 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
| 3780 __ push(rax); | 3915 __ push(rax); |
| 3781 CallRuntime(Runtime::kToFastProperties, 1, instr); | 3916 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 3782 } | 3917 } |
| 3783 | 3918 |
| 3784 | 3919 |
| 3785 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 3920 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 3786 NearLabel materialized; | 3921 Label materialized; |
| 3787 // Registers will be used as follows: | 3922 // Registers will be used as follows: |
| 3788 // rdi = JS function. | 3923 // rdi = JS function. |
| 3789 // rcx = literals array. | 3924 // rcx = literals array. |
| 3790 // rbx = regexp literal. | 3925 // rbx = regexp literal. |
| 3791 // rax = regexp literal clone. | 3926 // rax = regexp literal clone. |
| 3792 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3927 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3793 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 3928 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 3794 int literal_offset = FixedArray::kHeaderSize + | 3929 int literal_offset = FixedArray::kHeaderSize + |
| 3795 instr->hydrogen()->literal_index() * kPointerSize; | 3930 instr->hydrogen()->literal_index() * kPointerSize; |
| 3796 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 3931 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
| 3797 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 3932 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 3798 __ j(not_equal, &materialized); | 3933 __ j(not_equal, &materialized, Label::kNear); |
| 3799 | 3934 |
| 3800 // Create regexp literal using runtime function | 3935 // Create regexp literal using runtime function |
| 3801 // Result will be in rax. | 3936 // Result will be in rax. |
| 3802 __ push(rcx); | 3937 __ push(rcx); |
| 3803 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 3938 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
| 3804 __ Push(instr->hydrogen()->pattern()); | 3939 __ Push(instr->hydrogen()->pattern()); |
| 3805 __ Push(instr->hydrogen()->flags()); | 3940 __ Push(instr->hydrogen()->flags()); |
| 3806 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 3941 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
| 3807 __ movq(rbx, rax); | 3942 __ movq(rbx, rax); |
| 3808 | 3943 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3860 EmitPushTaggedOperand(input); | 3995 EmitPushTaggedOperand(input); |
| 3861 CallRuntime(Runtime::kTypeof, 1, instr); | 3996 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3862 } | 3997 } |
| 3863 | 3998 |
| 3864 | 3999 |
| 3865 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 4000 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 3866 Register input = ToRegister(instr->InputAt(0)); | 4001 Register input = ToRegister(instr->InputAt(0)); |
| 3867 Register result = ToRegister(instr->result()); | 4002 Register result = ToRegister(instr->result()); |
| 3868 Label true_label; | 4003 Label true_label; |
| 3869 Label false_label; | 4004 Label false_label; |
| 3870 NearLabel done; | 4005 Label done; |
| 3871 | 4006 |
| 3872 Condition final_branch_condition = EmitTypeofIs(&true_label, | 4007 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 3873 &false_label, | 4008 &false_label, |
| 3874 input, | 4009 input, |
| 3875 instr->type_literal()); | 4010 instr->type_literal()); |
| 3876 __ j(final_branch_condition, &true_label); | 4011 __ j(final_branch_condition, &true_label); |
| 3877 __ bind(&false_label); | 4012 __ bind(&false_label); |
| 3878 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 4013 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 3879 __ jmp(&done); | 4014 __ jmp(&done, Label::kNear); |
| 3880 | 4015 |
| 3881 __ bind(&true_label); | 4016 __ bind(&true_label); |
| 3882 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 4017 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 3883 | 4018 |
| 3884 __ bind(&done); | 4019 __ bind(&done); |
| 3885 } | 4020 } |
| 3886 | 4021 |
| 3887 | 4022 |
| 3888 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 4023 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
| 3889 ASSERT(!operand->IsDoubleRegister()); | 4024 ASSERT(!operand->IsDoubleRegister()); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3971 final_branch_condition = never; | 4106 final_branch_condition = never; |
| 3972 __ jmp(false_label); | 4107 __ jmp(false_label); |
| 3973 } | 4108 } |
| 3974 | 4109 |
| 3975 return final_branch_condition; | 4110 return final_branch_condition; |
| 3976 } | 4111 } |
| 3977 | 4112 |
| 3978 | 4113 |
| 3979 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | 4114 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
| 3980 Register result = ToRegister(instr->result()); | 4115 Register result = ToRegister(instr->result()); |
| 3981 NearLabel true_label; | 4116 Label true_label; |
| 3982 NearLabel false_label; | 4117 Label done; |
| 3983 NearLabel done; | |
| 3984 | 4118 |
| 3985 EmitIsConstructCall(result); | 4119 EmitIsConstructCall(result); |
| 3986 __ j(equal, &true_label); | 4120 __ j(equal, &true_label, Label::kNear); |
| 3987 | 4121 |
| 3988 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 4122 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 3989 __ jmp(&done); | 4123 __ jmp(&done, Label::kNear); |
| 3990 | 4124 |
| 3991 __ bind(&true_label); | 4125 __ bind(&true_label); |
| 3992 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 4126 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 3993 | 4127 |
| 3994 | 4128 |
| 3995 __ bind(&done); | 4129 __ bind(&done); |
| 3996 } | 4130 } |
| 3997 | 4131 |
| 3998 | 4132 |
| 3999 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4133 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 4000 Register temp = ToRegister(instr->TempAt(0)); | 4134 Register temp = ToRegister(instr->TempAt(0)); |
| 4001 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4135 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 4002 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4136 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 4003 | 4137 |
| 4004 EmitIsConstructCall(temp); | 4138 EmitIsConstructCall(temp); |
| 4005 EmitBranch(true_block, false_block, equal); | 4139 EmitBranch(true_block, false_block, equal); |
| 4006 } | 4140 } |
| 4007 | 4141 |
| 4008 | 4142 |
| 4009 void LCodeGen::EmitIsConstructCall(Register temp) { | 4143 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 4010 // Get the frame pointer for the calling frame. | 4144 // Get the frame pointer for the calling frame. |
| 4011 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 4145 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 4012 | 4146 |
| 4013 // Skip the arguments adaptor frame if it exists. | 4147 // Skip the arguments adaptor frame if it exists. |
| 4014 NearLabel check_frame_marker; | 4148 Label check_frame_marker; |
| 4015 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 4149 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| 4016 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 4150 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 4017 __ j(not_equal, &check_frame_marker); | 4151 __ j(not_equal, &check_frame_marker, Label::kNear); |
| 4018 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 4152 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
| 4019 | 4153 |
| 4020 // Check the marker in the calling frame. | 4154 // Check the marker in the calling frame. |
| 4021 __ bind(&check_frame_marker); | 4155 __ bind(&check_frame_marker); |
| 4022 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 4156 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 4023 Smi::FromInt(StackFrame::CONSTRUCT)); | 4157 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 4024 } | 4158 } |
| 4025 | 4159 |
| 4026 | 4160 |
| 4027 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 4161 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4071 // builtin) | 4205 // builtin) |
| 4072 SafepointGenerator safepoint_generator(this, | 4206 SafepointGenerator safepoint_generator(this, |
| 4073 pointers, | 4207 pointers, |
| 4074 env->deoptimization_index()); | 4208 env->deoptimization_index()); |
| 4075 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4209 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4076 } | 4210 } |
| 4077 | 4211 |
| 4078 | 4212 |
| 4079 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4213 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 4080 // Perform stack overflow check. | 4214 // Perform stack overflow check. |
| 4081 NearLabel done; | 4215 Label done; |
| 4082 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 4216 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 4083 __ j(above_equal, &done); | 4217 __ j(above_equal, &done, Label::kNear); |
| 4084 | 4218 |
| 4085 StackCheckStub stub; | 4219 StackCheckStub stub; |
| 4086 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4220 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4087 __ bind(&done); | 4221 __ bind(&done); |
| 4088 } | 4222 } |
| 4089 | 4223 |
| 4090 | 4224 |
| 4091 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 4225 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 4092 // This is a pseudo-instruction that ensures that the environment here is | 4226 // This is a pseudo-instruction that ensures that the environment here is |
| 4093 // properly registered for deoptimization and records the assembler's PC | 4227 // properly registered for deoptimization and records the assembler's PC |
| 4094 // offset. | 4228 // offset. |
| 4095 LEnvironment* environment = instr->environment(); | 4229 LEnvironment* environment = instr->environment(); |
| 4096 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), | 4230 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), |
| 4097 instr->SpilledDoubleRegisterArray()); | 4231 instr->SpilledDoubleRegisterArray()); |
| 4098 | 4232 |
| 4099 // If the environment were already registered, we would have no way of | 4233 // If the environment were already registered, we would have no way of |
| 4100 // backpatching it with the spill slot operands. | 4234 // backpatching it with the spill slot operands. |
| 4101 ASSERT(!environment->HasBeenRegistered()); | 4235 ASSERT(!environment->HasBeenRegistered()); |
| 4102 RegisterEnvironmentForDeoptimization(environment); | 4236 RegisterEnvironmentForDeoptimization(environment); |
| 4103 ASSERT(osr_pc_offset_ == -1); | 4237 ASSERT(osr_pc_offset_ == -1); |
| 4104 osr_pc_offset_ = masm()->pc_offset(); | 4238 osr_pc_offset_ = masm()->pc_offset(); |
| 4105 } | 4239 } |
| 4106 | 4240 |
| 4107 #undef __ | 4241 #undef __ |
| 4108 | 4242 |
| 4109 } } // namespace v8::internal | 4243 } } // namespace v8::internal |
| 4110 | 4244 |
| 4111 #endif // V8_TARGET_ARCH_X64 | 4245 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |