| 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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 | 539 |
| 540 if (FLAG_deopt_every_n_times != 0) { | 540 if (FLAG_deopt_every_n_times != 0) { |
| 541 Handle<SharedFunctionInfo> shared(info_->shared_info()); | 541 Handle<SharedFunctionInfo> shared(info_->shared_info()); |
| 542 Label no_deopt; | 542 Label no_deopt; |
| 543 __ pushfd(); | 543 __ pushfd(); |
| 544 __ push(eax); | 544 __ push(eax); |
| 545 __ push(ebx); | 545 __ push(ebx); |
| 546 __ mov(ebx, shared); | 546 __ mov(ebx, shared); |
| 547 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); | 547 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); |
| 548 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 548 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
| 549 __ j(not_zero, &no_deopt); | 549 __ j(not_zero, &no_deopt, Label::kNear); |
| 550 if (FLAG_trap_on_deopt) __ int3(); | 550 if (FLAG_trap_on_deopt) __ int3(); |
| 551 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); | 551 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); |
| 552 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); | 552 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); |
| 553 __ pop(ebx); | 553 __ pop(ebx); |
| 554 __ pop(eax); | 554 __ pop(eax); |
| 555 __ popfd(); | 555 __ popfd(); |
| 556 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 556 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
| 557 | 557 |
| 558 __ bind(&no_deopt); | 558 __ bind(&no_deopt); |
| 559 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); | 559 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); |
| 560 __ pop(ebx); | 560 __ pop(ebx); |
| 561 __ pop(eax); | 561 __ pop(eax); |
| 562 __ popfd(); | 562 __ popfd(); |
| 563 } | 563 } |
| 564 | 564 |
| 565 if (cc == no_condition) { | 565 if (cc == no_condition) { |
| 566 if (FLAG_trap_on_deopt) __ int3(); | 566 if (FLAG_trap_on_deopt) __ int3(); |
| 567 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 567 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
| 568 } else { | 568 } else { |
| 569 if (FLAG_trap_on_deopt) { | 569 if (FLAG_trap_on_deopt) { |
| 570 NearLabel done; | 570 Label done; |
| 571 __ j(NegateCondition(cc), &done); | 571 __ j(NegateCondition(cc), &done, Label::kNear); |
| 572 __ int3(); | 572 __ int3(); |
| 573 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 573 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); |
| 574 __ bind(&done); | 574 __ bind(&done); |
| 575 } else { | 575 } else { |
| 576 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY, not_taken); | 576 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY); |
| 577 } | 577 } |
| 578 } | 578 } |
| 579 } | 579 } |
| 580 | 580 |
| 581 | 581 |
| 582 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 582 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 583 int length = deoptimizations_.length(); | 583 int length = deoptimizations_.length(); |
| 584 if (length == 0) return; | 584 if (length == 0) return; |
| 585 ASSERT(FLAG_deopt); | 585 ASSERT(FLAG_deopt); |
| 586 Handle<DeoptimizationInputData> data = | 586 Handle<DeoptimizationInputData> data = |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 | 781 |
| 782 void LCodeGen::DoModI(LModI* instr) { | 782 void LCodeGen::DoModI(LModI* instr) { |
| 783 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 783 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 784 Register dividend = ToRegister(instr->InputAt(0)); | 784 Register dividend = ToRegister(instr->InputAt(0)); |
| 785 | 785 |
| 786 int32_t divisor = | 786 int32_t divisor = |
| 787 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 787 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| 788 | 788 |
| 789 if (divisor < 0) divisor = -divisor; | 789 if (divisor < 0) divisor = -divisor; |
| 790 | 790 |
| 791 NearLabel positive_dividend, done; | 791 Label positive_dividend, done; |
| 792 __ test(dividend, Operand(dividend)); | 792 __ test(dividend, Operand(dividend)); |
| 793 __ j(not_sign, &positive_dividend); | 793 __ j(not_sign, &positive_dividend, Label::kNear); |
| 794 __ neg(dividend); | 794 __ neg(dividend); |
| 795 __ and_(dividend, divisor - 1); | 795 __ and_(dividend, divisor - 1); |
| 796 __ neg(dividend); | 796 __ neg(dividend); |
| 797 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 797 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 798 __ j(not_zero, &done); | 798 __ j(not_zero, &done, Label::kNear); |
| 799 DeoptimizeIf(no_condition, instr->environment()); | 799 DeoptimizeIf(no_condition, instr->environment()); |
| 800 } | 800 } |
| 801 __ bind(&positive_dividend); | 801 __ bind(&positive_dividend); |
| 802 __ and_(dividend, divisor - 1); | 802 __ and_(dividend, divisor - 1); |
| 803 __ bind(&done); | 803 __ bind(&done); |
| 804 } else { | 804 } else { |
| 805 NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 805 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
| 806 Register left_reg = ToRegister(instr->InputAt(0)); | 806 Register left_reg = ToRegister(instr->InputAt(0)); |
| 807 Register right_reg = ToRegister(instr->InputAt(1)); | 807 Register right_reg = ToRegister(instr->InputAt(1)); |
| 808 Register result_reg = ToRegister(instr->result()); | 808 Register result_reg = ToRegister(instr->result()); |
| 809 | 809 |
| 810 ASSERT(left_reg.is(eax)); | 810 ASSERT(left_reg.is(eax)); |
| 811 ASSERT(result_reg.is(edx)); | 811 ASSERT(result_reg.is(edx)); |
| 812 ASSERT(!right_reg.is(eax)); | 812 ASSERT(!right_reg.is(eax)); |
| 813 ASSERT(!right_reg.is(edx)); | 813 ASSERT(!right_reg.is(edx)); |
| 814 | 814 |
| 815 // Check for x % 0. | 815 // Check for x % 0. |
| 816 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 816 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 817 __ test(right_reg, Operand(right_reg)); | 817 __ test(right_reg, Operand(right_reg)); |
| 818 DeoptimizeIf(zero, instr->environment()); | 818 DeoptimizeIf(zero, instr->environment()); |
| 819 } | 819 } |
| 820 | 820 |
| 821 __ test(left_reg, Operand(left_reg)); | 821 __ test(left_reg, Operand(left_reg)); |
| 822 __ j(zero, &remainder_eq_dividend); | 822 __ j(zero, &remainder_eq_dividend, Label::kNear); |
| 823 __ j(sign, &slow); | 823 __ j(sign, &slow, Label::kNear); |
| 824 | 824 |
| 825 __ test(right_reg, Operand(right_reg)); | 825 __ test(right_reg, Operand(right_reg)); |
| 826 __ j(not_sign, &both_positive); | 826 __ j(not_sign, &both_positive, Label::kNear); |
| 827 // The sign of the divisor doesn't matter. | 827 // The sign of the divisor doesn't matter. |
| 828 __ neg(right_reg); | 828 __ neg(right_reg); |
| 829 | 829 |
| 830 __ bind(&both_positive); | 830 __ bind(&both_positive); |
| 831 // If the dividend is smaller than the nonnegative | 831 // If the dividend is smaller than the nonnegative |
| 832 // divisor, the dividend is the result. | 832 // divisor, the dividend is the result. |
| 833 __ cmp(left_reg, Operand(right_reg)); | 833 __ cmp(left_reg, Operand(right_reg)); |
| 834 __ j(less, &remainder_eq_dividend); | 834 __ j(less, &remainder_eq_dividend, Label::kNear); |
| 835 | 835 |
| 836 // Check if the divisor is a PowerOfTwo integer. | 836 // Check if the divisor is a PowerOfTwo integer. |
| 837 Register scratch = ToRegister(instr->TempAt(0)); | 837 Register scratch = ToRegister(instr->TempAt(0)); |
| 838 __ mov(scratch, right_reg); | 838 __ mov(scratch, right_reg); |
| 839 __ sub(Operand(scratch), Immediate(1)); | 839 __ sub(Operand(scratch), Immediate(1)); |
| 840 __ test(scratch, Operand(right_reg)); | 840 __ test(scratch, Operand(right_reg)); |
| 841 __ j(not_zero, &do_subtraction); | 841 __ j(not_zero, &do_subtraction, Label::kNear); |
| 842 __ and_(left_reg, Operand(scratch)); | 842 __ and_(left_reg, Operand(scratch)); |
| 843 __ jmp(&remainder_eq_dividend); | 843 __ jmp(&remainder_eq_dividend, Label::kNear); |
| 844 | 844 |
| 845 __ bind(&do_subtraction); | 845 __ bind(&do_subtraction); |
| 846 const int kUnfolds = 3; | 846 const int kUnfolds = 3; |
| 847 // Try a few subtractions of the dividend. | 847 // Try a few subtractions of the dividend. |
| 848 __ mov(scratch, left_reg); | 848 __ mov(scratch, left_reg); |
| 849 for (int i = 0; i < kUnfolds; i++) { | 849 for (int i = 0; i < kUnfolds; i++) { |
| 850 // Reduce the dividend by the divisor. | 850 // Reduce the dividend by the divisor. |
| 851 __ sub(left_reg, Operand(right_reg)); | 851 __ sub(left_reg, Operand(right_reg)); |
| 852 // Check if the dividend is less than the divisor. | 852 // Check if the dividend is less than the divisor. |
| 853 __ cmp(left_reg, Operand(right_reg)); | 853 __ cmp(left_reg, Operand(right_reg)); |
| 854 __ j(less, &remainder_eq_dividend); | 854 __ j(less, &remainder_eq_dividend, Label::kNear); |
| 855 } | 855 } |
| 856 __ mov(left_reg, scratch); | 856 __ mov(left_reg, scratch); |
| 857 | 857 |
| 858 // Slow case, using idiv instruction. | 858 // Slow case, using idiv instruction. |
| 859 __ bind(&slow); | 859 __ bind(&slow); |
| 860 // Sign extend to edx. | 860 // Sign extend to edx. |
| 861 __ cdq(); | 861 __ cdq(); |
| 862 | 862 |
| 863 // Check for (0 % -x) that will produce negative zero. | 863 // Check for (0 % -x) that will produce negative zero. |
| 864 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 864 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 865 NearLabel positive_left; | 865 Label positive_left; |
| 866 NearLabel done; | 866 Label done; |
| 867 __ test(left_reg, Operand(left_reg)); | 867 __ test(left_reg, Operand(left_reg)); |
| 868 __ j(not_sign, &positive_left); | 868 __ j(not_sign, &positive_left, Label::kNear); |
| 869 __ idiv(right_reg); | 869 __ idiv(right_reg); |
| 870 | 870 |
| 871 // Test the remainder for 0, because then the result would be -0. | 871 // Test the remainder for 0, because then the result would be -0. |
| 872 __ test(result_reg, Operand(result_reg)); | 872 __ test(result_reg, Operand(result_reg)); |
| 873 __ j(not_zero, &done); | 873 __ j(not_zero, &done, Label::kNear); |
| 874 | 874 |
| 875 DeoptimizeIf(no_condition, instr->environment()); | 875 DeoptimizeIf(no_condition, instr->environment()); |
| 876 __ bind(&positive_left); | 876 __ bind(&positive_left); |
| 877 __ idiv(right_reg); | 877 __ idiv(right_reg); |
| 878 __ bind(&done); | 878 __ bind(&done); |
| 879 } else { | 879 } else { |
| 880 __ idiv(right_reg); | 880 __ idiv(right_reg); |
| 881 } | 881 } |
| 882 __ jmp(&done); | 882 __ jmp(&done, Label::kNear); |
| 883 | 883 |
| 884 __ bind(&remainder_eq_dividend); | 884 __ bind(&remainder_eq_dividend); |
| 885 __ mov(result_reg, left_reg); | 885 __ mov(result_reg, left_reg); |
| 886 | 886 |
| 887 __ bind(&done); | 887 __ bind(&done); |
| 888 } | 888 } |
| 889 } | 889 } |
| 890 | 890 |
| 891 | 891 |
| 892 void LCodeGen::DoDivI(LDivI* instr) { | 892 void LCodeGen::DoDivI(LDivI* instr) { |
| 893 LOperand* right = instr->InputAt(1); | 893 LOperand* right = instr->InputAt(1); |
| 894 ASSERT(ToRegister(instr->result()).is(eax)); | 894 ASSERT(ToRegister(instr->result()).is(eax)); |
| 895 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 895 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 896 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); | 896 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
| 897 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); | 897 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
| 898 | 898 |
| 899 Register left_reg = eax; | 899 Register left_reg = eax; |
| 900 | 900 |
| 901 // Check for x / 0. | 901 // Check for x / 0. |
| 902 Register right_reg = ToRegister(right); | 902 Register right_reg = ToRegister(right); |
| 903 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 903 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 904 __ test(right_reg, ToOperand(right)); | 904 __ test(right_reg, ToOperand(right)); |
| 905 DeoptimizeIf(zero, instr->environment()); | 905 DeoptimizeIf(zero, instr->environment()); |
| 906 } | 906 } |
| 907 | 907 |
| 908 // Check for (0 / -x) that will produce negative zero. | 908 // Check for (0 / -x) that will produce negative zero. |
| 909 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 909 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 910 NearLabel left_not_zero; | 910 Label left_not_zero; |
| 911 __ test(left_reg, Operand(left_reg)); | 911 __ test(left_reg, Operand(left_reg)); |
| 912 __ j(not_zero, &left_not_zero); | 912 __ j(not_zero, &left_not_zero, Label::kNear); |
| 913 __ test(right_reg, ToOperand(right)); | 913 __ test(right_reg, ToOperand(right)); |
| 914 DeoptimizeIf(sign, instr->environment()); | 914 DeoptimizeIf(sign, instr->environment()); |
| 915 __ bind(&left_not_zero); | 915 __ bind(&left_not_zero); |
| 916 } | 916 } |
| 917 | 917 |
| 918 // Check for (-kMinInt / -1). | 918 // Check for (-kMinInt / -1). |
| 919 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 919 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 920 NearLabel left_not_min_int; | 920 Label left_not_min_int; |
| 921 __ cmp(left_reg, kMinInt); | 921 __ cmp(left_reg, kMinInt); |
| 922 __ j(not_zero, &left_not_min_int); | 922 __ j(not_zero, &left_not_min_int, Label::kNear); |
| 923 __ cmp(right_reg, -1); | 923 __ cmp(right_reg, -1); |
| 924 DeoptimizeIf(zero, instr->environment()); | 924 DeoptimizeIf(zero, instr->environment()); |
| 925 __ bind(&left_not_min_int); | 925 __ bind(&left_not_min_int); |
| 926 } | 926 } |
| 927 | 927 |
| 928 // Sign extend to edx. | 928 // Sign extend to edx. |
| 929 __ cdq(); | 929 __ cdq(); |
| 930 __ idiv(right_reg); | 930 __ idiv(right_reg); |
| 931 | 931 |
| 932 // Deoptimize if remainder is not 0. | 932 // Deoptimize if remainder is not 0. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 } else { | 990 } else { |
| 991 __ imul(left, ToOperand(right)); | 991 __ imul(left, ToOperand(right)); |
| 992 } | 992 } |
| 993 | 993 |
| 994 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 994 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 995 DeoptimizeIf(overflow, instr->environment()); | 995 DeoptimizeIf(overflow, instr->environment()); |
| 996 } | 996 } |
| 997 | 997 |
| 998 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 998 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 999 // Bail out if the result is supposed to be negative zero. | 999 // Bail out if the result is supposed to be negative zero. |
| 1000 NearLabel done; | 1000 Label done; |
| 1001 __ test(left, Operand(left)); | 1001 __ test(left, Operand(left)); |
| 1002 __ j(not_zero, &done); | 1002 __ j(not_zero, &done, Label::kNear); |
| 1003 if (right->IsConstantOperand()) { | 1003 if (right->IsConstantOperand()) { |
| 1004 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { | 1004 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
| 1005 DeoptimizeIf(no_condition, instr->environment()); | 1005 DeoptimizeIf(no_condition, instr->environment()); |
| 1006 } | 1006 } |
| 1007 } else { | 1007 } else { |
| 1008 // Test the non-zero operand for negative sign. | 1008 // Test the non-zero operand for negative sign. |
| 1009 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); | 1009 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
| 1010 DeoptimizeIf(sign, instr->environment()); | 1010 DeoptimizeIf(sign, instr->environment()); |
| 1011 } | 1011 } |
| 1012 __ bind(&done); | 1012 __ bind(&done); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1197 Register array = ToRegister(instr->InputAt(0)); | 1197 Register array = ToRegister(instr->InputAt(0)); |
| 1198 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); | 1198 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); |
| 1199 } | 1199 } |
| 1200 | 1200 |
| 1201 | 1201 |
| 1202 void LCodeGen::DoValueOf(LValueOf* instr) { | 1202 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1203 Register input = ToRegister(instr->InputAt(0)); | 1203 Register input = ToRegister(instr->InputAt(0)); |
| 1204 Register result = ToRegister(instr->result()); | 1204 Register result = ToRegister(instr->result()); |
| 1205 Register map = ToRegister(instr->TempAt(0)); | 1205 Register map = ToRegister(instr->TempAt(0)); |
| 1206 ASSERT(input.is(result)); | 1206 ASSERT(input.is(result)); |
| 1207 NearLabel done; | 1207 Label done; |
| 1208 // If the object is a smi return the object. | 1208 // If the object is a smi return the object. |
| 1209 __ test(input, Immediate(kSmiTagMask)); | 1209 __ test(input, Immediate(kSmiTagMask)); |
| 1210 __ j(zero, &done); | 1210 __ j(zero, &done, Label::kNear); |
| 1211 | 1211 |
| 1212 // If the object is not a value type, return the object. | 1212 // If the object is not a value type, return the object. |
| 1213 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1213 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
| 1214 __ j(not_equal, &done); | 1214 __ j(not_equal, &done, Label::kNear); |
| 1215 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1215 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
| 1216 | 1216 |
| 1217 __ bind(&done); | 1217 __ bind(&done); |
| 1218 } | 1218 } |
| 1219 | 1219 |
| 1220 | 1220 |
| 1221 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1221 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1222 LOperand* input = instr->InputAt(0); | 1222 LOperand* input = instr->InputAt(0); |
| 1223 ASSERT(input->Equals(instr->result())); | 1223 ASSERT(input->Equals(instr->result())); |
| 1224 __ not_(ToRegister(input)); | 1224 __ not_(ToRegister(input)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 __ cmp(reg, factory()->true_value()); | 1362 __ cmp(reg, factory()->true_value()); |
| 1363 __ j(equal, true_label); | 1363 __ j(equal, true_label); |
| 1364 __ cmp(reg, factory()->false_value()); | 1364 __ cmp(reg, factory()->false_value()); |
| 1365 __ j(equal, false_label); | 1365 __ j(equal, false_label); |
| 1366 __ test(reg, Operand(reg)); | 1366 __ test(reg, Operand(reg)); |
| 1367 __ j(equal, false_label); | 1367 __ j(equal, false_label); |
| 1368 __ test(reg, Immediate(kSmiTagMask)); | 1368 __ test(reg, Immediate(kSmiTagMask)); |
| 1369 __ j(zero, true_label); | 1369 __ j(zero, true_label); |
| 1370 | 1370 |
| 1371 // Test for double values. Zero is false. | 1371 // Test for double values. Zero is false. |
| 1372 NearLabel call_stub; | 1372 Label call_stub; |
| 1373 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1373 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1374 factory()->heap_number_map()); | 1374 factory()->heap_number_map()); |
| 1375 __ j(not_equal, &call_stub); | 1375 __ j(not_equal, &call_stub, Label::kNear); |
| 1376 __ fldz(); | 1376 __ fldz(); |
| 1377 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1377 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1378 __ FCmp(); | 1378 __ FCmp(); |
| 1379 __ j(zero, false_label); | 1379 __ j(zero, false_label); |
| 1380 __ jmp(true_label); | 1380 __ jmp(true_label); |
| 1381 | 1381 |
| 1382 // The conversion stub doesn't cause garbage collections so it's | 1382 // The conversion stub doesn't cause garbage collections so it's |
| 1383 // safe to not record a safepoint after the call. | 1383 // safe to not record a safepoint after the call. |
| 1384 __ bind(&call_stub); | 1384 __ bind(&call_stub); |
| 1385 ToBooleanStub stub; | 1385 ToBooleanStub stub; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1471 __ cmp(ToRegister(left), ToOperand(right)); | 1471 __ cmp(ToRegister(left), ToOperand(right)); |
| 1472 } | 1472 } |
| 1473 } | 1473 } |
| 1474 | 1474 |
| 1475 | 1475 |
| 1476 void LCodeGen::DoCmpID(LCmpID* instr) { | 1476 void LCodeGen::DoCmpID(LCmpID* instr) { |
| 1477 LOperand* left = instr->InputAt(0); | 1477 LOperand* left = instr->InputAt(0); |
| 1478 LOperand* right = instr->InputAt(1); | 1478 LOperand* right = instr->InputAt(1); |
| 1479 LOperand* result = instr->result(); | 1479 LOperand* result = instr->result(); |
| 1480 | 1480 |
| 1481 NearLabel unordered; | 1481 Label unordered; |
| 1482 if (instr->is_double()) { | 1482 if (instr->is_double()) { |
| 1483 // Don't base result on EFLAGS when a NaN is involved. Instead | 1483 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 1484 // jump to the unordered case, which produces a false value. | 1484 // jump to the unordered case, which produces a false value. |
| 1485 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1485 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1486 __ j(parity_even, &unordered, not_taken); | 1486 __ j(parity_even, &unordered, Label::kNear); |
| 1487 } else { | 1487 } else { |
| 1488 EmitCmpI(left, right); | 1488 EmitCmpI(left, right); |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 NearLabel done; | 1491 Label done; |
| 1492 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1492 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 1493 __ mov(ToRegister(result), factory()->true_value()); | 1493 __ mov(ToRegister(result), factory()->true_value()); |
| 1494 __ j(cc, &done); | 1494 __ j(cc, &done, Label::kNear); |
| 1495 | 1495 |
| 1496 __ bind(&unordered); | 1496 __ bind(&unordered); |
| 1497 __ mov(ToRegister(result), factory()->false_value()); | 1497 __ mov(ToRegister(result), factory()->false_value()); |
| 1498 __ bind(&done); | 1498 __ bind(&done); |
| 1499 } | 1499 } |
| 1500 | 1500 |
| 1501 | 1501 |
| 1502 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1502 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1503 LOperand* left = instr->InputAt(0); | 1503 LOperand* left = instr->InputAt(0); |
| 1504 LOperand* right = instr->InputAt(1); | 1504 LOperand* right = instr->InputAt(1); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1519 } | 1519 } |
| 1520 | 1520 |
| 1521 | 1521 |
| 1522 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1522 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
| 1523 Register left = ToRegister(instr->InputAt(0)); | 1523 Register left = ToRegister(instr->InputAt(0)); |
| 1524 Register right = ToRegister(instr->InputAt(1)); | 1524 Register right = ToRegister(instr->InputAt(1)); |
| 1525 Register result = ToRegister(instr->result()); | 1525 Register result = ToRegister(instr->result()); |
| 1526 | 1526 |
| 1527 __ cmp(left, Operand(right)); | 1527 __ cmp(left, Operand(right)); |
| 1528 __ mov(result, factory()->true_value()); | 1528 __ mov(result, factory()->true_value()); |
| 1529 NearLabel done; | 1529 Label done; |
| 1530 __ j(equal, &done); | 1530 __ j(equal, &done, Label::kNear); |
| 1531 __ mov(result, factory()->false_value()); | 1531 __ mov(result, factory()->false_value()); |
| 1532 __ bind(&done); | 1532 __ bind(&done); |
| 1533 } | 1533 } |
| 1534 | 1534 |
| 1535 | 1535 |
| 1536 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1536 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1537 Register left = ToRegister(instr->InputAt(0)); | 1537 Register left = ToRegister(instr->InputAt(0)); |
| 1538 Register right = ToRegister(instr->InputAt(1)); | 1538 Register right = ToRegister(instr->InputAt(1)); |
| 1539 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1539 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1540 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1540 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1541 | 1541 |
| 1542 __ cmp(left, Operand(right)); | 1542 __ cmp(left, Operand(right)); |
| 1543 EmitBranch(true_block, false_block, equal); | 1543 EmitBranch(true_block, false_block, equal); |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 | 1546 |
| 1547 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) { |
| 1548 Register left = ToRegister(instr->InputAt(0)); |
| 1549 Register right = ToRegister(instr->InputAt(1)); |
| 1550 Register result = ToRegister(instr->result()); |
| 1551 |
| 1552 Label done; |
| 1553 __ cmp(left, Operand(right)); |
| 1554 __ mov(result, factory()->false_value()); |
| 1555 __ j(not_equal, &done, Label::kNear); |
| 1556 __ mov(result, factory()->true_value()); |
| 1557 __ bind(&done); |
| 1558 } |
| 1559 |
| 1560 |
| 1561 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) { |
| 1562 Register left = ToRegister(instr->InputAt(0)); |
| 1563 Register right = ToRegister(instr->InputAt(1)); |
| 1564 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1565 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1566 |
| 1567 __ cmp(left, Operand(right)); |
| 1568 EmitBranch(true_block, false_block, equal); |
| 1569 } |
| 1570 |
| 1571 |
| 1547 void LCodeGen::DoIsNull(LIsNull* instr) { | 1572 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1548 Register reg = ToRegister(instr->InputAt(0)); | 1573 Register reg = ToRegister(instr->InputAt(0)); |
| 1549 Register result = ToRegister(instr->result()); | 1574 Register result = ToRegister(instr->result()); |
| 1550 | 1575 |
| 1551 // TODO(fsc): If the expression is known to be a smi, then it's | 1576 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1552 // definitely not null. Materialize false. | 1577 // definitely not null. Materialize false. |
| 1553 | 1578 |
| 1554 __ cmp(reg, factory()->null_value()); | 1579 __ cmp(reg, factory()->null_value()); |
| 1555 if (instr->is_strict()) { | 1580 if (instr->is_strict()) { |
| 1556 __ mov(result, factory()->true_value()); | 1581 __ mov(result, factory()->true_value()); |
| 1557 NearLabel done; | 1582 Label done; |
| 1558 __ j(equal, &done); | 1583 __ j(equal, &done, Label::kNear); |
| 1559 __ mov(result, factory()->false_value()); | 1584 __ mov(result, factory()->false_value()); |
| 1560 __ bind(&done); | 1585 __ bind(&done); |
| 1561 } else { | 1586 } else { |
| 1562 NearLabel true_value, false_value, done; | 1587 Label true_value, false_value, done; |
| 1563 __ j(equal, &true_value); | 1588 __ j(equal, &true_value, Label::kNear); |
| 1564 __ cmp(reg, factory()->undefined_value()); | 1589 __ cmp(reg, factory()->undefined_value()); |
| 1565 __ j(equal, &true_value); | 1590 __ j(equal, &true_value, Label::kNear); |
| 1566 __ test(reg, Immediate(kSmiTagMask)); | 1591 __ test(reg, Immediate(kSmiTagMask)); |
| 1567 __ j(zero, &false_value); | 1592 __ j(zero, &false_value, Label::kNear); |
| 1568 // Check for undetectable objects by looking in the bit field in | 1593 // Check for undetectable objects by looking in the bit field in |
| 1569 // the map. The object has already been smi checked. | 1594 // the map. The object has already been smi checked. |
| 1570 Register scratch = result; | 1595 Register scratch = result; |
| 1571 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1596 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1572 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1597 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1573 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1598 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1574 __ j(not_zero, &true_value); | 1599 __ j(not_zero, &true_value, Label::kNear); |
| 1575 __ bind(&false_value); | 1600 __ bind(&false_value); |
| 1576 __ mov(result, factory()->false_value()); | 1601 __ mov(result, factory()->false_value()); |
| 1577 __ jmp(&done); | 1602 __ jmp(&done, Label::kNear); |
| 1578 __ bind(&true_value); | 1603 __ bind(&true_value); |
| 1579 __ mov(result, factory()->true_value()); | 1604 __ mov(result, factory()->true_value()); |
| 1580 __ bind(&done); | 1605 __ bind(&done); |
| 1581 } | 1606 } |
| 1582 } | 1607 } |
| 1583 | 1608 |
| 1584 | 1609 |
| 1585 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1610 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1586 Register reg = ToRegister(instr->InputAt(0)); | 1611 Register reg = ToRegister(instr->InputAt(0)); |
| 1587 | 1612 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1678 } | 1703 } |
| 1679 | 1704 |
| 1680 | 1705 |
| 1681 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1706 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1682 Operand input = ToOperand(instr->InputAt(0)); | 1707 Operand input = ToOperand(instr->InputAt(0)); |
| 1683 Register result = ToRegister(instr->result()); | 1708 Register result = ToRegister(instr->result()); |
| 1684 | 1709 |
| 1685 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1710 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1686 __ test(input, Immediate(kSmiTagMask)); | 1711 __ test(input, Immediate(kSmiTagMask)); |
| 1687 __ mov(result, factory()->true_value()); | 1712 __ mov(result, factory()->true_value()); |
| 1688 NearLabel done; | 1713 Label done; |
| 1689 __ j(zero, &done); | 1714 __ j(zero, &done, Label::kNear); |
| 1690 __ mov(result, factory()->false_value()); | 1715 __ mov(result, factory()->false_value()); |
| 1691 __ bind(&done); | 1716 __ bind(&done); |
| 1692 } | 1717 } |
| 1693 | 1718 |
| 1694 | 1719 |
| 1695 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1720 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1696 Operand input = ToOperand(instr->InputAt(0)); | 1721 Operand input = ToOperand(instr->InputAt(0)); |
| 1697 | 1722 |
| 1698 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1723 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1699 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1724 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1700 | 1725 |
| 1701 __ test(input, Immediate(kSmiTagMask)); | 1726 __ test(input, Immediate(kSmiTagMask)); |
| 1702 EmitBranch(true_block, false_block, zero); | 1727 EmitBranch(true_block, false_block, zero); |
| 1703 } | 1728 } |
| 1704 | 1729 |
| 1705 | 1730 |
| 1731 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) { |
| 1732 Register input = ToRegister(instr->InputAt(0)); |
| 1733 Register result = ToRegister(instr->result()); |
| 1734 |
| 1735 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1736 Label false_label, done; |
| 1737 STATIC_ASSERT(kSmiTag == 0); |
| 1738 __ test(input, Immediate(kSmiTagMask)); |
| 1739 __ j(zero, &false_label, Label::kNear); |
| 1740 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); |
| 1741 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
| 1742 1 << Map::kIsUndetectable); |
| 1743 __ j(zero, &false_label, Label::kNear); |
| 1744 __ mov(result, factory()->true_value()); |
| 1745 __ jmp(&done); |
| 1746 __ bind(&false_label); |
| 1747 __ mov(result, factory()->false_value()); |
| 1748 __ bind(&done); |
| 1749 } |
| 1750 |
| 1751 |
| 1752 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 1753 Register input = ToRegister(instr->InputAt(0)); |
| 1754 Register temp = ToRegister(instr->TempAt(0)); |
| 1755 |
| 1756 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1757 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1758 |
| 1759 STATIC_ASSERT(kSmiTag == 0); |
| 1760 __ test(input, Immediate(kSmiTagMask)); |
| 1761 __ j(zero, chunk_->GetAssemblyLabel(false_block)); |
| 1762 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 1763 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
| 1764 1 << Map::kIsUndetectable); |
| 1765 EmitBranch(true_block, false_block, not_zero); |
| 1766 } |
| 1767 |
| 1768 |
| 1706 static InstanceType TestType(HHasInstanceType* instr) { | 1769 static InstanceType TestType(HHasInstanceType* instr) { |
| 1707 InstanceType from = instr->from(); | 1770 InstanceType from = instr->from(); |
| 1708 InstanceType to = instr->to(); | 1771 InstanceType to = instr->to(); |
| 1709 if (from == FIRST_TYPE) return to; | 1772 if (from == FIRST_TYPE) return to; |
| 1710 ASSERT(from == to || to == LAST_TYPE); | 1773 ASSERT(from == to || to == LAST_TYPE); |
| 1711 return from; | 1774 return from; |
| 1712 } | 1775 } |
| 1713 | 1776 |
| 1714 | 1777 |
| 1715 static Condition BranchCondition(HHasInstanceType* instr) { | 1778 static Condition BranchCondition(HHasInstanceType* instr) { |
| 1716 InstanceType from = instr->from(); | 1779 InstanceType from = instr->from(); |
| 1717 InstanceType to = instr->to(); | 1780 InstanceType to = instr->to(); |
| 1718 if (from == to) return equal; | 1781 if (from == to) return equal; |
| 1719 if (to == LAST_TYPE) return above_equal; | 1782 if (to == LAST_TYPE) return above_equal; |
| 1720 if (from == FIRST_TYPE) return below_equal; | 1783 if (from == FIRST_TYPE) return below_equal; |
| 1721 UNREACHABLE(); | 1784 UNREACHABLE(); |
| 1722 return equal; | 1785 return equal; |
| 1723 } | 1786 } |
| 1724 | 1787 |
| 1725 | 1788 |
| 1726 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1789 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1727 Register input = ToRegister(instr->InputAt(0)); | 1790 Register input = ToRegister(instr->InputAt(0)); |
| 1728 Register result = ToRegister(instr->result()); | 1791 Register result = ToRegister(instr->result()); |
| 1729 | 1792 |
| 1730 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1793 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1731 __ test(input, Immediate(kSmiTagMask)); | 1794 __ test(input, Immediate(kSmiTagMask)); |
| 1732 NearLabel done, is_false; | 1795 Label done, is_false; |
| 1733 __ j(zero, &is_false); | 1796 __ j(zero, &is_false, Label::kNear); |
| 1734 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | 1797 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
| 1735 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); | 1798 __ j(NegateCondition(BranchCondition(instr->hydrogen())), |
| 1799 &is_false, Label::kNear); |
| 1736 __ mov(result, factory()->true_value()); | 1800 __ mov(result, factory()->true_value()); |
| 1737 __ jmp(&done); | 1801 __ jmp(&done, Label::kNear); |
| 1738 __ bind(&is_false); | 1802 __ bind(&is_false); |
| 1739 __ mov(result, factory()->false_value()); | 1803 __ mov(result, factory()->false_value()); |
| 1740 __ bind(&done); | 1804 __ bind(&done); |
| 1741 } | 1805 } |
| 1742 | 1806 |
| 1743 | 1807 |
| 1744 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1808 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1745 Register input = ToRegister(instr->InputAt(0)); | 1809 Register input = ToRegister(instr->InputAt(0)); |
| 1746 Register temp = ToRegister(instr->TempAt(0)); | 1810 Register temp = ToRegister(instr->TempAt(0)); |
| 1747 | 1811 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1772 | 1836 |
| 1773 | 1837 |
| 1774 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1838 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1775 Register input = ToRegister(instr->InputAt(0)); | 1839 Register input = ToRegister(instr->InputAt(0)); |
| 1776 Register result = ToRegister(instr->result()); | 1840 Register result = ToRegister(instr->result()); |
| 1777 | 1841 |
| 1778 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1842 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1779 __ mov(result, factory()->true_value()); | 1843 __ mov(result, factory()->true_value()); |
| 1780 __ test(FieldOperand(input, String::kHashFieldOffset), | 1844 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 1781 Immediate(String::kContainsCachedArrayIndexMask)); | 1845 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1782 NearLabel done; | 1846 Label done; |
| 1783 __ j(zero, &done); | 1847 __ j(zero, &done, Label::kNear); |
| 1784 __ mov(result, factory()->false_value()); | 1848 __ mov(result, factory()->false_value()); |
| 1785 __ bind(&done); | 1849 __ bind(&done); |
| 1786 } | 1850 } |
| 1787 | 1851 |
| 1788 | 1852 |
| 1789 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1853 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1790 LHasCachedArrayIndexAndBranch* instr) { | 1854 LHasCachedArrayIndexAndBranch* instr) { |
| 1791 Register input = ToRegister(instr->InputAt(0)); | 1855 Register input = ToRegister(instr->InputAt(0)); |
| 1792 | 1856 |
| 1793 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1857 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1855 // End with the answer in the z flag. | 1919 // End with the answer in the z flag. |
| 1856 } | 1920 } |
| 1857 | 1921 |
| 1858 | 1922 |
| 1859 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1923 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
| 1860 Register input = ToRegister(instr->InputAt(0)); | 1924 Register input = ToRegister(instr->InputAt(0)); |
| 1861 Register result = ToRegister(instr->result()); | 1925 Register result = ToRegister(instr->result()); |
| 1862 ASSERT(input.is(result)); | 1926 ASSERT(input.is(result)); |
| 1863 Register temp = ToRegister(instr->TempAt(0)); | 1927 Register temp = ToRegister(instr->TempAt(0)); |
| 1864 Handle<String> class_name = instr->hydrogen()->class_name(); | 1928 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1865 NearLabel done; | 1929 Label done; |
| 1866 Label is_true, is_false; | 1930 Label is_true, is_false; |
| 1867 | 1931 |
| 1868 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1932 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
| 1869 | 1933 |
| 1870 __ j(not_equal, &is_false); | 1934 __ j(not_equal, &is_false, Label::kNear); |
| 1871 | 1935 |
| 1872 __ bind(&is_true); | 1936 __ bind(&is_true); |
| 1873 __ mov(result, factory()->true_value()); | 1937 __ mov(result, factory()->true_value()); |
| 1874 __ jmp(&done); | 1938 __ jmp(&done, Label::kNear); |
| 1875 | 1939 |
| 1876 __ bind(&is_false); | 1940 __ bind(&is_false); |
| 1877 __ mov(result, factory()->false_value()); | 1941 __ mov(result, factory()->false_value()); |
| 1878 __ bind(&done); | 1942 __ bind(&done); |
| 1879 } | 1943 } |
| 1880 | 1944 |
| 1881 | 1945 |
| 1882 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1946 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1883 Register input = ToRegister(instr->InputAt(0)); | 1947 Register input = ToRegister(instr->InputAt(0)); |
| 1884 Register temp = ToRegister(instr->TempAt(0)); | 1948 Register temp = ToRegister(instr->TempAt(0)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1912 EmitBranch(true_block, false_block, equal); | 1976 EmitBranch(true_block, false_block, equal); |
| 1913 } | 1977 } |
| 1914 | 1978 |
| 1915 | 1979 |
| 1916 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1980 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1917 // Object and function are in fixed registers defined by the stub. | 1981 // Object and function are in fixed registers defined by the stub. |
| 1918 ASSERT(ToRegister(instr->context()).is(esi)); | 1982 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1919 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1983 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1920 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 1984 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); |
| 1921 | 1985 |
| 1922 NearLabel true_value, done; | 1986 Label true_value, done; |
| 1923 __ test(eax, Operand(eax)); | 1987 __ test(eax, Operand(eax)); |
| 1924 __ j(zero, &true_value); | 1988 __ j(zero, &true_value, Label::kNear); |
| 1925 __ mov(ToRegister(instr->result()), factory()->false_value()); | 1989 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 1926 __ jmp(&done); | 1990 __ jmp(&done, Label::kNear); |
| 1927 __ bind(&true_value); | 1991 __ bind(&true_value); |
| 1928 __ mov(ToRegister(instr->result()), factory()->true_value()); | 1992 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 1929 __ bind(&done); | 1993 __ bind(&done); |
| 1930 } | 1994 } |
| 1931 | 1995 |
| 1932 | 1996 |
| 1933 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1997 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1934 ASSERT(ToRegister(instr->context()).is(esi)); | 1998 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1935 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1999 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1936 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2000 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1961 | 2025 |
| 1962 DeferredInstanceOfKnownGlobal* deferred; | 2026 DeferredInstanceOfKnownGlobal* deferred; |
| 1963 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 2027 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1964 | 2028 |
| 1965 Label done, false_result; | 2029 Label done, false_result; |
| 1966 Register object = ToRegister(instr->InputAt(0)); | 2030 Register object = ToRegister(instr->InputAt(0)); |
| 1967 Register temp = ToRegister(instr->TempAt(0)); | 2031 Register temp = ToRegister(instr->TempAt(0)); |
| 1968 | 2032 |
| 1969 // A Smi is not an instance of anything. | 2033 // A Smi is not an instance of anything. |
| 1970 __ test(object, Immediate(kSmiTagMask)); | 2034 __ test(object, Immediate(kSmiTagMask)); |
| 1971 __ j(zero, &false_result, not_taken); | 2035 __ j(zero, &false_result); |
| 1972 | 2036 |
| 1973 // This is the inlined call site instanceof cache. The two occurences of the | 2037 // This is the inlined call site instanceof cache. The two occurences of the |
| 1974 // hole value will be patched to the last map/result pair generated by the | 2038 // hole value will be patched to the last map/result pair generated by the |
| 1975 // instanceof stub. | 2039 // instanceof stub. |
| 1976 NearLabel cache_miss; | 2040 Label cache_miss; |
| 1977 Register map = ToRegister(instr->TempAt(0)); | 2041 Register map = ToRegister(instr->TempAt(0)); |
| 1978 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 2042 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1979 __ bind(deferred->map_check()); // Label for calculating code patching. | 2043 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1980 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. | 2044 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. |
| 1981 __ j(not_equal, &cache_miss, not_taken); | 2045 __ j(not_equal, &cache_miss, Label::kNear); |
| 1982 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. | 2046 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. |
| 1983 __ jmp(&done); | 2047 __ jmp(&done); |
| 1984 | 2048 |
| 1985 // The inlined call site cache did not match. Check for null and string | 2049 // The inlined call site cache did not match. Check for null and string |
| 1986 // before calling the deferred code. | 2050 // before calling the deferred code. |
| 1987 __ bind(&cache_miss); | 2051 __ bind(&cache_miss); |
| 1988 // Null is not an instance of anything. | 2052 // Null is not an instance of anything. |
| 1989 __ cmp(object, factory()->null_value()); | 2053 __ cmp(object, factory()->null_value()); |
| 1990 __ j(equal, &false_result); | 2054 __ j(equal, &false_result); |
| 1991 | 2055 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 void LCodeGen::DoCmpT(LCmpT* instr) { | 2127 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2064 Token::Value op = instr->op(); | 2128 Token::Value op = instr->op(); |
| 2065 | 2129 |
| 2066 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2130 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 2067 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2131 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
| 2068 | 2132 |
| 2069 Condition condition = ComputeCompareCondition(op); | 2133 Condition condition = ComputeCompareCondition(op); |
| 2070 if (op == Token::GT || op == Token::LTE) { | 2134 if (op == Token::GT || op == Token::LTE) { |
| 2071 condition = ReverseCondition(condition); | 2135 condition = ReverseCondition(condition); |
| 2072 } | 2136 } |
| 2073 NearLabel true_value, done; | 2137 Label true_value, done; |
| 2074 __ test(eax, Operand(eax)); | 2138 __ test(eax, Operand(eax)); |
| 2075 __ j(condition, &true_value); | 2139 __ j(condition, &true_value, Label::kNear); |
| 2076 __ mov(ToRegister(instr->result()), factory()->false_value()); | 2140 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 2077 __ jmp(&done); | 2141 __ jmp(&done, Label::kNear); |
| 2078 __ bind(&true_value); | 2142 __ bind(&true_value); |
| 2079 __ mov(ToRegister(instr->result()), factory()->true_value()); | 2143 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 2080 __ bind(&done); | 2144 __ bind(&done); |
| 2081 } | 2145 } |
| 2082 | 2146 |
| 2083 | 2147 |
| 2084 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { | 2148 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
| 2085 Token::Value op = instr->op(); | 2149 Token::Value op = instr->op(); |
| 2086 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2150 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2087 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2151 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 Register result = ToRegister(instr->result()); | 2311 Register result = ToRegister(instr->result()); |
| 2248 | 2312 |
| 2249 int map_count = instr->hydrogen()->types()->length(); | 2313 int map_count = instr->hydrogen()->types()->length(); |
| 2250 Handle<String> name = instr->hydrogen()->name(); | 2314 Handle<String> name = instr->hydrogen()->name(); |
| 2251 if (map_count == 0) { | 2315 if (map_count == 0) { |
| 2252 ASSERT(instr->hydrogen()->need_generic()); | 2316 ASSERT(instr->hydrogen()->need_generic()); |
| 2253 __ mov(ecx, name); | 2317 __ mov(ecx, name); |
| 2254 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2318 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2255 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2319 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
| 2256 } else { | 2320 } else { |
| 2257 NearLabel done; | 2321 Label done; |
| 2258 for (int i = 0; i < map_count - 1; ++i) { | 2322 for (int i = 0; i < map_count - 1; ++i) { |
| 2259 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2323 Handle<Map> map = instr->hydrogen()->types()->at(i); |
| 2260 NearLabel next; | 2324 Label next; |
| 2261 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2325 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2262 __ j(not_equal, &next); | 2326 __ j(not_equal, &next, Label::kNear); |
| 2263 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2327 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2264 __ jmp(&done); | 2328 __ jmp(&done, Label::kNear); |
| 2265 __ bind(&next); | 2329 __ bind(&next); |
| 2266 } | 2330 } |
| 2267 Handle<Map> map = instr->hydrogen()->types()->last(); | 2331 Handle<Map> map = instr->hydrogen()->types()->last(); |
| 2268 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2332 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2269 if (instr->hydrogen()->need_generic()) { | 2333 if (instr->hydrogen()->need_generic()) { |
| 2270 NearLabel generic; | 2334 Label generic; |
| 2271 __ j(not_equal, &generic); | 2335 __ j(not_equal, &generic, Label::kNear); |
| 2272 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2336 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2273 __ jmp(&done); | 2337 __ jmp(&done, Label::kNear); |
| 2274 __ bind(&generic); | 2338 __ bind(&generic); |
| 2275 __ mov(ecx, name); | 2339 __ mov(ecx, name); |
| 2276 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2340 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2277 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2341 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
| 2278 } else { | 2342 } else { |
| 2279 DeoptimizeIf(not_equal, instr->environment()); | 2343 DeoptimizeIf(not_equal, instr->environment()); |
| 2280 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2344 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2281 } | 2345 } |
| 2282 __ bind(&done); | 2346 __ bind(&done); |
| 2283 } | 2347 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2298 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2362 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 2299 Register function = ToRegister(instr->function()); | 2363 Register function = ToRegister(instr->function()); |
| 2300 Register temp = ToRegister(instr->TempAt(0)); | 2364 Register temp = ToRegister(instr->TempAt(0)); |
| 2301 Register result = ToRegister(instr->result()); | 2365 Register result = ToRegister(instr->result()); |
| 2302 | 2366 |
| 2303 // Check that the function really is a function. | 2367 // Check that the function really is a function. |
| 2304 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2368 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
| 2305 DeoptimizeIf(not_equal, instr->environment()); | 2369 DeoptimizeIf(not_equal, instr->environment()); |
| 2306 | 2370 |
| 2307 // Check whether the function has an instance prototype. | 2371 // Check whether the function has an instance prototype. |
| 2308 NearLabel non_instance; | 2372 Label non_instance; |
| 2309 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 2373 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
| 2310 1 << Map::kHasNonInstancePrototype); | 2374 1 << Map::kHasNonInstancePrototype); |
| 2311 __ j(not_zero, &non_instance); | 2375 __ j(not_zero, &non_instance, Label::kNear); |
| 2312 | 2376 |
| 2313 // Get the prototype or initial map from the function. | 2377 // Get the prototype or initial map from the function. |
| 2314 __ mov(result, | 2378 __ mov(result, |
| 2315 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2379 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2316 | 2380 |
| 2317 // Check that the function has a prototype or an initial map. | 2381 // Check that the function has a prototype or an initial map. |
| 2318 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); | 2382 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); |
| 2319 DeoptimizeIf(equal, instr->environment()); | 2383 DeoptimizeIf(equal, instr->environment()); |
| 2320 | 2384 |
| 2321 // If the function does not have an initial map, we're done. | 2385 // If the function does not have an initial map, we're done. |
| 2322 NearLabel done; | 2386 Label done; |
| 2323 __ CmpObjectType(result, MAP_TYPE, temp); | 2387 __ CmpObjectType(result, MAP_TYPE, temp); |
| 2324 __ j(not_equal, &done); | 2388 __ j(not_equal, &done, Label::kNear); |
| 2325 | 2389 |
| 2326 // Get the prototype from the initial map. | 2390 // Get the prototype from the initial map. |
| 2327 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); | 2391 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); |
| 2328 __ jmp(&done); | 2392 __ jmp(&done, Label::kNear); |
| 2329 | 2393 |
| 2330 // Non-instance prototype: Fetch prototype from constructor field | 2394 // Non-instance prototype: Fetch prototype from constructor field |
| 2331 // in the function's map. | 2395 // in the function's map. |
| 2332 __ bind(&non_instance); | 2396 __ bind(&non_instance); |
| 2333 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 2397 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
| 2334 | 2398 |
| 2335 // All done. | 2399 // All done. |
| 2336 __ bind(&done); | 2400 __ bind(&done); |
| 2337 } | 2401 } |
| 2338 | 2402 |
| 2339 | 2403 |
| 2340 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2404 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2341 Register result = ToRegister(instr->result()); | 2405 Register result = ToRegister(instr->result()); |
| 2342 Register input = ToRegister(instr->InputAt(0)); | 2406 Register input = ToRegister(instr->InputAt(0)); |
| 2343 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); | 2407 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); |
| 2344 if (FLAG_debug_code) { | 2408 if (FLAG_debug_code) { |
| 2345 NearLabel done; | 2409 Label done; |
| 2346 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2410 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2347 Immediate(factory()->fixed_array_map())); | 2411 Immediate(factory()->fixed_array_map())); |
| 2348 __ j(equal, &done); | 2412 __ j(equal, &done, Label::kNear); |
| 2349 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2413 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2350 Immediate(factory()->fixed_cow_array_map())); | 2414 Immediate(factory()->fixed_cow_array_map())); |
| 2351 __ j(equal, &done); | 2415 __ j(equal, &done, Label::kNear); |
| 2352 Register temp((result.is(eax)) ? ebx : eax); | 2416 Register temp((result.is(eax)) ? ebx : eax); |
| 2353 __ push(temp); | 2417 __ push(temp); |
| 2354 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2418 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); |
| 2355 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 2419 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 2356 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); | 2420 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); |
| 2357 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); | 2421 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); |
| 2358 __ pop(temp); | 2422 __ pop(temp); |
| 2359 __ Check(below, "Check for fast elements or pixel array failed."); | 2423 __ Check(below, "Check for fast elements or pixel array failed."); |
| 2360 __ bind(&done); | 2424 __ bind(&done); |
| 2361 } | 2425 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2392 Register result = ToRegister(instr->result()); | 2456 Register result = ToRegister(instr->result()); |
| 2393 ASSERT(result.is(elements)); | 2457 ASSERT(result.is(elements)); |
| 2394 | 2458 |
| 2395 // Load the result. | 2459 // Load the result. |
| 2396 __ mov(result, FieldOperand(elements, | 2460 __ mov(result, FieldOperand(elements, |
| 2397 key, | 2461 key, |
| 2398 times_pointer_size, | 2462 times_pointer_size, |
| 2399 FixedArray::kHeaderSize)); | 2463 FixedArray::kHeaderSize)); |
| 2400 | 2464 |
| 2401 // Check for the hole value. | 2465 // Check for the hole value. |
| 2402 __ cmp(result, factory()->the_hole_value()); | 2466 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2403 DeoptimizeIf(equal, instr->environment()); | 2467 __ cmp(result, factory()->the_hole_value()); |
| 2468 DeoptimizeIf(equal, instr->environment()); |
| 2469 } |
| 2470 } |
| 2471 |
| 2472 |
| 2473 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer, |
| 2474 LOperand* key, |
| 2475 ExternalArrayType array_type) { |
| 2476 Register external_pointer_reg = ToRegister(external_pointer); |
| 2477 int shift_size = ExternalArrayTypeToShiftSize(array_type); |
| 2478 if (key->IsConstantOperand()) { |
| 2479 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
| 2480 if (constant_value & 0xF0000000) { |
| 2481 Abort("array index constant value too big"); |
| 2482 } |
| 2483 return Operand(external_pointer_reg, constant_value * (1 << shift_size)); |
| 2484 } else { |
| 2485 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 2486 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0); |
| 2487 } |
| 2404 } | 2488 } |
| 2405 | 2489 |
| 2406 | 2490 |
| 2407 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2491 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2408 LLoadKeyedSpecializedArrayElement* instr) { | 2492 LLoadKeyedSpecializedArrayElement* instr) { |
| 2409 Register external_pointer = ToRegister(instr->external_pointer()); | |
| 2410 Register key = ToRegister(instr->key()); | |
| 2411 ExternalArrayType array_type = instr->array_type(); | 2493 ExternalArrayType array_type = instr->array_type(); |
| 2494 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), |
| 2495 instr->key(), array_type)); |
| 2412 if (array_type == kExternalFloatArray) { | 2496 if (array_type == kExternalFloatArray) { |
| 2413 XMMRegister result(ToDoubleRegister(instr->result())); | 2497 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2414 __ movss(result, Operand(external_pointer, key, times_4, 0)); | 2498 __ movss(result, operand); |
| 2415 __ cvtss2sd(result, result); | 2499 __ cvtss2sd(result, result); |
| 2416 } else if (array_type == kExternalDoubleArray) { | 2500 } else if (array_type == kExternalDoubleArray) { |
| 2417 __ movdbl(ToDoubleRegister(instr->result()), | 2501 __ movdbl(ToDoubleRegister(instr->result()), operand); |
| 2418 Operand(external_pointer, key, times_8, 0)); | |
| 2419 } else { | 2502 } else { |
| 2420 Register result(ToRegister(instr->result())); | 2503 Register result(ToRegister(instr->result())); |
| 2421 switch (array_type) { | 2504 switch (array_type) { |
| 2422 case kExternalByteArray: | 2505 case kExternalByteArray: |
| 2423 __ movsx_b(result, Operand(external_pointer, key, times_1, 0)); | 2506 __ movsx_b(result, operand); |
| 2424 break; | 2507 break; |
| 2425 case kExternalUnsignedByteArray: | 2508 case kExternalUnsignedByteArray: |
| 2426 case kExternalPixelArray: | 2509 case kExternalPixelArray: |
| 2427 __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); | 2510 __ movzx_b(result, operand); |
| 2428 break; | 2511 break; |
| 2429 case kExternalShortArray: | 2512 case kExternalShortArray: |
| 2430 __ movsx_w(result, Operand(external_pointer, key, times_2, 0)); | 2513 __ movsx_w(result, operand); |
| 2431 break; | 2514 break; |
| 2432 case kExternalUnsignedShortArray: | 2515 case kExternalUnsignedShortArray: |
| 2433 __ movzx_w(result, Operand(external_pointer, key, times_2, 0)); | 2516 __ movzx_w(result, operand); |
| 2434 break; | 2517 break; |
| 2435 case kExternalIntArray: | 2518 case kExternalIntArray: |
| 2436 __ mov(result, Operand(external_pointer, key, times_4, 0)); | 2519 __ mov(result, operand); |
| 2437 break; | 2520 break; |
| 2438 case kExternalUnsignedIntArray: | 2521 case kExternalUnsignedIntArray: |
| 2439 __ mov(result, Operand(external_pointer, key, times_4, 0)); | 2522 __ mov(result, operand); |
| 2440 __ test(result, Operand(result)); | 2523 __ test(result, Operand(result)); |
| 2441 // TODO(danno): we could be more clever here, perhaps having a special | 2524 // TODO(danno): we could be more clever here, perhaps having a special |
| 2442 // version of the stub that detects if the overflow case actually | 2525 // version of the stub that detects if the overflow case actually |
| 2443 // happens, and generate code that returns a double rather than int. | 2526 // happens, and generate code that returns a double rather than int. |
| 2444 DeoptimizeIf(negative, instr->environment()); | 2527 DeoptimizeIf(negative, instr->environment()); |
| 2445 break; | 2528 break; |
| 2446 case kExternalFloatArray: | 2529 case kExternalFloatArray: |
| 2447 case kExternalDoubleArray: | 2530 case kExternalDoubleArray: |
| 2448 UNREACHABLE(); | 2531 UNREACHABLE(); |
| 2449 break; | 2532 break; |
| 2450 } | 2533 } |
| 2451 } | 2534 } |
| 2452 } | 2535 } |
| 2453 | 2536 |
| 2454 | 2537 |
| 2455 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2538 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 2456 ASSERT(ToRegister(instr->context()).is(esi)); | 2539 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2457 ASSERT(ToRegister(instr->object()).is(edx)); | 2540 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2458 ASSERT(ToRegister(instr->key()).is(eax)); | 2541 ASSERT(ToRegister(instr->key()).is(eax)); |
| 2459 | 2542 |
| 2460 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2543 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2461 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2544 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); |
| 2462 } | 2545 } |
| 2463 | 2546 |
| 2464 | 2547 |
| 2465 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2548 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 2466 Register result = ToRegister(instr->result()); | 2549 Register result = ToRegister(instr->result()); |
| 2467 | 2550 |
| 2468 // Check for arguments adapter frame. | 2551 // Check for arguments adapter frame. |
| 2469 NearLabel done, adapted; | 2552 Label done, adapted; |
| 2470 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2553 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2471 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); | 2554 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
| 2472 __ cmp(Operand(result), | 2555 __ cmp(Operand(result), |
| 2473 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2556 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2474 __ j(equal, &adapted); | 2557 __ j(equal, &adapted, Label::kNear); |
| 2475 | 2558 |
| 2476 // No arguments adaptor frame. | 2559 // No arguments adaptor frame. |
| 2477 __ mov(result, Operand(ebp)); | 2560 __ mov(result, Operand(ebp)); |
| 2478 __ jmp(&done); | 2561 __ jmp(&done, Label::kNear); |
| 2479 | 2562 |
| 2480 // Arguments adaptor frame present. | 2563 // Arguments adaptor frame present. |
| 2481 __ bind(&adapted); | 2564 __ bind(&adapted); |
| 2482 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2565 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2483 | 2566 |
| 2484 // Result is the frame pointer for the frame if not adapted and for the real | 2567 // Result is the frame pointer for the frame if not adapted and for the real |
| 2485 // frame below the adaptor frame if adapted. | 2568 // frame below the adaptor frame if adapted. |
| 2486 __ bind(&done); | 2569 __ bind(&done); |
| 2487 } | 2570 } |
| 2488 | 2571 |
| 2489 | 2572 |
| 2490 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2573 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2491 Operand elem = ToOperand(instr->InputAt(0)); | 2574 Operand elem = ToOperand(instr->InputAt(0)); |
| 2492 Register result = ToRegister(instr->result()); | 2575 Register result = ToRegister(instr->result()); |
| 2493 | 2576 |
| 2494 NearLabel done; | 2577 Label done; |
| 2495 | 2578 |
| 2496 // If no arguments adaptor frame the number of arguments is fixed. | 2579 // If no arguments adaptor frame the number of arguments is fixed. |
| 2497 __ cmp(ebp, elem); | 2580 __ cmp(ebp, elem); |
| 2498 __ mov(result, Immediate(scope()->num_parameters())); | 2581 __ mov(result, Immediate(scope()->num_parameters())); |
| 2499 __ j(equal, &done); | 2582 __ j(equal, &done, Label::kNear); |
| 2500 | 2583 |
| 2501 // Arguments adaptor frame present. Get argument length from there. | 2584 // Arguments adaptor frame present. Get argument length from there. |
| 2502 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2585 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2503 __ mov(result, Operand(result, | 2586 __ mov(result, Operand(result, |
| 2504 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2587 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2505 __ SmiUntag(result); | 2588 __ SmiUntag(result); |
| 2506 | 2589 |
| 2507 // Argument length is in result register. | 2590 // Argument length is in result register. |
| 2508 __ bind(&done); | 2591 __ bind(&done); |
| 2509 } | 2592 } |
| 2510 | 2593 |
| 2511 | 2594 |
| 2512 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 2595 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 2513 Register receiver = ToRegister(instr->receiver()); | 2596 Register receiver = ToRegister(instr->receiver()); |
| 2514 Register function = ToRegister(instr->function()); | 2597 Register function = ToRegister(instr->function()); |
| 2515 Register length = ToRegister(instr->length()); | 2598 Register length = ToRegister(instr->length()); |
| 2516 Register elements = ToRegister(instr->elements()); | 2599 Register elements = ToRegister(instr->elements()); |
| 2517 Register scratch = ToRegister(instr->TempAt(0)); | 2600 Register scratch = ToRegister(instr->TempAt(0)); |
| 2518 ASSERT(receiver.is(eax)); // Used for parameter count. | 2601 ASSERT(receiver.is(eax)); // Used for parameter count. |
| 2519 ASSERT(function.is(edi)); // Required by InvokeFunction. | 2602 ASSERT(function.is(edi)); // Required by InvokeFunction. |
| 2520 ASSERT(ToRegister(instr->result()).is(eax)); | 2603 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2521 | 2604 |
| 2522 // If the receiver is null or undefined, we have to pass the global object | 2605 // If the receiver is null or undefined, we have to pass the global object |
| 2523 // as a receiver. | 2606 // as a receiver. |
| 2524 NearLabel global_object, receiver_ok; | 2607 Label global_object, receiver_ok; |
| 2525 __ cmp(receiver, factory()->null_value()); | 2608 __ cmp(receiver, factory()->null_value()); |
| 2526 __ j(equal, &global_object); | 2609 __ j(equal, &global_object, Label::kNear); |
| 2527 __ cmp(receiver, factory()->undefined_value()); | 2610 __ cmp(receiver, factory()->undefined_value()); |
| 2528 __ j(equal, &global_object); | 2611 __ j(equal, &global_object, Label::kNear); |
| 2529 | 2612 |
| 2530 // The receiver should be a JS object. | 2613 // The receiver should be a JS object. |
| 2531 __ test(receiver, Immediate(kSmiTagMask)); | 2614 __ test(receiver, Immediate(kSmiTagMask)); |
| 2532 DeoptimizeIf(equal, instr->environment()); | 2615 DeoptimizeIf(equal, instr->environment()); |
| 2533 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); | 2616 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); |
| 2534 DeoptimizeIf(below, instr->environment()); | 2617 DeoptimizeIf(below, instr->environment()); |
| 2535 __ jmp(&receiver_ok); | 2618 __ jmp(&receiver_ok, Label::kNear); |
| 2536 | 2619 |
| 2537 __ bind(&global_object); | 2620 __ bind(&global_object); |
| 2538 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2621 // TODO(kmillikin): We have a hydrogen value for the global object. See |
| 2539 // if it's better to use it than to explicitly fetch it from the context | 2622 // if it's better to use it than to explicitly fetch it from the context |
| 2540 // here. | 2623 // here. |
| 2541 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2624 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2542 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); | 2625 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
| 2543 __ bind(&receiver_ok); | 2626 __ bind(&receiver_ok); |
| 2544 | 2627 |
| 2545 // Copy the arguments to this function possibly from the | 2628 // Copy the arguments to this function possibly from the |
| 2546 // adaptor frame below it. | 2629 // adaptor frame below it. |
| 2547 const uint32_t kArgumentsLimit = 1 * KB; | 2630 const uint32_t kArgumentsLimit = 1 * KB; |
| 2548 __ cmp(length, kArgumentsLimit); | 2631 __ cmp(length, kArgumentsLimit); |
| 2549 DeoptimizeIf(above, instr->environment()); | 2632 DeoptimizeIf(above, instr->environment()); |
| 2550 | 2633 |
| 2551 __ push(receiver); | 2634 __ push(receiver); |
| 2552 __ mov(receiver, length); | 2635 __ mov(receiver, length); |
| 2553 | 2636 |
| 2554 // Loop through the arguments pushing them onto the execution | 2637 // Loop through the arguments pushing them onto the execution |
| 2555 // stack. | 2638 // stack. |
| 2556 NearLabel invoke, loop; | 2639 Label invoke, loop; |
| 2557 // length is a small non-negative integer, due to the test above. | 2640 // length is a small non-negative integer, due to the test above. |
| 2558 __ test(length, Operand(length)); | 2641 __ test(length, Operand(length)); |
| 2559 __ j(zero, &invoke); | 2642 __ j(zero, &invoke, Label::kNear); |
| 2560 __ bind(&loop); | 2643 __ bind(&loop); |
| 2561 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 2644 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); |
| 2562 __ dec(length); | 2645 __ dec(length); |
| 2563 __ j(not_zero, &loop); | 2646 __ j(not_zero, &loop); |
| 2564 | 2647 |
| 2565 // Invoke the function. | 2648 // Invoke the function. |
| 2566 __ bind(&invoke); | 2649 __ bind(&invoke); |
| 2567 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 2650 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
| 2568 LPointerMap* pointers = instr->pointer_map(); | 2651 LPointerMap* pointers = instr->pointer_map(); |
| 2569 LEnvironment* env = instr->deoptimization_environment(); | 2652 LEnvironment* env = instr->deoptimization_environment(); |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2901 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2984 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2902 __ fstp_d(Operand(esp, 0)); | 2985 __ fstp_d(Operand(esp, 0)); |
| 2903 __ movdbl(result_reg, Operand(esp, 0)); | 2986 __ movdbl(result_reg, Operand(esp, 0)); |
| 2904 __ add(Operand(esp), Immediate(kDoubleSize)); | 2987 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2905 } | 2988 } |
| 2906 | 2989 |
| 2907 | 2990 |
| 2908 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2991 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 2909 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2992 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2910 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2993 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2911 NearLabel positive, done, zero, negative; | 2994 Label positive, done, zero; |
| 2912 __ xorps(xmm0, xmm0); | 2995 __ xorps(xmm0, xmm0); |
| 2913 __ ucomisd(input_reg, xmm0); | 2996 __ ucomisd(input_reg, xmm0); |
| 2914 __ j(above, &positive); | 2997 __ j(above, &positive, Label::kNear); |
| 2915 __ j(equal, &zero); | 2998 __ j(equal, &zero, Label::kNear); |
| 2916 ExternalReference nan = ExternalReference::address_of_nan(); | 2999 ExternalReference nan = ExternalReference::address_of_nan(); |
| 2917 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 3000 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
| 2918 __ jmp(&done); | 3001 __ jmp(&done, Label::kNear); |
| 2919 __ bind(&zero); | 3002 __ bind(&zero); |
| 2920 __ push(Immediate(0xFFF00000)); | 3003 __ push(Immediate(0xFFF00000)); |
| 2921 __ push(Immediate(0)); | 3004 __ push(Immediate(0)); |
| 2922 __ movdbl(input_reg, Operand(esp, 0)); | 3005 __ movdbl(input_reg, Operand(esp, 0)); |
| 2923 __ add(Operand(esp), Immediate(kDoubleSize)); | 3006 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2924 __ jmp(&done); | 3007 __ jmp(&done, Label::kNear); |
| 2925 __ bind(&positive); | 3008 __ bind(&positive); |
| 2926 __ fldln2(); | 3009 __ fldln2(); |
| 2927 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3010 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2928 __ movdbl(Operand(esp, 0), input_reg); | 3011 __ movdbl(Operand(esp, 0), input_reg); |
| 2929 __ fld_d(Operand(esp, 0)); | 3012 __ fld_d(Operand(esp, 0)); |
| 2930 __ fyl2x(); | 3013 __ fyl2x(); |
| 2931 __ fstp_d(Operand(esp, 0)); | 3014 __ fstp_d(Operand(esp, 0)); |
| 2932 __ movdbl(input_reg, Operand(esp, 0)); | 3015 __ movdbl(input_reg, Operand(esp, 0)); |
| 2933 __ add(Operand(esp), Immediate(kDoubleSize)); | 3016 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2934 __ bind(&done); | 3017 __ bind(&done); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3113 | 3196 |
| 3114 | 3197 |
| 3115 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3198 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 3116 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 3199 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 3117 DeoptimizeIf(above_equal, instr->environment()); | 3200 DeoptimizeIf(above_equal, instr->environment()); |
| 3118 } | 3201 } |
| 3119 | 3202 |
| 3120 | 3203 |
| 3121 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3204 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 3122 LStoreKeyedSpecializedArrayElement* instr) { | 3205 LStoreKeyedSpecializedArrayElement* instr) { |
| 3123 Register external_pointer = ToRegister(instr->external_pointer()); | |
| 3124 Register key = ToRegister(instr->key()); | |
| 3125 ExternalArrayType array_type = instr->array_type(); | 3206 ExternalArrayType array_type = instr->array_type(); |
| 3207 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), |
| 3208 instr->key(), array_type)); |
| 3126 if (array_type == kExternalFloatArray) { | 3209 if (array_type == kExternalFloatArray) { |
| 3127 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); | 3210 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); |
| 3128 __ movss(Operand(external_pointer, key, times_4, 0), xmm0); | 3211 __ movss(operand, xmm0); |
| 3129 } else if (array_type == kExternalDoubleArray) { | 3212 } else if (array_type == kExternalDoubleArray) { |
| 3130 __ movdbl(Operand(external_pointer, key, times_8, 0), | 3213 __ movdbl(operand, ToDoubleRegister(instr->value())); |
| 3131 ToDoubleRegister(instr->value())); | |
| 3132 } else { | 3214 } else { |
| 3133 Register value = ToRegister(instr->value()); | 3215 Register value = ToRegister(instr->value()); |
| 3134 switch (array_type) { | 3216 switch (array_type) { |
| 3135 case kExternalPixelArray: { | 3217 case kExternalPixelArray: |
| 3136 // Clamp the value to [0..255]. | |
| 3137 Register temp = ToRegister(instr->TempAt(0)); | |
| 3138 // The dec_b below requires that the clamped value is in a byte | |
| 3139 // register. eax is an arbitrary choice to satisfy this requirement, we | |
| 3140 // hinted the register allocator to give us eax when building the | |
| 3141 // instruction. | |
| 3142 ASSERT(temp.is(eax)); | |
| 3143 __ mov(temp, ToRegister(instr->value())); | |
| 3144 NearLabel done; | |
| 3145 __ test(temp, Immediate(0xFFFFFF00)); | |
| 3146 __ j(zero, &done); | |
| 3147 __ setcc(negative, temp); // 1 if negative, 0 if positive. | |
| 3148 __ dec_b(temp); // 0 if negative, 255 if positive. | |
| 3149 __ bind(&done); | |
| 3150 __ mov_b(Operand(external_pointer, key, times_1, 0), temp); | |
| 3151 break; | |
| 3152 } | |
| 3153 case kExternalByteArray: | 3218 case kExternalByteArray: |
| 3154 case kExternalUnsignedByteArray: | 3219 case kExternalUnsignedByteArray: |
| 3155 __ mov_b(Operand(external_pointer, key, times_1, 0), value); | 3220 __ mov_b(operand, value); |
| 3156 break; | 3221 break; |
| 3157 case kExternalShortArray: | 3222 case kExternalShortArray: |
| 3158 case kExternalUnsignedShortArray: | 3223 case kExternalUnsignedShortArray: |
| 3159 __ mov_w(Operand(external_pointer, key, times_2, 0), value); | 3224 __ mov_w(operand, value); |
| 3160 break; | 3225 break; |
| 3161 case kExternalIntArray: | 3226 case kExternalIntArray: |
| 3162 case kExternalUnsignedIntArray: | 3227 case kExternalUnsignedIntArray: |
| 3163 __ mov(Operand(external_pointer, key, times_4, 0), value); | 3228 __ mov(operand, value); |
| 3164 break; | 3229 break; |
| 3165 case kExternalFloatArray: | 3230 case kExternalFloatArray: |
| 3166 case kExternalDoubleArray: | 3231 case kExternalDoubleArray: |
| 3167 UNREACHABLE(); | 3232 UNREACHABLE(); |
| 3168 break; | 3233 break; |
| 3169 } | 3234 } |
| 3170 } | 3235 } |
| 3171 } | 3236 } |
| 3172 | 3237 |
| 3173 | 3238 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3243 return; | 3308 return; |
| 3244 } | 3309 } |
| 3245 } else { | 3310 } else { |
| 3246 index = ToRegister(instr->index()); | 3311 index = ToRegister(instr->index()); |
| 3247 } | 3312 } |
| 3248 Register result = ToRegister(instr->result()); | 3313 Register result = ToRegister(instr->result()); |
| 3249 | 3314 |
| 3250 DeferredStringCharCodeAt* deferred = | 3315 DeferredStringCharCodeAt* deferred = |
| 3251 new DeferredStringCharCodeAt(this, instr); | 3316 new DeferredStringCharCodeAt(this, instr); |
| 3252 | 3317 |
| 3253 NearLabel flat_string, ascii_string, done; | 3318 Label flat_string, ascii_string, done; |
| 3254 | 3319 |
| 3255 // Fetch the instance type of the receiver into result register. | 3320 // Fetch the instance type of the receiver into result register. |
| 3256 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3321 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 3257 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3322 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 3258 | 3323 |
| 3259 // We need special handling for non-flat strings. | 3324 // We need special handling for non-flat strings. |
| 3260 STATIC_ASSERT(kSeqStringTag == 0); | 3325 STATIC_ASSERT(kSeqStringTag == 0); |
| 3261 __ test(result, Immediate(kStringRepresentationMask)); | 3326 __ test(result, Immediate(kStringRepresentationMask)); |
| 3262 __ j(zero, &flat_string); | 3327 __ j(zero, &flat_string, Label::kNear); |
| 3263 | 3328 |
| 3264 // Handle non-flat strings. | 3329 // Handle non-flat strings. |
| 3265 __ test(result, Immediate(kIsConsStringMask)); | 3330 __ test(result, Immediate(kIsConsStringMask)); |
| 3266 __ j(zero, deferred->entry()); | 3331 __ j(zero, deferred->entry()); |
| 3267 | 3332 |
| 3268 // ConsString. | 3333 // ConsString. |
| 3269 // Check whether the right hand side is the empty string (i.e. if | 3334 // Check whether the right hand side is the empty string (i.e. if |
| 3270 // this is really a flat string in a cons string). If that is not | 3335 // this is really a flat string in a cons string). If that is not |
| 3271 // the case we would rather go to the runtime system now to flatten | 3336 // the case we would rather go to the runtime system now to flatten |
| 3272 // the string. | 3337 // the string. |
| 3273 __ cmp(FieldOperand(string, ConsString::kSecondOffset), | 3338 __ cmp(FieldOperand(string, ConsString::kSecondOffset), |
| 3274 Immediate(factory()->empty_string())); | 3339 Immediate(factory()->empty_string())); |
| 3275 __ j(not_equal, deferred->entry()); | 3340 __ j(not_equal, deferred->entry()); |
| 3276 // Get the first of the two strings and load its instance type. | 3341 // Get the first of the two strings and load its instance type. |
| 3277 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); | 3342 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); |
| 3278 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3343 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 3279 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3344 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 3280 // If the first cons component is also non-flat, then go to runtime. | 3345 // If the first cons component is also non-flat, then go to runtime. |
| 3281 STATIC_ASSERT(kSeqStringTag == 0); | 3346 STATIC_ASSERT(kSeqStringTag == 0); |
| 3282 __ test(result, Immediate(kStringRepresentationMask)); | 3347 __ test(result, Immediate(kStringRepresentationMask)); |
| 3283 __ j(not_zero, deferred->entry()); | 3348 __ j(not_zero, deferred->entry()); |
| 3284 | 3349 |
| 3285 // Check for ASCII or two-byte string. | 3350 // Check for ASCII or two-byte string. |
| 3286 __ bind(&flat_string); | 3351 __ bind(&flat_string); |
| 3287 STATIC_ASSERT(kAsciiStringTag != 0); | 3352 STATIC_ASSERT(kAsciiStringTag != 0); |
| 3288 __ test(result, Immediate(kStringEncodingMask)); | 3353 __ test(result, Immediate(kStringEncodingMask)); |
| 3289 __ j(not_zero, &ascii_string); | 3354 __ j(not_zero, &ascii_string, Label::kNear); |
| 3290 | 3355 |
| 3291 // Two-byte string. | 3356 // Two-byte string. |
| 3292 // Load the two-byte character code into the result register. | 3357 // Load the two-byte character code into the result register. |
| 3293 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 3358 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 3294 if (instr->index()->IsConstantOperand()) { | 3359 if (instr->index()->IsConstantOperand()) { |
| 3295 __ movzx_w(result, | 3360 __ movzx_w(result, |
| 3296 FieldOperand(string, | 3361 FieldOperand(string, |
| 3297 SeqTwoByteString::kHeaderSize + | 3362 SeqTwoByteString::kHeaderSize + |
| 3298 (kUC16Size * const_index))); | 3363 (kUC16Size * const_index))); |
| 3299 } else { | 3364 } else { |
| 3300 __ movzx_w(result, FieldOperand(string, | 3365 __ movzx_w(result, FieldOperand(string, |
| 3301 index, | 3366 index, |
| 3302 times_2, | 3367 times_2, |
| 3303 SeqTwoByteString::kHeaderSize)); | 3368 SeqTwoByteString::kHeaderSize)); |
| 3304 } | 3369 } |
| 3305 __ jmp(&done); | 3370 __ jmp(&done, Label::kNear); |
| 3306 | 3371 |
| 3307 // ASCII string. | 3372 // ASCII string. |
| 3308 // Load the byte into the result register. | 3373 // Load the byte into the result register. |
| 3309 __ bind(&ascii_string); | 3374 __ bind(&ascii_string); |
| 3310 if (instr->index()->IsConstantOperand()) { | 3375 if (instr->index()->IsConstantOperand()) { |
| 3311 __ movzx_b(result, FieldOperand(string, | 3376 __ movzx_b(result, FieldOperand(string, |
| 3312 SeqAsciiString::kHeaderSize + const_index)); | 3377 SeqAsciiString::kHeaderSize + const_index)); |
| 3313 } else { | 3378 } else { |
| 3314 __ movzx_b(result, FieldOperand(string, | 3379 __ movzx_b(result, FieldOperand(string, |
| 3315 index, | 3380 index, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3456 Label slow; | 3521 Label slow; |
| 3457 Register reg = ToRegister(instr->InputAt(0)); | 3522 Register reg = ToRegister(instr->InputAt(0)); |
| 3458 Register tmp = reg.is(eax) ? ecx : eax; | 3523 Register tmp = reg.is(eax) ? ecx : eax; |
| 3459 | 3524 |
| 3460 // Preserve the value of all registers. | 3525 // Preserve the value of all registers. |
| 3461 PushSafepointRegistersScope scope(this); | 3526 PushSafepointRegistersScope scope(this); |
| 3462 | 3527 |
| 3463 // There was overflow, so bits 30 and 31 of the original integer | 3528 // There was overflow, so bits 30 and 31 of the original integer |
| 3464 // disagree. Try to allocate a heap number in new space and store | 3529 // disagree. Try to allocate a heap number in new space and store |
| 3465 // the value in there. If that fails, call the runtime system. | 3530 // the value in there. If that fails, call the runtime system. |
| 3466 NearLabel done; | 3531 Label done; |
| 3467 __ SmiUntag(reg); | 3532 __ SmiUntag(reg); |
| 3468 __ xor_(reg, 0x80000000); | 3533 __ xor_(reg, 0x80000000); |
| 3469 __ cvtsi2sd(xmm0, Operand(reg)); | 3534 __ cvtsi2sd(xmm0, Operand(reg)); |
| 3470 if (FLAG_inline_new) { | 3535 if (FLAG_inline_new) { |
| 3471 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 3536 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
| 3472 __ jmp(&done); | 3537 __ jmp(&done, Label::kNear); |
| 3473 } | 3538 } |
| 3474 | 3539 |
| 3475 // Slow case: Call the runtime system to do the number allocation. | 3540 // Slow case: Call the runtime system to do the number allocation. |
| 3476 __ bind(&slow); | 3541 __ bind(&slow); |
| 3477 | 3542 |
| 3478 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3543 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
| 3479 // register is stored, as this register is in the pointer map, but contains an | 3544 // register is stored, as this register is in the pointer map, but contains an |
| 3480 // integer value. | 3545 // integer value. |
| 3481 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 3546 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
| 3482 | 3547 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3544 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3609 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3545 DeoptimizeIf(not_zero, instr->environment()); | 3610 DeoptimizeIf(not_zero, instr->environment()); |
| 3546 } | 3611 } |
| 3547 __ SmiUntag(ToRegister(input)); | 3612 __ SmiUntag(ToRegister(input)); |
| 3548 } | 3613 } |
| 3549 | 3614 |
| 3550 | 3615 |
| 3551 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3616 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 3552 XMMRegister result_reg, | 3617 XMMRegister result_reg, |
| 3553 LEnvironment* env) { | 3618 LEnvironment* env) { |
| 3554 NearLabel load_smi, heap_number, done; | 3619 Label load_smi, heap_number, done; |
| 3555 | 3620 |
| 3556 // Smi check. | 3621 // Smi check. |
| 3557 __ test(input_reg, Immediate(kSmiTagMask)); | 3622 __ test(input_reg, Immediate(kSmiTagMask)); |
| 3558 __ j(zero, &load_smi, not_taken); | 3623 __ j(zero, &load_smi, Label::kNear); |
| 3559 | 3624 |
| 3560 // Heap number map check. | 3625 // Heap number map check. |
| 3561 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3626 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3562 factory()->heap_number_map()); | 3627 factory()->heap_number_map()); |
| 3563 __ j(equal, &heap_number); | 3628 __ j(equal, &heap_number, Label::kNear); |
| 3564 | 3629 |
| 3565 __ cmp(input_reg, factory()->undefined_value()); | 3630 __ cmp(input_reg, factory()->undefined_value()); |
| 3566 DeoptimizeIf(not_equal, env); | 3631 DeoptimizeIf(not_equal, env); |
| 3567 | 3632 |
| 3568 // Convert undefined to NaN. | 3633 // Convert undefined to NaN. |
| 3569 ExternalReference nan = ExternalReference::address_of_nan(); | 3634 ExternalReference nan = ExternalReference::address_of_nan(); |
| 3570 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 3635 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
| 3571 __ jmp(&done); | 3636 __ jmp(&done, Label::kNear); |
| 3572 | 3637 |
| 3573 // Heap number to XMM conversion. | 3638 // Heap number to XMM conversion. |
| 3574 __ bind(&heap_number); | 3639 __ bind(&heap_number); |
| 3575 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3640 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3576 __ jmp(&done); | 3641 __ jmp(&done, Label::kNear); |
| 3577 | 3642 |
| 3578 // Smi to XMM conversion | 3643 // Smi to XMM conversion |
| 3579 __ bind(&load_smi); | 3644 __ bind(&load_smi); |
| 3580 __ SmiUntag(input_reg); // Untag smi before converting to float. | 3645 __ SmiUntag(input_reg); // Untag smi before converting to float. |
| 3581 __ cvtsi2sd(result_reg, Operand(input_reg)); | 3646 __ cvtsi2sd(result_reg, Operand(input_reg)); |
| 3582 __ SmiTag(input_reg); // Retag smi. | 3647 __ SmiTag(input_reg); // Retag smi. |
| 3583 __ bind(&done); | 3648 __ bind(&done); |
| 3584 } | 3649 } |
| 3585 | 3650 |
| 3586 | 3651 |
| 3587 class DeferredTaggedToI: public LDeferredCode { | 3652 class DeferredTaggedToI: public LDeferredCode { |
| 3588 public: | 3653 public: |
| 3589 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3654 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 3590 : LDeferredCode(codegen), instr_(instr) { } | 3655 : LDeferredCode(codegen), instr_(instr) { } |
| 3591 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3656 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 3592 private: | 3657 private: |
| 3593 LTaggedToI* instr_; | 3658 LTaggedToI* instr_; |
| 3594 }; | 3659 }; |
| 3595 | 3660 |
| 3596 | 3661 |
| 3597 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3662 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 3598 NearLabel done, heap_number; | 3663 Label done, heap_number; |
| 3599 Register input_reg = ToRegister(instr->InputAt(0)); | 3664 Register input_reg = ToRegister(instr->InputAt(0)); |
| 3600 | 3665 |
| 3601 // Heap number map check. | 3666 // Heap number map check. |
| 3602 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3667 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3603 factory()->heap_number_map()); | 3668 factory()->heap_number_map()); |
| 3604 | 3669 |
| 3605 if (instr->truncating()) { | 3670 if (instr->truncating()) { |
| 3606 __ j(equal, &heap_number); | 3671 __ j(equal, &heap_number, Label::kNear); |
| 3607 // Check for undefined. Undefined is converted to zero for truncating | 3672 // Check for undefined. Undefined is converted to zero for truncating |
| 3608 // conversions. | 3673 // conversions. |
| 3609 __ cmp(input_reg, factory()->undefined_value()); | 3674 __ cmp(input_reg, factory()->undefined_value()); |
| 3610 DeoptimizeIf(not_equal, instr->environment()); | 3675 DeoptimizeIf(not_equal, instr->environment()); |
| 3611 __ mov(input_reg, 0); | 3676 __ mov(input_reg, 0); |
| 3612 __ jmp(&done); | 3677 __ jmp(&done, Label::kNear); |
| 3613 | 3678 |
| 3614 __ bind(&heap_number); | 3679 __ bind(&heap_number); |
| 3615 if (CpuFeatures::IsSupported(SSE3)) { | 3680 if (CpuFeatures::IsSupported(SSE3)) { |
| 3616 CpuFeatures::Scope scope(SSE3); | 3681 CpuFeatures::Scope scope(SSE3); |
| 3617 NearLabel convert; | 3682 Label convert; |
| 3618 // Use more powerful conversion when sse3 is available. | 3683 // Use more powerful conversion when sse3 is available. |
| 3619 // Load x87 register with heap number. | 3684 // Load x87 register with heap number. |
| 3620 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3685 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3621 // Get exponent alone and check for too-big exponent. | 3686 // Get exponent alone and check for too-big exponent. |
| 3622 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3687 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 3623 __ and_(input_reg, HeapNumber::kExponentMask); | 3688 __ and_(input_reg, HeapNumber::kExponentMask); |
| 3624 const uint32_t kTooBigExponent = | 3689 const uint32_t kTooBigExponent = |
| 3625 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3690 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
| 3626 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); | 3691 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); |
| 3627 __ j(less, &convert); | 3692 __ j(less, &convert, Label::kNear); |
| 3628 // Pop FPU stack before deoptimizing. | 3693 // Pop FPU stack before deoptimizing. |
| 3629 __ ffree(0); | 3694 __ ffree(0); |
| 3630 __ fincstp(); | 3695 __ fincstp(); |
| 3631 DeoptimizeIf(no_condition, instr->environment()); | 3696 DeoptimizeIf(no_condition, instr->environment()); |
| 3632 | 3697 |
| 3633 // Reserve space for 64 bit answer. | 3698 // Reserve space for 64 bit answer. |
| 3634 __ bind(&convert); | 3699 __ bind(&convert); |
| 3635 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3700 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 3636 // Do conversion, which cannot fail because we checked the exponent. | 3701 // Do conversion, which cannot fail because we checked the exponent. |
| 3637 __ fisttp_d(Operand(esp, 0)); | 3702 __ fisttp_d(Operand(esp, 0)); |
| 3638 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 3703 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
| 3639 __ add(Operand(esp), Immediate(kDoubleSize)); | 3704 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 3640 } else { | 3705 } else { |
| 3641 NearLabel deopt; | |
| 3642 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); | 3706 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
| 3643 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3707 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3644 __ cvttsd2si(input_reg, Operand(xmm0)); | 3708 __ cvttsd2si(input_reg, Operand(xmm0)); |
| 3645 __ cmp(input_reg, 0x80000000u); | 3709 __ cmp(input_reg, 0x80000000u); |
| 3646 __ j(not_equal, &done); | 3710 __ j(not_equal, &done); |
| 3647 // Check if the input was 0x8000000 (kMinInt). | 3711 // Check if the input was 0x8000000 (kMinInt). |
| 3648 // If no, then we got an overflow and we deoptimize. | 3712 // If no, then we got an overflow and we deoptimize. |
| 3649 ExternalReference min_int = ExternalReference::address_of_min_int(); | 3713 ExternalReference min_int = ExternalReference::address_of_min_int(); |
| 3650 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 3714 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
| 3651 __ ucomisd(xmm_temp, xmm0); | 3715 __ ucomisd(xmm_temp, xmm0); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3718 Register result_reg = ToRegister(result); | 3782 Register result_reg = ToRegister(result); |
| 3719 | 3783 |
| 3720 if (instr->truncating()) { | 3784 if (instr->truncating()) { |
| 3721 // Performs a truncating conversion of a floating point number as used by | 3785 // Performs a truncating conversion of a floating point number as used by |
| 3722 // the JS bitwise operations. | 3786 // the JS bitwise operations. |
| 3723 __ cvttsd2si(result_reg, Operand(input_reg)); | 3787 __ cvttsd2si(result_reg, Operand(input_reg)); |
| 3724 __ cmp(result_reg, 0x80000000u); | 3788 __ cmp(result_reg, 0x80000000u); |
| 3725 if (CpuFeatures::IsSupported(SSE3)) { | 3789 if (CpuFeatures::IsSupported(SSE3)) { |
| 3726 // This will deoptimize if the exponent of the input in out of range. | 3790 // This will deoptimize if the exponent of the input in out of range. |
| 3727 CpuFeatures::Scope scope(SSE3); | 3791 CpuFeatures::Scope scope(SSE3); |
| 3728 NearLabel convert, done; | 3792 Label convert, done; |
| 3729 __ j(not_equal, &done); | 3793 __ j(not_equal, &done, Label::kNear); |
| 3730 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3794 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 3731 __ movdbl(Operand(esp, 0), input_reg); | 3795 __ movdbl(Operand(esp, 0), input_reg); |
| 3732 // Get exponent alone and check for too-big exponent. | 3796 // Get exponent alone and check for too-big exponent. |
| 3733 __ mov(result_reg, Operand(esp, sizeof(int32_t))); | 3797 __ mov(result_reg, Operand(esp, sizeof(int32_t))); |
| 3734 __ and_(result_reg, HeapNumber::kExponentMask); | 3798 __ and_(result_reg, HeapNumber::kExponentMask); |
| 3735 const uint32_t kTooBigExponent = | 3799 const uint32_t kTooBigExponent = |
| 3736 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3800 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
| 3737 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); | 3801 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); |
| 3738 __ j(less, &convert); | 3802 __ j(less, &convert, Label::kNear); |
| 3739 __ add(Operand(esp), Immediate(kDoubleSize)); | 3803 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 3740 DeoptimizeIf(no_condition, instr->environment()); | 3804 DeoptimizeIf(no_condition, instr->environment()); |
| 3741 __ bind(&convert); | 3805 __ bind(&convert); |
| 3742 // Do conversion, which cannot fail because we checked the exponent. | 3806 // Do conversion, which cannot fail because we checked the exponent. |
| 3743 __ fld_d(Operand(esp, 0)); | 3807 __ fld_d(Operand(esp, 0)); |
| 3744 __ fisttp_d(Operand(esp, 0)); | 3808 __ fisttp_d(Operand(esp, 0)); |
| 3745 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 3809 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
| 3746 __ add(Operand(esp), Immediate(kDoubleSize)); | 3810 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 3747 __ bind(&done); | 3811 __ bind(&done); |
| 3748 } else { | 3812 } else { |
| 3749 NearLabel done; | 3813 Label done; |
| 3750 Register temp_reg = ToRegister(instr->TempAt(0)); | 3814 Register temp_reg = ToRegister(instr->TempAt(0)); |
| 3751 XMMRegister xmm_scratch = xmm0; | 3815 XMMRegister xmm_scratch = xmm0; |
| 3752 | 3816 |
| 3753 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 3817 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
| 3754 // manual conversion. | 3818 // manual conversion. |
| 3755 __ j(not_equal, &done); | 3819 __ j(not_equal, &done, Label::kNear); |
| 3756 | 3820 |
| 3757 // Get high 32 bits of the input in result_reg and temp_reg. | 3821 // Get high 32 bits of the input in result_reg and temp_reg. |
| 3758 __ pshufd(xmm_scratch, input_reg, 1); | 3822 __ pshufd(xmm_scratch, input_reg, 1); |
| 3759 __ movd(Operand(temp_reg), xmm_scratch); | 3823 __ movd(Operand(temp_reg), xmm_scratch); |
| 3760 __ mov(result_reg, temp_reg); | 3824 __ mov(result_reg, temp_reg); |
| 3761 | 3825 |
| 3762 // Prepare negation mask in temp_reg. | 3826 // Prepare negation mask in temp_reg. |
| 3763 __ sar(temp_reg, kBitsPerInt - 1); | 3827 __ sar(temp_reg, kBitsPerInt - 1); |
| 3764 | 3828 |
| 3765 // Extract the exponent from result_reg and subtract adjusted | 3829 // Extract the exponent from result_reg and subtract adjusted |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3795 // Shift the input right and extract low 32 bits. | 3859 // Shift the input right and extract low 32 bits. |
| 3796 __ psrlq(input_reg, xmm_scratch); | 3860 __ psrlq(input_reg, xmm_scratch); |
| 3797 __ movd(Operand(result_reg), input_reg); | 3861 __ movd(Operand(result_reg), input_reg); |
| 3798 | 3862 |
| 3799 // Use the prepared mask in temp_reg to negate the result if necessary. | 3863 // Use the prepared mask in temp_reg to negate the result if necessary. |
| 3800 __ xor_(result_reg, Operand(temp_reg)); | 3864 __ xor_(result_reg, Operand(temp_reg)); |
| 3801 __ sub(result_reg, Operand(temp_reg)); | 3865 __ sub(result_reg, Operand(temp_reg)); |
| 3802 __ bind(&done); | 3866 __ bind(&done); |
| 3803 } | 3867 } |
| 3804 } else { | 3868 } else { |
| 3805 NearLabel done; | 3869 Label done; |
| 3806 __ cvttsd2si(result_reg, Operand(input_reg)); | 3870 __ cvttsd2si(result_reg, Operand(input_reg)); |
| 3807 __ cvtsi2sd(xmm0, Operand(result_reg)); | 3871 __ cvtsi2sd(xmm0, Operand(result_reg)); |
| 3808 __ ucomisd(xmm0, input_reg); | 3872 __ ucomisd(xmm0, input_reg); |
| 3809 DeoptimizeIf(not_equal, instr->environment()); | 3873 DeoptimizeIf(not_equal, instr->environment()); |
| 3810 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3874 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 3811 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3875 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3812 // The integer converted back is equal to the original. We | 3876 // The integer converted back is equal to the original. We |
| 3813 // only have to test if we got -0 as an input. | 3877 // only have to test if we got -0 as an input. |
| 3814 __ test(result_reg, Operand(result_reg)); | 3878 __ test(result_reg, Operand(result_reg)); |
| 3815 __ j(not_zero, &done); | 3879 __ j(not_zero, &done, Label::kNear); |
| 3816 __ movmskpd(result_reg, input_reg); | 3880 __ movmskpd(result_reg, input_reg); |
| 3817 // Bit 0 contains the sign of the double in input_reg. | 3881 // Bit 0 contains the sign of the double in input_reg. |
| 3818 // If input was positive, we are ok and return 0, otherwise | 3882 // If input was positive, we are ok and return 0, otherwise |
| 3819 // deoptimize. | 3883 // deoptimize. |
| 3820 __ and_(result_reg, 1); | 3884 __ and_(result_reg, 1); |
| 3821 DeoptimizeIf(not_zero, instr->environment()); | 3885 DeoptimizeIf(not_zero, instr->environment()); |
| 3822 } | 3886 } |
| 3823 __ bind(&done); | 3887 __ bind(&done); |
| 3824 } | 3888 } |
| 3825 } | 3889 } |
| 3826 | 3890 |
| 3827 | 3891 |
| 3828 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3892 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 3829 LOperand* input = instr->InputAt(0); | 3893 LOperand* input = instr->InputAt(0); |
| 3830 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3894 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3831 DeoptimizeIf(not_zero, instr->environment()); | 3895 DeoptimizeIf(not_zero, instr->environment()); |
| 3832 } | 3896 } |
| 3833 | 3897 |
| 3834 | 3898 |
| 3835 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 3899 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 3836 LOperand* input = instr->InputAt(0); | 3900 LOperand* input = instr->InputAt(0); |
| 3837 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3901 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3838 DeoptimizeIf(zero, instr->environment()); | 3902 DeoptimizeIf(zero, instr->environment()); |
| 3839 } | 3903 } |
| 3840 | 3904 |
| 3841 | 3905 |
| 3842 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3906 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 3843 Register input = ToRegister(instr->InputAt(0)); | 3907 Register input = ToRegister(instr->InputAt(0)); |
| 3844 Register temp = ToRegister(instr->TempAt(0)); | 3908 Register temp = ToRegister(instr->TempAt(0)); |
| 3845 InstanceType first = instr->hydrogen()->first(); | |
| 3846 InstanceType last = instr->hydrogen()->last(); | |
| 3847 | 3909 |
| 3848 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 3910 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 3849 | 3911 |
| 3850 // If there is only one type in the interval check for equality. | 3912 if (instr->hydrogen()->is_interval_check()) { |
| 3851 if (first == last) { | 3913 InstanceType first; |
| 3914 InstanceType last; |
| 3915 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 3916 |
| 3852 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3917 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 3853 static_cast<int8_t>(first)); | 3918 static_cast<int8_t>(first)); |
| 3854 DeoptimizeIf(not_equal, instr->environment()); | 3919 |
| 3855 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { | 3920 // If there is only one type in the interval check for equality. |
| 3856 // String has a dedicated bit in instance type. | 3921 if (first == last) { |
| 3857 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), kIsNotStringMask); | 3922 DeoptimizeIf(not_equal, instr->environment()); |
| 3858 DeoptimizeIf(not_zero, instr->environment()); | 3923 } else { |
| 3859 } else { | 3924 DeoptimizeIf(below, instr->environment()); |
| 3860 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3925 // Omit check for the last type. |
| 3861 static_cast<int8_t>(first)); | 3926 if (last != LAST_TYPE) { |
| 3862 DeoptimizeIf(below, instr->environment()); | 3927 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 3863 // Omit check for the last type. | 3928 static_cast<int8_t>(last)); |
| 3864 if (last != LAST_TYPE) { | 3929 DeoptimizeIf(above, instr->environment()); |
| 3865 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3930 } |
| 3866 static_cast<int8_t>(last)); | 3931 } |
| 3867 DeoptimizeIf(above, instr->environment()); | 3932 } else { |
| 3933 uint8_t mask; |
| 3934 uint8_t tag; |
| 3935 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 3936 |
| 3937 if (IsPowerOf2(mask)) { |
| 3938 ASSERT(tag == 0 || IsPowerOf2(tag)); |
| 3939 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); |
| 3940 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); |
| 3941 } else { |
| 3942 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 3943 __ and_(temp, mask); |
| 3944 __ cmpb(Operand(temp), tag); |
| 3945 DeoptimizeIf(not_equal, instr->environment()); |
| 3868 } | 3946 } |
| 3869 } | 3947 } |
| 3870 } | 3948 } |
| 3871 | 3949 |
| 3872 | 3950 |
| 3873 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3951 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 3874 ASSERT(instr->InputAt(0)->IsRegister()); | 3952 ASSERT(instr->InputAt(0)->IsRegister()); |
| 3875 Register reg = ToRegister(instr->InputAt(0)); | 3953 Register reg = ToRegister(instr->InputAt(0)); |
| 3876 __ cmp(reg, instr->hydrogen()->target()); | 3954 __ cmp(reg, instr->hydrogen()->target()); |
| 3877 DeoptimizeIf(not_equal, instr->environment()); | 3955 DeoptimizeIf(not_equal, instr->environment()); |
| 3878 } | 3956 } |
| 3879 | 3957 |
| 3880 | 3958 |
| 3881 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3959 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 3882 LOperand* input = instr->InputAt(0); | 3960 LOperand* input = instr->InputAt(0); |
| 3883 ASSERT(input->IsRegister()); | 3961 ASSERT(input->IsRegister()); |
| 3884 Register reg = ToRegister(input); | 3962 Register reg = ToRegister(input); |
| 3885 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3886 instr->hydrogen()->map()); | 3964 instr->hydrogen()->map()); |
| 3887 DeoptimizeIf(not_equal, instr->environment()); | 3965 DeoptimizeIf(not_equal, instr->environment()); |
| 3888 } | 3966 } |
| 3889 | 3967 |
| 3890 | 3968 |
| 3969 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 3970 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 3971 Register result_reg = ToRegister(instr->result()); |
| 3972 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); |
| 3973 } |
| 3974 |
| 3975 |
| 3976 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 3977 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 3978 Register value_reg = ToRegister(instr->result()); |
| 3979 __ ClampUint8(value_reg); |
| 3980 } |
| 3981 |
| 3982 |
| 3983 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 3984 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 3985 Register input_reg = ToRegister(instr->unclamped()); |
| 3986 Label is_smi, done, heap_number; |
| 3987 |
| 3988 __ JumpIfSmi(input_reg, &is_smi); |
| 3989 |
| 3990 // Check for heap number |
| 3991 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3992 factory()->heap_number_map()); |
| 3993 __ j(equal, &heap_number, Label::kNear); |
| 3994 |
| 3995 // Check for undefined. Undefined is converted to zero for clamping |
| 3996 // conversions. |
| 3997 __ cmp(input_reg, factory()->undefined_value()); |
| 3998 DeoptimizeIf(not_equal, instr->environment()); |
| 3999 __ mov(input_reg, 0); |
| 4000 __ jmp(&done, Label::kNear); |
| 4001 |
| 4002 // Heap number |
| 4003 __ bind(&heap_number); |
| 4004 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4005 __ ClampDoubleToUint8(xmm0, xmm1, input_reg); |
| 4006 __ jmp(&done, Label::kNear); |
| 4007 |
| 4008 // smi |
| 4009 __ bind(&is_smi); |
| 4010 __ SmiUntag(input_reg); |
| 4011 __ ClampUint8(input_reg); |
| 4012 |
| 4013 __ bind(&done); |
| 4014 } |
| 4015 |
| 4016 |
| 3891 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { | 4017 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { |
| 3892 if (isolate()->heap()->InNewSpace(*object)) { | 4018 if (isolate()->heap()->InNewSpace(*object)) { |
| 3893 Handle<JSGlobalPropertyCell> cell = | 4019 Handle<JSGlobalPropertyCell> cell = |
| 3894 isolate()->factory()->NewJSGlobalPropertyCell(object); | 4020 isolate()->factory()->NewJSGlobalPropertyCell(object); |
| 3895 __ mov(result, Operand::Cell(cell)); | 4021 __ mov(result, Operand::Cell(cell)); |
| 3896 } else { | 4022 } else { |
| 3897 __ mov(result, object); | 4023 __ mov(result, object); |
| 3898 } | 4024 } |
| 3899 } | 4025 } |
| 3900 | 4026 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3982 | 4108 |
| 3983 | 4109 |
| 3984 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 4110 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 3985 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 4111 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 3986 __ push(eax); | 4112 __ push(eax); |
| 3987 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); | 4113 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); |
| 3988 } | 4114 } |
| 3989 | 4115 |
| 3990 | 4116 |
| 3991 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 4117 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 3992 NearLabel materialized; | 4118 Label materialized; |
| 3993 // Registers will be used as follows: | 4119 // Registers will be used as follows: |
| 3994 // edi = JS function. | 4120 // edi = JS function. |
| 3995 // ecx = literals array. | 4121 // ecx = literals array. |
| 3996 // ebx = regexp literal. | 4122 // ebx = regexp literal. |
| 3997 // eax = regexp literal clone. | 4123 // eax = regexp literal clone. |
| 3998 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4124 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3999 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 4125 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 4000 int literal_offset = FixedArray::kHeaderSize + | 4126 int literal_offset = FixedArray::kHeaderSize + |
| 4001 instr->hydrogen()->literal_index() * kPointerSize; | 4127 instr->hydrogen()->literal_index() * kPointerSize; |
| 4002 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 4128 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 4003 __ cmp(ebx, factory()->undefined_value()); | 4129 __ cmp(ebx, factory()->undefined_value()); |
| 4004 __ j(not_equal, &materialized); | 4130 __ j(not_equal, &materialized, Label::kNear); |
| 4005 | 4131 |
| 4006 // Create regexp literal using runtime function | 4132 // Create regexp literal using runtime function |
| 4007 // Result will be in eax. | 4133 // Result will be in eax. |
| 4008 __ push(ecx); | 4134 __ push(ecx); |
| 4009 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4135 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 4010 __ push(Immediate(instr->hydrogen()->pattern())); | 4136 __ push(Immediate(instr->hydrogen()->pattern())); |
| 4011 __ push(Immediate(instr->hydrogen()->flags())); | 4137 __ push(Immediate(instr->hydrogen()->flags())); |
| 4012 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); | 4138 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); |
| 4013 __ mov(ebx, eax); | 4139 __ mov(ebx, eax); |
| 4014 | 4140 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4070 } | 4196 } |
| 4071 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 4197 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); |
| 4072 } | 4198 } |
| 4073 | 4199 |
| 4074 | 4200 |
| 4075 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 4201 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 4076 Register input = ToRegister(instr->InputAt(0)); | 4202 Register input = ToRegister(instr->InputAt(0)); |
| 4077 Register result = ToRegister(instr->result()); | 4203 Register result = ToRegister(instr->result()); |
| 4078 Label true_label; | 4204 Label true_label; |
| 4079 Label false_label; | 4205 Label false_label; |
| 4080 NearLabel done; | 4206 Label done; |
| 4081 | 4207 |
| 4082 Condition final_branch_condition = EmitTypeofIs(&true_label, | 4208 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 4083 &false_label, | 4209 &false_label, |
| 4084 input, | 4210 input, |
| 4085 instr->type_literal()); | 4211 instr->type_literal()); |
| 4086 __ j(final_branch_condition, &true_label); | 4212 __ j(final_branch_condition, &true_label, Label::kNear); |
| 4087 __ bind(&false_label); | 4213 __ bind(&false_label); |
| 4088 __ mov(result, factory()->false_value()); | 4214 __ mov(result, factory()->false_value()); |
| 4089 __ jmp(&done); | 4215 __ jmp(&done, Label::kNear); |
| 4090 | 4216 |
| 4091 __ bind(&true_label); | 4217 __ bind(&true_label); |
| 4092 __ mov(result, factory()->true_value()); | 4218 __ mov(result, factory()->true_value()); |
| 4093 | 4219 |
| 4094 __ bind(&done); | 4220 __ bind(&done); |
| 4095 } | 4221 } |
| 4096 | 4222 |
| 4097 | 4223 |
| 4098 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4224 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 4099 Register input = ToRegister(instr->InputAt(0)); | 4225 Register input = ToRegister(instr->InputAt(0)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4173 __ jmp(false_label); | 4299 __ jmp(false_label); |
| 4174 // A dead branch instruction will be generated after this point. | 4300 // A dead branch instruction will be generated after this point. |
| 4175 } | 4301 } |
| 4176 | 4302 |
| 4177 return final_branch_condition; | 4303 return final_branch_condition; |
| 4178 } | 4304 } |
| 4179 | 4305 |
| 4180 | 4306 |
| 4181 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | 4307 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
| 4182 Register result = ToRegister(instr->result()); | 4308 Register result = ToRegister(instr->result()); |
| 4183 NearLabel true_label; | 4309 Label true_label; |
| 4184 NearLabel false_label; | 4310 Label done; |
| 4185 NearLabel done; | |
| 4186 | 4311 |
| 4187 EmitIsConstructCall(result); | 4312 EmitIsConstructCall(result); |
| 4188 __ j(equal, &true_label); | 4313 __ j(equal, &true_label, Label::kNear); |
| 4189 | 4314 |
| 4190 __ mov(result, factory()->false_value()); | 4315 __ mov(result, factory()->false_value()); |
| 4191 __ jmp(&done); | 4316 __ jmp(&done, Label::kNear); |
| 4192 | 4317 |
| 4193 __ bind(&true_label); | 4318 __ bind(&true_label); |
| 4194 __ mov(result, factory()->true_value()); | 4319 __ mov(result, factory()->true_value()); |
| 4195 | 4320 |
| 4196 __ bind(&done); | 4321 __ bind(&done); |
| 4197 } | 4322 } |
| 4198 | 4323 |
| 4199 | 4324 |
| 4200 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4325 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 4201 Register temp = ToRegister(instr->TempAt(0)); | 4326 Register temp = ToRegister(instr->TempAt(0)); |
| 4202 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4327 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 4203 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4328 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 4204 | 4329 |
| 4205 EmitIsConstructCall(temp); | 4330 EmitIsConstructCall(temp); |
| 4206 EmitBranch(true_block, false_block, equal); | 4331 EmitBranch(true_block, false_block, equal); |
| 4207 } | 4332 } |
| 4208 | 4333 |
| 4209 | 4334 |
| 4210 void LCodeGen::EmitIsConstructCall(Register temp) { | 4335 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 4211 // Get the frame pointer for the calling frame. | 4336 // Get the frame pointer for the calling frame. |
| 4212 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 4337 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 4213 | 4338 |
| 4214 // Skip the arguments adaptor frame if it exists. | 4339 // Skip the arguments adaptor frame if it exists. |
| 4215 NearLabel check_frame_marker; | 4340 Label check_frame_marker; |
| 4216 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 4341 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| 4217 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 4342 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 4218 __ j(not_equal, &check_frame_marker); | 4343 __ j(not_equal, &check_frame_marker, Label::kNear); |
| 4219 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); | 4344 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); |
| 4220 | 4345 |
| 4221 // Check the marker in the calling frame. | 4346 // Check the marker in the calling frame. |
| 4222 __ bind(&check_frame_marker); | 4347 __ bind(&check_frame_marker); |
| 4223 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 4348 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 4224 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 4349 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 4225 } | 4350 } |
| 4226 | 4351 |
| 4227 | 4352 |
| 4228 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 4353 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4257 pointers, | 4382 pointers, |
| 4258 env->deoptimization_index()); | 4383 env->deoptimization_index()); |
| 4259 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4384 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4260 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4385 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 4261 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4386 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
| 4262 } | 4387 } |
| 4263 | 4388 |
| 4264 | 4389 |
| 4265 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4390 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 4266 // Perform stack overflow check. | 4391 // Perform stack overflow check. |
| 4267 NearLabel done; | 4392 Label done; |
| 4268 ExternalReference stack_limit = | 4393 ExternalReference stack_limit = |
| 4269 ExternalReference::address_of_stack_limit(isolate()); | 4394 ExternalReference::address_of_stack_limit(isolate()); |
| 4270 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4395 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 4271 __ j(above_equal, &done); | 4396 __ j(above_equal, &done, Label::kNear); |
| 4272 | 4397 |
| 4273 StackCheckStub stub; | 4398 StackCheckStub stub; |
| 4274 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4399 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); |
| 4275 __ bind(&done); | 4400 __ bind(&done); |
| 4276 } | 4401 } |
| 4277 | 4402 |
| 4278 | 4403 |
| 4279 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 4404 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 4280 // This is a pseudo-instruction that ensures that the environment here is | 4405 // This is a pseudo-instruction that ensures that the environment here is |
| 4281 // properly registered for deoptimization and records the assembler's PC | 4406 // properly registered for deoptimization and records the assembler's PC |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4320 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4445 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 4321 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4446 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4322 } | 4447 } |
| 4323 | 4448 |
| 4324 | 4449 |
| 4325 #undef __ | 4450 #undef __ |
| 4326 | 4451 |
| 4327 } } // namespace v8::internal | 4452 } } // namespace v8::internal |
| 4328 | 4453 |
| 4329 #endif // V8_TARGET_ARCH_IA32 | 4454 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |