OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 if (context->upper_bound() == length() && | 1027 if (context->upper_bound() == length() && |
1028 context->lower_bound_guarantee() != NULL && | 1028 context->lower_bound_guarantee() != NULL && |
1029 context->lower_bound_guarantee() != this && | 1029 context->lower_bound_guarantee() != this && |
1030 context->lower_bound_guarantee()->block() != block() && | 1030 context->lower_bound_guarantee()->block() != block() && |
1031 offset() < context->offset() && | 1031 offset() < context->offset() && |
1032 index_can_increase() && | 1032 index_can_increase() && |
1033 context->upper_bound_guarantee() == NULL) { | 1033 context->upper_bound_guarantee() == NULL) { |
1034 offset_ = context->offset(); | 1034 offset_ = context->offset(); |
1035 SetResponsibilityForRange(DIRECTION_UPPER); | 1035 SetResponsibilityForRange(DIRECTION_UPPER); |
1036 context->set_upper_bound_guarantee(this); | 1036 context->set_upper_bound_guarantee(this); |
| 1037 isolate()->counters()->bounds_checks_eliminated()->Increment(); |
1037 } else if (context->upper_bound_guarantee() != NULL && | 1038 } else if (context->upper_bound_guarantee() != NULL && |
1038 context->upper_bound_guarantee() != this && | 1039 context->upper_bound_guarantee() != this && |
1039 context->upper_bound_guarantee()->block() != block() && | 1040 context->upper_bound_guarantee()->block() != block() && |
1040 offset() > context->offset() && | 1041 offset() > context->offset() && |
1041 index_can_decrease() && | 1042 index_can_decrease() && |
1042 context->lower_bound_guarantee() == NULL) { | 1043 context->lower_bound_guarantee() == NULL) { |
1043 offset_ = context->offset(); | 1044 offset_ = context->offset(); |
1044 SetResponsibilityForRange(DIRECTION_LOWER); | 1045 SetResponsibilityForRange(DIRECTION_LOWER); |
1045 context->set_lower_bound_guarantee(this); | 1046 context->set_lower_bound_guarantee(this); |
| 1047 isolate()->counters()->bounds_checks_eliminated()->Increment(); |
1046 } | 1048 } |
1047 } | 1049 } |
1048 | 1050 |
1049 | 1051 |
1050 void HBoundsCheck::ApplyIndexChange() { | 1052 void HBoundsCheck::ApplyIndexChange() { |
1051 if (skip_check()) return; | 1053 if (skip_check()) return; |
1052 | 1054 |
1053 DecompositionResult decomposition; | 1055 DecompositionResult decomposition; |
1054 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 1056 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
1055 if (index_is_decomposable) { | 1057 if (index_is_decomposable) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 scale_ = 0; | 1098 scale_ = 0; |
1097 responsibility_direction_ = DIRECTION_NONE; | 1099 responsibility_direction_ = DIRECTION_NONE; |
1098 } | 1100 } |
1099 | 1101 |
1100 | 1102 |
1101 void HBoundsCheck::AddInformativeDefinitions() { | 1103 void HBoundsCheck::AddInformativeDefinitions() { |
1102 // TODO(mmassi): Executing this code during AddInformativeDefinitions | 1104 // TODO(mmassi): Executing this code during AddInformativeDefinitions |
1103 // is a hack. Move it to some other HPhase. | 1105 // is a hack. Move it to some other HPhase. |
1104 if (FLAG_array_bounds_checks_elimination) { | 1106 if (FLAG_array_bounds_checks_elimination) { |
1105 if (index()->TryGuaranteeRange(length())) { | 1107 if (index()->TryGuaranteeRange(length())) { |
1106 set_skip_check(true); | 1108 set_skip_check(); |
1107 } | 1109 } |
1108 if (DetectCompoundIndex()) { | 1110 if (DetectCompoundIndex()) { |
1109 HBoundsCheckBaseIndexInformation* base_index_info = | 1111 HBoundsCheckBaseIndexInformation* base_index_info = |
1110 new(block()->graph()->zone()) | 1112 new(block()->graph()->zone()) |
1111 HBoundsCheckBaseIndexInformation(this); | 1113 HBoundsCheckBaseIndexInformation(this); |
1112 base_index_info->InsertAfter(this); | 1114 base_index_info->InsertAfter(this); |
1113 } | 1115 } |
1114 } | 1116 } |
1115 } | 1117 } |
1116 | 1118 |
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1961 result = false; | 1963 result = false; |
1962 break; | 1964 break; |
1963 } | 1965 } |
1964 } | 1966 } |
1965 ClearFlag(kNumericConstraintEvaluationInProgress); | 1967 ClearFlag(kNumericConstraintEvaluationInProgress); |
1966 | 1968 |
1967 return result; | 1969 return result; |
1968 } | 1970 } |
1969 | 1971 |
1970 | 1972 |
| 1973 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { |
| 1974 if (phi->block()->loop_information() == NULL) return NULL; |
| 1975 if (phi->OperandCount() != 2) return NULL; |
| 1976 int32_t candidate_increment; |
| 1977 |
| 1978 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); |
| 1979 if (candidate_increment != 0) { |
| 1980 return new(phi->block()->graph()->zone()) |
| 1981 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); |
| 1982 } |
| 1983 |
| 1984 candidate_increment = ComputeIncrement(phi, phi->OperandAt(1)); |
| 1985 if (candidate_increment != 0) { |
| 1986 return new(phi->block()->graph()->zone()) |
| 1987 InductionVariableData(phi, phi->OperandAt(0), candidate_increment); |
| 1988 } |
| 1989 |
| 1990 return NULL; |
| 1991 } |
| 1992 |
| 1993 |
| 1994 /* |
| 1995 * This function tries to match the following patterns (and all the relevant |
| 1996 * variants related to |, & and + being commutative): |
| 1997 * base | constant_or_mask |
| 1998 * base & constant_and_mask |
| 1999 * (base + constant_offset) & constant_and_mask |
| 2000 * (base - constant_offset) & constant_and_mask |
| 2001 */ |
| 2002 void InductionVariableData::DecomposeBitwise( |
| 2003 HValue* value, |
| 2004 BitwiseDecompositionResult* result) { |
| 2005 HValue* base = IgnoreOsrValue(value); |
| 2006 result->base = value; |
| 2007 |
| 2008 if (!base->representation().IsInteger32()) return; |
| 2009 |
| 2010 if (base->IsBitwise()) { |
| 2011 bool allow_offset = false; |
| 2012 int32_t mask = 0; |
| 2013 |
| 2014 HBitwise* bitwise = HBitwise::cast(base); |
| 2015 if (bitwise->right()->IsInteger32Constant()) { |
| 2016 mask = bitwise->right()->GetInteger32Constant(); |
| 2017 base = bitwise->left(); |
| 2018 } else if (bitwise->left()->IsInteger32Constant()) { |
| 2019 mask = bitwise->left()->GetInteger32Constant(); |
| 2020 base = bitwise->right(); |
| 2021 } else { |
| 2022 return; |
| 2023 } |
| 2024 if (bitwise->op() == Token::BIT_AND) { |
| 2025 result->and_mask = mask; |
| 2026 allow_offset = true; |
| 2027 } else if (bitwise->op() == Token::BIT_OR) { |
| 2028 result->or_mask = mask; |
| 2029 } else { |
| 2030 return; |
| 2031 } |
| 2032 |
| 2033 result->context = bitwise->context(); |
| 2034 |
| 2035 if (allow_offset) { |
| 2036 if (base->IsAdd()) { |
| 2037 HAdd* add = HAdd::cast(base); |
| 2038 if (add->right()->IsInteger32Constant()) { |
| 2039 base = add->left(); |
| 2040 } else if (add->left()->IsInteger32Constant()) { |
| 2041 base = add->right(); |
| 2042 } |
| 2043 } else if (base->IsSub()) { |
| 2044 HSub* sub = HSub::cast(base); |
| 2045 if (sub->right()->IsInteger32Constant()) { |
| 2046 base = sub->left(); |
| 2047 } |
| 2048 } |
| 2049 } |
| 2050 |
| 2051 result->base = base; |
| 2052 } |
| 2053 } |
| 2054 |
| 2055 |
| 2056 void InductionVariableData::AddCheck(HBoundsCheck* check, |
| 2057 int32_t upper_limit) { |
| 2058 ASSERT(limit_validity() != NULL); |
| 2059 if (limit_validity() != check->block() && |
| 2060 !limit_validity()->Dominates(check->block())) return; |
| 2061 if (!phi()->block()->current_loop()->IsNestedInThisLoop( |
| 2062 check->block()->current_loop())) return; |
| 2063 |
| 2064 ChecksRelatedToLength* length_checks = checks(); |
| 2065 while (length_checks != NULL) { |
| 2066 if (length_checks->length() == check->length()) break; |
| 2067 length_checks = length_checks->next(); |
| 2068 } |
| 2069 if (length_checks == NULL) { |
| 2070 length_checks = new(check->block()->zone()) |
| 2071 ChecksRelatedToLength(check->length(), checks()); |
| 2072 checks_ = length_checks; |
| 2073 } |
| 2074 |
| 2075 length_checks->AddCheck(check, upper_limit); |
| 2076 } |
| 2077 |
| 2078 |
| 2079 void InductionVariableData::ChecksRelatedToLength::CloseCurrentBlock() { |
| 2080 if (checks() != NULL) { |
| 2081 InductionVariableCheck* c = checks(); |
| 2082 HBasicBlock* current_block = c->check()->block(); |
| 2083 while (c != NULL && c->check()->block() == current_block) { |
| 2084 c->set_upper_limit(current_upper_limit_); |
| 2085 c = c->next(); |
| 2086 } |
| 2087 } |
| 2088 } |
| 2089 |
| 2090 |
| 2091 void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock( |
| 2092 Token::Value token, |
| 2093 int32_t mask, |
| 2094 HValue* index_base, |
| 2095 HValue* context) { |
| 2096 ASSERT(first_check_in_block() != NULL); |
| 2097 HValue* previous_index = first_check_in_block()->index(); |
| 2098 ASSERT(context != NULL); |
| 2099 |
| 2100 set_added_constant(new(index_base->block()->graph()->zone()) HConstant( |
| 2101 mask, index_base->representation())); |
| 2102 if (added_index() != NULL) { |
| 2103 added_constant()->InsertBefore(added_index()); |
| 2104 } else { |
| 2105 added_constant()->InsertBefore(first_check_in_block()); |
| 2106 } |
| 2107 |
| 2108 if (added_index() == NULL) { |
| 2109 first_check_in_block()->ReplaceAllUsesWith(first_check_in_block()->index()); |
| 2110 HInstruction* new_index = HBitwise::New( |
| 2111 index_base->block()->graph()->zone(), |
| 2112 token, context, index_base, added_constant()); |
| 2113 ASSERT(new_index->IsBitwise()); |
| 2114 new_index->ClearAllSideEffects(); |
| 2115 new_index->AssumeRepresentation(Representation::Integer32()); |
| 2116 set_added_index(HBitwise::cast(new_index)); |
| 2117 added_index()->InsertBefore(first_check_in_block()); |
| 2118 } |
| 2119 ASSERT(added_index()->op() == token); |
| 2120 |
| 2121 added_index()->SetOperandAt(1, index_base); |
| 2122 added_index()->SetOperandAt(2, added_constant()); |
| 2123 first_check_in_block()->SetOperandAt(0, added_index()); |
| 2124 if (previous_index->UseCount() == 0) { |
| 2125 previous_index->DeleteAndReplaceWith(NULL); |
| 2126 } |
| 2127 } |
| 2128 |
| 2129 void InductionVariableData::ChecksRelatedToLength::AddCheck( |
| 2130 HBoundsCheck* check, |
| 2131 int32_t upper_limit) { |
| 2132 BitwiseDecompositionResult decomposition; |
| 2133 InductionVariableData::DecomposeBitwise(check->index(), &decomposition); |
| 2134 |
| 2135 if (first_check_in_block() == NULL || |
| 2136 first_check_in_block()->block() != check->block()) { |
| 2137 CloseCurrentBlock(); |
| 2138 |
| 2139 first_check_in_block_ = check; |
| 2140 set_added_index(NULL); |
| 2141 set_added_constant(NULL); |
| 2142 current_and_mask_in_block_ = decomposition.and_mask; |
| 2143 current_or_mask_in_block_ = decomposition.or_mask; |
| 2144 current_upper_limit_ = upper_limit; |
| 2145 |
| 2146 InductionVariableCheck* new_check = new(check->block()->graph()->zone()) |
| 2147 InductionVariableCheck(check, checks_, upper_limit); |
| 2148 checks_ = new_check; |
| 2149 return; |
| 2150 } |
| 2151 |
| 2152 if (upper_limit > current_upper_limit()) { |
| 2153 current_upper_limit_ = upper_limit; |
| 2154 } |
| 2155 |
| 2156 if (decomposition.and_mask != 0 && |
| 2157 current_or_mask_in_block() == 0) { |
| 2158 if (current_and_mask_in_block() == 0 || |
| 2159 decomposition.and_mask > current_and_mask_in_block()) { |
| 2160 UseNewIndexInCurrentBlock(Token::BIT_AND, |
| 2161 decomposition.and_mask, |
| 2162 decomposition.base, |
| 2163 decomposition.context); |
| 2164 current_and_mask_in_block_ = decomposition.and_mask; |
| 2165 } |
| 2166 check->set_skip_check(); |
| 2167 } |
| 2168 if (current_and_mask_in_block() == 0) { |
| 2169 if (decomposition.or_mask > current_or_mask_in_block()) { |
| 2170 UseNewIndexInCurrentBlock(Token::BIT_OR, |
| 2171 decomposition.or_mask, |
| 2172 decomposition.base, |
| 2173 decomposition.context); |
| 2174 current_or_mask_in_block_ = decomposition.or_mask; |
| 2175 } |
| 2176 check->set_skip_check(); |
| 2177 } |
| 2178 |
| 2179 if (!check->skip_check()) { |
| 2180 InductionVariableCheck* new_check = new(check->block()->graph()->zone()) |
| 2181 InductionVariableCheck(check, checks_, upper_limit); |
| 2182 checks_ = new_check; |
| 2183 } |
| 2184 } |
| 2185 |
| 2186 |
| 2187 /* |
| 2188 * This method detects if phi is an induction variable, with phi_operand as |
| 2189 * its "incremented" value (the other operand would be the "base" value). |
| 2190 * |
| 2191 * It cheks is phi_operand has the form "phi + constant". |
| 2192 * If yes, the constant is the increment that the induction variable gets at |
| 2193 * every loop iteration. |
| 2194 * Otherwise it returns 0. |
| 2195 */ |
| 2196 int32_t InductionVariableData::ComputeIncrement(HPhi* phi, |
| 2197 HValue* phi_operand) { |
| 2198 if (!phi_operand->representation().IsInteger32()) return 0; |
| 2199 |
| 2200 if (phi_operand->IsAdd()) { |
| 2201 HAdd* operation = HAdd::cast(phi_operand); |
| 2202 if (operation->left() == phi && |
| 2203 operation->right()->IsInteger32Constant()) { |
| 2204 return operation->right()->GetInteger32Constant(); |
| 2205 } else if (operation->right() == phi && |
| 2206 operation->left()->IsInteger32Constant()) { |
| 2207 return operation->left()->GetInteger32Constant(); |
| 2208 } |
| 2209 } else if (phi_operand->IsSub()) { |
| 2210 HSub* operation = HSub::cast(phi_operand); |
| 2211 if (operation->left() == phi && |
| 2212 operation->right()->IsInteger32Constant()) { |
| 2213 return -operation->right()->GetInteger32Constant(); |
| 2214 } |
| 2215 } |
| 2216 |
| 2217 return 0; |
| 2218 } |
| 2219 |
| 2220 |
| 2221 /* |
| 2222 * Swaps the information in "update" with the one contained in "this". |
| 2223 * The swapping is important because this method is used while doing a |
| 2224 * dominator tree traversal, and "update" will retain the old data that |
| 2225 * will be restored while backtracking. |
| 2226 */ |
| 2227 void InductionVariableData::UpdateAdditionalLimit( |
| 2228 InductionVariableLimitUpdate* update) { |
| 2229 ASSERT(update->updated_variable == this); |
| 2230 if (update->limit_is_upper) { |
| 2231 swap(&additional_upper_limit_, &update->limit); |
| 2232 swap(&additional_upper_limit_is_included_, &update->limit_is_included); |
| 2233 } else { |
| 2234 swap(&additional_lower_limit_, &update->limit); |
| 2235 swap(&additional_lower_limit_is_included_, &update->limit_is_included); |
| 2236 } |
| 2237 } |
| 2238 |
| 2239 |
| 2240 int32_t InductionVariableData::ComputeUpperLimit(int32_t and_mask, |
| 2241 int32_t or_mask) { |
| 2242 // Should be Smi::kMaxValue but it must fit 32 bits; lower is safe anyway. |
| 2243 const int32_t MAX_LIMIT = 1 << 30; |
| 2244 |
| 2245 int32_t result = MAX_LIMIT; |
| 2246 |
| 2247 if (limit() != NULL && |
| 2248 limit()->IsInteger32Constant()) { |
| 2249 int32_t limit_value = limit()->GetInteger32Constant(); |
| 2250 if (!limit_included()) { |
| 2251 limit_value--; |
| 2252 } |
| 2253 if (limit_value < result) result = limit_value; |
| 2254 } |
| 2255 |
| 2256 if (additional_upper_limit() != NULL && |
| 2257 additional_upper_limit()->IsInteger32Constant()) { |
| 2258 int32_t limit_value = additional_upper_limit()->GetInteger32Constant(); |
| 2259 if (!additional_upper_limit_is_included()) { |
| 2260 limit_value--; |
| 2261 } |
| 2262 if (limit_value < result) result = limit_value; |
| 2263 } |
| 2264 |
| 2265 if (and_mask > 0 && and_mask < MAX_LIMIT) { |
| 2266 if (and_mask < result) result = and_mask; |
| 2267 return result; |
| 2268 } |
| 2269 |
| 2270 // Add the effect of the or_mask. |
| 2271 result |= or_mask; |
| 2272 |
| 2273 return result >= MAX_LIMIT ? kNoLimit : result; |
| 2274 } |
| 2275 |
| 2276 |
| 2277 HValue* InductionVariableData::IgnoreOsrValue(HValue* v) { |
| 2278 if (!v->IsPhi()) return v; |
| 2279 HPhi* phi = HPhi::cast(v); |
| 2280 if (phi->OperandCount() != 2) return v; |
| 2281 if (phi->OperandAt(0)->block()->is_osr_entry()) { |
| 2282 return phi->OperandAt(1); |
| 2283 } else if (phi->OperandAt(1)->block()->is_osr_entry()) { |
| 2284 return phi->OperandAt(0); |
| 2285 } else { |
| 2286 return v; |
| 2287 } |
| 2288 } |
| 2289 |
| 2290 |
| 2291 InductionVariableData* InductionVariableData::GetInductionVariableData( |
| 2292 HValue* v) { |
| 2293 v = IgnoreOsrValue(v); |
| 2294 if (v->IsPhi()) { |
| 2295 return HPhi::cast(v)->induction_variable_data(); |
| 2296 } |
| 2297 return NULL; |
| 2298 } |
| 2299 |
| 2300 |
| 2301 /* |
| 2302 * Check if a conditional branch to "current_branch" with token "token" is |
| 2303 * the branch that keeps the induction loop running (and, conversely, will |
| 2304 * terminate it if the "other_branch" is taken). |
| 2305 * |
| 2306 * Three conditions must be met: |
| 2307 * - "current_branch" must be in the induction loop. |
| 2308 * - "other_branch" must be out of the induction loop. |
| 2309 * - "token" and the induction increment must be "compatible": the token should |
| 2310 * be a condition that keeps the execution inside the loop until the limit is |
| 2311 * reached. |
| 2312 */ |
| 2313 bool InductionVariableData::CheckIfBranchIsLoopGuard( |
| 2314 Token::Value token, |
| 2315 HBasicBlock* current_branch, |
| 2316 HBasicBlock* other_branch) { |
| 2317 if (!phi()->block()->current_loop()->IsNestedInThisLoop( |
| 2318 current_branch->current_loop())) { |
| 2319 return false; |
| 2320 } |
| 2321 |
| 2322 if (phi()->block()->current_loop()->IsNestedInThisLoop( |
| 2323 other_branch->current_loop())) { |
| 2324 return false; |
| 2325 } |
| 2326 |
| 2327 if (increment() > 0 && (token == Token::LT || token == Token::LTE)) { |
| 2328 return true; |
| 2329 } |
| 2330 if (increment() < 0 && (token == Token::GT || token == Token::GTE)) { |
| 2331 return true; |
| 2332 } |
| 2333 if (Token::IsInequalityOp(token) && (increment() == 1 || increment() == -1)) { |
| 2334 return true; |
| 2335 } |
| 2336 |
| 2337 return false; |
| 2338 } |
| 2339 |
| 2340 |
| 2341 void InductionVariableData::ComputeLimitFromPredecessorBlock( |
| 2342 HBasicBlock* block, |
| 2343 LimitFromPredecessorBlock* result) { |
| 2344 if (block->predecessors()->length() != 1) return; |
| 2345 HBasicBlock* predecessor = block->predecessors()->at(0); |
| 2346 HInstruction* end = predecessor->last(); |
| 2347 |
| 2348 if (!end->IsCompareNumericAndBranch()) return; |
| 2349 HCompareNumericAndBranch* branch = HCompareNumericAndBranch::cast(end); |
| 2350 |
| 2351 Token::Value token = branch->token(); |
| 2352 if (!Token::IsArithmeticCompareOp(token)) return; |
| 2353 |
| 2354 HBasicBlock* other_target; |
| 2355 if (block == branch->SuccessorAt(0)) { |
| 2356 other_target = branch->SuccessorAt(1); |
| 2357 } else { |
| 2358 other_target = branch->SuccessorAt(0); |
| 2359 token = Token::NegateCompareOp(token); |
| 2360 ASSERT(block == branch->SuccessorAt(1)); |
| 2361 } |
| 2362 |
| 2363 InductionVariableData* data; |
| 2364 |
| 2365 data = GetInductionVariableData(branch->left()); |
| 2366 HValue* limit = branch->right(); |
| 2367 if (data == NULL) { |
| 2368 data = GetInductionVariableData(branch->right()); |
| 2369 token = Token::ReverseCompareOp(token); |
| 2370 limit = branch->left(); |
| 2371 } |
| 2372 |
| 2373 if (data != NULL) { |
| 2374 result->variable = data; |
| 2375 result->token = token; |
| 2376 result->limit = limit; |
| 2377 result->other_target = other_target; |
| 2378 } |
| 2379 } |
| 2380 |
| 2381 |
| 2382 /* |
| 2383 * Compute the limit that is imposed on an induction variable when entering |
| 2384 * "block" (if any). |
| 2385 * If the limit is the "proper" induction limit (the one that makes the loop |
| 2386 * terminate when the induction variable reaches it) it is stored directly in |
| 2387 * the induction variable data. |
| 2388 * Otherwise the limit is written in "additional_limit" and the method |
| 2389 * returns true. |
| 2390 */ |
| 2391 bool InductionVariableData::ComputeInductionVariableLimit( |
| 2392 HBasicBlock* block, |
| 2393 InductionVariableLimitUpdate* additional_limit) { |
| 2394 LimitFromPredecessorBlock limit; |
| 2395 ComputeLimitFromPredecessorBlock(block, &limit); |
| 2396 if (!limit.LimitIsValid()) return false; |
| 2397 |
| 2398 if (limit.variable->CheckIfBranchIsLoopGuard(limit.token, |
| 2399 block, |
| 2400 limit.other_target)) { |
| 2401 limit.variable->limit_ = limit.limit; |
| 2402 limit.variable->limit_included_ = limit.LimitIsIncluded(); |
| 2403 limit.variable->limit_validity_ = block; |
| 2404 limit.variable->induction_exit_block_ = block->predecessors()->at(0); |
| 2405 limit.variable->induction_exit_target_ = limit.other_target; |
| 2406 return false; |
| 2407 } else { |
| 2408 additional_limit->updated_variable = limit.variable; |
| 2409 additional_limit->limit = limit.limit; |
| 2410 additional_limit->limit_is_upper = limit.LimitIsUpper(); |
| 2411 additional_limit->limit_is_included = limit.LimitIsIncluded(); |
| 2412 return true; |
| 2413 } |
| 2414 } |
| 2415 |
| 2416 |
1971 Range* HMathMinMax::InferRange(Zone* zone) { | 2417 Range* HMathMinMax::InferRange(Zone* zone) { |
1972 if (representation().IsInteger32()) { | 2418 if (representation().IsInteger32()) { |
1973 Range* a = left()->range(); | 2419 Range* a = left()->range(); |
1974 Range* b = right()->range(); | 2420 Range* b = right()->range(); |
1975 Range* res = a->Copy(zone); | 2421 Range* res = a->Copy(zone); |
1976 if (operation_ == kMathMax) { | 2422 if (operation_ == kMathMax) { |
1977 res->CombinedMax(b); | 2423 res->CombinedMax(b); |
1978 } else { | 2424 } else { |
1979 ASSERT(operation_ == kMathMin); | 2425 ASSERT(operation_ == kMathMin); |
1980 res->CombinedMin(b); | 2426 res->CombinedMin(b); |
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4045 case kBackingStore: | 4491 case kBackingStore: |
4046 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString()); | 4492 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString()); |
4047 stream->Add("[backing-store]"); | 4493 stream->Add("[backing-store]"); |
4048 break; | 4494 break; |
4049 } | 4495 } |
4050 | 4496 |
4051 stream->Add("@%d", offset()); | 4497 stream->Add("@%d", offset()); |
4052 } | 4498 } |
4053 | 4499 |
4054 } } // namespace v8::internal | 4500 } } // namespace v8::internal |
OLD | NEW |