| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
| 5 | 5 |
| 6 #include "src/crankshaft/s390/lithium-codegen-s390.h" | 6 #include "src/crankshaft/s390/lithium-codegen-s390.h" |
| 7 | 7 |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 WriteTranslation(environment, &translation); | 668 WriteTranslation(environment, &translation); |
| 669 int deoptimization_index = deoptimizations_.length(); | 669 int deoptimization_index = deoptimizations_.length(); |
| 670 int pc_offset = masm()->pc_offset(); | 670 int pc_offset = masm()->pc_offset(); |
| 671 environment->Register(deoptimization_index, translation.index(), | 671 environment->Register(deoptimization_index, translation.index(), |
| 672 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 672 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 673 deoptimizations_.Add(environment, zone()); | 673 deoptimizations_.Add(environment, zone()); |
| 674 } | 674 } |
| 675 } | 675 } |
| 676 | 676 |
| 677 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, | 677 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, |
| 678 Deoptimizer::DeoptReason deopt_reason, | 678 DeoptimizeReason deopt_reason, |
| 679 Deoptimizer::BailoutType bailout_type, | 679 Deoptimizer::BailoutType bailout_type, |
| 680 CRegister cr) { | 680 CRegister cr) { |
| 681 LEnvironment* environment = instr->environment(); | 681 LEnvironment* environment = instr->environment(); |
| 682 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 682 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 683 DCHECK(environment->HasBeenRegistered()); | 683 DCHECK(environment->HasBeenRegistered()); |
| 684 int id = environment->deoptimization_index(); | 684 int id = environment->deoptimization_index(); |
| 685 Address entry = | 685 Address entry = |
| 686 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 686 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 687 if (entry == NULL) { | 687 if (entry == NULL) { |
| 688 Abort(kBailoutWasNotPrepared); | 688 Abort(kBailoutWasNotPrepared); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 if (FLAG_trace_deopt || isolate()->is_profiling() || | 761 if (FLAG_trace_deopt || isolate()->is_profiling() || |
| 762 jump_table_.is_empty() || | 762 jump_table_.is_empty() || |
| 763 !table_entry.IsEquivalentTo(jump_table_.last())) { | 763 !table_entry.IsEquivalentTo(jump_table_.last())) { |
| 764 jump_table_.Add(table_entry, zone()); | 764 jump_table_.Add(table_entry, zone()); |
| 765 } | 765 } |
| 766 __ b(cond, &jump_table_.last().label /*, cr*/); | 766 __ b(cond, &jump_table_.last().label /*, cr*/); |
| 767 } | 767 } |
| 768 } | 768 } |
| 769 | 769 |
| 770 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, | 770 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, |
| 771 Deoptimizer::DeoptReason deopt_reason, | 771 DeoptimizeReason deopt_reason, CRegister cr) { |
| 772 CRegister cr) { | |
| 773 Deoptimizer::BailoutType bailout_type = | 772 Deoptimizer::BailoutType bailout_type = |
| 774 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; | 773 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; |
| 775 DeoptimizeIf(cond, instr, deopt_reason, bailout_type, cr); | 774 DeoptimizeIf(cond, instr, deopt_reason, bailout_type, cr); |
| 776 } | 775 } |
| 777 | 776 |
| 778 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, | 777 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, |
| 779 SafepointMode safepoint_mode) { | 778 SafepointMode safepoint_mode) { |
| 780 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { | 779 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
| 781 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); | 780 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); |
| 782 } else { | 781 } else { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 Label dividend_is_not_negative, done; | 870 Label dividend_is_not_negative, done; |
| 872 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 871 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
| 873 __ CmpP(dividend, Operand::Zero()); | 872 __ CmpP(dividend, Operand::Zero()); |
| 874 __ bge(÷nd_is_not_negative, Label::kNear); | 873 __ bge(÷nd_is_not_negative, Label::kNear); |
| 875 if (shift) { | 874 if (shift) { |
| 876 // Note that this is correct even for kMinInt operands. | 875 // Note that this is correct even for kMinInt operands. |
| 877 __ LoadComplementRR(dividend, dividend); | 876 __ LoadComplementRR(dividend, dividend); |
| 878 __ ExtractBitRange(dividend, dividend, shift - 1, 0); | 877 __ ExtractBitRange(dividend, dividend, shift - 1, 0); |
| 879 __ LoadComplementRR(dividend, dividend); | 878 __ LoadComplementRR(dividend, dividend); |
| 880 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 879 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 881 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 880 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 882 } | 881 } |
| 883 } else if (!hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 882 } else if (!hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 884 __ mov(dividend, Operand::Zero()); | 883 __ mov(dividend, Operand::Zero()); |
| 885 } else { | 884 } else { |
| 886 DeoptimizeIf(al, instr, Deoptimizer::kMinusZero); | 885 DeoptimizeIf(al, instr, DeoptimizeReason::kMinusZero); |
| 887 } | 886 } |
| 888 __ b(&done, Label::kNear); | 887 __ b(&done, Label::kNear); |
| 889 } | 888 } |
| 890 | 889 |
| 891 __ bind(÷nd_is_not_negative); | 890 __ bind(÷nd_is_not_negative); |
| 892 if (shift) { | 891 if (shift) { |
| 893 __ ExtractBitRange(dividend, dividend, shift - 1, 0); | 892 __ ExtractBitRange(dividend, dividend, shift - 1, 0); |
| 894 } else { | 893 } else { |
| 895 __ mov(dividend, Operand::Zero()); | 894 __ mov(dividend, Operand::Zero()); |
| 896 } | 895 } |
| 897 __ bind(&done); | 896 __ bind(&done); |
| 898 } | 897 } |
| 899 | 898 |
| 900 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 899 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 901 Register dividend = ToRegister(instr->dividend()); | 900 Register dividend = ToRegister(instr->dividend()); |
| 902 int32_t divisor = instr->divisor(); | 901 int32_t divisor = instr->divisor(); |
| 903 Register result = ToRegister(instr->result()); | 902 Register result = ToRegister(instr->result()); |
| 904 DCHECK(!dividend.is(result)); | 903 DCHECK(!dividend.is(result)); |
| 905 | 904 |
| 906 if (divisor == 0) { | 905 if (divisor == 0) { |
| 907 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 906 DeoptimizeIf(al, instr, DeoptimizeReason::kDivisionByZero); |
| 908 return; | 907 return; |
| 909 } | 908 } |
| 910 | 909 |
| 911 __ TruncatingDiv(result, dividend, Abs(divisor)); | 910 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 912 __ mov(ip, Operand(Abs(divisor))); | 911 __ mov(ip, Operand(Abs(divisor))); |
| 913 __ Mul(result, result, ip); | 912 __ Mul(result, result, ip); |
| 914 __ SubP(result, dividend, result /*, LeaveOE, SetRC*/); | 913 __ SubP(result, dividend, result /*, LeaveOE, SetRC*/); |
| 915 | 914 |
| 916 // Check for negative zero. | 915 // Check for negative zero. |
| 917 HMod* hmod = instr->hydrogen(); | 916 HMod* hmod = instr->hydrogen(); |
| 918 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 917 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 919 Label remainder_not_zero; | 918 Label remainder_not_zero; |
| 920 __ bne(&remainder_not_zero, Label::kNear /*, cr0*/); | 919 __ bne(&remainder_not_zero, Label::kNear /*, cr0*/); |
| 921 __ Cmp32(dividend, Operand::Zero()); | 920 __ Cmp32(dividend, Operand::Zero()); |
| 922 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 921 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 923 __ bind(&remainder_not_zero); | 922 __ bind(&remainder_not_zero); |
| 924 } | 923 } |
| 925 } | 924 } |
| 926 | 925 |
| 927 void LCodeGen::DoModI(LModI* instr) { | 926 void LCodeGen::DoModI(LModI* instr) { |
| 928 HMod* hmod = instr->hydrogen(); | 927 HMod* hmod = instr->hydrogen(); |
| 929 Register left_reg = ToRegister(instr->left()); | 928 Register left_reg = ToRegister(instr->left()); |
| 930 Register right_reg = ToRegister(instr->right()); | 929 Register right_reg = ToRegister(instr->right()); |
| 931 Register result_reg = ToRegister(instr->result()); | 930 Register result_reg = ToRegister(instr->result()); |
| 932 Label done; | 931 Label done; |
| 933 | 932 |
| 934 // Check for x % 0. | 933 // Check for x % 0. |
| 935 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 934 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 936 __ Cmp32(right_reg, Operand::Zero()); | 935 __ Cmp32(right_reg, Operand::Zero()); |
| 937 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 936 DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero); |
| 938 } | 937 } |
| 939 | 938 |
| 940 // Check for kMinInt % -1, dr will return undefined, which is not what we | 939 // Check for kMinInt % -1, dr will return undefined, which is not what we |
| 941 // want. We have to deopt if we care about -0, because we can't return that. | 940 // want. We have to deopt if we care about -0, because we can't return that. |
| 942 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 941 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 943 Label no_overflow_possible; | 942 Label no_overflow_possible; |
| 944 __ Cmp32(left_reg, Operand(kMinInt)); | 943 __ Cmp32(left_reg, Operand(kMinInt)); |
| 945 __ bne(&no_overflow_possible, Label::kNear); | 944 __ bne(&no_overflow_possible, Label::kNear); |
| 946 __ Cmp32(right_reg, Operand(-1)); | 945 __ Cmp32(right_reg, Operand(-1)); |
| 947 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 946 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 948 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 947 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 949 } else { | 948 } else { |
| 950 __ b(ne, &no_overflow_possible, Label::kNear); | 949 __ b(ne, &no_overflow_possible, Label::kNear); |
| 951 __ mov(result_reg, Operand::Zero()); | 950 __ mov(result_reg, Operand::Zero()); |
| 952 __ b(&done, Label::kNear); | 951 __ b(&done, Label::kNear); |
| 953 } | 952 } |
| 954 __ bind(&no_overflow_possible); | 953 __ bind(&no_overflow_possible); |
| 955 } | 954 } |
| 956 | 955 |
| 957 // Divide instruction dr will implicity use register pair | 956 // Divide instruction dr will implicity use register pair |
| 958 // r0 & r1 below. | 957 // r0 & r1 below. |
| 959 DCHECK(!left_reg.is(r1)); | 958 DCHECK(!left_reg.is(r1)); |
| 960 DCHECK(!right_reg.is(r1)); | 959 DCHECK(!right_reg.is(r1)); |
| 961 DCHECK(!result_reg.is(r1)); | 960 DCHECK(!result_reg.is(r1)); |
| 962 __ LoadRR(r0, left_reg); | 961 __ LoadRR(r0, left_reg); |
| 963 __ srda(r0, Operand(32)); | 962 __ srda(r0, Operand(32)); |
| 964 __ dr(r0, right_reg); // R0:R1 = R1 / divisor - R0 remainder | 963 __ dr(r0, right_reg); // R0:R1 = R1 / divisor - R0 remainder |
| 965 | 964 |
| 966 __ LoadAndTestP_ExtendSrc(result_reg, r0); // Copy remainder to resultreg | 965 __ LoadAndTestP_ExtendSrc(result_reg, r0); // Copy remainder to resultreg |
| 967 | 966 |
| 968 // If we care about -0, test if the dividend is <0 and the result is 0. | 967 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 969 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 968 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 970 __ bne(&done, Label::kNear); | 969 __ bne(&done, Label::kNear); |
| 971 __ Cmp32(left_reg, Operand::Zero()); | 970 __ Cmp32(left_reg, Operand::Zero()); |
| 972 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 971 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 973 } | 972 } |
| 974 | 973 |
| 975 __ bind(&done); | 974 __ bind(&done); |
| 976 } | 975 } |
| 977 | 976 |
| 978 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 977 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 979 Register dividend = ToRegister(instr->dividend()); | 978 Register dividend = ToRegister(instr->dividend()); |
| 980 int32_t divisor = instr->divisor(); | 979 int32_t divisor = instr->divisor(); |
| 981 Register result = ToRegister(instr->result()); | 980 Register result = ToRegister(instr->result()); |
| 982 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 981 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
| 983 DCHECK(!result.is(dividend)); | 982 DCHECK(!result.is(dividend)); |
| 984 | 983 |
| 985 // Check for (0 / -x) that will produce negative zero. | 984 // Check for (0 / -x) that will produce negative zero. |
| 986 HDiv* hdiv = instr->hydrogen(); | 985 HDiv* hdiv = instr->hydrogen(); |
| 987 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 986 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 988 __ Cmp32(dividend, Operand::Zero()); | 987 __ Cmp32(dividend, Operand::Zero()); |
| 989 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 988 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 990 } | 989 } |
| 991 // Check for (kMinInt / -1). | 990 // Check for (kMinInt / -1). |
| 992 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 991 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 993 __ Cmp32(dividend, Operand(0x80000000)); | 992 __ Cmp32(dividend, Operand(0x80000000)); |
| 994 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 993 DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow); |
| 995 } | 994 } |
| 996 | 995 |
| 997 int32_t shift = WhichPowerOf2Abs(divisor); | 996 int32_t shift = WhichPowerOf2Abs(divisor); |
| 998 | 997 |
| 999 // Deoptimize if remainder will not be 0. | 998 // Deoptimize if remainder will not be 0. |
| 1000 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && shift) { | 999 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && shift) { |
| 1001 __ TestBitRange(dividend, shift - 1, 0, r0); | 1000 __ TestBitRange(dividend, shift - 1, 0, r0); |
| 1002 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, cr0); | 1001 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, cr0); |
| 1003 } | 1002 } |
| 1004 | 1003 |
| 1005 if (divisor == -1) { // Nice shortcut, not needed for correctness. | 1004 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
| 1006 __ LoadComplementRR(result, dividend); | 1005 __ LoadComplementRR(result, dividend); |
| 1007 return; | 1006 return; |
| 1008 } | 1007 } |
| 1009 if (shift == 0) { | 1008 if (shift == 0) { |
| 1010 __ LoadRR(result, dividend); | 1009 __ LoadRR(result, dividend); |
| 1011 } else { | 1010 } else { |
| 1012 if (shift == 1) { | 1011 if (shift == 1) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1024 if (divisor < 0) __ LoadComplementRR(result, result); | 1023 if (divisor < 0) __ LoadComplementRR(result, result); |
| 1025 } | 1024 } |
| 1026 | 1025 |
| 1027 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1026 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
| 1028 Register dividend = ToRegister(instr->dividend()); | 1027 Register dividend = ToRegister(instr->dividend()); |
| 1029 int32_t divisor = instr->divisor(); | 1028 int32_t divisor = instr->divisor(); |
| 1030 Register result = ToRegister(instr->result()); | 1029 Register result = ToRegister(instr->result()); |
| 1031 DCHECK(!dividend.is(result)); | 1030 DCHECK(!dividend.is(result)); |
| 1032 | 1031 |
| 1033 if (divisor == 0) { | 1032 if (divisor == 0) { |
| 1034 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 1033 DeoptimizeIf(al, instr, DeoptimizeReason::kDivisionByZero); |
| 1035 return; | 1034 return; |
| 1036 } | 1035 } |
| 1037 | 1036 |
| 1038 // Check for (0 / -x) that will produce negative zero. | 1037 // Check for (0 / -x) that will produce negative zero. |
| 1039 HDiv* hdiv = instr->hydrogen(); | 1038 HDiv* hdiv = instr->hydrogen(); |
| 1040 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1039 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1041 __ Cmp32(dividend, Operand::Zero()); | 1040 __ Cmp32(dividend, Operand::Zero()); |
| 1042 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1041 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 1043 } | 1042 } |
| 1044 | 1043 |
| 1045 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1044 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1046 if (divisor < 0) __ LoadComplementRR(result, result); | 1045 if (divisor < 0) __ LoadComplementRR(result, result); |
| 1047 | 1046 |
| 1048 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1047 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1049 Register scratch = scratch0(); | 1048 Register scratch = scratch0(); |
| 1050 __ mov(ip, Operand(divisor)); | 1049 __ mov(ip, Operand(divisor)); |
| 1051 __ Mul(scratch, result, ip); | 1050 __ Mul(scratch, result, ip); |
| 1052 __ Cmp32(scratch, dividend); | 1051 __ Cmp32(scratch, dividend); |
| 1053 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1052 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision); |
| 1054 } | 1053 } |
| 1055 } | 1054 } |
| 1056 | 1055 |
| 1057 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1056 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1058 void LCodeGen::DoDivI(LDivI* instr) { | 1057 void LCodeGen::DoDivI(LDivI* instr) { |
| 1059 HBinaryOperation* hdiv = instr->hydrogen(); | 1058 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1060 const Register dividend = ToRegister(instr->dividend()); | 1059 const Register dividend = ToRegister(instr->dividend()); |
| 1061 const Register divisor = ToRegister(instr->divisor()); | 1060 const Register divisor = ToRegister(instr->divisor()); |
| 1062 Register result = ToRegister(instr->result()); | 1061 Register result = ToRegister(instr->result()); |
| 1063 | 1062 |
| 1064 DCHECK(!dividend.is(result)); | 1063 DCHECK(!dividend.is(result)); |
| 1065 DCHECK(!divisor.is(result)); | 1064 DCHECK(!divisor.is(result)); |
| 1066 | 1065 |
| 1067 // Check for x / 0. | 1066 // Check for x / 0. |
| 1068 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1067 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1069 __ Cmp32(divisor, Operand::Zero()); | 1068 __ Cmp32(divisor, Operand::Zero()); |
| 1070 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1069 DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero); |
| 1071 } | 1070 } |
| 1072 | 1071 |
| 1073 // Check for (0 / -x) that will produce negative zero. | 1072 // Check for (0 / -x) that will produce negative zero. |
| 1074 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1073 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1075 Label dividend_not_zero; | 1074 Label dividend_not_zero; |
| 1076 __ Cmp32(dividend, Operand::Zero()); | 1075 __ Cmp32(dividend, Operand::Zero()); |
| 1077 __ bne(÷nd_not_zero, Label::kNear); | 1076 __ bne(÷nd_not_zero, Label::kNear); |
| 1078 __ Cmp32(divisor, Operand::Zero()); | 1077 __ Cmp32(divisor, Operand::Zero()); |
| 1079 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1078 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 1080 __ bind(÷nd_not_zero); | 1079 __ bind(÷nd_not_zero); |
| 1081 } | 1080 } |
| 1082 | 1081 |
| 1083 // Check for (kMinInt / -1). | 1082 // Check for (kMinInt / -1). |
| 1084 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1083 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1085 Label dividend_not_min_int; | 1084 Label dividend_not_min_int; |
| 1086 __ Cmp32(dividend, Operand(kMinInt)); | 1085 __ Cmp32(dividend, Operand(kMinInt)); |
| 1087 __ bne(÷nd_not_min_int, Label::kNear); | 1086 __ bne(÷nd_not_min_int, Label::kNear); |
| 1088 __ Cmp32(divisor, Operand(-1)); | 1087 __ Cmp32(divisor, Operand(-1)); |
| 1089 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1088 DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow); |
| 1090 __ bind(÷nd_not_min_int); | 1089 __ bind(÷nd_not_min_int); |
| 1091 } | 1090 } |
| 1092 | 1091 |
| 1093 __ LoadRR(r0, dividend); | 1092 __ LoadRR(r0, dividend); |
| 1094 __ srda(r0, Operand(32)); | 1093 __ srda(r0, Operand(32)); |
| 1095 __ dr(r0, divisor); // R0:R1 = R1 / divisor - R0 remainder - R1 quotient | 1094 __ dr(r0, divisor); // R0:R1 = R1 / divisor - R0 remainder - R1 quotient |
| 1096 | 1095 |
| 1097 __ LoadAndTestP_ExtendSrc(result, r1); // Move quotient to result register | 1096 __ LoadAndTestP_ExtendSrc(result, r1); // Move quotient to result register |
| 1098 | 1097 |
| 1099 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1098 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1100 // Deoptimize if remainder is not 0. | 1099 // Deoptimize if remainder is not 0. |
| 1101 __ Cmp32(r0, Operand::Zero()); | 1100 __ Cmp32(r0, Operand::Zero()); |
| 1102 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1101 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision); |
| 1103 } | 1102 } |
| 1104 } | 1103 } |
| 1105 | 1104 |
| 1106 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1105 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
| 1107 HBinaryOperation* hdiv = instr->hydrogen(); | 1106 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1108 Register dividend = ToRegister(instr->dividend()); | 1107 Register dividend = ToRegister(instr->dividend()); |
| 1109 Register result = ToRegister(instr->result()); | 1108 Register result = ToRegister(instr->result()); |
| 1110 int32_t divisor = instr->divisor(); | 1109 int32_t divisor = instr->divisor(); |
| 1111 bool can_overflow = hdiv->CheckFlag(HValue::kLeftCanBeMinInt); | 1110 bool can_overflow = hdiv->CheckFlag(HValue::kLeftCanBeMinInt); |
| 1112 | 1111 |
| 1113 // If the divisor is positive, things are easy: There can be no deopts and we | 1112 // If the divisor is positive, things are easy: There can be no deopts and we |
| 1114 // can simply do an arithmetic right shift. | 1113 // can simply do an arithmetic right shift. |
| 1115 int32_t shift = WhichPowerOf2Abs(divisor); | 1114 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1116 if (divisor > 0) { | 1115 if (divisor > 0) { |
| 1117 if (shift || !result.is(dividend)) { | 1116 if (shift || !result.is(dividend)) { |
| 1118 __ ShiftRightArith(result, dividend, Operand(shift)); | 1117 __ ShiftRightArith(result, dividend, Operand(shift)); |
| 1119 #if V8_TARGET_ARCH_S390X | 1118 #if V8_TARGET_ARCH_S390X |
| 1120 __ lgfr(result, result); | 1119 __ lgfr(result, result); |
| 1121 #endif | 1120 #endif |
| 1122 } | 1121 } |
| 1123 return; | 1122 return; |
| 1124 } | 1123 } |
| 1125 | 1124 |
| 1126 // If the divisor is negative, we have to negate and handle edge cases. | 1125 // If the divisor is negative, we have to negate and handle edge cases. |
| 1127 #if V8_TARGET_ARCH_S390X | 1126 #if V8_TARGET_ARCH_S390X |
| 1128 if (divisor == -1 && can_overflow) { | 1127 if (divisor == -1 && can_overflow) { |
| 1129 __ Cmp32(dividend, Operand(0x80000000)); | 1128 __ Cmp32(dividend, Operand(0x80000000)); |
| 1130 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1129 DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow); |
| 1131 } | 1130 } |
| 1132 #endif | 1131 #endif |
| 1133 | 1132 |
| 1134 __ LoadComplementRR(result, dividend); | 1133 __ LoadComplementRR(result, dividend); |
| 1135 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1134 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1136 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0); | 1135 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, cr0); |
| 1137 } | 1136 } |
| 1138 | 1137 |
| 1139 // If the negation could not overflow, simply shifting is OK. | 1138 // If the negation could not overflow, simply shifting is OK. |
| 1140 #if !V8_TARGET_ARCH_S390X | 1139 #if !V8_TARGET_ARCH_S390X |
| 1141 if (!can_overflow) { | 1140 if (!can_overflow) { |
| 1142 #endif | 1141 #endif |
| 1143 if (shift) { | 1142 if (shift) { |
| 1144 __ ShiftRightArithP(result, result, Operand(shift)); | 1143 __ ShiftRightArithP(result, result, Operand(shift)); |
| 1145 } | 1144 } |
| 1146 return; | 1145 return; |
| 1147 #if !V8_TARGET_ARCH_S390X | 1146 #if !V8_TARGET_ARCH_S390X |
| 1148 } | 1147 } |
| 1149 | 1148 |
| 1150 // Dividing by -1 is basically negation, unless we overflow. | 1149 // Dividing by -1 is basically negation, unless we overflow. |
| 1151 if (divisor == -1) { | 1150 if (divisor == -1) { |
| 1152 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); | 1151 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow, cr0); |
| 1153 return; | 1152 return; |
| 1154 } | 1153 } |
| 1155 | 1154 |
| 1156 Label overflow_label, done; | 1155 Label overflow_label, done; |
| 1157 __ b(overflow, &overflow_label, Label::kNear); | 1156 __ b(overflow, &overflow_label, Label::kNear); |
| 1158 __ ShiftRightArith(result, result, Operand(shift)); | 1157 __ ShiftRightArith(result, result, Operand(shift)); |
| 1159 #if V8_TARGET_ARCH_S390X | 1158 #if V8_TARGET_ARCH_S390X |
| 1160 __ lgfr(result, result); | 1159 __ lgfr(result, result); |
| 1161 #endif | 1160 #endif |
| 1162 __ b(&done, Label::kNear); | 1161 __ b(&done, Label::kNear); |
| 1163 __ bind(&overflow_label); | 1162 __ bind(&overflow_label); |
| 1164 __ mov(result, Operand(kMinInt / divisor)); | 1163 __ mov(result, Operand(kMinInt / divisor)); |
| 1165 __ bind(&done); | 1164 __ bind(&done); |
| 1166 #endif | 1165 #endif |
| 1167 } | 1166 } |
| 1168 | 1167 |
| 1169 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1168 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1170 Register dividend = ToRegister(instr->dividend()); | 1169 Register dividend = ToRegister(instr->dividend()); |
| 1171 int32_t divisor = instr->divisor(); | 1170 int32_t divisor = instr->divisor(); |
| 1172 Register result = ToRegister(instr->result()); | 1171 Register result = ToRegister(instr->result()); |
| 1173 DCHECK(!dividend.is(result)); | 1172 DCHECK(!dividend.is(result)); |
| 1174 | 1173 |
| 1175 if (divisor == 0) { | 1174 if (divisor == 0) { |
| 1176 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 1175 DeoptimizeIf(al, instr, DeoptimizeReason::kDivisionByZero); |
| 1177 return; | 1176 return; |
| 1178 } | 1177 } |
| 1179 | 1178 |
| 1180 // Check for (0 / -x) that will produce negative zero. | 1179 // Check for (0 / -x) that will produce negative zero. |
| 1181 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1180 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
| 1182 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1183 __ Cmp32(dividend, Operand::Zero()); | 1182 __ Cmp32(dividend, Operand::Zero()); |
| 1184 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1183 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 1185 } | 1184 } |
| 1186 | 1185 |
| 1187 // Easy case: We need no dynamic check for the dividend and the flooring | 1186 // Easy case: We need no dynamic check for the dividend and the flooring |
| 1188 // division is the same as the truncating division. | 1187 // division is the same as the truncating division. |
| 1189 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1188 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1190 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1189 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
| 1191 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1190 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1192 if (divisor < 0) __ LoadComplementRR(result, result); | 1191 if (divisor < 0) __ LoadComplementRR(result, result); |
| 1193 return; | 1192 return; |
| 1194 } | 1193 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1217 const Register dividend = ToRegister(instr->dividend()); | 1216 const Register dividend = ToRegister(instr->dividend()); |
| 1218 const Register divisor = ToRegister(instr->divisor()); | 1217 const Register divisor = ToRegister(instr->divisor()); |
| 1219 Register result = ToRegister(instr->result()); | 1218 Register result = ToRegister(instr->result()); |
| 1220 | 1219 |
| 1221 DCHECK(!dividend.is(result)); | 1220 DCHECK(!dividend.is(result)); |
| 1222 DCHECK(!divisor.is(result)); | 1221 DCHECK(!divisor.is(result)); |
| 1223 | 1222 |
| 1224 // Check for x / 0. | 1223 // Check for x / 0. |
| 1225 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1224 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1226 __ Cmp32(divisor, Operand::Zero()); | 1225 __ Cmp32(divisor, Operand::Zero()); |
| 1227 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1226 DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero); |
| 1228 } | 1227 } |
| 1229 | 1228 |
| 1230 // Check for (0 / -x) that will produce negative zero. | 1229 // Check for (0 / -x) that will produce negative zero. |
| 1231 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1230 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1232 Label dividend_not_zero; | 1231 Label dividend_not_zero; |
| 1233 __ Cmp32(dividend, Operand::Zero()); | 1232 __ Cmp32(dividend, Operand::Zero()); |
| 1234 __ bne(÷nd_not_zero, Label::kNear); | 1233 __ bne(÷nd_not_zero, Label::kNear); |
| 1235 __ Cmp32(divisor, Operand::Zero()); | 1234 __ Cmp32(divisor, Operand::Zero()); |
| 1236 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1235 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 1237 __ bind(÷nd_not_zero); | 1236 __ bind(÷nd_not_zero); |
| 1238 } | 1237 } |
| 1239 | 1238 |
| 1240 // Check for (kMinInt / -1). | 1239 // Check for (kMinInt / -1). |
| 1241 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1240 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1242 Label no_overflow_possible; | 1241 Label no_overflow_possible; |
| 1243 __ Cmp32(dividend, Operand(kMinInt)); | 1242 __ Cmp32(dividend, Operand(kMinInt)); |
| 1244 __ bne(&no_overflow_possible, Label::kNear); | 1243 __ bne(&no_overflow_possible, Label::kNear); |
| 1245 __ Cmp32(divisor, Operand(-1)); | 1244 __ Cmp32(divisor, Operand(-1)); |
| 1246 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1245 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1247 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1246 DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow); |
| 1248 } else { | 1247 } else { |
| 1249 __ bne(&no_overflow_possible, Label::kNear); | 1248 __ bne(&no_overflow_possible, Label::kNear); |
| 1250 __ LoadRR(result, dividend); | 1249 __ LoadRR(result, dividend); |
| 1251 } | 1250 } |
| 1252 __ bind(&no_overflow_possible); | 1251 __ bind(&no_overflow_possible); |
| 1253 } | 1252 } |
| 1254 | 1253 |
| 1255 __ LoadRR(r0, dividend); | 1254 __ LoadRR(r0, dividend); |
| 1256 __ srda(r0, Operand(32)); | 1255 __ srda(r0, Operand(32)); |
| 1257 __ dr(r0, divisor); // R0:R1 = R1 / divisor - R0 remainder - R1 quotient | 1256 __ dr(r0, divisor); // R0:R1 = R1 / divisor - R0 remainder - R1 quotient |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1312 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1314 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1313 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1315 | 1314 |
| 1316 if (right_op->IsConstantOperand()) { | 1315 if (right_op->IsConstantOperand()) { |
| 1317 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1316 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1318 | 1317 |
| 1319 if (bailout_on_minus_zero && (constant < 0)) { | 1318 if (bailout_on_minus_zero && (constant < 0)) { |
| 1320 // The case of a null constant will be handled separately. | 1319 // The case of a null constant will be handled separately. |
| 1321 // If constant is negative and left is null, the result should be -0. | 1320 // If constant is negative and left is null, the result should be -0. |
| 1322 __ CmpP(left, Operand::Zero()); | 1321 __ CmpP(left, Operand::Zero()); |
| 1323 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1322 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 1324 } | 1323 } |
| 1325 | 1324 |
| 1326 switch (constant) { | 1325 switch (constant) { |
| 1327 case -1: | 1326 case -1: |
| 1328 if (can_overflow) { | 1327 if (can_overflow) { |
| 1329 #if V8_TARGET_ARCH_S390X | 1328 #if V8_TARGET_ARCH_S390X |
| 1330 if (instr->hydrogen()->representation().IsSmi()) { | 1329 if (instr->hydrogen()->representation().IsSmi()) { |
| 1331 #endif | 1330 #endif |
| 1332 __ LoadComplementRR(result, left); | 1331 __ LoadComplementRR(result, left); |
| 1333 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 1332 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow); |
| 1334 #if V8_TARGET_ARCH_S390X | 1333 #if V8_TARGET_ARCH_S390X |
| 1335 } else { | 1334 } else { |
| 1336 __ LoadComplementRR(result, left); | 1335 __ LoadComplementRR(result, left); |
| 1337 __ TestIfInt32(result, r0); | 1336 __ TestIfInt32(result, r0); |
| 1338 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1337 DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow); |
| 1339 } | 1338 } |
| 1340 #endif | 1339 #endif |
| 1341 } else { | 1340 } else { |
| 1342 __ LoadComplementRR(result, left); | 1341 __ LoadComplementRR(result, left); |
| 1343 } | 1342 } |
| 1344 break; | 1343 break; |
| 1345 case 0: | 1344 case 0: |
| 1346 if (bailout_on_minus_zero) { | 1345 if (bailout_on_minus_zero) { |
| 1347 // If left is strictly negative and the constant is null, the | 1346 // If left is strictly negative and the constant is null, the |
| 1348 // result is -0. Deoptimize if required, otherwise return 0. | 1347 // result is -0. Deoptimize if required, otherwise return 0. |
| 1349 #if V8_TARGET_ARCH_S390X | 1348 #if V8_TARGET_ARCH_S390X |
| 1350 if (instr->hydrogen()->representation().IsSmi()) { | 1349 if (instr->hydrogen()->representation().IsSmi()) { |
| 1351 #endif | 1350 #endif |
| 1352 __ Cmp32(left, Operand::Zero()); | 1351 __ Cmp32(left, Operand::Zero()); |
| 1353 #if V8_TARGET_ARCH_S390X | 1352 #if V8_TARGET_ARCH_S390X |
| 1354 } else { | 1353 } else { |
| 1355 __ Cmp32(left, Operand::Zero()); | 1354 __ Cmp32(left, Operand::Zero()); |
| 1356 } | 1355 } |
| 1357 #endif | 1356 #endif |
| 1358 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1357 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 1359 } | 1358 } |
| 1360 __ LoadImmP(result, Operand::Zero()); | 1359 __ LoadImmP(result, Operand::Zero()); |
| 1361 break; | 1360 break; |
| 1362 case 1: | 1361 case 1: |
| 1363 __ Move(result, left); | 1362 __ Move(result, left); |
| 1364 break; | 1363 break; |
| 1365 default: | 1364 default: |
| 1366 // Multiplying by powers of two and powers of two plus or minus | 1365 // Multiplying by powers of two and powers of two plus or minus |
| 1367 // one can be done faster with shifted operands. | 1366 // one can be done faster with shifted operands. |
| 1368 // For other constants we emit standard code. | 1367 // For other constants we emit standard code. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 // result = left * right. | 1401 // result = left * right. |
| 1403 if (instr->hydrogen()->representation().IsSmi()) { | 1402 if (instr->hydrogen()->representation().IsSmi()) { |
| 1404 __ SmiUntag(result, left); | 1403 __ SmiUntag(result, left); |
| 1405 __ SmiUntag(scratch, right); | 1404 __ SmiUntag(scratch, right); |
| 1406 __ msgr(result, scratch); | 1405 __ msgr(result, scratch); |
| 1407 } else { | 1406 } else { |
| 1408 __ LoadRR(result, left); | 1407 __ LoadRR(result, left); |
| 1409 __ msgr(result, right); | 1408 __ msgr(result, right); |
| 1410 } | 1409 } |
| 1411 __ TestIfInt32(result, r0); | 1410 __ TestIfInt32(result, r0); |
| 1412 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1411 DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow); |
| 1413 if (instr->hydrogen()->representation().IsSmi()) { | 1412 if (instr->hydrogen()->representation().IsSmi()) { |
| 1414 __ SmiTag(result); | 1413 __ SmiTag(result); |
| 1415 } | 1414 } |
| 1416 #else | 1415 #else |
| 1417 // r0:scratch = scratch * right | 1416 // r0:scratch = scratch * right |
| 1418 if (instr->hydrogen()->representation().IsSmi()) { | 1417 if (instr->hydrogen()->representation().IsSmi()) { |
| 1419 __ SmiUntag(scratch, left); | 1418 __ SmiUntag(scratch, left); |
| 1420 __ mr_z(r0, right); | 1419 __ mr_z(r0, right); |
| 1421 __ LoadRR(result, scratch); | 1420 __ LoadRR(result, scratch); |
| 1422 } else { | 1421 } else { |
| 1423 // r0:scratch = scratch * right | 1422 // r0:scratch = scratch * right |
| 1424 __ LoadRR(scratch, left); | 1423 __ LoadRR(scratch, left); |
| 1425 __ mr_z(r0, right); | 1424 __ mr_z(r0, right); |
| 1426 __ LoadRR(result, scratch); | 1425 __ LoadRR(result, scratch); |
| 1427 } | 1426 } |
| 1428 __ TestIfInt32(r0, result, scratch); | 1427 __ TestIfInt32(r0, result, scratch); |
| 1429 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1428 DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow); |
| 1430 #endif | 1429 #endif |
| 1431 } else { | 1430 } else { |
| 1432 if (instr->hydrogen()->representation().IsSmi()) { | 1431 if (instr->hydrogen()->representation().IsSmi()) { |
| 1433 __ SmiUntag(result, left); | 1432 __ SmiUntag(result, left); |
| 1434 __ Mul(result, result, right); | 1433 __ Mul(result, result, right); |
| 1435 } else { | 1434 } else { |
| 1436 __ Mul(result, left, right); | 1435 __ Mul(result, left, right); |
| 1437 } | 1436 } |
| 1438 } | 1437 } |
| 1439 | 1438 |
| 1440 if (bailout_on_minus_zero) { | 1439 if (bailout_on_minus_zero) { |
| 1441 Label done; | 1440 Label done; |
| 1442 #if V8_TARGET_ARCH_S390X | 1441 #if V8_TARGET_ARCH_S390X |
| 1443 if (instr->hydrogen()->representation().IsSmi()) { | 1442 if (instr->hydrogen()->representation().IsSmi()) { |
| 1444 #endif | 1443 #endif |
| 1445 __ XorP(r0, left, right); | 1444 __ XorP(r0, left, right); |
| 1446 __ LoadAndTestRR(r0, r0); | 1445 __ LoadAndTestRR(r0, r0); |
| 1447 __ bge(&done, Label::kNear); | 1446 __ bge(&done, Label::kNear); |
| 1448 #if V8_TARGET_ARCH_S390X | 1447 #if V8_TARGET_ARCH_S390X |
| 1449 } else { | 1448 } else { |
| 1450 __ XorP(r0, left, right); | 1449 __ XorP(r0, left, right); |
| 1451 __ Cmp32(r0, Operand::Zero()); | 1450 __ Cmp32(r0, Operand::Zero()); |
| 1452 __ bge(&done, Label::kNear); | 1451 __ bge(&done, Label::kNear); |
| 1453 } | 1452 } |
| 1454 #endif | 1453 #endif |
| 1455 // Bail out if the result is minus zero. | 1454 // Bail out if the result is minus zero. |
| 1456 __ CmpP(result, Operand::Zero()); | 1455 __ CmpP(result, Operand::Zero()); |
| 1457 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1456 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 1458 __ bind(&done); | 1457 __ bind(&done); |
| 1459 } | 1458 } |
| 1460 } | 1459 } |
| 1461 } | 1460 } |
| 1462 | 1461 |
| 1463 void LCodeGen::DoBitI(LBitI* instr) { | 1462 void LCodeGen::DoBitI(LBitI* instr) { |
| 1464 LOperand* left_op = instr->left(); | 1463 LOperand* left_op = instr->left(); |
| 1465 LOperand* right_op = instr->right(); | 1464 LOperand* right_op = instr->right(); |
| 1466 DCHECK(left_op->IsRegister()); | 1465 DCHECK(left_op->IsRegister()); |
| 1467 Register left = ToRegister(left_op); | 1466 Register left = ToRegister(left_op); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 __ ShiftRight(result, left, scratch); | 1547 __ ShiftRight(result, left, scratch); |
| 1549 #if V8_TARGET_ARCH_S390X | 1548 #if V8_TARGET_ARCH_S390X |
| 1550 __ lgfr(result, result); | 1549 __ lgfr(result, result); |
| 1551 #endif | 1550 #endif |
| 1552 if (instr->can_deopt()) { | 1551 if (instr->can_deopt()) { |
| 1553 #if V8_TARGET_ARCH_S390X | 1552 #if V8_TARGET_ARCH_S390X |
| 1554 __ ltgfr(result, result /*, SetRC*/); | 1553 __ ltgfr(result, result /*, SetRC*/); |
| 1555 #else | 1554 #else |
| 1556 __ ltr(result, result); // Set the <,==,> condition | 1555 __ ltr(result, result); // Set the <,==,> condition |
| 1557 #endif | 1556 #endif |
| 1558 DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, cr0); | 1557 DeoptimizeIf(lt, instr, DeoptimizeReason::kNegativeValue, cr0); |
| 1559 } | 1558 } |
| 1560 break; | 1559 break; |
| 1561 case Token::SHL: | 1560 case Token::SHL: |
| 1562 __ ShiftLeft(result, left, scratch); | 1561 __ ShiftLeft(result, left, scratch); |
| 1563 #if V8_TARGET_ARCH_S390X | 1562 #if V8_TARGET_ARCH_S390X |
| 1564 __ lgfr(result, result); | 1563 __ lgfr(result, result); |
| 1565 #endif | 1564 #endif |
| 1566 break; | 1565 break; |
| 1567 default: | 1566 default: |
| 1568 UNREACHABLE(); | 1567 UNREACHABLE(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1595 break; | 1594 break; |
| 1596 case Token::SHR: | 1595 case Token::SHR: |
| 1597 if (shift_count != 0) { | 1596 if (shift_count != 0) { |
| 1598 __ ShiftRight(result, left, Operand(shift_count)); | 1597 __ ShiftRight(result, left, Operand(shift_count)); |
| 1599 #if V8_TARGET_ARCH_S390X | 1598 #if V8_TARGET_ARCH_S390X |
| 1600 __ lgfr(result, result); | 1599 __ lgfr(result, result); |
| 1601 #endif | 1600 #endif |
| 1602 } else { | 1601 } else { |
| 1603 if (instr->can_deopt()) { | 1602 if (instr->can_deopt()) { |
| 1604 __ Cmp32(left, Operand::Zero()); | 1603 __ Cmp32(left, Operand::Zero()); |
| 1605 DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue); | 1604 DeoptimizeIf(lt, instr, DeoptimizeReason::kNegativeValue); |
| 1606 } | 1605 } |
| 1607 __ Move(result, left); | 1606 __ Move(result, left); |
| 1608 } | 1607 } |
| 1609 break; | 1608 break; |
| 1610 case Token::SHL: | 1609 case Token::SHL: |
| 1611 if (shift_count != 0) { | 1610 if (shift_count != 0) { |
| 1612 #if V8_TARGET_ARCH_S390X | 1611 #if V8_TARGET_ARCH_S390X |
| 1613 if (instr->hydrogen_value()->representation().IsSmi()) { | 1612 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 1614 __ ShiftLeftP(result, left, Operand(shift_count)); | 1613 __ ShiftLeftP(result, left, Operand(shift_count)); |
| 1615 #else | 1614 #else |
| 1616 if (instr->hydrogen_value()->representation().IsSmi() && | 1615 if (instr->hydrogen_value()->representation().IsSmi() && |
| 1617 instr->can_deopt()) { | 1616 instr->can_deopt()) { |
| 1618 if (shift_count != 1) { | 1617 if (shift_count != 1) { |
| 1619 __ ShiftLeft(result, left, Operand(shift_count - 1)); | 1618 __ ShiftLeft(result, left, Operand(shift_count - 1)); |
| 1620 #if V8_TARGET_ARCH_S390X | 1619 #if V8_TARGET_ARCH_S390X |
| 1621 __ lgfr(result, result); | 1620 __ lgfr(result, result); |
| 1622 #endif | 1621 #endif |
| 1623 __ SmiTagCheckOverflow(result, result, scratch); | 1622 __ SmiTagCheckOverflow(result, result, scratch); |
| 1624 } else { | 1623 } else { |
| 1625 __ SmiTagCheckOverflow(result, left, scratch); | 1624 __ SmiTagCheckOverflow(result, left, scratch); |
| 1626 } | 1625 } |
| 1627 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); | 1626 DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, cr0); |
| 1628 #endif | 1627 #endif |
| 1629 } else { | 1628 } else { |
| 1630 __ ShiftLeft(result, left, Operand(shift_count)); | 1629 __ ShiftLeft(result, left, Operand(shift_count)); |
| 1631 #if V8_TARGET_ARCH_S390X | 1630 #if V8_TARGET_ARCH_S390X |
| 1632 __ lgfr(result, result); | 1631 __ lgfr(result, result); |
| 1633 #endif | 1632 #endif |
| 1634 } | 1633 } |
| 1635 } else { | 1634 } else { |
| 1636 __ Move(result, left); | 1635 __ Move(result, left); |
| 1637 } | 1636 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 __ SubP_ExtendSrc(ToRegister(result), Upper32Mem); | 1692 __ SubP_ExtendSrc(ToRegister(result), Upper32Mem); |
| 1694 } | 1693 } |
| 1695 } | 1694 } |
| 1696 } | 1695 } |
| 1697 | 1696 |
| 1698 #if V8_TARGET_ARCH_S390X | 1697 #if V8_TARGET_ARCH_S390X |
| 1699 if (isInteger && checkOverflow) | 1698 if (isInteger && checkOverflow) |
| 1700 __ lgfr(ToRegister(result), ToRegister(result)); | 1699 __ lgfr(ToRegister(result), ToRegister(result)); |
| 1701 #endif | 1700 #endif |
| 1702 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1701 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1703 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 1702 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow); |
| 1704 } | 1703 } |
| 1705 } | 1704 } |
| 1706 | 1705 |
| 1707 void LCodeGen::DoRSubI(LRSubI* instr) { | 1706 void LCodeGen::DoRSubI(LRSubI* instr) { |
| 1708 LOperand* left = instr->left(); | 1707 LOperand* left = instr->left(); |
| 1709 LOperand* right = instr->right(); | 1708 LOperand* right = instr->right(); |
| 1710 LOperand* result = instr->result(); | 1709 LOperand* result = instr->result(); |
| 1711 | 1710 |
| 1712 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && | 1711 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && |
| 1713 right->IsConstantOperand()); | 1712 right->IsConstantOperand()); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1881 } | 1880 } |
| 1882 } | 1881 } |
| 1883 } | 1882 } |
| 1884 | 1883 |
| 1885 #if V8_TARGET_ARCH_S390X | 1884 #if V8_TARGET_ARCH_S390X |
| 1886 if (isInteger && checkOverflow) | 1885 if (isInteger && checkOverflow) |
| 1887 __ lgfr(ToRegister(result), ToRegister(result)); | 1886 __ lgfr(ToRegister(result), ToRegister(result)); |
| 1888 #endif | 1887 #endif |
| 1889 // Doptimize on overflow | 1888 // Doptimize on overflow |
| 1890 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1889 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1891 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 1890 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow); |
| 1892 } | 1891 } |
| 1893 } | 1892 } |
| 1894 | 1893 |
| 1895 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1894 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 1896 LOperand* left = instr->left(); | 1895 LOperand* left = instr->left(); |
| 1897 LOperand* right = instr->right(); | 1896 LOperand* right = instr->right(); |
| 1898 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1897 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 1899 Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge; | 1898 Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge; |
| 1900 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 1899 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
| 1901 Register left_reg = ToRegister(left); | 1900 Register left_reg = ToRegister(left); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2124 } | 2123 } |
| 2125 | 2124 |
| 2126 if (expected.Contains(ToBooleanICStub::SMI)) { | 2125 if (expected.Contains(ToBooleanICStub::SMI)) { |
| 2127 // Smis: 0 -> false, all other -> true. | 2126 // Smis: 0 -> false, all other -> true. |
| 2128 __ CmpP(reg, Operand::Zero()); | 2127 __ CmpP(reg, Operand::Zero()); |
| 2129 __ beq(instr->FalseLabel(chunk_)); | 2128 __ beq(instr->FalseLabel(chunk_)); |
| 2130 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2129 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2131 } else if (expected.NeedsMap()) { | 2130 } else if (expected.NeedsMap()) { |
| 2132 // If we need a map later and have a Smi -> deopt. | 2131 // If we need a map later and have a Smi -> deopt. |
| 2133 __ TestIfSmi(reg); | 2132 __ TestIfSmi(reg); |
| 2134 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0); | 2133 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
| 2135 } | 2134 } |
| 2136 | 2135 |
| 2137 const Register map = scratch0(); | 2136 const Register map = scratch0(); |
| 2138 if (expected.NeedsMap()) { | 2137 if (expected.NeedsMap()) { |
| 2139 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2138 __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2140 | 2139 |
| 2141 if (expected.CanBeUndetectable()) { | 2140 if (expected.CanBeUndetectable()) { |
| 2142 // Undetectable -> false. | 2141 // Undetectable -> false. |
| 2143 __ tm(FieldMemOperand(map, Map::kBitFieldOffset), | 2142 __ tm(FieldMemOperand(map, Map::kBitFieldOffset), |
| 2144 Operand(1 << Map::kIsUndetectable)); | 2143 Operand(1 << Map::kIsUndetectable)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2188 __ cdbr(dbl_scratch, kDoubleRegZero); | 2187 __ cdbr(dbl_scratch, kDoubleRegZero); |
| 2189 __ bunordered(instr->FalseLabel(chunk_)); // NaN -> false. | 2188 __ bunordered(instr->FalseLabel(chunk_)); // NaN -> false. |
| 2190 __ beq(instr->FalseLabel(chunk_)); // +0, -0 -> false. | 2189 __ beq(instr->FalseLabel(chunk_)); // +0, -0 -> false. |
| 2191 __ b(instr->TrueLabel(chunk_)); | 2190 __ b(instr->TrueLabel(chunk_)); |
| 2192 __ bind(¬_heap_number); | 2191 __ bind(¬_heap_number); |
| 2193 } | 2192 } |
| 2194 | 2193 |
| 2195 if (!expected.IsGeneric()) { | 2194 if (!expected.IsGeneric()) { |
| 2196 // We've seen something for the first time -> deopt. | 2195 // We've seen something for the first time -> deopt. |
| 2197 // This can only happen if we are not generic already. | 2196 // This can only happen if we are not generic already. |
| 2198 DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject); | 2197 DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject); |
| 2199 } | 2198 } |
| 2200 } | 2199 } |
| 2201 } | 2200 } |
| 2202 } | 2201 } |
| 2203 | 2202 |
| 2204 void LCodeGen::EmitGoto(int block) { | 2203 void LCodeGen::EmitGoto(int block) { |
| 2205 if (!IsNextEmittedBlock(block)) { | 2204 if (!IsNextEmittedBlock(block)) { |
| 2206 __ b(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2205 __ b(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2207 } | 2206 } |
| 2208 } | 2207 } |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2551 } | 2550 } |
| 2552 // Loop through the {object}s prototype chain looking for the {prototype}. | 2551 // Loop through the {object}s prototype chain looking for the {prototype}. |
| 2553 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | 2552 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2554 Label loop; | 2553 Label loop; |
| 2555 __ bind(&loop); | 2554 __ bind(&loop); |
| 2556 | 2555 |
| 2557 // Deoptimize if the object needs to be access checked. | 2556 // Deoptimize if the object needs to be access checked. |
| 2558 __ LoadlB(object_instance_type, | 2557 __ LoadlB(object_instance_type, |
| 2559 FieldMemOperand(object_map, Map::kBitFieldOffset)); | 2558 FieldMemOperand(object_map, Map::kBitFieldOffset)); |
| 2560 __ TestBit(object_instance_type, Map::kIsAccessCheckNeeded, r0); | 2559 __ TestBit(object_instance_type, Map::kIsAccessCheckNeeded, r0); |
| 2561 DeoptimizeIf(ne, instr, Deoptimizer::kAccessCheck, cr0); | 2560 DeoptimizeIf(ne, instr, DeoptimizeReason::kAccessCheck, cr0); |
| 2562 // Deoptimize for proxies. | 2561 // Deoptimize for proxies. |
| 2563 __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE); | 2562 __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE); |
| 2564 DeoptimizeIf(eq, instr, Deoptimizer::kProxy); | 2563 DeoptimizeIf(eq, instr, DeoptimizeReason::kProxy); |
| 2565 __ LoadP(object_prototype, | 2564 __ LoadP(object_prototype, |
| 2566 FieldMemOperand(object_map, Map::kPrototypeOffset)); | 2565 FieldMemOperand(object_map, Map::kPrototypeOffset)); |
| 2567 __ CompareRoot(object_prototype, Heap::kNullValueRootIndex); | 2566 __ CompareRoot(object_prototype, Heap::kNullValueRootIndex); |
| 2568 EmitFalseBranch(instr, eq); | 2567 EmitFalseBranch(instr, eq); |
| 2569 __ CmpP(object_prototype, prototype); | 2568 __ CmpP(object_prototype, prototype); |
| 2570 EmitTrueBranch(instr, eq); | 2569 EmitTrueBranch(instr, eq); |
| 2571 __ LoadP(object_map, | 2570 __ LoadP(object_map, |
| 2572 FieldMemOperand(object_prototype, HeapObject::kMapOffset)); | 2571 FieldMemOperand(object_prototype, HeapObject::kMapOffset)); |
| 2573 __ b(&loop); | 2572 __ b(&loop); |
| 2574 } | 2573 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2674 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2676 } | 2675 } |
| 2677 | 2676 |
| 2678 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2677 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 2679 Register context = ToRegister(instr->context()); | 2678 Register context = ToRegister(instr->context()); |
| 2680 Register result = ToRegister(instr->result()); | 2679 Register result = ToRegister(instr->result()); |
| 2681 __ LoadP(result, ContextMemOperand(context, instr->slot_index())); | 2680 __ LoadP(result, ContextMemOperand(context, instr->slot_index())); |
| 2682 if (instr->hydrogen()->RequiresHoleCheck()) { | 2681 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2683 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2682 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2684 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2683 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2685 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 2684 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole); |
| 2686 } else { | 2685 } else { |
| 2687 Label skip; | 2686 Label skip; |
| 2688 __ bne(&skip, Label::kNear); | 2687 __ bne(&skip, Label::kNear); |
| 2689 __ mov(result, Operand(factory()->undefined_value())); | 2688 __ mov(result, Operand(factory()->undefined_value())); |
| 2690 __ bind(&skip); | 2689 __ bind(&skip); |
| 2691 } | 2690 } |
| 2692 } | 2691 } |
| 2693 } | 2692 } |
| 2694 | 2693 |
| 2695 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2694 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 2696 Register context = ToRegister(instr->context()); | 2695 Register context = ToRegister(instr->context()); |
| 2697 Register value = ToRegister(instr->value()); | 2696 Register value = ToRegister(instr->value()); |
| 2698 Register scratch = scratch0(); | 2697 Register scratch = scratch0(); |
| 2699 MemOperand target = ContextMemOperand(context, instr->slot_index()); | 2698 MemOperand target = ContextMemOperand(context, instr->slot_index()); |
| 2700 | 2699 |
| 2701 Label skip_assignment; | 2700 Label skip_assignment; |
| 2702 | 2701 |
| 2703 if (instr->hydrogen()->RequiresHoleCheck()) { | 2702 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2704 __ LoadP(scratch, target); | 2703 __ LoadP(scratch, target); |
| 2705 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); | 2704 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 2706 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2705 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2707 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 2706 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole); |
| 2708 } else { | 2707 } else { |
| 2709 __ bne(&skip_assignment); | 2708 __ bne(&skip_assignment); |
| 2710 } | 2709 } |
| 2711 } | 2710 } |
| 2712 | 2711 |
| 2713 __ StoreP(value, target); | 2712 __ StoreP(value, target); |
| 2714 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2713 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2715 SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject() | 2714 SmiCheck check_needed = instr->hydrogen()->value()->type().IsHeapObject() |
| 2716 ? OMIT_SMI_CHECK | 2715 ? OMIT_SMI_CHECK |
| 2717 : INLINE_SMI_CHECK; | 2716 : INLINE_SMI_CHECK; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2780 Register scratch = scratch0(); | 2779 Register scratch = scratch0(); |
| 2781 Register function = ToRegister(instr->function()); | 2780 Register function = ToRegister(instr->function()); |
| 2782 Register result = ToRegister(instr->result()); | 2781 Register result = ToRegister(instr->result()); |
| 2783 | 2782 |
| 2784 // Get the prototype or initial map from the function. | 2783 // Get the prototype or initial map from the function. |
| 2785 __ LoadP(result, | 2784 __ LoadP(result, |
| 2786 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2785 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2787 | 2786 |
| 2788 // Check that the function has a prototype or an initial map. | 2787 // Check that the function has a prototype or an initial map. |
| 2789 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2788 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2790 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 2789 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole); |
| 2791 | 2790 |
| 2792 // If the function does not have an initial map, we're done. | 2791 // If the function does not have an initial map, we're done. |
| 2793 Label done; | 2792 Label done; |
| 2794 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); | 2793 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); |
| 2795 __ bne(&done, Label::kNear); | 2794 __ bne(&done, Label::kNear); |
| 2796 | 2795 |
| 2797 // Get the prototype from the initial map. | 2796 // Get the prototype from the initial map. |
| 2798 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 2797 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 2799 | 2798 |
| 2800 // All done. | 2799 // All done. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2913 case UINT16_ELEMENTS: | 2912 case UINT16_ELEMENTS: |
| 2914 __ LoadLogicalHalfWordP(result, mem_operand); | 2913 __ LoadLogicalHalfWordP(result, mem_operand); |
| 2915 break; | 2914 break; |
| 2916 case INT32_ELEMENTS: | 2915 case INT32_ELEMENTS: |
| 2917 __ LoadW(result, mem_operand, r0); | 2916 __ LoadW(result, mem_operand, r0); |
| 2918 break; | 2917 break; |
| 2919 case UINT32_ELEMENTS: | 2918 case UINT32_ELEMENTS: |
| 2920 __ LoadlW(result, mem_operand, r0); | 2919 __ LoadlW(result, mem_operand, r0); |
| 2921 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 2920 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 2922 __ CmpLogical32(result, Operand(0x80000000)); | 2921 __ CmpLogical32(result, Operand(0x80000000)); |
| 2923 DeoptimizeIf(ge, instr, Deoptimizer::kNegativeValue); | 2922 DeoptimizeIf(ge, instr, DeoptimizeReason::kNegativeValue); |
| 2924 } | 2923 } |
| 2925 break; | 2924 break; |
| 2926 case FLOAT32_ELEMENTS: | 2925 case FLOAT32_ELEMENTS: |
| 2927 case FLOAT64_ELEMENTS: | 2926 case FLOAT64_ELEMENTS: |
| 2928 case FAST_HOLEY_DOUBLE_ELEMENTS: | 2927 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 2929 case FAST_HOLEY_ELEMENTS: | 2928 case FAST_HOLEY_ELEMENTS: |
| 2930 case FAST_HOLEY_SMI_ELEMENTS: | 2929 case FAST_HOLEY_SMI_ELEMENTS: |
| 2931 case FAST_DOUBLE_ELEMENTS: | 2930 case FAST_DOUBLE_ELEMENTS: |
| 2932 case FAST_ELEMENTS: | 2931 case FAST_ELEMENTS: |
| 2933 case FAST_SMI_ELEMENTS: | 2932 case FAST_SMI_ELEMENTS: |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2992 | 2991 |
| 2993 if (instr->hydrogen()->RequiresHoleCheck()) { | 2992 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2994 if (!use_scratch) { | 2993 if (!use_scratch) { |
| 2995 __ LoadlW(r0, | 2994 __ LoadlW(r0, |
| 2996 MemOperand(elements, base_offset + Register::kExponentOffset)); | 2995 MemOperand(elements, base_offset + Register::kExponentOffset)); |
| 2997 } else { | 2996 } else { |
| 2998 __ LoadlW(r0, MemOperand(scratch, elements, | 2997 __ LoadlW(r0, MemOperand(scratch, elements, |
| 2999 base_offset + Register::kExponentOffset)); | 2998 base_offset + Register::kExponentOffset)); |
| 3000 } | 2999 } |
| 3001 __ Cmp32(r0, Operand(kHoleNanUpper32)); | 3000 __ Cmp32(r0, Operand(kHoleNanUpper32)); |
| 3002 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3001 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole); |
| 3003 } | 3002 } |
| 3004 } | 3003 } |
| 3005 | 3004 |
| 3006 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3005 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3007 HLoadKeyed* hinstr = instr->hydrogen(); | 3006 HLoadKeyed* hinstr = instr->hydrogen(); |
| 3008 Register elements = ToRegister(instr->elements()); | 3007 Register elements = ToRegister(instr->elements()); |
| 3009 Register result = ToRegister(instr->result()); | 3008 Register result = ToRegister(instr->result()); |
| 3010 Register scratch = scratch0(); | 3009 Register scratch = scratch0(); |
| 3011 int offset = instr->base_offset(); | 3010 int offset = instr->base_offset(); |
| 3012 | 3011 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3044 r1); | 3043 r1); |
| 3045 } else { | 3044 } else { |
| 3046 __ LoadRepresentation(result, MemOperand(scratch, elements, offset), | 3045 __ LoadRepresentation(result, MemOperand(scratch, elements, offset), |
| 3047 representation, r1); | 3046 representation, r1); |
| 3048 } | 3047 } |
| 3049 | 3048 |
| 3050 // Check for the hole value. | 3049 // Check for the hole value. |
| 3051 if (requires_hole_check) { | 3050 if (requires_hole_check) { |
| 3052 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3051 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
| 3053 __ TestIfSmi(result); | 3052 __ TestIfSmi(result); |
| 3054 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0); | 3053 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, cr0); |
| 3055 } else { | 3054 } else { |
| 3056 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 3055 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 3057 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3056 DeoptimizeIf(eq, instr, DeoptimizeReason::kHole); |
| 3058 } | 3057 } |
| 3059 } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) { | 3058 } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) { |
| 3060 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); | 3059 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); |
| 3061 Label done; | 3060 Label done; |
| 3062 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 3061 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 3063 __ CmpP(result, scratch); | 3062 __ CmpP(result, scratch); |
| 3064 __ bne(&done); | 3063 __ bne(&done); |
| 3065 if (info()->IsStub()) { | 3064 if (info()->IsStub()) { |
| 3066 // A stub can safely convert the hole to undefined only if the array | 3065 // A stub can safely convert the hole to undefined only if the array |
| 3067 // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise | 3066 // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise |
| 3068 // it needs to bail out. | 3067 // it needs to bail out. |
| 3069 __ LoadRoot(result, Heap::kArrayProtectorRootIndex); | 3068 __ LoadRoot(result, Heap::kArrayProtectorRootIndex); |
| 3070 __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset)); | 3069 __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset)); |
| 3071 __ CmpSmiLiteral(result, Smi::FromInt(Isolate::kArrayProtectorValid), r0); | 3070 __ CmpSmiLiteral(result, Smi::FromInt(Isolate::kArrayProtectorValid), r0); |
| 3072 DeoptimizeIf(ne, instr, Deoptimizer::kHole); | 3071 DeoptimizeIf(ne, instr, DeoptimizeReason::kHole); |
| 3073 } | 3072 } |
| 3074 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 3073 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 3075 __ bind(&done); | 3074 __ bind(&done); |
| 3076 } | 3075 } |
| 3077 } | 3076 } |
| 3078 | 3077 |
| 3079 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3078 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 3080 if (instr->is_fixed_typed_array()) { | 3079 if (instr->is_fixed_typed_array()) { |
| 3081 DoLoadKeyedExternalArray(instr); | 3080 DoLoadKeyedExternalArray(instr); |
| 3082 } else if (instr->hydrogen()->representation().IsDouble()) { | 3081 } else if (instr->hydrogen()->representation().IsDouble()) { |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3206 } | 3205 } |
| 3207 | 3206 |
| 3208 // Normal function. Replace undefined or null with global receiver. | 3207 // Normal function. Replace undefined or null with global receiver. |
| 3209 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 3208 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 3210 __ beq(&global_object, Label::kNear); | 3209 __ beq(&global_object, Label::kNear); |
| 3211 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 3210 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
| 3212 __ beq(&global_object, Label::kNear); | 3211 __ beq(&global_object, Label::kNear); |
| 3213 | 3212 |
| 3214 // Deoptimize if the receiver is not a JS object. | 3213 // Deoptimize if the receiver is not a JS object. |
| 3215 __ TestIfSmi(receiver); | 3214 __ TestIfSmi(receiver); |
| 3216 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0); | 3215 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
| 3217 __ CompareObjectType(receiver, scratch, scratch, FIRST_JS_RECEIVER_TYPE); | 3216 __ CompareObjectType(receiver, scratch, scratch, FIRST_JS_RECEIVER_TYPE); |
| 3218 DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject); | 3217 DeoptimizeIf(lt, instr, DeoptimizeReason::kNotAJavaScriptObject); |
| 3219 | 3218 |
| 3220 __ b(&result_in_receiver, Label::kNear); | 3219 __ b(&result_in_receiver, Label::kNear); |
| 3221 __ bind(&global_object); | 3220 __ bind(&global_object); |
| 3222 __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3221 __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3223 __ LoadP(result, ContextMemOperand(result, Context::NATIVE_CONTEXT_INDEX)); | 3222 __ LoadP(result, ContextMemOperand(result, Context::NATIVE_CONTEXT_INDEX)); |
| 3224 __ LoadP(result, ContextMemOperand(result, Context::GLOBAL_PROXY_INDEX)); | 3223 __ LoadP(result, ContextMemOperand(result, Context::GLOBAL_PROXY_INDEX)); |
| 3225 | 3224 |
| 3226 if (result.is(receiver)) { | 3225 if (result.is(receiver)) { |
| 3227 __ bind(&result_in_receiver); | 3226 __ bind(&result_in_receiver); |
| 3228 } else { | 3227 } else { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3241 Register elements = ToRegister(instr->elements()); | 3240 Register elements = ToRegister(instr->elements()); |
| 3242 Register scratch = scratch0(); | 3241 Register scratch = scratch0(); |
| 3243 DCHECK(receiver.is(r2)); // Used for parameter count. | 3242 DCHECK(receiver.is(r2)); // Used for parameter count. |
| 3244 DCHECK(function.is(r3)); // Required by InvokeFunction. | 3243 DCHECK(function.is(r3)); // Required by InvokeFunction. |
| 3245 DCHECK(ToRegister(instr->result()).is(r2)); | 3244 DCHECK(ToRegister(instr->result()).is(r2)); |
| 3246 | 3245 |
| 3247 // Copy the arguments to this function possibly from the | 3246 // Copy the arguments to this function possibly from the |
| 3248 // adaptor frame below it. | 3247 // adaptor frame below it. |
| 3249 const uint32_t kArgumentsLimit = 1 * KB; | 3248 const uint32_t kArgumentsLimit = 1 * KB; |
| 3250 __ CmpLogicalP(length, Operand(kArgumentsLimit)); | 3249 __ CmpLogicalP(length, Operand(kArgumentsLimit)); |
| 3251 DeoptimizeIf(gt, instr, Deoptimizer::kTooManyArguments); | 3250 DeoptimizeIf(gt, instr, DeoptimizeReason::kTooManyArguments); |
| 3252 | 3251 |
| 3253 // Push the receiver and use the register to keep the original | 3252 // Push the receiver and use the register to keep the original |
| 3254 // number of arguments. | 3253 // number of arguments. |
| 3255 __ push(receiver); | 3254 __ push(receiver); |
| 3256 __ LoadRR(receiver, length); | 3255 __ LoadRR(receiver, length); |
| 3257 // The arguments are at a one pointer size offset from elements. | 3256 // The arguments are at a one pointer size offset from elements. |
| 3258 __ AddP(elements, Operand(1 * kPointerSize)); | 3257 __ AddP(elements, Operand(1 * kPointerSize)); |
| 3259 | 3258 |
| 3260 // Loop through the arguments pushing them onto the execution | 3259 // Loop through the arguments pushing them onto the execution |
| 3261 // stack. | 3260 // stack. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3386 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3385 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3387 DCHECK(instr->context() != NULL); | 3386 DCHECK(instr->context() != NULL); |
| 3388 DCHECK(ToRegister(instr->context()).is(cp)); | 3387 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3389 Register input = ToRegister(instr->value()); | 3388 Register input = ToRegister(instr->value()); |
| 3390 Register result = ToRegister(instr->result()); | 3389 Register result = ToRegister(instr->result()); |
| 3391 Register scratch = scratch0(); | 3390 Register scratch = scratch0(); |
| 3392 | 3391 |
| 3393 // Deoptimize if not a heap number. | 3392 // Deoptimize if not a heap number. |
| 3394 __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3393 __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3395 __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); | 3394 __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 3396 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 3395 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber); |
| 3397 | 3396 |
| 3398 Label done; | 3397 Label done; |
| 3399 Register exponent = scratch0(); | 3398 Register exponent = scratch0(); |
| 3400 scratch = no_reg; | 3399 scratch = no_reg; |
| 3401 __ LoadlW(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3400 __ LoadlW(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3402 // Check the sign of the argument. If the argument is positive, just | 3401 // Check the sign of the argument. If the argument is positive, just |
| 3403 // return it. | 3402 // return it. |
| 3404 __ Cmp32(exponent, Operand::Zero()); | 3403 __ Cmp32(exponent, Operand::Zero()); |
| 3405 // Move the input to the result if necessary. | 3404 // Move the input to the result if necessary. |
| 3406 __ Move(result, input); | 3405 __ Move(result, input); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3454 | 3453 |
| 3455 void LCodeGen::EmitMathAbs(LMathAbs* instr) { | 3454 void LCodeGen::EmitMathAbs(LMathAbs* instr) { |
| 3456 Register input = ToRegister(instr->value()); | 3455 Register input = ToRegister(instr->value()); |
| 3457 Register result = ToRegister(instr->result()); | 3456 Register result = ToRegister(instr->result()); |
| 3458 Label done; | 3457 Label done; |
| 3459 __ CmpP(input, Operand::Zero()); | 3458 __ CmpP(input, Operand::Zero()); |
| 3460 __ Move(result, input); | 3459 __ Move(result, input); |
| 3461 __ bge(&done, Label::kNear); | 3460 __ bge(&done, Label::kNear); |
| 3462 __ LoadComplementRR(result, result); | 3461 __ LoadComplementRR(result, result); |
| 3463 // Deoptimize on overflow. | 3462 // Deoptimize on overflow. |
| 3464 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); | 3463 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow, cr0); |
| 3465 __ bind(&done); | 3464 __ bind(&done); |
| 3466 } | 3465 } |
| 3467 | 3466 |
| 3468 #if V8_TARGET_ARCH_S390X | 3467 #if V8_TARGET_ARCH_S390X |
| 3469 void LCodeGen::EmitInteger32MathAbs(LMathAbs* instr) { | 3468 void LCodeGen::EmitInteger32MathAbs(LMathAbs* instr) { |
| 3470 Register input = ToRegister(instr->value()); | 3469 Register input = ToRegister(instr->value()); |
| 3471 Register result = ToRegister(instr->result()); | 3470 Register result = ToRegister(instr->result()); |
| 3472 Label done; | 3471 Label done; |
| 3473 __ Cmp32(input, Operand::Zero()); | 3472 __ Cmp32(input, Operand::Zero()); |
| 3474 __ Move(result, input); | 3473 __ Move(result, input); |
| 3475 __ bge(&done, Label::kNear); | 3474 __ bge(&done, Label::kNear); |
| 3476 | 3475 |
| 3477 // Deoptimize on overflow. | 3476 // Deoptimize on overflow. |
| 3478 __ Cmp32(input, Operand(0x80000000)); | 3477 __ Cmp32(input, Operand(0x80000000)); |
| 3479 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 3478 DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow); |
| 3480 | 3479 |
| 3481 __ LoadComplementRR(result, result); | 3480 __ LoadComplementRR(result, result); |
| 3482 __ bind(&done); | 3481 __ bind(&done); |
| 3483 } | 3482 } |
| 3484 #endif | 3483 #endif |
| 3485 | 3484 |
| 3486 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3485 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3487 // Class for deferred case. | 3486 // Class for deferred case. |
| 3488 class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode { | 3487 class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode { |
| 3489 public: | 3488 public: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3526 | 3525 |
| 3527 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3526 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3528 DoubleRegister input = ToDoubleRegister(instr->value()); | 3527 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3529 Register result = ToRegister(instr->result()); | 3528 Register result = ToRegister(instr->result()); |
| 3530 Register input_high = scratch0(); | 3529 Register input_high = scratch0(); |
| 3531 Register scratch = ip; | 3530 Register scratch = ip; |
| 3532 Label done, exact; | 3531 Label done, exact; |
| 3533 | 3532 |
| 3534 __ TryInt32Floor(result, input, input_high, scratch, double_scratch0(), &done, | 3533 __ TryInt32Floor(result, input, input_high, scratch, double_scratch0(), &done, |
| 3535 &exact); | 3534 &exact); |
| 3536 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); | 3535 DeoptimizeIf(al, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 3537 | 3536 |
| 3538 __ bind(&exact); | 3537 __ bind(&exact); |
| 3539 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3538 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3540 // Test for -0. | 3539 // Test for -0. |
| 3541 __ CmpP(result, Operand::Zero()); | 3540 __ CmpP(result, Operand::Zero()); |
| 3542 __ bne(&done, Label::kNear); | 3541 __ bne(&done, Label::kNear); |
| 3543 __ Cmp32(input_high, Operand::Zero()); | 3542 __ Cmp32(input_high, Operand::Zero()); |
| 3544 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 3543 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 3545 } | 3544 } |
| 3546 __ bind(&done); | 3545 __ bind(&done); |
| 3547 } | 3546 } |
| 3548 | 3547 |
| 3549 void LCodeGen::DoMathRound(LMathRound* instr) { | 3548 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3550 DoubleRegister input = ToDoubleRegister(instr->value()); | 3549 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3551 Register result = ToRegister(instr->result()); | 3550 Register result = ToRegister(instr->result()); |
| 3552 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3551 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
| 3553 DoubleRegister input_plus_dot_five = double_scratch1; | 3552 DoubleRegister input_plus_dot_five = double_scratch1; |
| 3554 Register scratch1 = scratch0(); | 3553 Register scratch1 = scratch0(); |
| 3555 Register scratch2 = ip; | 3554 Register scratch2 = ip; |
| 3556 DoubleRegister dot_five = double_scratch0(); | 3555 DoubleRegister dot_five = double_scratch0(); |
| 3557 Label convert, done; | 3556 Label convert, done; |
| 3558 | 3557 |
| 3559 __ LoadDoubleLiteral(dot_five, 0.5, r0); | 3558 __ LoadDoubleLiteral(dot_five, 0.5, r0); |
| 3560 __ lpdbr(double_scratch1, input); | 3559 __ lpdbr(double_scratch1, input); |
| 3561 __ cdbr(double_scratch1, dot_five); | 3560 __ cdbr(double_scratch1, dot_five); |
| 3562 DeoptimizeIf(unordered, instr, Deoptimizer::kLostPrecisionOrNaN); | 3561 DeoptimizeIf(unordered, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 3563 // If input is in [-0.5, -0], the result is -0. | 3562 // If input is in [-0.5, -0], the result is -0. |
| 3564 // If input is in [+0, +0.5[, the result is +0. | 3563 // If input is in [+0, +0.5[, the result is +0. |
| 3565 // If the input is +0.5, the result is 1. | 3564 // If the input is +0.5, the result is 1. |
| 3566 __ bgt(&convert, Label::kNear); // Out of [-0.5, +0.5]. | 3565 __ bgt(&convert, Label::kNear); // Out of [-0.5, +0.5]. |
| 3567 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3566 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3568 // [-0.5, -0] (negative) yields minus zero. | 3567 // [-0.5, -0] (negative) yields minus zero. |
| 3569 __ TestDoubleSign(input, scratch1); | 3568 __ TestDoubleSign(input, scratch1); |
| 3570 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 3569 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 3571 } | 3570 } |
| 3572 Label return_zero; | 3571 Label return_zero; |
| 3573 __ cdbr(input, dot_five); | 3572 __ cdbr(input, dot_five); |
| 3574 __ bne(&return_zero, Label::kNear); | 3573 __ bne(&return_zero, Label::kNear); |
| 3575 __ LoadImmP(result, Operand(1)); // +0.5. | 3574 __ LoadImmP(result, Operand(1)); // +0.5. |
| 3576 __ b(&done, Label::kNear); | 3575 __ b(&done, Label::kNear); |
| 3577 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on | 3576 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on |
| 3578 // flag kBailoutOnMinusZero. | 3577 // flag kBailoutOnMinusZero. |
| 3579 __ bind(&return_zero); | 3578 __ bind(&return_zero); |
| 3580 __ LoadImmP(result, Operand::Zero()); | 3579 __ LoadImmP(result, Operand::Zero()); |
| 3581 __ b(&done, Label::kNear); | 3580 __ b(&done, Label::kNear); |
| 3582 | 3581 |
| 3583 __ bind(&convert); | 3582 __ bind(&convert); |
| 3584 __ ldr(input_plus_dot_five, input); | 3583 __ ldr(input_plus_dot_five, input); |
| 3585 __ adbr(input_plus_dot_five, dot_five); | 3584 __ adbr(input_plus_dot_five, dot_five); |
| 3586 // Reuse dot_five (double_scratch0) as we no longer need this value. | 3585 // Reuse dot_five (double_scratch0) as we no longer need this value. |
| 3587 __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2, | 3586 __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2, |
| 3588 double_scratch0(), &done, &done); | 3587 double_scratch0(), &done, &done); |
| 3589 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); | 3588 DeoptimizeIf(al, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 3590 __ bind(&done); | 3589 __ bind(&done); |
| 3591 } | 3590 } |
| 3592 | 3591 |
| 3593 void LCodeGen::DoMathFround(LMathFround* instr) { | 3592 void LCodeGen::DoMathFround(LMathFround* instr) { |
| 3594 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | 3593 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
| 3595 DoubleRegister output_reg = ToDoubleRegister(instr->result()); | 3594 DoubleRegister output_reg = ToDoubleRegister(instr->result()); |
| 3596 | 3595 |
| 3597 // Round double to float | 3596 // Round double to float |
| 3598 __ ledbr(output_reg, input_reg); | 3597 __ ledbr(output_reg, input_reg); |
| 3599 // Extend from float to double | 3598 // Extend from float to double |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3644 DCHECK(ToDoubleRegister(instr->result()).is(d3)); | 3643 DCHECK(ToDoubleRegister(instr->result()).is(d3)); |
| 3645 | 3644 |
| 3646 if (exponent_type.IsSmi()) { | 3645 if (exponent_type.IsSmi()) { |
| 3647 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3646 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3648 __ CallStub(&stub); | 3647 __ CallStub(&stub); |
| 3649 } else if (exponent_type.IsTagged()) { | 3648 } else if (exponent_type.IsTagged()) { |
| 3650 Label no_deopt; | 3649 Label no_deopt; |
| 3651 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3650 __ JumpIfSmi(tagged_exponent, &no_deopt); |
| 3652 __ LoadP(r9, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); | 3651 __ LoadP(r9, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
| 3653 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex); | 3652 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex); |
| 3654 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 3653 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber); |
| 3655 __ bind(&no_deopt); | 3654 __ bind(&no_deopt); |
| 3656 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3655 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3657 __ CallStub(&stub); | 3656 __ CallStub(&stub); |
| 3658 } else if (exponent_type.IsInteger32()) { | 3657 } else if (exponent_type.IsInteger32()) { |
| 3659 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3658 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
| 3660 __ CallStub(&stub); | 3659 __ CallStub(&stub); |
| 3661 } else { | 3660 } else { |
| 3662 DCHECK(exponent_type.IsDouble()); | 3661 DCHECK(exponent_type.IsDouble()); |
| 3663 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3662 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
| 3664 __ CallStub(&stub); | 3663 __ CallStub(&stub); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4028 } else { | 4027 } else { |
| 4029 __ CmpLogical32(length, index); | 4028 __ CmpLogical32(length, index); |
| 4030 } | 4029 } |
| 4031 } | 4030 } |
| 4032 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4031 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
| 4033 Label done; | 4032 Label done; |
| 4034 __ b(NegateCondition(cc), &done, Label::kNear); | 4033 __ b(NegateCondition(cc), &done, Label::kNear); |
| 4035 __ stop("eliminated bounds check failed"); | 4034 __ stop("eliminated bounds check failed"); |
| 4036 __ bind(&done); | 4035 __ bind(&done); |
| 4037 } else { | 4036 } else { |
| 4038 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds); | 4037 DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds); |
| 4039 } | 4038 } |
| 4040 } | 4039 } |
| 4041 | 4040 |
| 4042 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4041 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4043 Register external_pointer = ToRegister(instr->elements()); | 4042 Register external_pointer = ToRegister(instr->elements()); |
| 4044 Register key = no_reg; | 4043 Register key = no_reg; |
| 4045 ElementsKind elements_kind = instr->elements_kind(); | 4044 ElementsKind elements_kind = instr->elements_kind(); |
| 4046 bool key_is_constant = instr->key()->IsConstantOperand(); | 4045 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4047 int constant_key = 0; | 4046 int constant_key = 0; |
| 4048 if (key_is_constant) { | 4047 if (key_is_constant) { |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4388 GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(), | 4387 GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(), |
| 4389 instr->hydrogen()->kind()); | 4388 instr->hydrogen()->kind()); |
| 4390 __ CallStub(&stub); | 4389 __ CallStub(&stub); |
| 4391 RecordSafepointWithLazyDeopt( | 4390 RecordSafepointWithLazyDeopt( |
| 4392 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 4391 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 4393 __ StoreToSafepointRegisterSlot(result, result); | 4392 __ StoreToSafepointRegisterSlot(result, result); |
| 4394 } | 4393 } |
| 4395 | 4394 |
| 4396 // Deopt on smi, which means the elements array changed to dictionary mode. | 4395 // Deopt on smi, which means the elements array changed to dictionary mode. |
| 4397 __ TestIfSmi(result); | 4396 __ TestIfSmi(result); |
| 4398 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0); | 4397 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
| 4399 } | 4398 } |
| 4400 | 4399 |
| 4401 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4400 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4402 Register object_reg = ToRegister(instr->object()); | 4401 Register object_reg = ToRegister(instr->object()); |
| 4403 Register scratch = scratch0(); | 4402 Register scratch = scratch0(); |
| 4404 | 4403 |
| 4405 Handle<Map> from_map = instr->original_map(); | 4404 Handle<Map> from_map = instr->original_map(); |
| 4406 Handle<Map> to_map = instr->transitioned_map(); | 4405 Handle<Map> to_map = instr->transitioned_map(); |
| 4407 ElementsKind from_kind = instr->from_kind(); | 4406 ElementsKind from_kind = instr->from_kind(); |
| 4408 ElementsKind to_kind = instr->to_kind(); | 4407 ElementsKind to_kind = instr->to_kind(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4431 } | 4430 } |
| 4432 __ bind(¬_applicable); | 4431 __ bind(¬_applicable); |
| 4433 } | 4432 } |
| 4434 | 4433 |
| 4435 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4434 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4436 Register object = ToRegister(instr->object()); | 4435 Register object = ToRegister(instr->object()); |
| 4437 Register temp1 = ToRegister(instr->temp1()); | 4436 Register temp1 = ToRegister(instr->temp1()); |
| 4438 Register temp2 = ToRegister(instr->temp2()); | 4437 Register temp2 = ToRegister(instr->temp2()); |
| 4439 Label no_memento_found; | 4438 Label no_memento_found; |
| 4440 __ TestJSArrayForAllocationMemento(object, temp1, temp2, &no_memento_found); | 4439 __ TestJSArrayForAllocationMemento(object, temp1, temp2, &no_memento_found); |
| 4441 DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound); | 4440 DeoptimizeIf(eq, instr, DeoptimizeReason::kMementoFound); |
| 4442 __ bind(&no_memento_found); | 4441 __ bind(&no_memento_found); |
| 4443 } | 4442 } |
| 4444 | 4443 |
| 4445 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4444 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4446 DCHECK(ToRegister(instr->context()).is(cp)); | 4445 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4447 DCHECK(ToRegister(instr->left()).is(r3)); | 4446 DCHECK(ToRegister(instr->left()).is(r3)); |
| 4448 DCHECK(ToRegister(instr->right()).is(r2)); | 4447 DCHECK(ToRegister(instr->right()).is(r2)); |
| 4449 StringAddStub stub(isolate(), instr->hydrogen()->flags(), | 4448 StringAddStub stub(isolate(), instr->hydrogen()->flags(), |
| 4450 instr->hydrogen()->pretenure_flag()); | 4449 instr->hydrogen()->pretenure_flag()); |
| 4451 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4450 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4729 __ StoreToSafepointRegisterSlot(r2, reg); | 4728 __ StoreToSafepointRegisterSlot(r2, reg); |
| 4730 } | 4729 } |
| 4731 | 4730 |
| 4732 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4731 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4733 HChange* hchange = instr->hydrogen(); | 4732 HChange* hchange = instr->hydrogen(); |
| 4734 Register input = ToRegister(instr->value()); | 4733 Register input = ToRegister(instr->value()); |
| 4735 Register output = ToRegister(instr->result()); | 4734 Register output = ToRegister(instr->result()); |
| 4736 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4735 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4737 hchange->value()->CheckFlag(HValue::kUint32)) { | 4736 hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4738 __ TestUnsignedSmiCandidate(input, r0); | 4737 __ TestUnsignedSmiCandidate(input, r0); |
| 4739 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, cr0); | 4738 DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, cr0); |
| 4740 } | 4739 } |
| 4741 #if !V8_TARGET_ARCH_S390X | 4740 #if !V8_TARGET_ARCH_S390X |
| 4742 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4741 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4743 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4742 !hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4744 __ SmiTagCheckOverflow(output, input, r0); | 4743 __ SmiTagCheckOverflow(output, input, r0); |
| 4745 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); | 4744 DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, cr0); |
| 4746 } else { | 4745 } else { |
| 4747 #endif | 4746 #endif |
| 4748 __ SmiTag(output, input); | 4747 __ SmiTag(output, input); |
| 4749 #if !V8_TARGET_ARCH_S390X | 4748 #if !V8_TARGET_ARCH_S390X |
| 4750 } | 4749 } |
| 4751 #endif | 4750 #endif |
| 4752 } | 4751 } |
| 4753 | 4752 |
| 4754 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4753 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4755 Register input = ToRegister(instr->value()); | 4754 Register input = ToRegister(instr->value()); |
| 4756 Register result = ToRegister(instr->result()); | 4755 Register result = ToRegister(instr->result()); |
| 4757 if (instr->needs_check()) { | 4756 if (instr->needs_check()) { |
| 4758 __ tmll(input, Operand(kHeapObjectTag)); | 4757 __ tmll(input, Operand(kHeapObjectTag)); |
| 4759 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0); | 4758 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, cr0); |
| 4760 __ SmiUntag(result, input); | 4759 __ SmiUntag(result, input); |
| 4761 } else { | 4760 } else { |
| 4762 __ SmiUntag(result, input); | 4761 __ SmiUntag(result, input); |
| 4763 } | 4762 } |
| 4764 } | 4763 } |
| 4765 | 4764 |
| 4766 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, | 4765 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
| 4767 DoubleRegister result_reg, | 4766 DoubleRegister result_reg, |
| 4768 NumberUntagDMode mode) { | 4767 NumberUntagDMode mode) { |
| 4769 bool can_convert_undefined_to_nan = | 4768 bool can_convert_undefined_to_nan = |
| 4770 instr->hydrogen()->can_convert_undefined_to_nan(); | 4769 instr->hydrogen()->can_convert_undefined_to_nan(); |
| 4771 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); | 4770 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4772 | 4771 |
| 4773 Register scratch = scratch0(); | 4772 Register scratch = scratch0(); |
| 4774 DCHECK(!result_reg.is(double_scratch0())); | 4773 DCHECK(!result_reg.is(double_scratch0())); |
| 4775 | 4774 |
| 4776 Label convert, load_smi, done; | 4775 Label convert, load_smi, done; |
| 4777 | 4776 |
| 4778 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4777 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4779 // Smi check. | 4778 // Smi check. |
| 4780 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4779 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4781 | 4780 |
| 4782 // Heap number map check. | 4781 // Heap number map check. |
| 4783 __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4782 __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4784 __ CmpP(scratch, RootMemOperand(Heap::kHeapNumberMapRootIndex)); | 4783 __ CmpP(scratch, RootMemOperand(Heap::kHeapNumberMapRootIndex)); |
| 4785 | 4784 |
| 4786 if (can_convert_undefined_to_nan) { | 4785 if (can_convert_undefined_to_nan) { |
| 4787 __ bne(&convert, Label::kNear); | 4786 __ bne(&convert, Label::kNear); |
| 4788 } else { | 4787 } else { |
| 4789 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 4788 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber); |
| 4790 } | 4789 } |
| 4791 // load heap number | 4790 // load heap number |
| 4792 __ ld(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4791 __ ld(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4793 if (deoptimize_on_minus_zero) { | 4792 if (deoptimize_on_minus_zero) { |
| 4794 __ TestDoubleIsMinusZero(result_reg, scratch, ip); | 4793 __ TestDoubleIsMinusZero(result_reg, scratch, ip); |
| 4795 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 4794 DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero); |
| 4796 } | 4795 } |
| 4797 __ b(&done, Label::kNear); | 4796 __ b(&done, Label::kNear); |
| 4798 if (can_convert_undefined_to_nan) { | 4797 if (can_convert_undefined_to_nan) { |
| 4799 __ bind(&convert); | 4798 __ bind(&convert); |
| 4800 // Convert undefined (and hole) to NaN. | 4799 // Convert undefined (and hole) to NaN. |
| 4801 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4800 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 4802 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined); | 4801 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined); |
| 4803 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4802 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4804 __ ld(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4803 __ ld(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
| 4805 __ b(&done, Label::kNear); | 4804 __ b(&done, Label::kNear); |
| 4806 } | 4805 } |
| 4807 } else { | 4806 } else { |
| 4808 __ SmiUntag(scratch, input_reg); | 4807 __ SmiUntag(scratch, input_reg); |
| 4809 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4808 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
| 4810 } | 4809 } |
| 4811 // Smi to double register conversion | 4810 // Smi to double register conversion |
| 4812 __ bind(&load_smi); | 4811 __ bind(&load_smi); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4849 __ b(&done, Label::kNear); | 4848 __ b(&done, Label::kNear); |
| 4850 | 4849 |
| 4851 __ bind(&check_bools); | 4850 __ bind(&check_bools); |
| 4852 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); | 4851 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); |
| 4853 __ bne(&check_false, Label::kNear); | 4852 __ bne(&check_false, Label::kNear); |
| 4854 __ LoadImmP(input_reg, Operand(1)); | 4853 __ LoadImmP(input_reg, Operand(1)); |
| 4855 __ b(&done, Label::kNear); | 4854 __ b(&done, Label::kNear); |
| 4856 | 4855 |
| 4857 __ bind(&check_false); | 4856 __ bind(&check_false); |
| 4858 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); | 4857 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); |
| 4859 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean); | 4858 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefinedBoolean); |
| 4860 __ LoadImmP(input_reg, Operand::Zero()); | 4859 __ LoadImmP(input_reg, Operand::Zero()); |
| 4861 } else { | 4860 } else { |
| 4862 // Deoptimize if we don't have a heap number. | 4861 // Deoptimize if we don't have a heap number. |
| 4863 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 4862 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber); |
| 4864 | 4863 |
| 4865 __ ld(double_scratch2, | 4864 __ ld(double_scratch2, |
| 4866 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4865 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4867 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4866 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4868 // preserve heap number pointer in scratch2 for minus zero check below | 4867 // preserve heap number pointer in scratch2 for minus zero check below |
| 4869 __ LoadRR(scratch2, input_reg); | 4868 __ LoadRR(scratch2, input_reg); |
| 4870 } | 4869 } |
| 4871 __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1, | 4870 __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1, |
| 4872 double_scratch); | 4871 double_scratch); |
| 4873 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 4872 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 4874 | 4873 |
| 4875 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4874 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4876 __ CmpP(input_reg, Operand::Zero()); | 4875 __ CmpP(input_reg, Operand::Zero()); |
| 4877 __ bne(&done, Label::kNear); | 4876 __ bne(&done, Label::kNear); |
| 4878 __ TestHeapNumberSign(scratch2, scratch1); | 4877 __ TestHeapNumberSign(scratch2, scratch1); |
| 4879 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 4878 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 4880 } | 4879 } |
| 4881 } | 4880 } |
| 4882 __ bind(&done); | 4881 __ bind(&done); |
| 4883 } | 4882 } |
| 4884 | 4883 |
| 4885 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4884 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 4886 class DeferredTaggedToI final : public LDeferredCode { | 4885 class DeferredTaggedToI final : public LDeferredCode { |
| 4887 public: | 4886 public: |
| 4888 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4887 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 4889 : LDeferredCode(codegen), instr_(instr) {} | 4888 : LDeferredCode(codegen), instr_(instr) {} |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4935 Register scratch1 = scratch0(); | 4934 Register scratch1 = scratch0(); |
| 4936 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 4935 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 4937 DoubleRegister double_scratch = double_scratch0(); | 4936 DoubleRegister double_scratch = double_scratch0(); |
| 4938 | 4937 |
| 4939 if (instr->truncating()) { | 4938 if (instr->truncating()) { |
| 4940 __ TruncateDoubleToI(result_reg, double_input); | 4939 __ TruncateDoubleToI(result_reg, double_input); |
| 4941 } else { | 4940 } else { |
| 4942 __ TryDoubleToInt32Exact(result_reg, double_input, scratch1, | 4941 __ TryDoubleToInt32Exact(result_reg, double_input, scratch1, |
| 4943 double_scratch); | 4942 double_scratch); |
| 4944 // Deoptimize if the input wasn't a int32 (inside a double). | 4943 // Deoptimize if the input wasn't a int32 (inside a double). |
| 4945 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 4944 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 4946 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4945 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4947 Label done; | 4946 Label done; |
| 4948 __ CmpP(result_reg, Operand::Zero()); | 4947 __ CmpP(result_reg, Operand::Zero()); |
| 4949 __ bne(&done, Label::kNear); | 4948 __ bne(&done, Label::kNear); |
| 4950 __ TestDoubleSign(double_input, scratch1); | 4949 __ TestDoubleSign(double_input, scratch1); |
| 4951 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 4950 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 4952 __ bind(&done); | 4951 __ bind(&done); |
| 4953 } | 4952 } |
| 4954 } | 4953 } |
| 4955 } | 4954 } |
| 4956 | 4955 |
| 4957 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 4956 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 4958 Register result_reg = ToRegister(instr->result()); | 4957 Register result_reg = ToRegister(instr->result()); |
| 4959 Register scratch1 = scratch0(); | 4958 Register scratch1 = scratch0(); |
| 4960 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 4959 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 4961 DoubleRegister double_scratch = double_scratch0(); | 4960 DoubleRegister double_scratch = double_scratch0(); |
| 4962 | 4961 |
| 4963 if (instr->truncating()) { | 4962 if (instr->truncating()) { |
| 4964 __ TruncateDoubleToI(result_reg, double_input); | 4963 __ TruncateDoubleToI(result_reg, double_input); |
| 4965 } else { | 4964 } else { |
| 4966 __ TryDoubleToInt32Exact(result_reg, double_input, scratch1, | 4965 __ TryDoubleToInt32Exact(result_reg, double_input, scratch1, |
| 4967 double_scratch); | 4966 double_scratch); |
| 4968 // Deoptimize if the input wasn't a int32 (inside a double). | 4967 // Deoptimize if the input wasn't a int32 (inside a double). |
| 4969 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 4968 DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN); |
| 4970 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4969 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4971 Label done; | 4970 Label done; |
| 4972 __ CmpP(result_reg, Operand::Zero()); | 4971 __ CmpP(result_reg, Operand::Zero()); |
| 4973 __ bne(&done, Label::kNear); | 4972 __ bne(&done, Label::kNear); |
| 4974 __ TestDoubleSign(double_input, scratch1); | 4973 __ TestDoubleSign(double_input, scratch1); |
| 4975 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 4974 DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero); |
| 4976 __ bind(&done); | 4975 __ bind(&done); |
| 4977 } | 4976 } |
| 4978 } | 4977 } |
| 4979 #if V8_TARGET_ARCH_S390X | 4978 #if V8_TARGET_ARCH_S390X |
| 4980 __ SmiTag(result_reg); | 4979 __ SmiTag(result_reg); |
| 4981 #else | 4980 #else |
| 4982 __ SmiTagCheckOverflow(result_reg, r0); | 4981 __ SmiTagCheckOverflow(result_reg, r0); |
| 4983 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); | 4982 DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, cr0); |
| 4984 #endif | 4983 #endif |
| 4985 } | 4984 } |
| 4986 | 4985 |
| 4987 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4986 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 4988 LOperand* input = instr->value(); | 4987 LOperand* input = instr->value(); |
| 4989 __ TestIfSmi(ToRegister(input)); | 4988 __ TestIfSmi(ToRegister(input)); |
| 4990 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0); | 4989 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, cr0); |
| 4991 } | 4990 } |
| 4992 | 4991 |
| 4993 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4992 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 4994 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4993 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4995 LOperand* input = instr->value(); | 4994 LOperand* input = instr->value(); |
| 4996 __ TestIfSmi(ToRegister(input)); | 4995 __ TestIfSmi(ToRegister(input)); |
| 4997 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0); | 4996 DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, cr0); |
| 4998 } | 4997 } |
| 4999 } | 4998 } |
| 5000 | 4999 |
| 5001 void LCodeGen::DoCheckArrayBufferNotNeutered( | 5000 void LCodeGen::DoCheckArrayBufferNotNeutered( |
| 5002 LCheckArrayBufferNotNeutered* instr) { | 5001 LCheckArrayBufferNotNeutered* instr) { |
| 5003 Register view = ToRegister(instr->view()); | 5002 Register view = ToRegister(instr->view()); |
| 5004 Register scratch = scratch0(); | 5003 Register scratch = scratch0(); |
| 5005 | 5004 |
| 5006 __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset)); | 5005 __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset)); |
| 5007 __ LoadlW(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset)); | 5006 __ LoadlW(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset)); |
| 5008 __ And(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift)); | 5007 __ And(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift)); |
| 5009 DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, cr0); | 5008 DeoptimizeIf(ne, instr, DeoptimizeReason::kOutOfBounds, cr0); |
| 5010 } | 5009 } |
| 5011 | 5010 |
| 5012 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 5011 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 5013 Register input = ToRegister(instr->value()); | 5012 Register input = ToRegister(instr->value()); |
| 5014 Register scratch = scratch0(); | 5013 Register scratch = scratch0(); |
| 5015 | 5014 |
| 5016 __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 5015 __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 5017 | 5016 |
| 5018 if (instr->hydrogen()->is_interval_check()) { | 5017 if (instr->hydrogen()->is_interval_check()) { |
| 5019 InstanceType first; | 5018 InstanceType first; |
| 5020 InstanceType last; | 5019 InstanceType last; |
| 5021 instr->hydrogen()->GetCheckInterval(&first, &last); | 5020 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 5022 | 5021 |
| 5023 __ CmpLogicalByte(FieldMemOperand(scratch, Map::kInstanceTypeOffset), | 5022 __ CmpLogicalByte(FieldMemOperand(scratch, Map::kInstanceTypeOffset), |
| 5024 Operand(first)); | 5023 Operand(first)); |
| 5025 | 5024 |
| 5026 // If there is only one type in the interval check for equality. | 5025 // If there is only one type in the interval check for equality. |
| 5027 if (first == last) { | 5026 if (first == last) { |
| 5028 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType); | 5027 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType); |
| 5029 } else { | 5028 } else { |
| 5030 DeoptimizeIf(lt, instr, Deoptimizer::kWrongInstanceType); | 5029 DeoptimizeIf(lt, instr, DeoptimizeReason::kWrongInstanceType); |
| 5031 // Omit check for the last type. | 5030 // Omit check for the last type. |
| 5032 if (last != LAST_TYPE) { | 5031 if (last != LAST_TYPE) { |
| 5033 __ CmpLogicalByte(FieldMemOperand(scratch, Map::kInstanceTypeOffset), | 5032 __ CmpLogicalByte(FieldMemOperand(scratch, Map::kInstanceTypeOffset), |
| 5034 Operand(last)); | 5033 Operand(last)); |
| 5035 DeoptimizeIf(gt, instr, Deoptimizer::kWrongInstanceType); | 5034 DeoptimizeIf(gt, instr, DeoptimizeReason::kWrongInstanceType); |
| 5036 } | 5035 } |
| 5037 } | 5036 } |
| 5038 } else { | 5037 } else { |
| 5039 uint8_t mask; | 5038 uint8_t mask; |
| 5040 uint8_t tag; | 5039 uint8_t tag; |
| 5041 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5040 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 5042 | 5041 |
| 5043 __ LoadlB(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 5042 __ LoadlB(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 5044 | 5043 |
| 5045 if (base::bits::IsPowerOfTwo32(mask)) { | 5044 if (base::bits::IsPowerOfTwo32(mask)) { |
| 5046 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 5045 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
| 5047 __ AndP(scratch, Operand(mask)); | 5046 __ AndP(scratch, Operand(mask)); |
| 5048 DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType); | 5047 DeoptimizeIf(tag == 0 ? ne : eq, instr, |
| 5048 DeoptimizeReason::kWrongInstanceType); |
| 5049 } else { | 5049 } else { |
| 5050 __ AndP(scratch, Operand(mask)); | 5050 __ AndP(scratch, Operand(mask)); |
| 5051 __ CmpP(scratch, Operand(tag)); | 5051 __ CmpP(scratch, Operand(tag)); |
| 5052 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType); | 5052 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType); |
| 5053 } | 5053 } |
| 5054 } | 5054 } |
| 5055 } | 5055 } |
| 5056 | 5056 |
| 5057 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5057 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 5058 Register reg = ToRegister(instr->value()); | 5058 Register reg = ToRegister(instr->value()); |
| 5059 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 5059 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 5060 AllowDeferredHandleDereference smi_check; | 5060 AllowDeferredHandleDereference smi_check; |
| 5061 if (isolate()->heap()->InNewSpace(*object)) { | 5061 if (isolate()->heap()->InNewSpace(*object)) { |
| 5062 Register reg = ToRegister(instr->value()); | 5062 Register reg = ToRegister(instr->value()); |
| 5063 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 5063 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 5064 __ mov(ip, Operand(cell)); | 5064 __ mov(ip, Operand(cell)); |
| 5065 __ CmpP(reg, FieldMemOperand(ip, Cell::kValueOffset)); | 5065 __ CmpP(reg, FieldMemOperand(ip, Cell::kValueOffset)); |
| 5066 } else { | 5066 } else { |
| 5067 __ CmpP(reg, Operand(object)); | 5067 __ CmpP(reg, Operand(object)); |
| 5068 } | 5068 } |
| 5069 DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch); | 5069 DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch); |
| 5070 } | 5070 } |
| 5071 | 5071 |
| 5072 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5072 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5073 Register temp = ToRegister(instr->temp()); | 5073 Register temp = ToRegister(instr->temp()); |
| 5074 { | 5074 { |
| 5075 PushSafepointRegistersScope scope(this); | 5075 PushSafepointRegistersScope scope(this); |
| 5076 __ push(object); | 5076 __ push(object); |
| 5077 __ LoadImmP(cp, Operand::Zero()); | 5077 __ LoadImmP(cp, Operand::Zero()); |
| 5078 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 5078 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 5079 RecordSafepointWithRegisters(instr->pointer_map(), 1, | 5079 RecordSafepointWithRegisters(instr->pointer_map(), 1, |
| 5080 Safepoint::kNoLazyDeopt); | 5080 Safepoint::kNoLazyDeopt); |
| 5081 __ StoreToSafepointRegisterSlot(r2, temp); | 5081 __ StoreToSafepointRegisterSlot(r2, temp); |
| 5082 } | 5082 } |
| 5083 __ TestIfSmi(temp); | 5083 __ TestIfSmi(temp); |
| 5084 DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, cr0); | 5084 DeoptimizeIf(eq, instr, DeoptimizeReason::kInstanceMigrationFailed, cr0); |
| 5085 } | 5085 } |
| 5086 | 5086 |
| 5087 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5087 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5088 class DeferredCheckMaps final : public LDeferredCode { | 5088 class DeferredCheckMaps final : public LDeferredCode { |
| 5089 public: | 5089 public: |
| 5090 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5090 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5091 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5091 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5092 SetExit(check_maps()); | 5092 SetExit(check_maps()); |
| 5093 } | 5093 } |
| 5094 void Generate() override { | 5094 void Generate() override { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5127 Handle<Map> map = maps->at(i).handle(); | 5127 Handle<Map> map = maps->at(i).handle(); |
| 5128 __ CompareMap(reg, map, &success); | 5128 __ CompareMap(reg, map, &success); |
| 5129 __ beq(&success); | 5129 __ beq(&success); |
| 5130 } | 5130 } |
| 5131 | 5131 |
| 5132 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5132 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
| 5133 __ CompareMap(reg, map, &success); | 5133 __ CompareMap(reg, map, &success); |
| 5134 if (instr->hydrogen()->HasMigrationTarget()) { | 5134 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5135 __ bne(deferred->entry()); | 5135 __ bne(deferred->entry()); |
| 5136 } else { | 5136 } else { |
| 5137 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap); | 5137 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap); |
| 5138 } | 5138 } |
| 5139 | 5139 |
| 5140 __ bind(&success); | 5140 __ bind(&success); |
| 5141 } | 5141 } |
| 5142 | 5142 |
| 5143 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5143 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5144 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5144 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5145 Register result_reg = ToRegister(instr->result()); | 5145 Register result_reg = ToRegister(instr->result()); |
| 5146 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); | 5146 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); |
| 5147 } | 5147 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5163 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 5163 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
| 5164 | 5164 |
| 5165 // Check for heap number | 5165 // Check for heap number |
| 5166 __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5166 __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 5167 __ CmpP(scratch, Operand(factory()->heap_number_map())); | 5167 __ CmpP(scratch, Operand(factory()->heap_number_map())); |
| 5168 __ beq(&heap_number, Label::kNear); | 5168 __ beq(&heap_number, Label::kNear); |
| 5169 | 5169 |
| 5170 // Check for undefined. Undefined is converted to zero for clamping | 5170 // Check for undefined. Undefined is converted to zero for clamping |
| 5171 // conversions. | 5171 // conversions. |
| 5172 __ CmpP(input_reg, Operand(factory()->undefined_value())); | 5172 __ CmpP(input_reg, Operand(factory()->undefined_value())); |
| 5173 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined); | 5173 DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined); |
| 5174 __ LoadImmP(result_reg, Operand::Zero()); | 5174 __ LoadImmP(result_reg, Operand::Zero()); |
| 5175 __ b(&done, Label::kNear); | 5175 __ b(&done, Label::kNear); |
| 5176 | 5176 |
| 5177 // Heap number | 5177 // Heap number |
| 5178 __ bind(&heap_number); | 5178 __ bind(&heap_number); |
| 5179 __ ld(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 5179 __ ld(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 5180 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); | 5180 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); |
| 5181 __ b(&done, Label::kNear); | 5181 __ b(&done, Label::kNear); |
| 5182 | 5182 |
| 5183 // smi | 5183 // smi |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5584 __ CmpSmiLiteral(result, Smi::FromInt(0), r0); | 5584 __ CmpSmiLiteral(result, Smi::FromInt(0), r0); |
| 5585 __ bne(&load_cache, Label::kNear); | 5585 __ bne(&load_cache, Label::kNear); |
| 5586 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); | 5586 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); |
| 5587 __ b(&done, Label::kNear); | 5587 __ b(&done, Label::kNear); |
| 5588 | 5588 |
| 5589 __ bind(&load_cache); | 5589 __ bind(&load_cache); |
| 5590 __ LoadInstanceDescriptors(map, result); | 5590 __ LoadInstanceDescriptors(map, result); |
| 5591 __ LoadP(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5591 __ LoadP(result, FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5592 __ LoadP(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | 5592 __ LoadP(result, FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5593 __ CmpP(result, Operand::Zero()); | 5593 __ CmpP(result, Operand::Zero()); |
| 5594 DeoptimizeIf(eq, instr, Deoptimizer::kNoCache); | 5594 DeoptimizeIf(eq, instr, DeoptimizeReason::kNoCache); |
| 5595 | 5595 |
| 5596 __ bind(&done); | 5596 __ bind(&done); |
| 5597 } | 5597 } |
| 5598 | 5598 |
| 5599 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5599 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5600 Register object = ToRegister(instr->value()); | 5600 Register object = ToRegister(instr->value()); |
| 5601 Register map = ToRegister(instr->map()); | 5601 Register map = ToRegister(instr->map()); |
| 5602 __ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5602 __ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5603 __ CmpP(map, scratch0()); | 5603 __ CmpP(map, scratch0()); |
| 5604 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap); | 5604 DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap); |
| 5605 } | 5605 } |
| 5606 | 5606 |
| 5607 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5607 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
| 5608 Register result, Register object, | 5608 Register result, Register object, |
| 5609 Register index) { | 5609 Register index) { |
| 5610 PushSafepointRegistersScope scope(this); | 5610 PushSafepointRegistersScope scope(this); |
| 5611 __ Push(object, index); | 5611 __ Push(object, index); |
| 5612 __ LoadImmP(cp, Operand::Zero()); | 5612 __ LoadImmP(cp, Operand::Zero()); |
| 5613 __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble); | 5613 __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble); |
| 5614 RecordSafepointWithRegisters(instr->pointer_map(), 2, | 5614 RecordSafepointWithRegisters(instr->pointer_map(), 2, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5670 __ LoadP(result, | 5670 __ LoadP(result, |
| 5671 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); | 5671 FieldMemOperand(scratch, FixedArray::kHeaderSize - kPointerSize)); |
| 5672 __ bind(deferred->exit()); | 5672 __ bind(deferred->exit()); |
| 5673 __ bind(&done); | 5673 __ bind(&done); |
| 5674 } | 5674 } |
| 5675 | 5675 |
| 5676 #undef __ | 5676 #undef __ |
| 5677 | 5677 |
| 5678 } // namespace internal | 5678 } // namespace internal |
| 5679 } // namespace v8 | 5679 } // namespace v8 |
| OLD | NEW |