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 |