| 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/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 } | 1209 } |
| 1210 InvokeMathCFunctionInstr* invoke = | 1210 InvokeMathCFunctionInstr* invoke = |
| 1211 new(Z) InvokeMathCFunctionInstr(args, | 1211 new(Z) InvokeMathCFunctionInstr(args, |
| 1212 call->deopt_id(), | 1212 call->deopt_id(), |
| 1213 recognized_kind, | 1213 recognized_kind, |
| 1214 call->token_pos()); | 1214 call->token_pos()); |
| 1215 ReplaceCall(call, invoke); | 1215 ReplaceCall(call, invoke); |
| 1216 } | 1216 } |
| 1217 | 1217 |
| 1218 | 1218 |
| 1219 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | |
| 1220 switch (cid) { | |
| 1221 case kTypedDataInt8ArrayCid: | |
| 1222 case kTypedDataUint8ArrayCid: | |
| 1223 case kExternalTypedDataUint8ArrayCid: | |
| 1224 case kTypedDataUint8ClampedArrayCid: | |
| 1225 case kExternalTypedDataUint8ClampedArrayCid: | |
| 1226 case kTypedDataInt16ArrayCid: | |
| 1227 case kTypedDataUint16ArrayCid: | |
| 1228 case kTypedDataInt32ArrayCid: | |
| 1229 case kTypedDataUint32ArrayCid: | |
| 1230 case kTypedDataFloat32ArrayCid: | |
| 1231 case kTypedDataFloat64ArrayCid: | |
| 1232 case kTypedDataFloat32x4ArrayCid: | |
| 1233 case kTypedDataInt32x4ArrayCid: | |
| 1234 return true; | |
| 1235 default: | |
| 1236 return false; | |
| 1237 } | |
| 1238 } | |
| 1239 | |
| 1240 | |
| 1241 // Inline only simple, frequently called core library methods. | 1219 // Inline only simple, frequently called core library methods. |
| 1242 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 1220 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 1243 ASSERT(call->HasICData()); | 1221 ASSERT(call->HasICData()); |
| 1244 const ICData& ic_data = *call->ic_data(); | 1222 const ICData& ic_data = *call->ic_data(); |
| 1245 if (ic_data.NumberOfUsedChecks() != 1) { | 1223 if (ic_data.NumberOfUsedChecks() != 1) { |
| 1246 // No type feedback collected or multiple receivers/targets found. | 1224 // No type feedback collected or multiple receivers/targets found. |
| 1247 return false; | 1225 return false; |
| 1248 } | 1226 } |
| 1249 | 1227 |
| 1250 Function& target = Function::Handle(Z); | 1228 Function& target = Function::Handle(Z); |
| 1251 GrowableArray<intptr_t> class_ids; | 1229 GrowableArray<intptr_t> class_ids; |
| 1252 ic_data.GetCheckAt(0, &class_ids, &target); | 1230 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1253 MethodRecognizer::Kind recognized_kind = | 1231 MethodRecognizer::Kind recognized_kind = |
| 1254 MethodRecognizer::RecognizeKind(target); | 1232 MethodRecognizer::RecognizeKind(target); |
| 1255 | 1233 |
| 1256 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || | |
| 1257 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || | |
| 1258 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || | |
| 1259 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) || | |
| 1260 (recognized_kind == MethodRecognizer::kGrowableArraySetData) || | |
| 1261 (recognized_kind == MethodRecognizer::kGrowableArraySetLength) || | |
| 1262 (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi)) { | |
| 1263 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1264 flow_graph_, current_iterator(), call); | |
| 1265 } | |
| 1266 | |
| 1267 if (recognized_kind == MethodRecognizer::kStringBaseCharAt) { | |
| 1268 ASSERT((class_ids[0] == kOneByteStringCid) || | |
| 1269 (class_ids[0] == kTwoByteStringCid) || | |
| 1270 (class_ids[0] == kExternalOneByteStringCid) || | |
| 1271 (class_ids[0] == kExternalTwoByteStringCid)); | |
| 1272 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1273 flow_graph_, current_iterator(), call); | |
| 1274 } | |
| 1275 | |
| 1276 if (class_ids[0] == kOneByteStringCid) { | |
| 1277 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | |
| 1278 // This is an internal method, no need to check argument types nor | |
| 1279 // range. | |
| 1280 Definition* str = call->ArgumentAt(0); | |
| 1281 Definition* index = call->ArgumentAt(1); | |
| 1282 Definition* value = call->ArgumentAt(2); | |
| 1283 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( | |
| 1284 new(Z) Value(str), | |
| 1285 new(Z) Value(index), | |
| 1286 new(Z) Value(value), | |
| 1287 kNoStoreBarrier, | |
| 1288 1, // Index scale | |
| 1289 kOneByteStringCid, | |
| 1290 call->deopt_id(), | |
| 1291 call->token_pos()); | |
| 1292 ReplaceCall(call, store_op); | |
| 1293 return true; | |
| 1294 } | |
| 1295 return false; | |
| 1296 } | |
| 1297 | |
| 1298 if (CanUnboxDouble() && | 1234 if (CanUnboxDouble() && |
| 1299 (recognized_kind == MethodRecognizer::kIntegerToDouble)) { | 1235 (recognized_kind == MethodRecognizer::kIntegerToDouble)) { |
| 1300 if (class_ids[0] == kSmiCid) { | 1236 if (class_ids[0] == kSmiCid) { |
| 1301 AddReceiverCheck(call); | 1237 AddReceiverCheck(call); |
| 1302 ReplaceCall(call, | 1238 ReplaceCall(call, |
| 1303 new(Z) SmiToDoubleInstr( | 1239 new(Z) SmiToDoubleInstr( |
| 1304 new(Z) Value(call->ArgumentAt(0)), | 1240 new(Z) Value(call->ArgumentAt(0)), |
| 1305 call->token_pos())); | 1241 call->token_pos())); |
| 1306 return true; | 1242 return true; |
| 1307 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { | 1243 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 if (!TargetCPUFeatures::double_truncate_round_supported()) { | 1282 if (!TargetCPUFeatures::double_truncate_round_supported()) { |
| 1347 ReplaceWithMathCFunction(call, recognized_kind); | 1283 ReplaceWithMathCFunction(call, recognized_kind); |
| 1348 } else { | 1284 } else { |
| 1349 AddReceiverCheck(call); | 1285 AddReceiverCheck(call); |
| 1350 DoubleToDoubleInstr* d2d_instr = | 1286 DoubleToDoubleInstr* d2d_instr = |
| 1351 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), | 1287 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), |
| 1352 recognized_kind, call->deopt_id()); | 1288 recognized_kind, call->deopt_id()); |
| 1353 ReplaceCall(call, d2d_instr); | 1289 ReplaceCall(call, d2d_instr); |
| 1354 } | 1290 } |
| 1355 return true; | 1291 return true; |
| 1356 case MethodRecognizer::kDoubleAdd: | |
| 1357 case MethodRecognizer::kDoubleSub: | |
| 1358 case MethodRecognizer::kDoubleMul: | |
| 1359 case MethodRecognizer::kDoubleDiv: | |
| 1360 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1361 flow_graph_, current_iterator(), call); | |
| 1362 default: | 1292 default: |
| 1363 // Unsupported method. | 1293 break; |
| 1364 return false; | |
| 1365 } | 1294 } |
| 1366 } | 1295 } |
| 1367 | 1296 |
| 1368 if (IsSupportedByteArrayViewCid(class_ids[0]) || | 1297 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1369 (class_ids[0] == kFloat32x4Cid) || | 1298 flow_graph_, current_iterator(), call); |
| 1370 (class_ids[0] == kInt32x4Cid) || | |
| 1371 (class_ids[0] == kFloat64x2Cid)) { | |
| 1372 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1373 flow_graph_, current_iterator(), call); | |
| 1374 } | |
| 1375 | |
| 1376 return false; | |
| 1377 } | 1299 } |
| 1378 | 1300 |
| 1379 | 1301 |
| 1380 // If type tests specified by 'ic_data' do not depend on type arguments, | 1302 // If type tests specified by 'ic_data' do not depend on type arguments, |
| 1381 // return mapping cid->result in 'results' (i : cid; i + 1: result). | 1303 // return mapping cid->result in 'results' (i : cid; i + 1: result). |
| 1382 // If all tests yield the same result, return it otherwise return Bool::null. | 1304 // If all tests yield the same result, return it otherwise return Bool::null. |
| 1383 // If no mapping is possible, 'results' has less than | 1305 // If no mapping is possible, 'results' has less than |
| 1384 // (ic_data.NumberOfChecks() * 2) entries | 1306 // (ic_data.NumberOfChecks() * 2) entries |
| 1385 // An instance-of test returning all same results can be converted to a class | 1307 // An instance-of test returning all same results can be converted to a class |
| 1386 // check. | 1308 // check. |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2023 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 1945 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 2024 /* with_checks = */ true, | 1946 /* with_checks = */ true, |
| 2025 /* complete = */ false); | 1947 /* complete = */ false); |
| 2026 instr->ReplaceWith(call, current_iterator()); | 1948 instr->ReplaceWith(call, current_iterator()); |
| 2027 return; | 1949 return; |
| 2028 } | 1950 } |
| 2029 } | 1951 } |
| 2030 | 1952 |
| 2031 | 1953 |
| 2032 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { | 1954 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { |
| 2033 if (!CanUnboxDouble()) { | 1955 if (!IsAllowedForInlining(call->deopt_id())) { |
| 1956 // Inlining disabled after a speculative inlining attempt. |
| 2034 return; | 1957 return; |
| 2035 } | 1958 } |
| 2036 MethodRecognizer::Kind recognized_kind = | 1959 MethodRecognizer::Kind recognized_kind = |
| 2037 MethodRecognizer::RecognizeKind(call->function()); | 1960 MethodRecognizer::RecognizeKind(call->function()); |
| 2038 MathUnaryInstr::MathUnaryKind unary_kind; | |
| 2039 switch (recognized_kind) { | 1961 switch (recognized_kind) { |
| 2040 case MethodRecognizer::kMathSqrt: | 1962 case MethodRecognizer::kObjectConstructor: |
| 2041 unary_kind = MathUnaryInstr::kSqrt; | 1963 case MethodRecognizer::kObjectArrayAllocate: |
| 2042 break; | |
| 2043 case MethodRecognizer::kMathSin: | |
| 2044 unary_kind = MathUnaryInstr::kSin; | |
| 2045 break; | |
| 2046 case MethodRecognizer::kMathCos: | |
| 2047 unary_kind = MathUnaryInstr::kCos; | |
| 2048 break; | |
| 2049 default: | |
| 2050 unary_kind = MathUnaryInstr::kIllegal; | |
| 2051 break; | |
| 2052 } | |
| 2053 if (unary_kind != MathUnaryInstr::kIllegal) { | |
| 2054 ASSERT(FLAG_precompiled_mode); | |
| 2055 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well. | |
| 2056 return; | |
| 2057 } | |
| 2058 | |
| 2059 switch (recognized_kind) { | |
| 2060 case MethodRecognizer::kFloat32x4Zero: | 1964 case MethodRecognizer::kFloat32x4Zero: |
| 2061 case MethodRecognizer::kFloat32x4Splat: | 1965 case MethodRecognizer::kFloat32x4Splat: |
| 2062 case MethodRecognizer::kFloat32x4Constructor: | 1966 case MethodRecognizer::kFloat32x4Constructor: |
| 2063 case MethodRecognizer::kFloat32x4FromFloat64x2: | 1967 case MethodRecognizer::kFloat32x4FromFloat64x2: |
| 2064 case MethodRecognizer::kFloat64x2Constructor: | 1968 case MethodRecognizer::kFloat64x2Constructor: |
| 2065 case MethodRecognizer::kFloat64x2Zero: | 1969 case MethodRecognizer::kFloat64x2Zero: |
| 2066 case MethodRecognizer::kFloat64x2Splat: | 1970 case MethodRecognizer::kFloat64x2Splat: |
| 2067 case MethodRecognizer::kFloat64x2FromFloat32x4: | 1971 case MethodRecognizer::kFloat64x2FromFloat32x4: |
| 2068 case MethodRecognizer::kInt32x4BoolConstructor: | 1972 case MethodRecognizer::kInt32x4BoolConstructor: |
| 2069 case MethodRecognizer::kInt32x4Constructor: | 1973 case MethodRecognizer::kInt32x4Constructor: |
| 2070 if (!ShouldInlineSimd() || !IsAllowedForInlining(call->deopt_id())) { | 1974 case MethodRecognizer::kMathSqrt: |
| 2071 return; | 1975 case MethodRecognizer::kMathDoublePow: |
| 2072 } | 1976 case MethodRecognizer::kMathSin: |
| 1977 case MethodRecognizer::kMathCos: |
| 1978 case MethodRecognizer::kMathTan: |
| 1979 case MethodRecognizer::kMathAsin: |
| 1980 case MethodRecognizer::kMathAcos: |
| 1981 case MethodRecognizer::kMathAtan: |
| 1982 case MethodRecognizer::kMathAtan2: |
| 2073 FlowGraphInliner::TryReplaceStaticCallWithInline( | 1983 FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 2074 flow_graph_, current_iterator(), call); | 1984 flow_graph_, current_iterator(), call); |
| 2075 break; | 1985 break; |
| 2076 case MethodRecognizer::kObjectConstructor: { | |
| 2077 // Remove the original push arguments. | |
| 2078 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | |
| 2079 PushArgumentInstr* push = call->PushArgumentAt(i); | |
| 2080 push->ReplaceUsesWith(push->value()->definition()); | |
| 2081 push->RemoveFromGraph(); | |
| 2082 } | |
| 2083 // Manually replace call with global null constant. ReplaceCall can't | |
| 2084 // be used for definitions that are already in the graph. | |
| 2085 call->ReplaceUsesWith(flow_graph_->constant_null()); | |
| 2086 ASSERT(current_iterator()->Current() == call); | |
| 2087 current_iterator()->RemoveCurrentFromGraph(); | |
| 2088 break; | |
| 2089 } | |
| 2090 case MethodRecognizer::kMathMin: | 1986 case MethodRecognizer::kMathMin: |
| 2091 case MethodRecognizer::kMathMax: { | 1987 case MethodRecognizer::kMathMax: { |
| 2092 // We can handle only monomorphic min/max call sites with both arguments | 1988 // We can handle only monomorphic min/max call sites with both arguments |
| 2093 // being either doubles or smis. | 1989 // being either doubles or smis. |
| 2094 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 1990 if (CanUnboxDouble() && |
| 1991 call->HasICData() && |
| 1992 (call->ic_data()->NumberOfChecks() == 1)) { |
| 2095 const ICData& ic_data = *call->ic_data(); | 1993 const ICData& ic_data = *call->ic_data(); |
| 2096 intptr_t result_cid = kIllegalCid; | 1994 intptr_t result_cid = kIllegalCid; |
| 2097 if (ICDataHasReceiverArgumentClassIds(ic_data, | 1995 if (ICDataHasReceiverArgumentClassIds(ic_data, |
| 2098 kDoubleCid, kDoubleCid)) { | 1996 kDoubleCid, kDoubleCid)) { |
| 2099 result_cid = kDoubleCid; | 1997 result_cid = kDoubleCid; |
| 2100 } else if (ICDataHasReceiverArgumentClassIds(ic_data, | 1998 } else if (ICDataHasReceiverArgumentClassIds(ic_data, |
| 2101 kSmiCid, kSmiCid)) { | 1999 kSmiCid, kSmiCid)) { |
| 2102 result_cid = kSmiCid; | 2000 result_cid = kSmiCid; |
| 2103 } | 2001 } |
| 2104 if (result_cid != kIllegalCid) { | 2002 if (result_cid != kIllegalCid) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2118 AddCheckClass(min_max->right()->definition(), | 2016 AddCheckClass(min_max->right()->definition(), |
| 2119 unary_checks, | 2017 unary_checks, |
| 2120 call->deopt_id(), | 2018 call->deopt_id(), |
| 2121 call->env(), | 2019 call->env(), |
| 2122 call); | 2020 call); |
| 2123 ReplaceCall(call, min_max); | 2021 ReplaceCall(call, min_max); |
| 2124 } | 2022 } |
| 2125 } | 2023 } |
| 2126 break; | 2024 break; |
| 2127 } | 2025 } |
| 2128 case MethodRecognizer::kMathDoublePow: | |
| 2129 case MethodRecognizer::kMathTan: | |
| 2130 case MethodRecognizer::kMathAsin: | |
| 2131 case MethodRecognizer::kMathAcos: | |
| 2132 case MethodRecognizer::kMathAtan: | |
| 2133 case MethodRecognizer::kMathAtan2: { | |
| 2134 ASSERT(FLAG_precompiled_mode); | |
| 2135 // No UnboxDouble instructions allowed. | |
| 2136 return; | |
| 2137 } | |
| 2138 case MethodRecognizer::kDoubleFromInteger: { | 2026 case MethodRecognizer::kDoubleFromInteger: { |
| 2139 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 2027 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { |
| 2140 const ICData& ic_data = *call->ic_data(); | 2028 const ICData& ic_data = *call->ic_data(); |
| 2141 if (CanUnboxDouble()) { | 2029 if (CanUnboxDouble()) { |
| 2142 if (ArgIsAlways(kSmiCid, ic_data, 1)) { | 2030 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
| 2143 Definition* arg = call->ArgumentAt(1); | 2031 Definition* arg = call->ArgumentAt(1); |
| 2144 AddCheckSmi(arg, call->deopt_id(), call->env(), call); | 2032 AddCheckSmi(arg, call->deopt_id(), call->env(), call); |
| 2145 ReplaceCall(call, | 2033 ReplaceCall(call, |
| 2146 new(Z) SmiToDoubleInstr(new(Z) Value(arg), | 2034 new(Z) SmiToDoubleInstr(new(Z) Value(arg), |
| 2147 call->token_pos())); | 2035 call->token_pos())); |
| 2148 } else if (ArgIsAlways(kMintCid, ic_data, 1) && | 2036 } else if (ArgIsAlways(kMintCid, ic_data, 1) && |
| 2149 CanConvertUnboxedMintToDouble()) { | 2037 CanConvertUnboxedMintToDouble()) { |
| 2150 Definition* arg = call->ArgumentAt(1); | 2038 Definition* arg = call->ArgumentAt(1); |
| 2151 ReplaceCall(call, | 2039 ReplaceCall(call, |
| 2152 new(Z) MintToDoubleInstr(new(Z) Value(arg), | 2040 new(Z) MintToDoubleInstr(new(Z) Value(arg), |
| 2153 call->deopt_id())); | 2041 call->deopt_id())); |
| 2154 } | 2042 } |
| 2155 } | 2043 } |
| 2156 } | 2044 } |
| 2157 break; | 2045 break; |
| 2158 } | 2046 } |
| 2159 default: { | 2047 default: |
| 2160 if (call->function().IsFactory()) { | 2048 break; |
| 2161 const Class& function_class = | |
| 2162 Class::Handle(Z, call->function().Owner()); | |
| 2163 if ((function_class.library() == Library::CoreLibrary()) || | |
| 2164 (function_class.library() == Library::TypedDataLibrary())) { | |
| 2165 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | |
| 2166 switch (cid) { | |
| 2167 case kArrayCid: { | |
| 2168 Value* type = new(Z) Value(call->ArgumentAt(0)); | |
| 2169 Value* num_elements = new(Z) Value(call->ArgumentAt(1)); | |
| 2170 if (num_elements->BindsToConstant() && | |
| 2171 num_elements->BoundConstant().IsSmi()) { | |
| 2172 intptr_t length = | |
| 2173 Smi::Cast(num_elements->BoundConstant()).Value(); | |
| 2174 if (length >= 0 && length <= Array::kMaxElements) { | |
| 2175 CreateArrayInstr* create_array = | |
| 2176 new(Z) CreateArrayInstr( | |
| 2177 call->token_pos(), type, num_elements); | |
| 2178 ReplaceCall(call, create_array); | |
| 2179 } | |
| 2180 } | |
| 2181 } | |
| 2182 default: | |
| 2183 break; | |
| 2184 } | |
| 2185 } | |
| 2186 } | |
| 2187 } | |
| 2188 } | 2049 } |
| 2189 } | 2050 } |
| 2190 | 2051 |
| 2191 | 2052 |
| 2192 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 2053 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 2193 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. | 2054 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. |
| 2194 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 2055 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
| 2195 if (!instr->can_pack_into_smi()) | 2056 if (!instr->can_pack_into_smi()) |
| 2196 instr->set_representation(kUnboxedMint); | 2057 instr->set_representation(kUnboxedMint); |
| 2197 #endif | 2058 #endif |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 flow_graph_->InsertBefore(check, new_check, | 2133 flow_graph_->InsertBefore(check, new_check, |
| 2273 check->env(), FlowGraph::kEffect); | 2134 check->env(), FlowGraph::kEffect); |
| 2274 current_iterator()->RemoveCurrentFromGraph(); | 2135 current_iterator()->RemoveCurrentFromGraph(); |
| 2275 } | 2136 } |
| 2276 } | 2137 } |
| 2277 } | 2138 } |
| 2278 } | 2139 } |
| 2279 | 2140 |
| 2280 | 2141 |
| 2281 } // namespace dart | 2142 } // namespace dart |
| OLD | NEW |