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 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 | 538 |
539 if (FLAG_deopt_every_n_times != 0) { | 539 if (FLAG_deopt_every_n_times != 0) { |
540 Handle<SharedFunctionInfo> shared(info_->shared_info()); | 540 Handle<SharedFunctionInfo> shared(info_->shared_info()); |
541 Label no_deopt; | 541 Label no_deopt; |
542 __ pushfd(); | 542 __ pushfd(); |
543 __ push(eax); | 543 __ push(eax); |
544 __ push(ebx); | 544 __ push(ebx); |
545 __ mov(ebx, shared); | 545 __ mov(ebx, shared); |
546 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); | 546 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); |
547 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 547 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
548 __ j(not_zero, &no_deopt); | 548 __ j(not_zero, &no_deopt, Label::kNear); |
549 if (FLAG_trap_on_deopt) __ int3(); | 549 if (FLAG_trap_on_deopt) __ int3(); |
550 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); | 550 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); |
551 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); | 551 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); |
552 __ pop(ebx); | 552 __ pop(ebx); |
553 __ pop(eax); | 553 __ pop(eax); |
554 __ popfd(); | 554 __ popfd(); |
555 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 555 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
556 | 556 |
557 __ bind(&no_deopt); | 557 __ bind(&no_deopt); |
558 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); | 558 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); |
559 __ pop(ebx); | 559 __ pop(ebx); |
560 __ pop(eax); | 560 __ pop(eax); |
561 __ popfd(); | 561 __ popfd(); |
562 } | 562 } |
563 | 563 |
564 if (cc == no_condition) { | 564 if (cc == no_condition) { |
565 if (FLAG_trap_on_deopt) __ int3(); | 565 if (FLAG_trap_on_deopt) __ int3(); |
566 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 566 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
567 } else { | 567 } else { |
568 if (FLAG_trap_on_deopt) { | 568 if (FLAG_trap_on_deopt) { |
569 NearLabel done; | 569 Label done; |
570 __ j(NegateCondition(cc), &done); | 570 __ j(NegateCondition(cc), &done, Label::kNear); |
571 __ int3(); | 571 __ int3(); |
572 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 572 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
573 __ bind(&done); | 573 __ bind(&done); |
574 } else { | 574 } else { |
575 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY, not_taken); | 575 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY, not_taken); |
576 } | 576 } |
577 } | 577 } |
578 } | 578 } |
579 | 579 |
580 | 580 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 | 780 |
781 void LCodeGen::DoModI(LModI* instr) { | 781 void LCodeGen::DoModI(LModI* instr) { |
782 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 782 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
783 Register dividend = ToRegister(instr->InputAt(0)); | 783 Register dividend = ToRegister(instr->InputAt(0)); |
784 | 784 |
785 int32_t divisor = | 785 int32_t divisor = |
786 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 786 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
787 | 787 |
788 if (divisor < 0) divisor = -divisor; | 788 if (divisor < 0) divisor = -divisor; |
789 | 789 |
790 NearLabel positive_dividend, done; | 790 Label positive_dividend, done; |
791 __ test(dividend, Operand(dividend)); | 791 __ test(dividend, Operand(dividend)); |
792 __ j(not_sign, &positive_dividend); | 792 __ j(not_sign, &positive_dividend, Label::kNear); |
793 __ neg(dividend); | 793 __ neg(dividend); |
794 __ and_(dividend, divisor - 1); | 794 __ and_(dividend, divisor - 1); |
795 __ neg(dividend); | 795 __ neg(dividend); |
796 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 796 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
797 __ j(not_zero, &done); | 797 __ j(not_zero, &done, Label::kNear); |
798 DeoptimizeIf(no_condition, instr->environment()); | 798 DeoptimizeIf(no_condition, instr->environment()); |
799 } | 799 } |
800 __ bind(&positive_dividend); | 800 __ bind(&positive_dividend); |
801 __ and_(dividend, divisor - 1); | 801 __ and_(dividend, divisor - 1); |
802 __ bind(&done); | 802 __ bind(&done); |
803 } else { | 803 } else { |
804 NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 804 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
805 Register left_reg = ToRegister(instr->InputAt(0)); | 805 Register left_reg = ToRegister(instr->InputAt(0)); |
806 Register right_reg = ToRegister(instr->InputAt(1)); | 806 Register right_reg = ToRegister(instr->InputAt(1)); |
807 Register result_reg = ToRegister(instr->result()); | 807 Register result_reg = ToRegister(instr->result()); |
808 | 808 |
809 ASSERT(left_reg.is(eax)); | 809 ASSERT(left_reg.is(eax)); |
810 ASSERT(result_reg.is(edx)); | 810 ASSERT(result_reg.is(edx)); |
811 ASSERT(!right_reg.is(eax)); | 811 ASSERT(!right_reg.is(eax)); |
812 ASSERT(!right_reg.is(edx)); | 812 ASSERT(!right_reg.is(edx)); |
813 | 813 |
814 // Check for x % 0. | 814 // Check for x % 0. |
815 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 815 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
816 __ test(right_reg, Operand(right_reg)); | 816 __ test(right_reg, Operand(right_reg)); |
817 DeoptimizeIf(zero, instr->environment()); | 817 DeoptimizeIf(zero, instr->environment()); |
818 } | 818 } |
819 | 819 |
820 __ test(left_reg, Operand(left_reg)); | 820 __ test(left_reg, Operand(left_reg)); |
821 __ j(zero, &remainder_eq_dividend); | 821 __ j(zero, &remainder_eq_dividend, Label::kNear); |
822 __ j(sign, &slow); | 822 __ j(sign, &slow, Label::kNear); |
823 | 823 |
824 __ test(right_reg, Operand(right_reg)); | 824 __ test(right_reg, Operand(right_reg)); |
825 __ j(not_sign, &both_positive); | 825 __ j(not_sign, &both_positive, Label::kNear); |
826 // The sign of the divisor doesn't matter. | 826 // The sign of the divisor doesn't matter. |
827 __ neg(right_reg); | 827 __ neg(right_reg); |
828 | 828 |
829 __ bind(&both_positive); | 829 __ bind(&both_positive); |
830 // If the dividend is smaller than the nonnegative | 830 // If the dividend is smaller than the nonnegative |
831 // divisor, the dividend is the result. | 831 // divisor, the dividend is the result. |
832 __ cmp(left_reg, Operand(right_reg)); | 832 __ cmp(left_reg, Operand(right_reg)); |
833 __ j(less, &remainder_eq_dividend); | 833 __ j(less, &remainder_eq_dividend, Label::kNear); |
834 | 834 |
835 // Check if the divisor is a PowerOfTwo integer. | 835 // Check if the divisor is a PowerOfTwo integer. |
836 Register scratch = ToRegister(instr->TempAt(0)); | 836 Register scratch = ToRegister(instr->TempAt(0)); |
837 __ mov(scratch, right_reg); | 837 __ mov(scratch, right_reg); |
838 __ sub(Operand(scratch), Immediate(1)); | 838 __ sub(Operand(scratch), Immediate(1)); |
839 __ test(scratch, Operand(right_reg)); | 839 __ test(scratch, Operand(right_reg)); |
840 __ j(not_zero, &do_subtraction); | 840 __ j(not_zero, &do_subtraction, Label::kNear); |
841 __ and_(left_reg, Operand(scratch)); | 841 __ and_(left_reg, Operand(scratch)); |
842 __ jmp(&remainder_eq_dividend); | 842 __ jmp(&remainder_eq_dividend, Label::kNear); |
843 | 843 |
844 __ bind(&do_subtraction); | 844 __ bind(&do_subtraction); |
845 const int kUnfolds = 3; | 845 const int kUnfolds = 3; |
846 // Try a few subtractions of the dividend. | 846 // Try a few subtractions of the dividend. |
847 __ mov(scratch, left_reg); | 847 __ mov(scratch, left_reg); |
848 for (int i = 0; i < kUnfolds; i++) { | 848 for (int i = 0; i < kUnfolds; i++) { |
849 // Reduce the dividend by the divisor. | 849 // Reduce the dividend by the divisor. |
850 __ sub(left_reg, Operand(right_reg)); | 850 __ sub(left_reg, Operand(right_reg)); |
851 // Check if the dividend is less than the divisor. | 851 // Check if the dividend is less than the divisor. |
852 __ cmp(left_reg, Operand(right_reg)); | 852 __ cmp(left_reg, Operand(right_reg)); |
853 __ j(less, &remainder_eq_dividend); | 853 __ j(less, &remainder_eq_dividend, Label::kNear); |
854 } | 854 } |
855 __ mov(left_reg, scratch); | 855 __ mov(left_reg, scratch); |
856 | 856 |
857 // Slow case, using idiv instruction. | 857 // Slow case, using idiv instruction. |
858 __ bind(&slow); | 858 __ bind(&slow); |
859 // Sign extend to edx. | 859 // Sign extend to edx. |
860 __ cdq(); | 860 __ cdq(); |
861 | 861 |
862 // Check for (0 % -x) that will produce negative zero. | 862 // Check for (0 % -x) that will produce negative zero. |
863 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 863 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
864 NearLabel positive_left; | 864 Label positive_left; |
865 NearLabel done; | 865 Label done; |
866 __ test(left_reg, Operand(left_reg)); | 866 __ test(left_reg, Operand(left_reg)); |
867 __ j(not_sign, &positive_left); | 867 __ j(not_sign, &positive_left, Label::kNear); |
868 __ idiv(right_reg); | 868 __ idiv(right_reg); |
869 | 869 |
870 // Test the remainder for 0, because then the result would be -0. | 870 // Test the remainder for 0, because then the result would be -0. |
871 __ test(result_reg, Operand(result_reg)); | 871 __ test(result_reg, Operand(result_reg)); |
872 __ j(not_zero, &done); | 872 __ j(not_zero, &done, Label::kNear); |
873 | 873 |
874 DeoptimizeIf(no_condition, instr->environment()); | 874 DeoptimizeIf(no_condition, instr->environment()); |
875 __ bind(&positive_left); | 875 __ bind(&positive_left); |
876 __ idiv(right_reg); | 876 __ idiv(right_reg); |
877 __ bind(&done); | 877 __ bind(&done); |
878 } else { | 878 } else { |
879 __ idiv(right_reg); | 879 __ idiv(right_reg); |
880 } | 880 } |
881 __ jmp(&done); | 881 __ jmp(&done, Label::kNear); |
882 | 882 |
883 __ bind(&remainder_eq_dividend); | 883 __ bind(&remainder_eq_dividend); |
884 __ mov(result_reg, left_reg); | 884 __ mov(result_reg, left_reg); |
885 | 885 |
886 __ bind(&done); | 886 __ bind(&done); |
887 } | 887 } |
888 } | 888 } |
889 | 889 |
890 | 890 |
891 void LCodeGen::DoDivI(LDivI* instr) { | 891 void LCodeGen::DoDivI(LDivI* instr) { |
892 LOperand* right = instr->InputAt(1); | 892 LOperand* right = instr->InputAt(1); |
893 ASSERT(ToRegister(instr->result()).is(eax)); | 893 ASSERT(ToRegister(instr->result()).is(eax)); |
894 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 894 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
895 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); | 895 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
896 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); | 896 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
897 | 897 |
898 Register left_reg = eax; | 898 Register left_reg = eax; |
899 | 899 |
900 // Check for x / 0. | 900 // Check for x / 0. |
901 Register right_reg = ToRegister(right); | 901 Register right_reg = ToRegister(right); |
902 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 902 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
903 __ test(right_reg, ToOperand(right)); | 903 __ test(right_reg, ToOperand(right)); |
904 DeoptimizeIf(zero, instr->environment()); | 904 DeoptimizeIf(zero, instr->environment()); |
905 } | 905 } |
906 | 906 |
907 // Check for (0 / -x) that will produce negative zero. | 907 // Check for (0 / -x) that will produce negative zero. |
908 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 908 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
909 NearLabel left_not_zero; | 909 Label left_not_zero; |
910 __ test(left_reg, Operand(left_reg)); | 910 __ test(left_reg, Operand(left_reg)); |
911 __ j(not_zero, &left_not_zero); | 911 __ j(not_zero, &left_not_zero, Label::kNear); |
912 __ test(right_reg, ToOperand(right)); | 912 __ test(right_reg, ToOperand(right)); |
913 DeoptimizeIf(sign, instr->environment()); | 913 DeoptimizeIf(sign, instr->environment()); |
914 __ bind(&left_not_zero); | 914 __ bind(&left_not_zero); |
915 } | 915 } |
916 | 916 |
917 // Check for (-kMinInt / -1). | 917 // Check for (-kMinInt / -1). |
918 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 918 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
919 NearLabel left_not_min_int; | 919 Label left_not_min_int; |
920 __ cmp(left_reg, kMinInt); | 920 __ cmp(left_reg, kMinInt); |
921 __ j(not_zero, &left_not_min_int); | 921 __ j(not_zero, &left_not_min_int, Label::kNear); |
922 __ cmp(right_reg, -1); | 922 __ cmp(right_reg, -1); |
923 DeoptimizeIf(zero, instr->environment()); | 923 DeoptimizeIf(zero, instr->environment()); |
924 __ bind(&left_not_min_int); | 924 __ bind(&left_not_min_int); |
925 } | 925 } |
926 | 926 |
927 // Sign extend to edx. | 927 // Sign extend to edx. |
928 __ cdq(); | 928 __ cdq(); |
929 __ idiv(right_reg); | 929 __ idiv(right_reg); |
930 | 930 |
931 // Deoptimize if remainder is not 0. | 931 // Deoptimize if remainder is not 0. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 } else { | 989 } else { |
990 __ imul(left, ToOperand(right)); | 990 __ imul(left, ToOperand(right)); |
991 } | 991 } |
992 | 992 |
993 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 993 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
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 __ test(left, Operand(left)); | 1000 __ test(left, Operand(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 { | 1006 } else { |
1007 // Test the non-zero operand for negative sign. | 1007 // Test the non-zero operand for negative sign. |
1008 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); | 1008 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
1009 DeoptimizeIf(sign, instr->environment()); | 1009 DeoptimizeIf(sign, instr->environment()); |
1010 } | 1010 } |
1011 __ bind(&done); | 1011 __ bind(&done); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 Register array = ToRegister(instr->InputAt(0)); | 1196 Register array = ToRegister(instr->InputAt(0)); |
1197 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); | 1197 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); |
1198 } | 1198 } |
1199 | 1199 |
1200 | 1200 |
1201 void LCodeGen::DoValueOf(LValueOf* instr) { | 1201 void LCodeGen::DoValueOf(LValueOf* instr) { |
1202 Register input = ToRegister(instr->InputAt(0)); | 1202 Register input = ToRegister(instr->InputAt(0)); |
1203 Register result = ToRegister(instr->result()); | 1203 Register result = ToRegister(instr->result()); |
1204 Register map = ToRegister(instr->TempAt(0)); | 1204 Register map = ToRegister(instr->TempAt(0)); |
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 __ test(input, Immediate(kSmiTagMask)); | 1208 __ test(input, Immediate(kSmiTagMask)); |
1209 __ j(zero, &done); | 1209 __ j(zero, &done, Label::kNear); |
1210 | 1210 |
1211 // If the object is not a value type, return the object. | 1211 // If the object is not a value type, return the object. |
1212 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1212 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
1213 __ j(not_equal, &done); | 1213 __ j(not_equal, &done, Label::kNear); |
1214 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1214 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
1215 | 1215 |
1216 __ bind(&done); | 1216 __ bind(&done); |
1217 } | 1217 } |
1218 | 1218 |
1219 | 1219 |
1220 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1220 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1221 LOperand* input = instr->InputAt(0); | 1221 LOperand* input = instr->InputAt(0); |
1222 ASSERT(input->Equals(instr->result())); | 1222 ASSERT(input->Equals(instr->result())); |
1223 __ not_(ToRegister(input)); | 1223 __ not_(ToRegister(input)); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1361 __ cmp(reg, factory()->true_value()); | 1361 __ cmp(reg, factory()->true_value()); |
1362 __ j(equal, true_label); | 1362 __ j(equal, true_label); |
1363 __ cmp(reg, factory()->false_value()); | 1363 __ cmp(reg, factory()->false_value()); |
1364 __ j(equal, false_label); | 1364 __ j(equal, false_label); |
1365 __ test(reg, Operand(reg)); | 1365 __ test(reg, Operand(reg)); |
1366 __ j(equal, false_label); | 1366 __ j(equal, false_label); |
1367 __ test(reg, Immediate(kSmiTagMask)); | 1367 __ test(reg, Immediate(kSmiTagMask)); |
1368 __ j(zero, true_label); | 1368 __ j(zero, true_label); |
1369 | 1369 |
1370 // Test for double values. Zero is false. | 1370 // Test for double values. Zero is false. |
1371 NearLabel call_stub; | 1371 Label call_stub; |
1372 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1372 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
1373 factory()->heap_number_map()); | 1373 factory()->heap_number_map()); |
1374 __ j(not_equal, &call_stub); | 1374 __ j(not_equal, &call_stub, Label::kNear); |
1375 __ fldz(); | 1375 __ fldz(); |
1376 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1376 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
1377 __ FCmp(); | 1377 __ FCmp(); |
1378 __ j(zero, false_label); | 1378 __ j(zero, false_label); |
1379 __ jmp(true_label); | 1379 __ jmp(true_label); |
1380 | 1380 |
1381 // The conversion stub doesn't cause garbage collections so it's | 1381 // The conversion stub doesn't cause garbage collections so it's |
1382 // safe to not record a safepoint after the call. | 1382 // safe to not record a safepoint after the call. |
1383 __ bind(&call_stub); | 1383 __ bind(&call_stub); |
1384 ToBooleanStub stub; | 1384 ToBooleanStub stub; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1470 __ cmp(ToRegister(left), ToOperand(right)); | 1470 __ cmp(ToRegister(left), ToOperand(right)); |
1471 } | 1471 } |
1472 } | 1472 } |
1473 | 1473 |
1474 | 1474 |
1475 void LCodeGen::DoCmpID(LCmpID* instr) { | 1475 void LCodeGen::DoCmpID(LCmpID* instr) { |
1476 LOperand* left = instr->InputAt(0); | 1476 LOperand* left = instr->InputAt(0); |
1477 LOperand* right = instr->InputAt(1); | 1477 LOperand* right = instr->InputAt(1); |
1478 LOperand* result = instr->result(); | 1478 LOperand* result = instr->result(); |
1479 | 1479 |
1480 NearLabel unordered; | 1480 Label unordered; |
1481 if (instr->is_double()) { | 1481 if (instr->is_double()) { |
1482 // Don't base result on EFLAGS when a NaN is involved. Instead | 1482 // Don't base result on EFLAGS when a NaN is involved. Instead |
1483 // jump to the unordered case, which produces a false value. | 1483 // jump to the unordered case, which produces a false value. |
1484 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1484 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1485 __ j(parity_even, &unordered, not_taken); | 1485 __ j(parity_even, &unordered, not_taken, Label::kNear); |
1486 } else { | 1486 } else { |
1487 EmitCmpI(left, right); | 1487 EmitCmpI(left, right); |
1488 } | 1488 } |
1489 | 1489 |
1490 NearLabel done; | 1490 Label done; |
1491 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1491 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1492 __ mov(ToRegister(result), factory()->true_value()); | 1492 __ mov(ToRegister(result), factory()->true_value()); |
1493 __ j(cc, &done); | 1493 __ j(cc, &done, Label::kNear); |
1494 | 1494 |
1495 __ bind(&unordered); | 1495 __ bind(&unordered); |
1496 __ mov(ToRegister(result), factory()->false_value()); | 1496 __ mov(ToRegister(result), factory()->false_value()); |
1497 __ bind(&done); | 1497 __ bind(&done); |
1498 } | 1498 } |
1499 | 1499 |
1500 | 1500 |
1501 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1501 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1502 LOperand* left = instr->InputAt(0); | 1502 LOperand* left = instr->InputAt(0); |
1503 LOperand* right = instr->InputAt(1); | 1503 LOperand* right = instr->InputAt(1); |
(...skipping 14 matching lines...) Expand all Loading... |
1518 } | 1518 } |
1519 | 1519 |
1520 | 1520 |
1521 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1521 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
1522 Register left = ToRegister(instr->InputAt(0)); | 1522 Register left = ToRegister(instr->InputAt(0)); |
1523 Register right = ToRegister(instr->InputAt(1)); | 1523 Register right = ToRegister(instr->InputAt(1)); |
1524 Register result = ToRegister(instr->result()); | 1524 Register result = ToRegister(instr->result()); |
1525 | 1525 |
1526 __ cmp(left, Operand(right)); | 1526 __ cmp(left, Operand(right)); |
1527 __ mov(result, factory()->true_value()); | 1527 __ mov(result, factory()->true_value()); |
1528 NearLabel done; | 1528 Label done; |
1529 __ j(equal, &done); | 1529 __ j(equal, &done, Label::kNear); |
1530 __ mov(result, factory()->false_value()); | 1530 __ mov(result, factory()->false_value()); |
1531 __ bind(&done); | 1531 __ bind(&done); |
1532 } | 1532 } |
1533 | 1533 |
1534 | 1534 |
1535 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1535 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
1536 Register left = ToRegister(instr->InputAt(0)); | 1536 Register left = ToRegister(instr->InputAt(0)); |
1537 Register right = ToRegister(instr->InputAt(1)); | 1537 Register right = ToRegister(instr->InputAt(1)); |
1538 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1538 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1539 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1539 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1540 | 1540 |
1541 __ cmp(left, Operand(right)); | 1541 __ cmp(left, Operand(right)); |
1542 EmitBranch(true_block, false_block, equal); | 1542 EmitBranch(true_block, false_block, equal); |
1543 } | 1543 } |
1544 | 1544 |
1545 | 1545 |
1546 void LCodeGen::DoIsNull(LIsNull* instr) { | 1546 void LCodeGen::DoIsNull(LIsNull* instr) { |
1547 Register reg = ToRegister(instr->InputAt(0)); | 1547 Register reg = ToRegister(instr->InputAt(0)); |
1548 Register result = ToRegister(instr->result()); | 1548 Register result = ToRegister(instr->result()); |
1549 | 1549 |
1550 // TODO(fsc): If the expression is known to be a smi, then it's | 1550 // TODO(fsc): If the expression is known to be a smi, then it's |
1551 // definitely not null. Materialize false. | 1551 // definitely not null. Materialize false. |
1552 | 1552 |
1553 __ cmp(reg, factory()->null_value()); | 1553 __ cmp(reg, factory()->null_value()); |
1554 if (instr->is_strict()) { | 1554 if (instr->is_strict()) { |
1555 __ mov(result, factory()->true_value()); | 1555 __ mov(result, factory()->true_value()); |
1556 NearLabel done; | 1556 Label done; |
1557 __ j(equal, &done); | 1557 __ j(equal, &done, Label::kNear); |
1558 __ mov(result, factory()->false_value()); | 1558 __ mov(result, factory()->false_value()); |
1559 __ bind(&done); | 1559 __ bind(&done); |
1560 } else { | 1560 } else { |
1561 NearLabel true_value, false_value, done; | 1561 Label true_value, false_value, done; |
1562 __ j(equal, &true_value); | 1562 __ j(equal, &true_value, Label::kNear); |
1563 __ cmp(reg, factory()->undefined_value()); | 1563 __ cmp(reg, factory()->undefined_value()); |
1564 __ j(equal, &true_value); | 1564 __ j(equal, &true_value, Label::kNear); |
1565 __ test(reg, Immediate(kSmiTagMask)); | 1565 __ test(reg, Immediate(kSmiTagMask)); |
1566 __ j(zero, &false_value); | 1566 __ j(zero, &false_value, Label::kNear); |
1567 // Check for undetectable objects by looking in the bit field in | 1567 // Check for undetectable objects by looking in the bit field in |
1568 // the map. The object has already been smi checked. | 1568 // the map. The object has already been smi checked. |
1569 Register scratch = result; | 1569 Register scratch = result; |
1570 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1570 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1571 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1571 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
1572 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1572 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
1573 __ j(not_zero, &true_value); | 1573 __ j(not_zero, &true_value, Label::kNear); |
1574 __ bind(&false_value); | 1574 __ bind(&false_value); |
1575 __ mov(result, factory()->false_value()); | 1575 __ mov(result, factory()->false_value()); |
1576 __ jmp(&done); | 1576 __ jmp(&done, Label::kNear); |
1577 __ bind(&true_value); | 1577 __ bind(&true_value); |
1578 __ mov(result, factory()->true_value()); | 1578 __ mov(result, factory()->true_value()); |
1579 __ bind(&done); | 1579 __ bind(&done); |
1580 } | 1580 } |
1581 } | 1581 } |
1582 | 1582 |
1583 | 1583 |
1584 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1584 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1585 Register reg = ToRegister(instr->InputAt(0)); | 1585 Register reg = ToRegister(instr->InputAt(0)); |
1586 | 1586 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 } | 1677 } |
1678 | 1678 |
1679 | 1679 |
1680 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1680 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
1681 Operand input = ToOperand(instr->InputAt(0)); | 1681 Operand input = ToOperand(instr->InputAt(0)); |
1682 Register result = ToRegister(instr->result()); | 1682 Register result = ToRegister(instr->result()); |
1683 | 1683 |
1684 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1684 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1685 __ test(input, Immediate(kSmiTagMask)); | 1685 __ test(input, Immediate(kSmiTagMask)); |
1686 __ mov(result, factory()->true_value()); | 1686 __ mov(result, factory()->true_value()); |
1687 NearLabel done; | 1687 Label done; |
1688 __ j(zero, &done); | 1688 __ j(zero, &done, Label::kNear); |
1689 __ mov(result, factory()->false_value()); | 1689 __ mov(result, factory()->false_value()); |
1690 __ bind(&done); | 1690 __ bind(&done); |
1691 } | 1691 } |
1692 | 1692 |
1693 | 1693 |
1694 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1694 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1695 Operand input = ToOperand(instr->InputAt(0)); | 1695 Operand input = ToOperand(instr->InputAt(0)); |
1696 | 1696 |
1697 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1697 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1698 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1698 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 22 matching lines...) Expand all Loading... |
1721 return equal; | 1721 return equal; |
1722 } | 1722 } |
1723 | 1723 |
1724 | 1724 |
1725 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1725 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
1726 Register input = ToRegister(instr->InputAt(0)); | 1726 Register input = ToRegister(instr->InputAt(0)); |
1727 Register result = ToRegister(instr->result()); | 1727 Register result = ToRegister(instr->result()); |
1728 | 1728 |
1729 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1729 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1730 __ test(input, Immediate(kSmiTagMask)); | 1730 __ test(input, Immediate(kSmiTagMask)); |
1731 NearLabel done, is_false; | 1731 Label done, is_false; |
1732 __ j(zero, &is_false); | 1732 __ j(zero, &is_false, Label::kNear); |
1733 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | 1733 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
1734 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); | 1734 __ j(NegateCondition(BranchCondition(instr->hydrogen())), |
| 1735 &is_false, Label::kNear); |
1735 __ mov(result, factory()->true_value()); | 1736 __ mov(result, factory()->true_value()); |
1736 __ jmp(&done); | 1737 __ jmp(&done, Label::kNear); |
1737 __ bind(&is_false); | 1738 __ bind(&is_false); |
1738 __ mov(result, factory()->false_value()); | 1739 __ mov(result, factory()->false_value()); |
1739 __ bind(&done); | 1740 __ bind(&done); |
1740 } | 1741 } |
1741 | 1742 |
1742 | 1743 |
1743 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1744 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1744 Register input = ToRegister(instr->InputAt(0)); | 1745 Register input = ToRegister(instr->InputAt(0)); |
1745 Register temp = ToRegister(instr->TempAt(0)); | 1746 Register temp = ToRegister(instr->TempAt(0)); |
1746 | 1747 |
(...skipping 24 matching lines...) Expand all Loading... |
1771 | 1772 |
1772 | 1773 |
1773 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1774 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
1774 Register input = ToRegister(instr->InputAt(0)); | 1775 Register input = ToRegister(instr->InputAt(0)); |
1775 Register result = ToRegister(instr->result()); | 1776 Register result = ToRegister(instr->result()); |
1776 | 1777 |
1777 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1778 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1778 __ mov(result, factory()->true_value()); | 1779 __ mov(result, factory()->true_value()); |
1779 __ test(FieldOperand(input, String::kHashFieldOffset), | 1780 __ test(FieldOperand(input, String::kHashFieldOffset), |
1780 Immediate(String::kContainsCachedArrayIndexMask)); | 1781 Immediate(String::kContainsCachedArrayIndexMask)); |
1781 NearLabel done; | 1782 Label done; |
1782 __ j(zero, &done); | 1783 __ j(zero, &done, Label::kNear); |
1783 __ mov(result, factory()->false_value()); | 1784 __ mov(result, factory()->false_value()); |
1784 __ bind(&done); | 1785 __ bind(&done); |
1785 } | 1786 } |
1786 | 1787 |
1787 | 1788 |
1788 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1789 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1789 LHasCachedArrayIndexAndBranch* instr) { | 1790 LHasCachedArrayIndexAndBranch* instr) { |
1790 Register input = ToRegister(instr->InputAt(0)); | 1791 Register input = ToRegister(instr->InputAt(0)); |
1791 | 1792 |
1792 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1793 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1854 // End with the answer in the z flag. | 1855 // End with the answer in the z flag. |
1855 } | 1856 } |
1856 | 1857 |
1857 | 1858 |
1858 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1859 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1859 Register input = ToRegister(instr->InputAt(0)); | 1860 Register input = ToRegister(instr->InputAt(0)); |
1860 Register result = ToRegister(instr->result()); | 1861 Register result = ToRegister(instr->result()); |
1861 ASSERT(input.is(result)); | 1862 ASSERT(input.is(result)); |
1862 Register temp = ToRegister(instr->TempAt(0)); | 1863 Register temp = ToRegister(instr->TempAt(0)); |
1863 Handle<String> class_name = instr->hydrogen()->class_name(); | 1864 Handle<String> class_name = instr->hydrogen()->class_name(); |
1864 NearLabel done; | 1865 Label done; |
1865 Label is_true, is_false; | 1866 Label is_true, is_false; |
1866 | 1867 |
1867 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1868 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
1868 | 1869 |
1869 __ j(not_equal, &is_false); | 1870 __ j(not_equal, &is_false, Label::kNear); |
1870 | 1871 |
1871 __ bind(&is_true); | 1872 __ bind(&is_true); |
1872 __ mov(result, factory()->true_value()); | 1873 __ mov(result, factory()->true_value()); |
1873 __ jmp(&done); | 1874 __ jmp(&done, Label::kNear); |
1874 | 1875 |
1875 __ bind(&is_false); | 1876 __ bind(&is_false); |
1876 __ mov(result, factory()->false_value()); | 1877 __ mov(result, factory()->false_value()); |
1877 __ bind(&done); | 1878 __ bind(&done); |
1878 } | 1879 } |
1879 | 1880 |
1880 | 1881 |
1881 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1882 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1882 Register input = ToRegister(instr->InputAt(0)); | 1883 Register input = ToRegister(instr->InputAt(0)); |
1883 Register temp = ToRegister(instr->TempAt(0)); | 1884 Register temp = ToRegister(instr->TempAt(0)); |
(...skipping 27 matching lines...) Expand all Loading... |
1911 EmitBranch(true_block, false_block, equal); | 1912 EmitBranch(true_block, false_block, equal); |
1912 } | 1913 } |
1913 | 1914 |
1914 | 1915 |
1915 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1916 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1916 // Object and function are in fixed registers defined by the stub. | 1917 // Object and function are in fixed registers defined by the stub. |
1917 ASSERT(ToRegister(instr->context()).is(esi)); | 1918 ASSERT(ToRegister(instr->context()).is(esi)); |
1918 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1919 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
1919 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 1920 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); |
1920 | 1921 |
1921 NearLabel true_value, done; | 1922 Label true_value, done; |
1922 __ test(eax, Operand(eax)); | 1923 __ test(eax, Operand(eax)); |
1923 __ j(zero, &true_value); | 1924 __ j(zero, &true_value, Label::kNear); |
1924 __ mov(ToRegister(instr->result()), factory()->false_value()); | 1925 __ mov(ToRegister(instr->result()), factory()->false_value()); |
1925 __ jmp(&done); | 1926 __ jmp(&done, Label::kNear); |
1926 __ bind(&true_value); | 1927 __ bind(&true_value); |
1927 __ mov(ToRegister(instr->result()), factory()->true_value()); | 1928 __ mov(ToRegister(instr->result()), factory()->true_value()); |
1928 __ bind(&done); | 1929 __ bind(&done); |
1929 } | 1930 } |
1930 | 1931 |
1931 | 1932 |
1932 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1933 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
1933 ASSERT(ToRegister(instr->context()).is(esi)); | 1934 ASSERT(ToRegister(instr->context()).is(esi)); |
1934 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1935 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1935 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1936 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 29 matching lines...) Expand all Loading... |
1965 Register object = ToRegister(instr->InputAt(0)); | 1966 Register object = ToRegister(instr->InputAt(0)); |
1966 Register temp = ToRegister(instr->TempAt(0)); | 1967 Register temp = ToRegister(instr->TempAt(0)); |
1967 | 1968 |
1968 // A Smi is not an instance of anything. | 1969 // A Smi is not an instance of anything. |
1969 __ test(object, Immediate(kSmiTagMask)); | 1970 __ test(object, Immediate(kSmiTagMask)); |
1970 __ j(zero, &false_result, not_taken); | 1971 __ j(zero, &false_result, not_taken); |
1971 | 1972 |
1972 // This is the inlined call site instanceof cache. The two occurences of the | 1973 // This is the inlined call site instanceof cache. The two occurences of the |
1973 // hole value will be patched to the last map/result pair generated by the | 1974 // hole value will be patched to the last map/result pair generated by the |
1974 // instanceof stub. | 1975 // instanceof stub. |
1975 NearLabel cache_miss; | 1976 Label cache_miss; |
1976 Register map = ToRegister(instr->TempAt(0)); | 1977 Register map = ToRegister(instr->TempAt(0)); |
1977 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1978 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
1978 __ bind(deferred->map_check()); // Label for calculating code patching. | 1979 __ bind(deferred->map_check()); // Label for calculating code patching. |
1979 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. | 1980 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. |
1980 __ j(not_equal, &cache_miss, not_taken); | 1981 __ j(not_equal, &cache_miss, not_taken, Label::kNear); |
1981 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. | 1982 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. |
1982 __ jmp(&done); | 1983 __ jmp(&done); |
1983 | 1984 |
1984 // The inlined call site cache did not match. Check for null and string | 1985 // The inlined call site cache did not match. Check for null and string |
1985 // before calling the deferred code. | 1986 // before calling the deferred code. |
1986 __ bind(&cache_miss); | 1987 __ bind(&cache_miss); |
1987 // Null is not an instance of anything. | 1988 // Null is not an instance of anything. |
1988 __ cmp(object, factory()->null_value()); | 1989 __ cmp(object, factory()->null_value()); |
1989 __ j(equal, &false_result); | 1990 __ j(equal, &false_result); |
1990 | 1991 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2062 void LCodeGen::DoCmpT(LCmpT* instr) { | 2063 void LCodeGen::DoCmpT(LCmpT* instr) { |
2063 Token::Value op = instr->op(); | 2064 Token::Value op = instr->op(); |
2064 | 2065 |
2065 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2066 Handle<Code> ic = CompareIC::GetUninitialized(op); |
2066 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2067 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
2067 | 2068 |
2068 Condition condition = ComputeCompareCondition(op); | 2069 Condition condition = ComputeCompareCondition(op); |
2069 if (op == Token::GT || op == Token::LTE) { | 2070 if (op == Token::GT || op == Token::LTE) { |
2070 condition = ReverseCondition(condition); | 2071 condition = ReverseCondition(condition); |
2071 } | 2072 } |
2072 NearLabel true_value, done; | 2073 Label true_value, done; |
2073 __ test(eax, Operand(eax)); | 2074 __ test(eax, Operand(eax)); |
2074 __ j(condition, &true_value); | 2075 __ j(condition, &true_value, Label::kNear); |
2075 __ mov(ToRegister(instr->result()), factory()->false_value()); | 2076 __ mov(ToRegister(instr->result()), factory()->false_value()); |
2076 __ jmp(&done); | 2077 __ jmp(&done, Label::kNear); |
2077 __ bind(&true_value); | 2078 __ bind(&true_value); |
2078 __ mov(ToRegister(instr->result()), factory()->true_value()); | 2079 __ mov(ToRegister(instr->result()), factory()->true_value()); |
2079 __ bind(&done); | 2080 __ bind(&done); |
2080 } | 2081 } |
2081 | 2082 |
2082 | 2083 |
2083 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { | 2084 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
2084 Token::Value op = instr->op(); | 2085 Token::Value op = instr->op(); |
2085 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2086 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2086 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2087 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 Register result = ToRegister(instr->result()); | 2233 Register result = ToRegister(instr->result()); |
2233 | 2234 |
2234 int map_count = instr->hydrogen()->types()->length(); | 2235 int map_count = instr->hydrogen()->types()->length(); |
2235 Handle<String> name = instr->hydrogen()->name(); | 2236 Handle<String> name = instr->hydrogen()->name(); |
2236 if (map_count == 0) { | 2237 if (map_count == 0) { |
2237 ASSERT(instr->hydrogen()->need_generic()); | 2238 ASSERT(instr->hydrogen()->need_generic()); |
2238 __ mov(ecx, name); | 2239 __ mov(ecx, name); |
2239 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2240 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2240 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2241 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
2241 } else { | 2242 } else { |
2242 NearLabel done; | 2243 Label done; |
2243 for (int i = 0; i < map_count - 1; ++i) { | 2244 for (int i = 0; i < map_count - 1; ++i) { |
2244 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2245 Handle<Map> map = instr->hydrogen()->types()->at(i); |
2245 NearLabel next; | 2246 Label next; |
2246 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2247 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2247 __ j(not_equal, &next); | 2248 __ j(not_equal, &next, Label::kNear); |
2248 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2249 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2249 __ jmp(&done); | 2250 __ jmp(&done, Label::kNear); |
2250 __ bind(&next); | 2251 __ bind(&next); |
2251 } | 2252 } |
2252 Handle<Map> map = instr->hydrogen()->types()->last(); | 2253 Handle<Map> map = instr->hydrogen()->types()->last(); |
2253 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2254 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2254 if (instr->hydrogen()->need_generic()) { | 2255 if (instr->hydrogen()->need_generic()) { |
2255 NearLabel generic; | 2256 Label generic; |
2256 __ j(not_equal, &generic); | 2257 __ j(not_equal, &generic, Label::kNear); |
2257 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2258 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2258 __ jmp(&done); | 2259 __ jmp(&done, Label::kNear); |
2259 __ bind(&generic); | 2260 __ bind(&generic); |
2260 __ mov(ecx, name); | 2261 __ mov(ecx, name); |
2261 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2262 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2262 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2263 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
2263 } else { | 2264 } else { |
2264 DeoptimizeIf(not_equal, instr->environment()); | 2265 DeoptimizeIf(not_equal, instr->environment()); |
2265 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2266 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2266 } | 2267 } |
2267 __ bind(&done); | 2268 __ bind(&done); |
2268 } | 2269 } |
(...skipping 14 matching lines...) Expand all Loading... |
2283 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2284 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
2284 Register function = ToRegister(instr->function()); | 2285 Register function = ToRegister(instr->function()); |
2285 Register temp = ToRegister(instr->TempAt(0)); | 2286 Register temp = ToRegister(instr->TempAt(0)); |
2286 Register result = ToRegister(instr->result()); | 2287 Register result = ToRegister(instr->result()); |
2287 | 2288 |
2288 // Check that the function really is a function. | 2289 // Check that the function really is a function. |
2289 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2290 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
2290 DeoptimizeIf(not_equal, instr->environment()); | 2291 DeoptimizeIf(not_equal, instr->environment()); |
2291 | 2292 |
2292 // Check whether the function has an instance prototype. | 2293 // Check whether the function has an instance prototype. |
2293 NearLabel non_instance; | 2294 Label non_instance; |
2294 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 2295 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
2295 1 << Map::kHasNonInstancePrototype); | 2296 1 << Map::kHasNonInstancePrototype); |
2296 __ j(not_zero, &non_instance); | 2297 __ j(not_zero, &non_instance, Label::kNear); |
2297 | 2298 |
2298 // Get the prototype or initial map from the function. | 2299 // Get the prototype or initial map from the function. |
2299 __ mov(result, | 2300 __ mov(result, |
2300 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2301 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
2301 | 2302 |
2302 // Check that the function has a prototype or an initial map. | 2303 // Check that the function has a prototype or an initial map. |
2303 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); | 2304 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); |
2304 DeoptimizeIf(equal, instr->environment()); | 2305 DeoptimizeIf(equal, instr->environment()); |
2305 | 2306 |
2306 // If the function does not have an initial map, we're done. | 2307 // If the function does not have an initial map, we're done. |
2307 NearLabel done; | 2308 Label done; |
2308 __ CmpObjectType(result, MAP_TYPE, temp); | 2309 __ CmpObjectType(result, MAP_TYPE, temp); |
2309 __ j(not_equal, &done); | 2310 __ j(not_equal, &done, Label::kNear); |
2310 | 2311 |
2311 // Get the prototype from the initial map. | 2312 // Get the prototype from the initial map. |
2312 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); | 2313 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); |
2313 __ jmp(&done); | 2314 __ jmp(&done, Label::kNear); |
2314 | 2315 |
2315 // Non-instance prototype: Fetch prototype from constructor field | 2316 // Non-instance prototype: Fetch prototype from constructor field |
2316 // in the function's map. | 2317 // in the function's map. |
2317 __ bind(&non_instance); | 2318 __ bind(&non_instance); |
2318 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 2319 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
2319 | 2320 |
2320 // All done. | 2321 // All done. |
2321 __ bind(&done); | 2322 __ bind(&done); |
2322 } | 2323 } |
2323 | 2324 |
2324 | 2325 |
2325 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2326 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2326 Register result = ToRegister(instr->result()); | 2327 Register result = ToRegister(instr->result()); |
2327 Register input = ToRegister(instr->InputAt(0)); | 2328 Register input = ToRegister(instr->InputAt(0)); |
2328 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); | 2329 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); |
2329 if (FLAG_debug_code) { | 2330 if (FLAG_debug_code) { |
2330 NearLabel done; | 2331 Label done; |
2331 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2332 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
2332 Immediate(factory()->fixed_array_map())); | 2333 Immediate(factory()->fixed_array_map())); |
2333 __ j(equal, &done); | 2334 __ j(equal, &done, Label::kNear); |
2334 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2335 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
2335 Immediate(factory()->fixed_cow_array_map())); | 2336 Immediate(factory()->fixed_cow_array_map())); |
2336 __ j(equal, &done); | 2337 __ j(equal, &done, Label::kNear); |
2337 Register temp((result.is(eax)) ? ebx : eax); | 2338 Register temp((result.is(eax)) ? ebx : eax); |
2338 __ push(temp); | 2339 __ push(temp); |
2339 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2340 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2340 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 2341 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
2341 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); | 2342 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); |
2342 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); | 2343 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); |
2343 __ pop(temp); | 2344 __ pop(temp); |
2344 __ Check(below, "Check for fast elements or pixel array failed."); | 2345 __ Check(below, "Check for fast elements or pixel array failed."); |
2345 __ bind(&done); | 2346 __ bind(&done); |
2346 } | 2347 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2444 | 2445 |
2445 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2446 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2446 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2447 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); |
2447 } | 2448 } |
2448 | 2449 |
2449 | 2450 |
2450 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2451 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
2451 Register result = ToRegister(instr->result()); | 2452 Register result = ToRegister(instr->result()); |
2452 | 2453 |
2453 // Check for arguments adapter frame. | 2454 // Check for arguments adapter frame. |
2454 NearLabel done, adapted; | 2455 Label done, adapted; |
2455 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2456 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2456 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); | 2457 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
2457 __ cmp(Operand(result), | 2458 __ cmp(Operand(result), |
2458 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2459 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2459 __ j(equal, &adapted); | 2460 __ j(equal, &adapted, Label::kNear); |
2460 | 2461 |
2461 // No arguments adaptor frame. | 2462 // No arguments adaptor frame. |
2462 __ mov(result, Operand(ebp)); | 2463 __ mov(result, Operand(ebp)); |
2463 __ jmp(&done); | 2464 __ jmp(&done, Label::kNear); |
2464 | 2465 |
2465 // Arguments adaptor frame present. | 2466 // Arguments adaptor frame present. |
2466 __ bind(&adapted); | 2467 __ bind(&adapted); |
2467 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2468 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2468 | 2469 |
2469 // Result is the frame pointer for the frame if not adapted and for the real | 2470 // Result is the frame pointer for the frame if not adapted and for the real |
2470 // frame below the adaptor frame if adapted. | 2471 // frame below the adaptor frame if adapted. |
2471 __ bind(&done); | 2472 __ bind(&done); |
2472 } | 2473 } |
2473 | 2474 |
2474 | 2475 |
2475 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2476 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2476 Operand elem = ToOperand(instr->InputAt(0)); | 2477 Operand elem = ToOperand(instr->InputAt(0)); |
2477 Register result = ToRegister(instr->result()); | 2478 Register result = ToRegister(instr->result()); |
2478 | 2479 |
2479 NearLabel done; | 2480 Label done; |
2480 | 2481 |
2481 // If no arguments adaptor frame the number of arguments is fixed. | 2482 // If no arguments adaptor frame the number of arguments is fixed. |
2482 __ cmp(ebp, elem); | 2483 __ cmp(ebp, elem); |
2483 __ mov(result, Immediate(scope()->num_parameters())); | 2484 __ mov(result, Immediate(scope()->num_parameters())); |
2484 __ j(equal, &done); | 2485 __ j(equal, &done, Label::kNear); |
2485 | 2486 |
2486 // Arguments adaptor frame present. Get argument length from there. | 2487 // Arguments adaptor frame present. Get argument length from there. |
2487 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2488 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2488 __ mov(result, Operand(result, | 2489 __ mov(result, Operand(result, |
2489 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2490 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2490 __ SmiUntag(result); | 2491 __ SmiUntag(result); |
2491 | 2492 |
2492 // Argument length is in result register. | 2493 // Argument length is in result register. |
2493 __ bind(&done); | 2494 __ bind(&done); |
2494 } | 2495 } |
2495 | 2496 |
2496 | 2497 |
2497 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 2498 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
2498 Register receiver = ToRegister(instr->receiver()); | 2499 Register receiver = ToRegister(instr->receiver()); |
2499 Register function = ToRegister(instr->function()); | 2500 Register function = ToRegister(instr->function()); |
2500 Register length = ToRegister(instr->length()); | 2501 Register length = ToRegister(instr->length()); |
2501 Register elements = ToRegister(instr->elements()); | 2502 Register elements = ToRegister(instr->elements()); |
2502 Register scratch = ToRegister(instr->TempAt(0)); | 2503 Register scratch = ToRegister(instr->TempAt(0)); |
2503 ASSERT(receiver.is(eax)); // Used for parameter count. | 2504 ASSERT(receiver.is(eax)); // Used for parameter count. |
2504 ASSERT(function.is(edi)); // Required by InvokeFunction. | 2505 ASSERT(function.is(edi)); // Required by InvokeFunction. |
2505 ASSERT(ToRegister(instr->result()).is(eax)); | 2506 ASSERT(ToRegister(instr->result()).is(eax)); |
2506 | 2507 |
2507 // If the receiver is null or undefined, we have to pass the global object | 2508 // If the receiver is null or undefined, we have to pass the global object |
2508 // as a receiver. | 2509 // as a receiver. |
2509 NearLabel global_object, receiver_ok; | 2510 Label global_object, receiver_ok; |
2510 __ cmp(receiver, factory()->null_value()); | 2511 __ cmp(receiver, factory()->null_value()); |
2511 __ j(equal, &global_object); | 2512 __ j(equal, &global_object, Label::kNear); |
2512 __ cmp(receiver, factory()->undefined_value()); | 2513 __ cmp(receiver, factory()->undefined_value()); |
2513 __ j(equal, &global_object); | 2514 __ j(equal, &global_object, Label::kNear); |
2514 | 2515 |
2515 // The receiver should be a JS object. | 2516 // The receiver should be a JS object. |
2516 __ test(receiver, Immediate(kSmiTagMask)); | 2517 __ test(receiver, Immediate(kSmiTagMask)); |
2517 DeoptimizeIf(equal, instr->environment()); | 2518 DeoptimizeIf(equal, instr->environment()); |
2518 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); | 2519 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); |
2519 DeoptimizeIf(below, instr->environment()); | 2520 DeoptimizeIf(below, instr->environment()); |
2520 __ jmp(&receiver_ok); | 2521 __ jmp(&receiver_ok, Label::kNear); |
2521 | 2522 |
2522 __ bind(&global_object); | 2523 __ bind(&global_object); |
2523 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2524 // TODO(kmillikin): We have a hydrogen value for the global object. See |
2524 // if it's better to use it than to explicitly fetch it from the context | 2525 // if it's better to use it than to explicitly fetch it from the context |
2525 // here. | 2526 // here. |
2526 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2527 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2527 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2528 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
2528 __ bind(&receiver_ok); | 2529 __ bind(&receiver_ok); |
2529 | 2530 |
2530 // Copy the arguments to this function possibly from the | 2531 // Copy the arguments to this function possibly from the |
2531 // adaptor frame below it. | 2532 // adaptor frame below it. |
2532 const uint32_t kArgumentsLimit = 1 * KB; | 2533 const uint32_t kArgumentsLimit = 1 * KB; |
2533 __ cmp(length, kArgumentsLimit); | 2534 __ cmp(length, kArgumentsLimit); |
2534 DeoptimizeIf(above, instr->environment()); | 2535 DeoptimizeIf(above, instr->environment()); |
2535 | 2536 |
2536 __ push(receiver); | 2537 __ push(receiver); |
2537 __ mov(receiver, length); | 2538 __ mov(receiver, length); |
2538 | 2539 |
2539 // Loop through the arguments pushing them onto the execution | 2540 // Loop through the arguments pushing them onto the execution |
2540 // stack. | 2541 // stack. |
2541 NearLabel invoke, loop; | 2542 Label invoke, loop; |
2542 // length is a small non-negative integer, due to the test above. | 2543 // length is a small non-negative integer, due to the test above. |
2543 __ test(length, Operand(length)); | 2544 __ test(length, Operand(length)); |
2544 __ j(zero, &invoke); | 2545 __ j(zero, &invoke, Label::kNear); |
2545 __ bind(&loop); | 2546 __ bind(&loop); |
2546 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 2547 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); |
2547 __ dec(length); | 2548 __ dec(length); |
2548 __ j(not_zero, &loop); | 2549 __ j(not_zero, &loop); |
2549 | 2550 |
2550 // Invoke the function. | 2551 // Invoke the function. |
2551 __ bind(&invoke); | 2552 __ bind(&invoke); |
2552 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 2553 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
2553 LPointerMap* pointers = instr->pointer_map(); | 2554 LPointerMap* pointers = instr->pointer_map(); |
2554 LEnvironment* env = instr->deoptimization_environment(); | 2555 LEnvironment* env = instr->deoptimization_environment(); |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2886 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2887 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2887 __ fstp_d(Operand(esp, 0)); | 2888 __ fstp_d(Operand(esp, 0)); |
2888 __ movdbl(result_reg, Operand(esp, 0)); | 2889 __ movdbl(result_reg, Operand(esp, 0)); |
2889 __ add(Operand(esp), Immediate(kDoubleSize)); | 2890 __ add(Operand(esp), Immediate(kDoubleSize)); |
2890 } | 2891 } |
2891 | 2892 |
2892 | 2893 |
2893 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2894 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
2894 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2895 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
2895 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2896 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
2896 NearLabel positive, done, zero, negative; | 2897 Label positive, done, zero; |
2897 __ xorps(xmm0, xmm0); | 2898 __ xorps(xmm0, xmm0); |
2898 __ ucomisd(input_reg, xmm0); | 2899 __ ucomisd(input_reg, xmm0); |
2899 __ j(above, &positive); | 2900 __ j(above, &positive, Label::kNear); |
2900 __ j(equal, &zero); | 2901 __ j(equal, &zero, Label::kNear); |
2901 ExternalReference nan = ExternalReference::address_of_nan(); | 2902 ExternalReference nan = ExternalReference::address_of_nan(); |
2902 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 2903 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
2903 __ jmp(&done); | 2904 __ jmp(&done, Label::kNear); |
2904 __ bind(&zero); | 2905 __ bind(&zero); |
2905 __ push(Immediate(0xFFF00000)); | 2906 __ push(Immediate(0xFFF00000)); |
2906 __ push(Immediate(0)); | 2907 __ push(Immediate(0)); |
2907 __ movdbl(input_reg, Operand(esp, 0)); | 2908 __ movdbl(input_reg, Operand(esp, 0)); |
2908 __ add(Operand(esp), Immediate(kDoubleSize)); | 2909 __ add(Operand(esp), Immediate(kDoubleSize)); |
2909 __ jmp(&done); | 2910 __ jmp(&done, Label::kNear); |
2910 __ bind(&positive); | 2911 __ bind(&positive); |
2911 __ fldln2(); | 2912 __ fldln2(); |
2912 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2913 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2913 __ movdbl(Operand(esp, 0), input_reg); | 2914 __ movdbl(Operand(esp, 0), input_reg); |
2914 __ fld_d(Operand(esp, 0)); | 2915 __ fld_d(Operand(esp, 0)); |
2915 __ fyl2x(); | 2916 __ fyl2x(); |
2916 __ fstp_d(Operand(esp, 0)); | 2917 __ fstp_d(Operand(esp, 0)); |
2917 __ movdbl(input_reg, Operand(esp, 0)); | 2918 __ movdbl(input_reg, Operand(esp, 0)); |
2918 __ add(Operand(esp), Immediate(kDoubleSize)); | 2919 __ add(Operand(esp), Immediate(kDoubleSize)); |
2919 __ bind(&done); | 2920 __ bind(&done); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3119 switch (array_type) { | 3120 switch (array_type) { |
3120 case kExternalPixelArray: { | 3121 case kExternalPixelArray: { |
3121 // Clamp the value to [0..255]. | 3122 // Clamp the value to [0..255]. |
3122 Register temp = ToRegister(instr->TempAt(0)); | 3123 Register temp = ToRegister(instr->TempAt(0)); |
3123 // The dec_b below requires that the clamped value is in a byte | 3124 // The dec_b below requires that the clamped value is in a byte |
3124 // register. eax is an arbitrary choice to satisfy this requirement, we | 3125 // register. eax is an arbitrary choice to satisfy this requirement, we |
3125 // hinted the register allocator to give us eax when building the | 3126 // hinted the register allocator to give us eax when building the |
3126 // instruction. | 3127 // instruction. |
3127 ASSERT(temp.is(eax)); | 3128 ASSERT(temp.is(eax)); |
3128 __ mov(temp, ToRegister(instr->value())); | 3129 __ mov(temp, ToRegister(instr->value())); |
3129 NearLabel done; | 3130 Label done; |
3130 __ test(temp, Immediate(0xFFFFFF00)); | 3131 __ test(temp, Immediate(0xFFFFFF00)); |
3131 __ j(zero, &done); | 3132 __ j(zero, &done, Label::kNear); |
3132 __ setcc(negative, temp); // 1 if negative, 0 if positive. | 3133 __ setcc(negative, temp); // 1 if negative, 0 if positive. |
3133 __ dec_b(temp); // 0 if negative, 255 if positive. | 3134 __ dec_b(temp); // 0 if negative, 255 if positive. |
3134 __ bind(&done); | 3135 __ bind(&done); |
3135 __ mov_b(Operand(external_pointer, key, times_1, 0), temp); | 3136 __ mov_b(Operand(external_pointer, key, times_1, 0), temp); |
3136 break; | 3137 break; |
3137 } | 3138 } |
3138 case kExternalByteArray: | 3139 case kExternalByteArray: |
3139 case kExternalUnsignedByteArray: | 3140 case kExternalUnsignedByteArray: |
3140 __ mov_b(Operand(external_pointer, key, times_1, 0), value); | 3141 __ mov_b(Operand(external_pointer, key, times_1, 0), value); |
3141 break; | 3142 break; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3228 return; | 3229 return; |
3229 } | 3230 } |
3230 } else { | 3231 } else { |
3231 index = ToRegister(instr->index()); | 3232 index = ToRegister(instr->index()); |
3232 } | 3233 } |
3233 Register result = ToRegister(instr->result()); | 3234 Register result = ToRegister(instr->result()); |
3234 | 3235 |
3235 DeferredStringCharCodeAt* deferred = | 3236 DeferredStringCharCodeAt* deferred = |
3236 new DeferredStringCharCodeAt(this, instr); | 3237 new DeferredStringCharCodeAt(this, instr); |
3237 | 3238 |
3238 NearLabel flat_string, ascii_string, done; | 3239 Label flat_string, ascii_string, done; |
3239 | 3240 |
3240 // Fetch the instance type of the receiver into result register. | 3241 // Fetch the instance type of the receiver into result register. |
3241 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3242 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
3242 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3243 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
3243 | 3244 |
3244 // We need special handling for non-flat strings. | 3245 // We need special handling for non-flat strings. |
3245 STATIC_ASSERT(kSeqStringTag == 0); | 3246 STATIC_ASSERT(kSeqStringTag == 0); |
3246 __ test(result, Immediate(kStringRepresentationMask)); | 3247 __ test(result, Immediate(kStringRepresentationMask)); |
3247 __ j(zero, &flat_string); | 3248 __ j(zero, &flat_string, Label::kNear); |
3248 | 3249 |
3249 // Handle non-flat strings. | 3250 // Handle non-flat strings. |
3250 __ test(result, Immediate(kIsConsStringMask)); | 3251 __ test(result, Immediate(kIsConsStringMask)); |
3251 __ j(zero, deferred->entry()); | 3252 __ j(zero, deferred->entry()); |
3252 | 3253 |
3253 // ConsString. | 3254 // ConsString. |
3254 // Check whether the right hand side is the empty string (i.e. if | 3255 // Check whether the right hand side is the empty string (i.e. if |
3255 // this is really a flat string in a cons string). If that is not | 3256 // this is really a flat string in a cons string). If that is not |
3256 // the case we would rather go to the runtime system now to flatten | 3257 // the case we would rather go to the runtime system now to flatten |
3257 // the string. | 3258 // the string. |
3258 __ cmp(FieldOperand(string, ConsString::kSecondOffset), | 3259 __ cmp(FieldOperand(string, ConsString::kSecondOffset), |
3259 Immediate(factory()->empty_string())); | 3260 Immediate(factory()->empty_string())); |
3260 __ j(not_equal, deferred->entry()); | 3261 __ j(not_equal, deferred->entry()); |
3261 // Get the first of the two strings and load its instance type. | 3262 // Get the first of the two strings and load its instance type. |
3262 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); | 3263 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); |
3263 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3264 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
3264 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3265 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
3265 // If the first cons component is also non-flat, then go to runtime. | 3266 // If the first cons component is also non-flat, then go to runtime. |
3266 STATIC_ASSERT(kSeqStringTag == 0); | 3267 STATIC_ASSERT(kSeqStringTag == 0); |
3267 __ test(result, Immediate(kStringRepresentationMask)); | 3268 __ test(result, Immediate(kStringRepresentationMask)); |
3268 __ j(not_zero, deferred->entry()); | 3269 __ j(not_zero, deferred->entry()); |
3269 | 3270 |
3270 // Check for ASCII or two-byte string. | 3271 // Check for ASCII or two-byte string. |
3271 __ bind(&flat_string); | 3272 __ bind(&flat_string); |
3272 STATIC_ASSERT(kAsciiStringTag != 0); | 3273 STATIC_ASSERT(kAsciiStringTag != 0); |
3273 __ test(result, Immediate(kStringEncodingMask)); | 3274 __ test(result, Immediate(kStringEncodingMask)); |
3274 __ j(not_zero, &ascii_string); | 3275 __ j(not_zero, &ascii_string, Label::kNear); |
3275 | 3276 |
3276 // Two-byte string. | 3277 // Two-byte string. |
3277 // Load the two-byte character code into the result register. | 3278 // Load the two-byte character code into the result register. |
3278 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 3279 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
3279 if (instr->index()->IsConstantOperand()) { | 3280 if (instr->index()->IsConstantOperand()) { |
3280 __ movzx_w(result, | 3281 __ movzx_w(result, |
3281 FieldOperand(string, | 3282 FieldOperand(string, |
3282 SeqTwoByteString::kHeaderSize + | 3283 SeqTwoByteString::kHeaderSize + |
3283 (kUC16Size * const_index))); | 3284 (kUC16Size * const_index))); |
3284 } else { | 3285 } else { |
3285 __ movzx_w(result, FieldOperand(string, | 3286 __ movzx_w(result, FieldOperand(string, |
3286 index, | 3287 index, |
3287 times_2, | 3288 times_2, |
3288 SeqTwoByteString::kHeaderSize)); | 3289 SeqTwoByteString::kHeaderSize)); |
3289 } | 3290 } |
3290 __ jmp(&done); | 3291 __ jmp(&done, Label::kNear); |
3291 | 3292 |
3292 // ASCII string. | 3293 // ASCII string. |
3293 // Load the byte into the result register. | 3294 // Load the byte into the result register. |
3294 __ bind(&ascii_string); | 3295 __ bind(&ascii_string); |
3295 if (instr->index()->IsConstantOperand()) { | 3296 if (instr->index()->IsConstantOperand()) { |
3296 __ movzx_b(result, FieldOperand(string, | 3297 __ movzx_b(result, FieldOperand(string, |
3297 SeqAsciiString::kHeaderSize + const_index)); | 3298 SeqAsciiString::kHeaderSize + const_index)); |
3298 } else { | 3299 } else { |
3299 __ movzx_b(result, FieldOperand(string, | 3300 __ movzx_b(result, FieldOperand(string, |
3300 index, | 3301 index, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3441 Label slow; | 3442 Label slow; |
3442 Register reg = ToRegister(instr->InputAt(0)); | 3443 Register reg = ToRegister(instr->InputAt(0)); |
3443 Register tmp = reg.is(eax) ? ecx : eax; | 3444 Register tmp = reg.is(eax) ? ecx : eax; |
3444 | 3445 |
3445 // Preserve the value of all registers. | 3446 // Preserve the value of all registers. |
3446 PushSafepointRegistersScope scope(this); | 3447 PushSafepointRegistersScope scope(this); |
3447 | 3448 |
3448 // There was overflow, so bits 30 and 31 of the original integer | 3449 // There was overflow, so bits 30 and 31 of the original integer |
3449 // disagree. Try to allocate a heap number in new space and store | 3450 // disagree. Try to allocate a heap number in new space and store |
3450 // the value in there. If that fails, call the runtime system. | 3451 // the value in there. If that fails, call the runtime system. |
3451 NearLabel done; | 3452 Label done; |
3452 __ SmiUntag(reg); | 3453 __ SmiUntag(reg); |
3453 __ xor_(reg, 0x80000000); | 3454 __ xor_(reg, 0x80000000); |
3454 __ cvtsi2sd(xmm0, Operand(reg)); | 3455 __ cvtsi2sd(xmm0, Operand(reg)); |
3455 if (FLAG_inline_new) { | 3456 if (FLAG_inline_new) { |
3456 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 3457 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
3457 __ jmp(&done); | 3458 __ jmp(&done, Label::kNear); |
3458 } | 3459 } |
3459 | 3460 |
3460 // Slow case: Call the runtime system to do the number allocation. | 3461 // Slow case: Call the runtime system to do the number allocation. |
3461 __ bind(&slow); | 3462 __ bind(&slow); |
3462 | 3463 |
3463 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3464 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
3464 // register is stored, as this register is in the pointer map, but contains an | 3465 // register is stored, as this register is in the pointer map, but contains an |
3465 // integer value. | 3466 // integer value. |
3466 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 3467 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
3467 | 3468 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3529 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3530 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
3530 DeoptimizeIf(not_zero, instr->environment()); | 3531 DeoptimizeIf(not_zero, instr->environment()); |
3531 } | 3532 } |
3532 __ SmiUntag(ToRegister(input)); | 3533 __ SmiUntag(ToRegister(input)); |
3533 } | 3534 } |
3534 | 3535 |
3535 | 3536 |
3536 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3537 void LCodeGen::EmitNumberUntagD(Register input_reg, |
3537 XMMRegister result_reg, | 3538 XMMRegister result_reg, |
3538 LEnvironment* env) { | 3539 LEnvironment* env) { |
3539 NearLabel load_smi, heap_number, done; | 3540 Label load_smi, heap_number, done; |
3540 | 3541 |
3541 // Smi check. | 3542 // Smi check. |
3542 __ test(input_reg, Immediate(kSmiTagMask)); | 3543 __ test(input_reg, Immediate(kSmiTagMask)); |
3543 __ j(zero, &load_smi, not_taken); | 3544 __ j(zero, &load_smi, not_taken, Label::kNear); |
3544 | 3545 |
3545 // Heap number map check. | 3546 // Heap number map check. |
3546 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3547 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
3547 factory()->heap_number_map()); | 3548 factory()->heap_number_map()); |
3548 __ j(equal, &heap_number); | 3549 __ j(equal, &heap_number, Label::kNear); |
3549 | 3550 |
3550 __ cmp(input_reg, factory()->undefined_value()); | 3551 __ cmp(input_reg, factory()->undefined_value()); |
3551 DeoptimizeIf(not_equal, env); | 3552 DeoptimizeIf(not_equal, env); |
3552 | 3553 |
3553 // Convert undefined to NaN. | 3554 // Convert undefined to NaN. |
3554 ExternalReference nan = ExternalReference::address_of_nan(); | 3555 ExternalReference nan = ExternalReference::address_of_nan(); |
3555 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 3556 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
3556 __ jmp(&done); | 3557 __ jmp(&done, Label::kNear); |
3557 | 3558 |
3558 // Heap number to XMM conversion. | 3559 // Heap number to XMM conversion. |
3559 __ bind(&heap_number); | 3560 __ bind(&heap_number); |
3560 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3561 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3561 __ jmp(&done); | 3562 __ jmp(&done, Label::kNear); |
3562 | 3563 |
3563 // Smi to XMM conversion | 3564 // Smi to XMM conversion |
3564 __ bind(&load_smi); | 3565 __ bind(&load_smi); |
3565 __ SmiUntag(input_reg); // Untag smi before converting to float. | 3566 __ SmiUntag(input_reg); // Untag smi before converting to float. |
3566 __ cvtsi2sd(result_reg, Operand(input_reg)); | 3567 __ cvtsi2sd(result_reg, Operand(input_reg)); |
3567 __ SmiTag(input_reg); // Retag smi. | 3568 __ SmiTag(input_reg); // Retag smi. |
3568 __ bind(&done); | 3569 __ bind(&done); |
3569 } | 3570 } |
3570 | 3571 |
3571 | 3572 |
3572 class DeferredTaggedToI: public LDeferredCode { | 3573 class DeferredTaggedToI: public LDeferredCode { |
3573 public: | 3574 public: |
3574 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3575 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
3575 : LDeferredCode(codegen), instr_(instr) { } | 3576 : LDeferredCode(codegen), instr_(instr) { } |
3576 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3577 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
3577 private: | 3578 private: |
3578 LTaggedToI* instr_; | 3579 LTaggedToI* instr_; |
3579 }; | 3580 }; |
3580 | 3581 |
3581 | 3582 |
3582 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3583 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
3583 NearLabel done, heap_number; | 3584 Label done, heap_number; |
3584 Register input_reg = ToRegister(instr->InputAt(0)); | 3585 Register input_reg = ToRegister(instr->InputAt(0)); |
3585 | 3586 |
3586 // Heap number map check. | 3587 // Heap number map check. |
3587 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3588 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
3588 factory()->heap_number_map()); | 3589 factory()->heap_number_map()); |
3589 | 3590 |
3590 if (instr->truncating()) { | 3591 if (instr->truncating()) { |
3591 __ j(equal, &heap_number); | 3592 __ j(equal, &heap_number, Label::kNear); |
3592 // Check for undefined. Undefined is converted to zero for truncating | 3593 // Check for undefined. Undefined is converted to zero for truncating |
3593 // conversions. | 3594 // conversions. |
3594 __ cmp(input_reg, factory()->undefined_value()); | 3595 __ cmp(input_reg, factory()->undefined_value()); |
3595 DeoptimizeIf(not_equal, instr->environment()); | 3596 DeoptimizeIf(not_equal, instr->environment()); |
3596 __ mov(input_reg, 0); | 3597 __ mov(input_reg, 0); |
3597 __ jmp(&done); | 3598 __ jmp(&done, Label::kNear); |
3598 | 3599 |
3599 __ bind(&heap_number); | 3600 __ bind(&heap_number); |
3600 if (CpuFeatures::IsSupported(SSE3)) { | 3601 if (CpuFeatures::IsSupported(SSE3)) { |
3601 CpuFeatures::Scope scope(SSE3); | 3602 CpuFeatures::Scope scope(SSE3); |
3602 NearLabel convert; | 3603 Label convert; |
3603 // Use more powerful conversion when sse3 is available. | 3604 // Use more powerful conversion when sse3 is available. |
3604 // Load x87 register with heap number. | 3605 // Load x87 register with heap number. |
3605 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3606 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3606 // Get exponent alone and check for too-big exponent. | 3607 // Get exponent alone and check for too-big exponent. |
3607 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3608 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
3608 __ and_(input_reg, HeapNumber::kExponentMask); | 3609 __ and_(input_reg, HeapNumber::kExponentMask); |
3609 const uint32_t kTooBigExponent = | 3610 const uint32_t kTooBigExponent = |
3610 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3611 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
3611 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); | 3612 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); |
3612 __ j(less, &convert); | 3613 __ j(less, &convert, Label::kNear); |
3613 // Pop FPU stack before deoptimizing. | 3614 // Pop FPU stack before deoptimizing. |
3614 __ ffree(0); | 3615 __ ffree(0); |
3615 __ fincstp(); | 3616 __ fincstp(); |
3616 DeoptimizeIf(no_condition, instr->environment()); | 3617 DeoptimizeIf(no_condition, instr->environment()); |
3617 | 3618 |
3618 // Reserve space for 64 bit answer. | 3619 // Reserve space for 64 bit answer. |
3619 __ bind(&convert); | 3620 __ bind(&convert); |
3620 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3621 __ sub(Operand(esp), Immediate(kDoubleSize)); |
3621 // Do conversion, which cannot fail because we checked the exponent. | 3622 // Do conversion, which cannot fail because we checked the exponent. |
3622 __ fisttp_d(Operand(esp, 0)); | 3623 __ fisttp_d(Operand(esp, 0)); |
3623 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 3624 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
3624 __ add(Operand(esp), Immediate(kDoubleSize)); | 3625 __ add(Operand(esp), Immediate(kDoubleSize)); |
3625 } else { | 3626 } else { |
3626 NearLabel deopt; | |
3627 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 3627 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
3628 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3628 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
3629 __ cvttsd2si(input_reg, Operand(xmm0)); | 3629 __ cvttsd2si(input_reg, Operand(xmm0)); |
3630 __ cmp(input_reg, 0x80000000u); | 3630 __ cmp(input_reg, 0x80000000u); |
3631 __ j(not_equal, &done); | 3631 __ j(not_equal, &done); |
3632 // Check if the input was 0x8000000 (kMinInt). | 3632 // Check if the input was 0x8000000 (kMinInt). |
3633 // If no, then we got an overflow and we deoptimize. | 3633 // If no, then we got an overflow and we deoptimize. |
3634 ExternalReference min_int = ExternalReference::address_of_min_int(); | 3634 ExternalReference min_int = ExternalReference::address_of_min_int(); |
3635 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 3635 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
3636 __ ucomisd(xmm_temp, xmm0); | 3636 __ ucomisd(xmm_temp, xmm0); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3703 Register result_reg = ToRegister(result); | 3703 Register result_reg = ToRegister(result); |
3704 | 3704 |
3705 if (instr->truncating()) { | 3705 if (instr->truncating()) { |
3706 // Performs a truncating conversion of a floating point number as used by | 3706 // Performs a truncating conversion of a floating point number as used by |
3707 // the JS bitwise operations. | 3707 // the JS bitwise operations. |
3708 __ cvttsd2si(result_reg, Operand(input_reg)); | 3708 __ cvttsd2si(result_reg, Operand(input_reg)); |
3709 __ cmp(result_reg, 0x80000000u); | 3709 __ cmp(result_reg, 0x80000000u); |
3710 if (CpuFeatures::IsSupported(SSE3)) { | 3710 if (CpuFeatures::IsSupported(SSE3)) { |
3711 // This will deoptimize if the exponent of the input in out of range. | 3711 // This will deoptimize if the exponent of the input in out of range. |
3712 CpuFeatures::Scope scope(SSE3); | 3712 CpuFeatures::Scope scope(SSE3); |
3713 NearLabel convert, done; | 3713 Label convert, done; |
3714 __ j(not_equal, &done); | 3714 __ j(not_equal, &done, Label::kNear); |
3715 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3715 __ sub(Operand(esp), Immediate(kDoubleSize)); |
3716 __ movdbl(Operand(esp, 0), input_reg); | 3716 __ movdbl(Operand(esp, 0), input_reg); |
3717 // Get exponent alone and check for too-big exponent. | 3717 // Get exponent alone and check for too-big exponent. |
3718 __ mov(result_reg, Operand(esp, sizeof(int32_t))); | 3718 __ mov(result_reg, Operand(esp, sizeof(int32_t))); |
3719 __ and_(result_reg, HeapNumber::kExponentMask); | 3719 __ and_(result_reg, HeapNumber::kExponentMask); |
3720 const uint32_t kTooBigExponent = | 3720 const uint32_t kTooBigExponent = |
3721 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3721 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
3722 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); | 3722 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); |
3723 __ j(less, &convert); | 3723 __ j(less, &convert, Label::kNear); |
3724 __ add(Operand(esp), Immediate(kDoubleSize)); | 3724 __ add(Operand(esp), Immediate(kDoubleSize)); |
3725 DeoptimizeIf(no_condition, instr->environment()); | 3725 DeoptimizeIf(no_condition, instr->environment()); |
3726 __ bind(&convert); | 3726 __ bind(&convert); |
3727 // Do conversion, which cannot fail because we checked the exponent. | 3727 // Do conversion, which cannot fail because we checked the exponent. |
3728 __ fld_d(Operand(esp, 0)); | 3728 __ fld_d(Operand(esp, 0)); |
3729 __ fisttp_d(Operand(esp, 0)); | 3729 __ fisttp_d(Operand(esp, 0)); |
3730 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 3730 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
3731 __ add(Operand(esp), Immediate(kDoubleSize)); | 3731 __ add(Operand(esp), Immediate(kDoubleSize)); |
3732 __ bind(&done); | 3732 __ bind(&done); |
3733 } else { | 3733 } else { |
3734 NearLabel done; | 3734 Label done; |
3735 Register temp_reg = ToRegister(instr->TempAt(0)); | 3735 Register temp_reg = ToRegister(instr->TempAt(0)); |
3736 XMMRegister xmm_scratch = xmm0; | 3736 XMMRegister xmm_scratch = xmm0; |
3737 | 3737 |
3738 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 3738 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
3739 // manual conversion. | 3739 // manual conversion. |
3740 __ j(not_equal, &done); | 3740 __ j(not_equal, &done, Label::kNear); |
3741 | 3741 |
3742 // Get high 32 bits of the input in result_reg and temp_reg. | 3742 // Get high 32 bits of the input in result_reg and temp_reg. |
3743 __ pshufd(xmm_scratch, input_reg, 1); | 3743 __ pshufd(xmm_scratch, input_reg, 1); |
3744 __ movd(Operand(temp_reg), xmm_scratch); | 3744 __ movd(Operand(temp_reg), xmm_scratch); |
3745 __ mov(result_reg, temp_reg); | 3745 __ mov(result_reg, temp_reg); |
3746 | 3746 |
3747 // Prepare negation mask in temp_reg. | 3747 // Prepare negation mask in temp_reg. |
3748 __ sar(temp_reg, kBitsPerInt - 1); | 3748 __ sar(temp_reg, kBitsPerInt - 1); |
3749 | 3749 |
3750 // Extract the exponent from result_reg and subtract adjusted | 3750 // Extract the exponent from result_reg and subtract adjusted |
(...skipping 29 matching lines...) Expand all Loading... |
3780 // Shift the input right and extract low 32 bits. | 3780 // Shift the input right and extract low 32 bits. |
3781 __ psrlq(input_reg, xmm_scratch); | 3781 __ psrlq(input_reg, xmm_scratch); |
3782 __ movd(Operand(result_reg), input_reg); | 3782 __ movd(Operand(result_reg), input_reg); |
3783 | 3783 |
3784 // Use the prepared mask in temp_reg to negate the result if necessary. | 3784 // Use the prepared mask in temp_reg to negate the result if necessary. |
3785 __ xor_(result_reg, Operand(temp_reg)); | 3785 __ xor_(result_reg, Operand(temp_reg)); |
3786 __ sub(result_reg, Operand(temp_reg)); | 3786 __ sub(result_reg, Operand(temp_reg)); |
3787 __ bind(&done); | 3787 __ bind(&done); |
3788 } | 3788 } |
3789 } else { | 3789 } else { |
3790 NearLabel done; | 3790 Label done; |
3791 __ cvttsd2si(result_reg, Operand(input_reg)); | 3791 __ cvttsd2si(result_reg, Operand(input_reg)); |
3792 __ cvtsi2sd(xmm0, Operand(result_reg)); | 3792 __ cvtsi2sd(xmm0, Operand(result_reg)); |
3793 __ ucomisd(xmm0, input_reg); | 3793 __ ucomisd(xmm0, input_reg); |
3794 DeoptimizeIf(not_equal, instr->environment()); | 3794 DeoptimizeIf(not_equal, instr->environment()); |
3795 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3795 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
3796 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3796 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3797 // The integer converted back is equal to the original. We | 3797 // The integer converted back is equal to the original. We |
3798 // only have to test if we got -0 as an input. | 3798 // only have to test if we got -0 as an input. |
3799 __ test(result_reg, Operand(result_reg)); | 3799 __ test(result_reg, Operand(result_reg)); |
3800 __ j(not_zero, &done); | 3800 __ j(not_zero, &done, Label::kNear); |
3801 __ movmskpd(result_reg, input_reg); | 3801 __ movmskpd(result_reg, input_reg); |
3802 // Bit 0 contains the sign of the double in input_reg. | 3802 // Bit 0 contains the sign of the double in input_reg. |
3803 // If input was positive, we are ok and return 0, otherwise | 3803 // If input was positive, we are ok and return 0, otherwise |
3804 // deoptimize. | 3804 // deoptimize. |
3805 __ and_(result_reg, 1); | 3805 __ and_(result_reg, 1); |
3806 DeoptimizeIf(not_zero, instr->environment()); | 3806 DeoptimizeIf(not_zero, instr->environment()); |
3807 } | 3807 } |
3808 __ bind(&done); | 3808 __ bind(&done); |
3809 } | 3809 } |
3810 } | 3810 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3967 | 3967 |
3968 | 3968 |
3969 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 3969 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
3970 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 3970 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
3971 __ push(eax); | 3971 __ push(eax); |
3972 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); | 3972 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); |
3973 } | 3973 } |
3974 | 3974 |
3975 | 3975 |
3976 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 3976 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
3977 NearLabel materialized; | 3977 Label materialized; |
3978 // Registers will be used as follows: | 3978 // Registers will be used as follows: |
3979 // edi = JS function. | 3979 // edi = JS function. |
3980 // ecx = literals array. | 3980 // ecx = literals array. |
3981 // ebx = regexp literal. | 3981 // ebx = regexp literal. |
3982 // eax = regexp literal clone. | 3982 // eax = regexp literal clone. |
3983 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3983 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
3984 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 3984 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
3985 int literal_offset = FixedArray::kHeaderSize + | 3985 int literal_offset = FixedArray::kHeaderSize + |
3986 instr->hydrogen()->literal_index() * kPointerSize; | 3986 instr->hydrogen()->literal_index() * kPointerSize; |
3987 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 3987 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
3988 __ cmp(ebx, factory()->undefined_value()); | 3988 __ cmp(ebx, factory()->undefined_value()); |
3989 __ j(not_equal, &materialized); | 3989 __ j(not_equal, &materialized, Label::kNear); |
3990 | 3990 |
3991 // Create regexp literal using runtime function | 3991 // Create regexp literal using runtime function |
3992 // Result will be in eax. | 3992 // Result will be in eax. |
3993 __ push(ecx); | 3993 __ push(ecx); |
3994 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 3994 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
3995 __ push(Immediate(instr->hydrogen()->pattern())); | 3995 __ push(Immediate(instr->hydrogen()->pattern())); |
3996 __ push(Immediate(instr->hydrogen()->flags())); | 3996 __ push(Immediate(instr->hydrogen()->flags())); |
3997 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); | 3997 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); |
3998 __ mov(ebx, eax); | 3998 __ mov(ebx, eax); |
3999 | 3999 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4055 } | 4055 } |
4056 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 4056 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); |
4057 } | 4057 } |
4058 | 4058 |
4059 | 4059 |
4060 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 4060 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
4061 Register input = ToRegister(instr->InputAt(0)); | 4061 Register input = ToRegister(instr->InputAt(0)); |
4062 Register result = ToRegister(instr->result()); | 4062 Register result = ToRegister(instr->result()); |
4063 Label true_label; | 4063 Label true_label; |
4064 Label false_label; | 4064 Label false_label; |
4065 NearLabel done; | 4065 Label done; |
4066 | 4066 |
4067 Condition final_branch_condition = EmitTypeofIs(&true_label, | 4067 Condition final_branch_condition = EmitTypeofIs(&true_label, |
4068 &false_label, | 4068 &false_label, |
4069 input, | 4069 input, |
4070 instr->type_literal()); | 4070 instr->type_literal()); |
4071 __ j(final_branch_condition, &true_label); | 4071 __ j(final_branch_condition, &true_label, Label::kNear); |
4072 __ bind(&false_label); | 4072 __ bind(&false_label); |
4073 __ mov(result, factory()->false_value()); | 4073 __ mov(result, factory()->false_value()); |
4074 __ jmp(&done); | 4074 __ jmp(&done, Label::kNear); |
4075 | 4075 |
4076 __ bind(&true_label); | 4076 __ bind(&true_label); |
4077 __ mov(result, factory()->true_value()); | 4077 __ mov(result, factory()->true_value()); |
4078 | 4078 |
4079 __ bind(&done); | 4079 __ bind(&done); |
4080 } | 4080 } |
4081 | 4081 |
4082 | 4082 |
4083 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4083 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4084 Register input = ToRegister(instr->InputAt(0)); | 4084 Register input = ToRegister(instr->InputAt(0)); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4158 __ jmp(false_label); | 4158 __ jmp(false_label); |
4159 // A dead branch instruction will be generated after this point. | 4159 // A dead branch instruction will be generated after this point. |
4160 } | 4160 } |
4161 | 4161 |
4162 return final_branch_condition; | 4162 return final_branch_condition; |
4163 } | 4163 } |
4164 | 4164 |
4165 | 4165 |
4166 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | 4166 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
4167 Register result = ToRegister(instr->result()); | 4167 Register result = ToRegister(instr->result()); |
4168 NearLabel true_label; | 4168 Label true_label; |
4169 NearLabel false_label; | 4169 Label done; |
4170 NearLabel done; | |
4171 | 4170 |
4172 EmitIsConstructCall(result); | 4171 EmitIsConstructCall(result); |
4173 __ j(equal, &true_label); | 4172 __ j(equal, &true_label, Label::kNear); |
4174 | 4173 |
4175 __ mov(result, factory()->false_value()); | 4174 __ mov(result, factory()->false_value()); |
4176 __ jmp(&done); | 4175 __ jmp(&done, Label::kNear); |
4177 | 4176 |
4178 __ bind(&true_label); | 4177 __ bind(&true_label); |
4179 __ mov(result, factory()->true_value()); | 4178 __ mov(result, factory()->true_value()); |
4180 | 4179 |
4181 __ bind(&done); | 4180 __ bind(&done); |
4182 } | 4181 } |
4183 | 4182 |
4184 | 4183 |
4185 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4184 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4186 Register temp = ToRegister(instr->TempAt(0)); | 4185 Register temp = ToRegister(instr->TempAt(0)); |
4187 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4186 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4188 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4187 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4189 | 4188 |
4190 EmitIsConstructCall(temp); | 4189 EmitIsConstructCall(temp); |
4191 EmitBranch(true_block, false_block, equal); | 4190 EmitBranch(true_block, false_block, equal); |
4192 } | 4191 } |
4193 | 4192 |
4194 | 4193 |
4195 void LCodeGen::EmitIsConstructCall(Register temp) { | 4194 void LCodeGen::EmitIsConstructCall(Register temp) { |
4196 // Get the frame pointer for the calling frame. | 4195 // Get the frame pointer for the calling frame. |
4197 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 4196 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
4198 | 4197 |
4199 // Skip the arguments adaptor frame if it exists. | 4198 // Skip the arguments adaptor frame if it exists. |
4200 NearLabel check_frame_marker; | 4199 Label check_frame_marker; |
4201 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 4200 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
4202 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 4201 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
4203 __ j(not_equal, &check_frame_marker); | 4202 __ j(not_equal, &check_frame_marker, Label::kNear); |
4204 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); | 4203 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); |
4205 | 4204 |
4206 // Check the marker in the calling frame. | 4205 // Check the marker in the calling frame. |
4207 __ bind(&check_frame_marker); | 4206 __ bind(&check_frame_marker); |
4208 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 4207 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
4209 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 4208 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
4210 } | 4209 } |
4211 | 4210 |
4212 | 4211 |
4213 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 4212 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
(...skipping 28 matching lines...) Expand all Loading... |
4242 pointers, | 4241 pointers, |
4243 env->deoptimization_index()); | 4242 env->deoptimization_index()); |
4244 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4243 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4245 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4244 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
4246 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4245 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
4247 } | 4246 } |
4248 | 4247 |
4249 | 4248 |
4250 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4249 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
4251 // Perform stack overflow check. | 4250 // Perform stack overflow check. |
4252 NearLabel done; | 4251 Label done; |
4253 ExternalReference stack_limit = | 4252 ExternalReference stack_limit = |
4254 ExternalReference::address_of_stack_limit(isolate()); | 4253 ExternalReference::address_of_stack_limit(isolate()); |
4255 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4254 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
4256 __ j(above_equal, &done); | 4255 __ j(above_equal, &done, Label::kNear); |
4257 | 4256 |
4258 StackCheckStub stub; | 4257 StackCheckStub stub; |
4259 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4258 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
4260 __ bind(&done); | 4259 __ bind(&done); |
4261 } | 4260 } |
4262 | 4261 |
4263 | 4262 |
4264 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 4263 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
4265 // This is a pseudo-instruction that ensures that the environment here is | 4264 // This is a pseudo-instruction that ensures that the environment here is |
4266 // properly registered for deoptimization and records the assembler's PC | 4265 // properly registered for deoptimization and records the assembler's PC |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4305 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4304 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4306 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4305 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4307 } | 4306 } |
4308 | 4307 |
4309 | 4308 |
4310 #undef __ | 4309 #undef __ |
4311 | 4310 |
4312 } } // namespace v8::internal | 4311 } } // namespace v8::internal |
4313 | 4312 |
4314 #endif // V8_TARGET_ARCH_IA32 | 4313 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |