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