| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1938 compiler->AddSlowPathCode(slow_path); | 1938 compiler->AddSlowPathCode(slow_path); |
| 1939 | 1939 |
| 1940 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); | 1940 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); |
| 1941 __ ldr(IP, Address(IP)); | 1941 __ ldr(IP, Address(IP)); |
| 1942 __ cmp(SP, ShifterOperand(IP)); | 1942 __ cmp(SP, ShifterOperand(IP)); |
| 1943 __ b(slow_path->entry_label(), LS); | 1943 __ b(slow_path->entry_label(), LS); |
| 1944 __ Bind(slow_path->exit_label()); | 1944 __ Bind(slow_path->exit_label()); |
| 1945 } | 1945 } |
| 1946 | 1946 |
| 1947 | 1947 |
| 1948 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 1949 BinarySmiOpInstr* shift_left) { |
| 1950 const bool is_truncating = shift_left->is_truncating(); |
| 1951 const LocationSummary& locs = *shift_left->locs(); |
| 1952 Register left = locs.in(0).reg(); |
| 1953 Register result = locs.out().reg(); |
| 1954 Label* deopt = shift_left->CanDeoptimize() ? |
| 1955 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL; |
| 1956 if (locs.in(1).IsConstant()) { |
| 1957 const Object& constant = locs.in(1).constant(); |
| 1958 ASSERT(constant.IsSmi()); |
| 1959 // Immediate shift operation takes 5 bits for the count. |
| 1960 const intptr_t kCountLimit = 0x1F; |
| 1961 const intptr_t value = Smi::Cast(constant).Value(); |
| 1962 if (value == 0) { |
| 1963 // No code needed. |
| 1964 } else if ((value < 0) || (value >= kCountLimit)) { |
| 1965 // This condition may not be known earlier in some cases because |
| 1966 // of constant propagation, inlining, etc. |
| 1967 if ((value >=kCountLimit) && is_truncating) { |
| 1968 __ mov(result, ShifterOperand(0)); |
| 1969 } else { |
| 1970 // Result is Mint or exception. |
| 1971 __ b(deopt); |
| 1972 } |
| 1973 } else { |
| 1974 if (!is_truncating) { |
| 1975 // Check for overflow (preserve left). |
| 1976 __ Lsl(IP, left, value); |
| 1977 __ cmp(left, ShifterOperand(IP, ASR, value)); |
| 1978 __ b(deopt, NE); // Overflow. |
| 1979 } |
| 1980 // Shift for result now we know there is no overflow. |
| 1981 __ Lsl(result, left, value); |
| 1982 } |
| 1983 return; |
| 1984 } |
| 1985 |
| 1986 // Right (locs.in(1)) is not constant. |
| 1987 Register right = locs.in(1).reg(); |
| 1988 Range* right_range = shift_left->right()->definition()->range(); |
| 1989 if (shift_left->left()->BindsToConstant() && !is_truncating) { |
| 1990 // TODO(srdjan): Implement code below for is_truncating(). |
| 1991 // If left is constant, we know the maximal allowed size for right. |
| 1992 const Object& obj = shift_left->left()->BoundConstant(); |
| 1993 if (obj.IsSmi()) { |
| 1994 const intptr_t left_int = Smi::Cast(obj).Value(); |
| 1995 if (left_int == 0) { |
| 1996 __ cmp(right, ShifterOperand(0)); |
| 1997 __ b(deopt, MI); |
| 1998 return; |
| 1999 } |
| 2000 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2001 const bool right_needs_check = |
| 2002 (right_range == NULL) || |
| 2003 !right_range->IsWithin(0, max_right - 1); |
| 2004 if (right_needs_check) { |
| 2005 __ cmp(right, |
| 2006 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
| 2007 __ b(deopt, CS); |
| 2008 } |
| 2009 __ SmiUntag(right); |
| 2010 __ Lsl(result, left, right); |
| 2011 } |
| 2012 return; |
| 2013 } |
| 2014 |
| 2015 const bool right_needs_check = |
| 2016 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 2017 if (is_truncating) { |
| 2018 if (right_needs_check) { |
| 2019 const bool right_may_be_negative = |
| 2020 (right_range == NULL) || |
| 2021 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); |
| 2022 if (right_may_be_negative) { |
| 2023 ASSERT(shift_left->CanDeoptimize()); |
| 2024 __ cmp(right, ShifterOperand(0)); |
| 2025 __ b(deopt, MI); |
| 2026 } |
| 2027 Label done, is_not_zero; |
| 2028 __ cmp(right, |
| 2029 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 2030 __ mov(result, ShifterOperand(0), CS); |
| 2031 __ SmiUntag(right, CC); |
| 2032 __ Lsl(result, left, right, CC); |
| 2033 } else { |
| 2034 __ SmiUntag(right); |
| 2035 __ Lsl(result, left, right); |
| 2036 } |
| 2037 } else { |
| 2038 if (right_needs_check) { |
| 2039 ASSERT(shift_left->CanDeoptimize()); |
| 2040 __ cmp(right, |
| 2041 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 2042 __ b(deopt, CS); |
| 2043 } |
| 2044 // Left is not a constant. |
| 2045 // Check if count too large for handling it inlined. |
| 2046 __ SmiUntag(right); |
| 2047 // Overflow test (preserve left and right); |
| 2048 __ Lsl(IP, left, right); |
| 2049 __ cmp(left, ShifterOperand(IP, ASR, right)); |
| 2050 __ b(deopt, NE); // Overflow. |
| 2051 // Shift for result now we know there is no overflow. |
| 2052 __ Lsl(result, left, right); |
| 2053 } |
| 2054 } |
| 2055 |
| 2056 |
| 1948 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 2057 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1949 const intptr_t kNumInputs = 2; | 2058 const intptr_t kNumInputs = 2; |
| 1950 if (op_kind() == Token::kTRUNCDIV) { | 2059 if (op_kind() == Token::kTRUNCDIV) { |
| 1951 UNIMPLEMENTED(); | 2060 UNIMPLEMENTED(); |
| 1952 return NULL; | 2061 return NULL; |
| 1953 } else { | 2062 } else { |
| 1954 const intptr_t kNumTemps = 0; | 2063 const intptr_t kNumTemps = 0; |
| 1955 LocationSummary* summary = | 2064 LocationSummary* summary = |
| 1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1957 summary->set_in(0, Location::RequiresRegister()); | 2066 summary->set_in(0, Location::RequiresRegister()); |
| 1958 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2067 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1959 // We make use of 3-operand instructions by not requiring result register | 2068 // We make use of 3-operand instructions by not requiring result register |
| 1960 // to be identical to first input register as on Intel. | 2069 // to be identical to first input register as on Intel. |
| 1961 summary->set_out(Location::RequiresRegister()); | 2070 summary->set_out(Location::RequiresRegister()); |
| 1962 return summary; | 2071 return summary; |
| 1963 } | 2072 } |
| 1964 } | 2073 } |
| 1965 | 2074 |
| 1966 | 2075 |
| 1967 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2076 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1968 if (op_kind() == Token::kSHL) { | 2077 if (op_kind() == Token::kSHL) { |
| 1969 UNIMPLEMENTED(); | 2078 EmitSmiShiftLeft(compiler, this); |
| 1970 return; | 2079 return; |
| 1971 } | 2080 } |
| 1972 | 2081 |
| 1973 ASSERT(!is_truncating()); | 2082 ASSERT(!is_truncating()); |
| 1974 Register left = locs()->in(0).reg(); | 2083 Register left = locs()->in(0).reg(); |
| 1975 Register result = locs()->out().reg(); | 2084 Register result = locs()->out().reg(); |
| 1976 Label* deopt = NULL; | 2085 Label* deopt = NULL; |
| 1977 if (CanDeoptimize()) { | 2086 if (CanDeoptimize()) { |
| 1978 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 2087 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 1979 } | 2088 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 ShifterOperand shifter_op; | 2162 ShifterOperand shifter_op; |
| 2054 if (ShifterOperand::CanHold(imm, &shifter_op)) { | 2163 if (ShifterOperand::CanHold(imm, &shifter_op)) { |
| 2055 __ eor(result, left, shifter_op); | 2164 __ eor(result, left, shifter_op); |
| 2056 } else { | 2165 } else { |
| 2057 __ LoadImmediate(IP, imm); | 2166 __ LoadImmediate(IP, imm); |
| 2058 __ eor(result, left, ShifterOperand(IP)); | 2167 __ eor(result, left, ShifterOperand(IP)); |
| 2059 } | 2168 } |
| 2060 break; | 2169 break; |
| 2061 } | 2170 } |
| 2062 case Token::kSHR: { | 2171 case Token::kSHR: { |
| 2063 UNIMPLEMENTED(); | 2172 // sarl operation masks the count to 5 bits. |
| 2173 const intptr_t kCountLimit = 0x1F; |
| 2174 intptr_t value = Smi::Cast(constant).Value(); |
| 2175 |
| 2176 if (value == 0) { |
| 2177 // TODO(vegorov): should be handled outside. |
| 2178 break; |
| 2179 } else if (value < 0) { |
| 2180 // TODO(vegorov): should be handled outside. |
| 2181 __ b(deopt); |
| 2182 break; |
| 2183 } |
| 2184 |
| 2185 value = value + kSmiTagSize; |
| 2186 if (value >= kCountLimit) value = kCountLimit; |
| 2187 |
| 2188 __ Asr(result, left, value); |
| 2189 __ SmiTag(result); |
| 2064 break; | 2190 break; |
| 2065 } | 2191 } |
| 2066 | 2192 |
| 2067 default: | 2193 default: |
| 2068 UNREACHABLE(); | 2194 UNREACHABLE(); |
| 2069 break; | 2195 break; |
| 2070 } | 2196 } |
| 2071 return; | 2197 return; |
| 2072 } | 2198 } |
| 2073 | 2199 |
| (...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3023 compiler->GenerateCall(token_pos(), | 3149 compiler->GenerateCall(token_pos(), |
| 3024 &label, | 3150 &label, |
| 3025 PcDescriptors::kOther, | 3151 PcDescriptors::kOther, |
| 3026 locs()); | 3152 locs()); |
| 3027 __ Drop(2); // Discard type arguments and receiver. | 3153 __ Drop(2); // Discard type arguments and receiver. |
| 3028 } | 3154 } |
| 3029 | 3155 |
| 3030 } // namespace dart | 3156 } // namespace dart |
| 3031 | 3157 |
| 3032 #endif // defined TARGET_ARCH_ARM | 3158 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |