Chromium Code Reviews| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "lithium-allocator-inl.h" | 7 #include "lithium-allocator-inl.h" |
| 8 #include "arm64/lithium-arm64.h" | 8 #include "arm64/lithium-arm64.h" |
| 9 #include "arm64/lithium-codegen-arm64.h" | 9 #include "arm64/lithium-codegen-arm64.h" |
| 10 #include "hydrogen-osr.h" | 10 #include "hydrogen-osr.h" |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 } | 818 } |
| 819 | 819 |
| 820 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index)); | 820 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index)); |
| 821 } | 821 } |
| 822 | 822 |
| 823 | 823 |
| 824 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 824 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 825 if (instr->representation().IsSmiOrInteger32()) { | 825 if (instr->representation().IsSmiOrInteger32()) { |
| 826 ASSERT(instr->left()->representation().Equals(instr->representation())); | 826 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 827 ASSERT(instr->right()->representation().Equals(instr->representation())); | 827 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 828 | |
| 829 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr); | |
| 830 if (shifted_operation != NULL) { | |
| 831 return shifted_operation; | |
| 832 } | |
| 833 | |
| 828 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 834 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 829 LOperand* right = | 835 LOperand* right = |
| 830 UseRegisterOrConstantAtStart(instr->BetterRightOperand()); | 836 UseRegisterOrConstantAtStart(instr->BetterRightOperand()); |
| 831 LInstruction* result = instr->representation().IsSmi() ? | 837 LInstruction* result = instr->representation().IsSmi() ? |
| 832 DefineAsRegister(new(zone()) LAddS(left, right)) : | 838 DefineAsRegister(new(zone()) LAddS(left, right)) : |
| 833 DefineAsRegister(new(zone()) LAddI(left, right)); | 839 DefineAsRegister(new(zone()) LAddI(left, right)); |
| 834 if (instr->CheckFlag(HValue::kCanOverflow)) { | 840 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 835 result = AssignEnvironment(result); | 841 result = AssignEnvironment(result); |
| 836 } | 842 } |
| 837 return result; | 843 return result; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 898 return NULL; | 904 return NULL; |
| 899 } | 905 } |
| 900 | 906 |
| 901 | 907 |
| 902 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 908 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 903 if (instr->representation().IsSmiOrInteger32()) { | 909 if (instr->representation().IsSmiOrInteger32()) { |
| 904 ASSERT(instr->left()->representation().Equals(instr->representation())); | 910 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 905 ASSERT(instr->right()->representation().Equals(instr->representation())); | 911 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 906 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | 912 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); |
| 907 | 913 |
| 914 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr); | |
| 915 if (shifted_operation != NULL) { | |
| 916 return shifted_operation; | |
| 917 } | |
| 918 | |
| 908 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 919 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 909 LOperand* right = | 920 LOperand* right = |
| 910 UseRegisterOrConstantAtStart(instr->BetterRightOperand()); | 921 UseRegisterOrConstantAtStart(instr->BetterRightOperand()); |
| 911 return instr->representation().IsSmi() ? | 922 return instr->representation().IsSmi() ? |
| 912 DefineAsRegister(new(zone()) LBitS(left, right)) : | 923 DefineAsRegister(new(zone()) LBitS(left, right)) : |
| 913 DefineAsRegister(new(zone()) LBitI(left, right)); | 924 DefineAsRegister(new(zone()) LBitI(left, right)); |
| 914 } else { | 925 } else { |
| 915 return DoArithmeticT(instr->op(), instr); | 926 return DoArithmeticT(instr->op(), instr); |
| 916 } | 927 } |
| 917 } | 928 } |
| (...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2023 : UseRegisterOrConstant(instr->index()); | 2034 : UseRegisterOrConstant(instr->index()); |
| 2024 LOperand* value = UseRegister(instr->value()); | 2035 LOperand* value = UseRegister(instr->value()); |
| 2025 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; | 2036 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; |
| 2026 LOperand* temp = TempRegister(); | 2037 LOperand* temp = TempRegister(); |
| 2027 LSeqStringSetChar* result = | 2038 LSeqStringSetChar* result = |
| 2028 new(zone()) LSeqStringSetChar(context, string, index, value, temp); | 2039 new(zone()) LSeqStringSetChar(context, string, index, value, temp); |
| 2029 return DefineAsRegister(result); | 2040 return DefineAsRegister(result); |
| 2030 } | 2041 } |
| 2031 | 2042 |
| 2032 | 2043 |
| 2044 HBitwiseBinaryOperation* LChunkBuilder::CanTransformToShiftedOp(HValue* val, | |
| 2045 HValue** left) { | |
| 2046 if (!val->representation().IsInteger32()) return NULL; | |
| 2047 if (!val->IsBitwise() && !(val->IsAdd() || val->IsSub())) return NULL; | |
|
ulan
2014/05/02 10:01:18
Simpler condition: !(val->IsBitwise() || val->IsAd
Alexandre Rames
2014/05/02 13:51:44
Done.
| |
| 2048 | |
| 2049 HBinaryOperation* hinstr = HBinaryOperation::cast(val); | |
| 2050 HValue* hleft = hinstr->left(); | |
| 2051 HValue* hright = hinstr->right(); | |
| 2052 ASSERT(hleft->representation().Equals(hinstr->representation())); | |
| 2053 ASSERT(hright->representation().Equals(hinstr->representation())); | |
| 2054 | |
| 2055 if ((hright->IsConstant() && | |
| 2056 LikelyFitsImmField(hinstr, HConstant::cast(hright)->Integer32Value())) || | |
| 2057 (hinstr->IsCommutative() && hleft->IsConstant() && | |
| 2058 LikelyFitsImmField(hinstr, HConstant::cast(hleft)->Integer32Value()))) { | |
| 2059 // The constant operand will likely fit in the immediate field. We are | |
| 2060 // better off with | |
| 2061 // lsl x8, x9, #imm | |
| 2062 // add x0, x8, #imm2 | |
| 2063 // than with | |
| 2064 // mov x16, #imm2 | |
| 2065 // add x0, x16, x9 LSL #imm | |
| 2066 return NULL; | |
| 2067 } | |
| 2068 | |
| 2069 HBitwiseBinaryOperation* shift = NULL; | |
| 2070 // TODO(aleram): We will miss situations where a shift operation is used by | |
| 2071 // different instructions both as a left and right operands. | |
| 2072 if (hright->IsBitwiseBinaryShift() && | |
| 2073 HBitwiseBinaryOperation::cast(hright)->right()->IsConstant()) { | |
| 2074 shift = HBitwiseBinaryOperation::cast(hright); | |
| 2075 if (left != NULL) { | |
| 2076 *left = hleft; | |
| 2077 } | |
| 2078 } else if (hinstr->IsCommutative() && | |
| 2079 hleft->IsBitwiseBinaryShift() && | |
| 2080 HBitwiseBinaryOperation::cast(hleft)->right()->IsConstant()) { | |
| 2081 shift = HBitwiseBinaryOperation::cast(hleft); | |
| 2082 if (left != NULL) { | |
| 2083 *left = hright; | |
| 2084 } | |
| 2085 } else { | |
| 2086 return NULL; | |
| 2087 } | |
| 2088 | |
| 2089 if ((ShiftAmountFromHConstant(shift->right()) == 0) && shift->IsShr()) { | |
| 2090 // Shifts right by zero can deoptimize. | |
| 2091 return NULL; | |
| 2092 } | |
| 2093 | |
| 2094 return shift; | |
| 2095 } | |
| 2096 | |
| 2097 | |
| 2098 bool LChunkBuilder::ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift) { | |
| 2099 if (!shift->representation().IsInteger32()) { | |
| 2100 return false; | |
| 2101 } | |
| 2102 for (HUseIterator it(shift->uses()); !it.Done(); it.Advance()) { | |
| 2103 if (shift != CanTransformToShiftedOp(it.value())) { | |
| 2104 return false; | |
| 2105 } | |
| 2106 } | |
| 2107 return true; | |
| 2108 } | |
| 2109 | |
| 2110 | |
| 2111 LInstruction* LChunkBuilder::TryDoOpWithShiftedRightOperand( | |
| 2112 HBinaryOperation* instr) { | |
| 2113 HValue* left; | |
| 2114 HBitwiseBinaryOperation* shift = CanTransformToShiftedOp(instr, &left); | |
| 2115 | |
| 2116 if ((shift != NULL) && ShiftCanBeOptimizedAway(shift)) { | |
| 2117 return DoShiftedBinaryOp(instr, left, shift); | |
| 2118 } | |
| 2119 return NULL; | |
| 2120 } | |
| 2121 | |
| 2122 | |
| 2123 LInstruction* LChunkBuilder::DoShiftedBinaryOp( | |
| 2124 HBinaryOperation* hinstr, HValue* hleft, HBitwiseBinaryOperation* hshift) { | |
| 2125 ASSERT(hshift->IsBitwiseBinaryShift()); | |
| 2126 ASSERT(!hshift->IsShr() || (ShiftAmountFromHConstant(hshift->right()) > 0)); | |
| 2127 | |
| 2128 LTemplateResultInstruction<1>* res; | |
| 2129 LOperand* left = UseRegisterAtStart(hleft); | |
| 2130 LOperand* right = UseRegisterAtStart(hshift->left()); | |
| 2131 LOperand* shift_amount = UseConstant(hshift->right()); | |
| 2132 Shift shift_op; | |
| 2133 switch (hshift->opcode()) { | |
| 2134 case HValue::kShl: shift_op = LSL; break; | |
| 2135 case HValue::kShr: shift_op = LSR; break; | |
| 2136 case HValue::kSar: shift_op = ASR; break; | |
| 2137 default: UNREACHABLE(); shift_op = NO_SHIFT; | |
| 2138 } | |
| 2139 bool can_overflow = hinstr->CheckFlag(HValue::kCanOverflow); | |
|
ulan
2014/05/02 10:01:18
You can inline hinstr->CheckFlag(HValue::kCanOverf
Alexandre Rames
2014/05/02 13:51:44
Done.
| |
| 2140 | |
| 2141 if (hinstr->IsBitwise()) { | |
| 2142 res = new(zone()) LBitI(left, right, shift_op, shift_amount); | |
| 2143 } else if (hinstr->IsAdd()) { | |
| 2144 res = new(zone()) LAddI(left, right, shift_op, shift_amount); | |
| 2145 } else if (hinstr->IsSub()) { | |
| 2146 res = new(zone()) LSubI(left, right, shift_op, shift_amount); | |
| 2147 } else { | |
| 2148 UNREACHABLE(); | |
|
ulan
2014/05/02 10:01:18
nit: I'd ASSERT(hinstr->IsSub()) above.
Alexandre Rames
2014/05/02 13:51:44
Done.
| |
| 2149 res = NULL; | |
| 2150 } | |
| 2151 if (can_overflow) { | |
| 2152 AssignEnvironment(res); | |
| 2153 } | |
| 2154 return DefineAsRegister(res); | |
| 2155 } | |
| 2156 | |
| 2157 | |
| 2033 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 2158 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 2034 HBitwiseBinaryOperation* instr) { | 2159 HBitwiseBinaryOperation* instr) { |
| 2035 if (instr->representation().IsTagged()) { | 2160 if (instr->representation().IsTagged()) { |
| 2036 return DoArithmeticT(op, instr); | 2161 return DoArithmeticT(op, instr); |
| 2037 } | 2162 } |
| 2038 | 2163 |
| 2039 ASSERT(instr->representation().IsInteger32() || | 2164 ASSERT(instr->representation().IsInteger32() || |
| 2040 instr->representation().IsSmi()); | 2165 instr->representation().IsSmi()); |
| 2041 ASSERT(instr->left()->representation().Equals(instr->representation())); | 2166 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 2042 ASSERT(instr->right()->representation().Equals(instr->representation())); | 2167 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 2043 | 2168 |
| 2169 if (ShiftCanBeOptimizedAway(instr)) { | |
| 2170 return NULL; | |
| 2171 } | |
| 2172 | |
| 2044 LOperand* left = instr->representation().IsSmi() | 2173 LOperand* left = instr->representation().IsSmi() |
| 2045 ? UseRegister(instr->left()) | 2174 ? UseRegister(instr->left()) |
| 2046 : UseRegisterAtStart(instr->left()); | 2175 : UseRegisterAtStart(instr->left()); |
| 2047 | 2176 |
| 2048 HValue* right_value = instr->right(); | 2177 HValue* right_value = instr->right(); |
| 2049 LOperand* right = NULL; | 2178 LOperand* right = NULL; |
| 2050 LOperand* temp = NULL; | 2179 LOperand* temp = NULL; |
| 2051 int constant_value = 0; | 2180 int constant_value = 0; |
| 2052 if (right_value->IsConstant()) { | 2181 if (right_value->IsConstant()) { |
| 2053 right = UseConstant(right_value); | 2182 right = UseConstant(right_value); |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2307 LStringCompareAndBranch* result = | 2436 LStringCompareAndBranch* result = |
| 2308 new(zone()) LStringCompareAndBranch(context, left, right); | 2437 new(zone()) LStringCompareAndBranch(context, left, right); |
| 2309 return MarkAsCall(result, instr); | 2438 return MarkAsCall(result, instr); |
| 2310 } | 2439 } |
| 2311 | 2440 |
| 2312 | 2441 |
| 2313 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 2442 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 2314 if (instr->representation().IsSmiOrInteger32()) { | 2443 if (instr->representation().IsSmiOrInteger32()) { |
| 2315 ASSERT(instr->left()->representation().Equals(instr->representation())); | 2444 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 2316 ASSERT(instr->right()->representation().Equals(instr->representation())); | 2445 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 2446 | |
| 2447 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr); | |
| 2448 if (shifted_operation != NULL) { | |
| 2449 return shifted_operation; | |
| 2450 } | |
| 2451 | |
| 2317 LOperand *left; | 2452 LOperand *left; |
| 2318 if (instr->left()->IsConstant() && | 2453 if (instr->left()->IsConstant() && |
| 2319 (HConstant::cast(instr->left())->Integer32Value() == 0)) { | 2454 (HConstant::cast(instr->left())->Integer32Value() == 0)) { |
| 2320 left = UseConstant(instr->left()); | 2455 left = UseConstant(instr->left()); |
| 2321 } else { | 2456 } else { |
| 2322 left = UseRegisterAtStart(instr->left()); | 2457 left = UseRegisterAtStart(instr->left()); |
| 2323 } | 2458 } |
| 2324 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); | 2459 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
| 2325 LInstruction* result = instr->representation().IsSmi() ? | 2460 LInstruction* result = instr->representation().IsSmi() ? |
| 2326 DefineAsRegister(new(zone()) LSubS(left, right)) : | 2461 DefineAsRegister(new(zone()) LSubS(left, right)) : |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2553 | 2688 |
| 2554 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 2689 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
| 2555 LOperand* receiver = UseRegister(instr->receiver()); | 2690 LOperand* receiver = UseRegister(instr->receiver()); |
| 2556 LOperand* function = UseRegister(instr->function()); | 2691 LOperand* function = UseRegister(instr->function()); |
| 2557 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); | 2692 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); |
| 2558 return AssignEnvironment(DefineAsRegister(result)); | 2693 return AssignEnvironment(DefineAsRegister(result)); |
| 2559 } | 2694 } |
| 2560 | 2695 |
| 2561 | 2696 |
| 2562 } } // namespace v8::internal | 2697 } } // namespace v8::internal |
| OLD | NEW |