OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arm64/lithium-codegen-arm64.h" | 7 #include "src/arm64/lithium-codegen-arm64.h" |
8 #include "src/hydrogen-osr.h" | 8 #include "src/hydrogen-osr.h" |
9 #include "src/lithium-inl.h" | 9 #include "src/lithium-inl.h" |
10 | 10 |
(...skipping 2185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2196 return DefineAsRegister(res); | 2196 return DefineAsRegister(res); |
2197 } | 2197 } |
2198 | 2198 |
2199 | 2199 |
2200 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 2200 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
2201 HBitwiseBinaryOperation* instr) { | 2201 HBitwiseBinaryOperation* instr) { |
2202 if (instr->representation().IsTagged()) { | 2202 if (instr->representation().IsTagged()) { |
2203 return DoArithmeticT(op, instr); | 2203 return DoArithmeticT(op, instr); |
2204 } | 2204 } |
2205 | 2205 |
2206 DCHECK(instr->representation().IsInteger32() || | 2206 DCHECK(instr->representation().IsSmiOrInteger32()); |
2207 instr->representation().IsSmi()); | |
2208 DCHECK(instr->left()->representation().Equals(instr->representation())); | 2207 DCHECK(instr->left()->representation().Equals(instr->representation())); |
2209 DCHECK(instr->right()->representation().Equals(instr->representation())); | 2208 DCHECK(instr->right()->representation().Equals(instr->representation())); |
2210 | 2209 |
2211 if (ShiftCanBeOptimizedAway(instr)) { | 2210 if (ShiftCanBeOptimizedAway(instr)) { |
2212 return NULL; | 2211 return NULL; |
2213 } | 2212 } |
2214 | 2213 |
2215 LOperand* left = instr->representation().IsSmi() | 2214 LOperand* left = instr->representation().IsSmi() |
2216 ? UseRegister(instr->left()) | 2215 ? UseRegister(instr->left()) |
2217 : UseRegisterAtStart(instr->left()); | 2216 : UseRegisterAtStart(instr->left()); |
| 2217 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
2218 | 2218 |
2219 HValue* right_value = instr->right(); | 2219 // The only shift that can deoptimize is `left >>> 0`, where left is negative. |
2220 LOperand* right = NULL; | 2220 // In these cases, the result is a uint32 that is too large for an int32. |
2221 LOperand* temp = NULL; | 2221 bool right_can_be_zero = !instr->right()->IsConstant() || |
2222 int constant_value = 0; | 2222 (JSShiftAmountFromHConstant(instr->right()) == 0); |
2223 if (right_value->IsConstant()) { | 2223 bool can_deopt = false; |
2224 right = UseConstant(right_value); | 2224 if ((op == Token::SHR) && right_can_be_zero) { |
2225 constant_value = JSShiftAmountFromHConstant(right_value); | |
2226 } else { | |
2227 right = UseRegisterAtStart(right_value); | |
2228 if (op == Token::ROR) { | |
2229 temp = TempRegister(); | |
2230 } | |
2231 } | |
2232 | |
2233 // Shift operations can only deoptimize if we do a logical shift by 0 and the | |
2234 // result cannot be truncated to int32. | |
2235 bool does_deopt = false; | |
2236 if ((op == Token::SHR) && (constant_value == 0)) { | |
2237 if (FLAG_opt_safe_uint32_operations) { | 2225 if (FLAG_opt_safe_uint32_operations) { |
2238 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | 2226 can_deopt = !instr->CheckFlag(HInstruction::kUint32); |
2239 } else { | 2227 } else { |
2240 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | 2228 can_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
2241 } | 2229 } |
2242 } | 2230 } |
2243 | 2231 |
2244 LInstruction* result; | 2232 LInstruction* result; |
2245 if (instr->representation().IsInteger32()) { | 2233 if (instr->representation().IsInteger32()) { |
2246 result = DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | 2234 result = DefineAsRegister(new (zone()) LShiftI(op, left, right, can_deopt)); |
2247 } else { | 2235 } else { |
2248 DCHECK(instr->representation().IsSmi()); | 2236 DCHECK(instr->representation().IsSmi()); |
2249 result = DefineAsRegister( | 2237 result = DefineAsRegister(new (zone()) LShiftS(op, left, right, can_deopt)); |
2250 new(zone()) LShiftS(op, left, right, temp, does_deopt)); | |
2251 } | 2238 } |
2252 | 2239 |
2253 return does_deopt ? AssignEnvironment(result) : result; | 2240 return can_deopt ? AssignEnvironment(result) : result; |
2254 } | 2241 } |
2255 | 2242 |
2256 | 2243 |
2257 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 2244 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
2258 return DoShift(Token::ROR, instr); | 2245 return DoShift(Token::ROR, instr); |
2259 } | 2246 } |
2260 | 2247 |
2261 | 2248 |
2262 LInstruction* LChunkBuilder::DoSar(HSar* instr) { | 2249 LInstruction* LChunkBuilder::DoSar(HSar* instr) { |
2263 return DoShift(Token::SAR, instr); | 2250 return DoShift(Token::SAR, instr); |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2746 HAllocateBlockContext* instr) { | 2733 HAllocateBlockContext* instr) { |
2747 LOperand* context = UseFixed(instr->context(), cp); | 2734 LOperand* context = UseFixed(instr->context(), cp); |
2748 LOperand* function = UseRegisterAtStart(instr->function()); | 2735 LOperand* function = UseRegisterAtStart(instr->function()); |
2749 LAllocateBlockContext* result = | 2736 LAllocateBlockContext* result = |
2750 new(zone()) LAllocateBlockContext(context, function); | 2737 new(zone()) LAllocateBlockContext(context, function); |
2751 return MarkAsCall(DefineFixed(result, cp), instr); | 2738 return MarkAsCall(DefineFixed(result, cp), instr); |
2752 } | 2739 } |
2753 | 2740 |
2754 | 2741 |
2755 } } // namespace v8::internal | 2742 } } // namespace v8::internal |
OLD | NEW |