OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1006 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1007 0, | 1007 0, |
1008 Safepoint::kNoDeoptimizationIndex); | 1008 Safepoint::kNoDeoptimizationIndex); |
1009 // Overwrite the stored value of r0 with the result of the stub. | 1009 // Overwrite the stored value of r0 with the result of the stub. |
1010 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1010 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1011 __ PopSafepointRegistersAndDoubles(); | 1011 __ PopSafepointRegistersAndDoubles(); |
1012 } | 1012 } |
1013 | 1013 |
1014 | 1014 |
1015 void LCodeGen::DoMulI(LMulI* instr) { | 1015 void LCodeGen::DoMulI(LMulI* instr) { |
1016 LOperand* left_op = instr->InputAt(0); | 1016 Register scratch = scratch0(); |
1017 LOperand* right_op = instr->InputAt(1); | 1017 Register left = ToRegister(instr->InputAt(0)); |
| 1018 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
1018 | 1019 |
1019 Register scratch = scratch0(); | 1020 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
1020 Register left = ToRegister(left_op); | 1021 !instr->InputAt(1)->IsConstantOperand()) { |
| 1022 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1023 } |
1021 | 1024 |
1022 ASSERT(left_op->Equals(instr->result())); | 1025 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1026 // scratch:left = left * right. |
| 1027 __ smull(left, scratch, left, right); |
| 1028 __ mov(ip, Operand(left, ASR, 31)); |
| 1029 __ cmp(ip, Operand(scratch)); |
| 1030 DeoptimizeIf(ne, instr->environment()); |
| 1031 } else { |
| 1032 __ mul(left, left, right); |
| 1033 } |
1023 | 1034 |
1024 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1035 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1025 bool bailout_on_minus_zero = | 1036 // Bail out if the result is supposed to be negative zero. |
1026 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1037 Label done; |
1027 | 1038 __ tst(left, Operand(left)); |
1028 if (right_op->IsConstantOperand()) { | 1039 __ b(ne, &done); |
1029 // Use optimized code for specific constants. | 1040 if (instr->InputAt(1)->IsConstantOperand()) { |
1030 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1041 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) { |
1031 Condition overflow_deopt_cond = kNoCondition; | 1042 DeoptimizeIf(al, instr->environment()); |
1032 switch (constant) { | 1043 } |
1033 case -1: | |
1034 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
1035 __ rsb(left, | |
1036 left, | |
1037 Operand(0), | |
1038 can_overflow ? SetCC : LeaveCC); | |
1039 break; | |
1040 case 0: | |
1041 if (bailout_on_minus_zero) { | |
1042 // If left is strictly negative and the constant is null, the | |
1043 // result is -0. Deoptimize if required, otherwise return 0. | |
1044 __ cmp(left, Operand(0)); | |
1045 DeoptimizeIf(mi, instr->environment()); | |
1046 } | |
1047 __ mov(left, Operand(0)); | |
1048 break; | |
1049 case 1: | |
1050 // Do nothing. | |
1051 break; | |
1052 default: | |
1053 // Multiplying by powers of two and powers of two plus or minus | |
1054 // one can be done faster with shifted operands. | |
1055 // For other constants we emit standard code. | |
1056 int32_t mask = constant >> 31; | |
1057 uint32_t constant_abs = (constant + mask) ^ mask; | |
1058 if (IsPowerOf2(constant_abs)) { | |
1059 if (!can_overflow) { | |
1060 int32_t shift = WhichPowerOf2(constant_abs); | |
1061 __ mov(left, Operand(left, LSL, shift)); | |
1062 if (constant < 0) __ rsb(left, left, Operand(0)); | |
1063 } else { | |
1064 // scratch:left = left * constant. | |
1065 __ mov(ip, Operand(constant)); | |
1066 __ smull(left, scratch, left, ip); | |
1067 __ cmp(scratch, Operand(left, ASR, 31)); | |
1068 overflow_deopt_cond = ne; | |
1069 } | |
1070 } else if (IsPowerOf2(constant_abs - 1)) { | |
1071 int32_t shift = WhichPowerOf2(constant_abs - 1); | |
1072 __ add(left, | |
1073 left, | |
1074 Operand(left, LSL, shift), | |
1075 can_overflow ? SetCC : LeaveCC); | |
1076 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
1077 if (constant < 0) __ rsb(left, left, Operand(0)); | |
1078 } else if (IsPowerOf2(constant_abs + 1)) { | |
1079 int32_t shift = WhichPowerOf2(constant_abs + 1); | |
1080 __ rsb(left, | |
1081 left, | |
1082 Operand(left, LSL, shift), | |
1083 can_overflow ? SetCC : LeaveCC); | |
1084 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
1085 if (constant < 0) __ rsb(left, left, Operand(0)); | |
1086 } else { | |
1087 if (!can_overflow) { | |
1088 __ mov(ip, Operand(constant)); | |
1089 __ mul(left, left, ip); | |
1090 } else { | |
1091 // scratch:left = left * constant. | |
1092 __ mov(ip, Operand(constant)); | |
1093 __ smull(left, scratch, left, ip); | |
1094 __ cmp(scratch, Operand(left, ASR, 31)); | |
1095 overflow_deopt_cond = ne; | |
1096 } | |
1097 } | |
1098 break; | |
1099 } | |
1100 | |
1101 if (can_overflow && (constant != 0) && (constant != 1)) { | |
1102 ASSERT(overflow_deopt_cond != kNoCondition); | |
1103 DeoptimizeIf(overflow_deopt_cond, instr->environment()); | |
1104 } | |
1105 if (bailout_on_minus_zero && (constant < 0)) { | |
1106 // The case of a null constant was handled separately. | |
1107 // If constant is negative and left is null, the result should be -0. | |
1108 __ cmp(left, Operand(0)); | |
1109 DeoptimizeIf(eq, instr->environment()); | |
1110 } | |
1111 } else { | |
1112 Register right = EmitLoadRegister(right_op, scratch); | |
1113 if (bailout_on_minus_zero) { | |
1114 __ orr(ToRegister(instr->TempAt(0)), left, right); | |
1115 } | |
1116 if (can_overflow) { | |
1117 // scratch:left = left * right. | |
1118 __ smull(left, scratch, left, right); | |
1119 __ cmp(scratch, Operand(left, ASR, 31)); | |
1120 DeoptimizeIf(ne, instr->environment()); | |
1121 } else { | 1044 } else { |
1122 __ mul(left, left, right); | 1045 // Test the non-zero operand for negative sign. |
1123 } | |
1124 if (bailout_on_minus_zero) { | |
1125 // Bail out if the result is supposed to be negative zero. | |
1126 Label done; | |
1127 __ cmp(left, Operand(0)); | |
1128 __ b(ne, &done); | |
1129 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1046 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
1130 DeoptimizeIf(mi, instr->environment()); | 1047 DeoptimizeIf(mi, instr->environment()); |
1131 __ bind(&done); | |
1132 } | 1048 } |
| 1049 __ bind(&done); |
1133 } | 1050 } |
1134 } | 1051 } |
1135 | 1052 |
1136 | 1053 |
1137 void LCodeGen::DoBitI(LBitI* instr) { | 1054 void LCodeGen::DoBitI(LBitI* instr) { |
1138 LOperand* left = instr->InputAt(0); | 1055 LOperand* left = instr->InputAt(0); |
1139 LOperand* right = instr->InputAt(1); | 1056 LOperand* right = instr->InputAt(1); |
1140 ASSERT(left->Equals(instr->result())); | 1057 ASSERT(left->Equals(instr->result())); |
1141 ASSERT(left->IsRegister()); | 1058 ASSERT(left->IsRegister()); |
1142 Register result = ToRegister(left); | 1059 Register result = ToRegister(left); |
(...skipping 2912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4055 ASSERT(!environment->HasBeenRegistered()); | 3972 ASSERT(!environment->HasBeenRegistered()); |
4056 RegisterEnvironmentForDeoptimization(environment); | 3973 RegisterEnvironmentForDeoptimization(environment); |
4057 ASSERT(osr_pc_offset_ == -1); | 3974 ASSERT(osr_pc_offset_ == -1); |
4058 osr_pc_offset_ = masm()->pc_offset(); | 3975 osr_pc_offset_ = masm()->pc_offset(); |
4059 } | 3976 } |
4060 | 3977 |
4061 | 3978 |
4062 #undef __ | 3979 #undef __ |
4063 | 3980 |
4064 } } // namespace v8::internal | 3981 } } // namespace v8::internal |
OLD | NEW |