Chromium Code Reviews| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 "Print constant propagation and useless code elimination."); | 37 "Print constant propagation and useless code elimination."); |
| 38 DEFINE_FLAG(bool, trace_load_optimization, false, | 38 DEFINE_FLAG(bool, trace_load_optimization, false, |
| 39 "Print live sets for load optimization pass."); | 39 "Print live sets for load optimization pass."); |
| 40 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 40 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
| 41 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); | 41 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
| 42 DEFINE_FLAG(bool, truncating_left_shift, true, | 42 DEFINE_FLAG(bool, truncating_left_shift, true, |
| 43 "Optimize left shift to truncate if possible"); | 43 "Optimize left shift to truncate if possible"); |
| 44 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 44 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
| 45 DECLARE_FLAG(bool, eliminate_type_checks); | 45 DECLARE_FLAG(bool, eliminate_type_checks); |
| 46 DECLARE_FLAG(bool, enable_type_checks); | 46 DECLARE_FLAG(bool, enable_type_checks); |
| 47 DECLARE_FLAG(bool, source_lines); | |
| 47 DECLARE_FLAG(bool, trace_type_check_elimination); | 48 DECLARE_FLAG(bool, trace_type_check_elimination); |
| 48 | 49 |
| 49 | |
| 50 static bool ShouldInlineSimd() { | 50 static bool ShouldInlineSimd() { |
| 51 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 51 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 // Optimize instance calls using ICData. | 55 // Optimize instance calls using ICData. |
| 56 void FlowGraphOptimizer::ApplyICData() { | 56 void FlowGraphOptimizer::ApplyICData() { |
| 57 VisitBlocks(); | 57 VisitBlocks(); |
| 58 } | 58 } |
| 59 | 59 |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 | 270 |
| 271 // Pattern recognized. | 271 // Pattern recognized. |
| 272 smi_shift_left->set_is_truncating(true); | 272 smi_shift_left->set_is_truncating(true); |
| 273 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 273 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
| 274 if (bit_and_instr->IsBinaryMintOp()) { | 274 if (bit_and_instr->IsBinaryMintOp()) { |
| 275 // Replace Mint op with Smi op. | 275 // Replace Mint op with Smi op. |
| 276 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( | 276 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( |
| 277 Token::kBIT_AND, | 277 Token::kBIT_AND, |
| 278 new Value(left_instr), | 278 new Value(left_instr), |
| 279 new Value(right_instr), | 279 new Value(right_instr), |
| 280 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. | 280 Isolate::kNoDeoptId, // BIT_AND cannot deoptimize. |
| 281 kNoTokenPos); | |
| 281 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 282 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
| 282 } | 283 } |
| 283 } | 284 } |
| 284 | 285 |
| 285 | 286 |
| 286 | 287 |
| 287 // Used by TryMergeDivMod. | 288 // Used by TryMergeDivMod. |
| 288 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 289 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
| 289 // and the using instruction. This is an intermediate step before merging. | 290 // and the using instruction. This is an intermediate step before merging. |
| 290 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 291 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
| 291 intptr_t ix, | 292 intptr_t ix, |
| 292 intptr_t cid) { | 293 intptr_t cid) { |
| 293 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); | 294 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); |
| 294 ConstantInstr* index_instr = | 295 ConstantInstr* index_instr = |
| 295 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); | 296 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); |
| 296 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | 297 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), |
| 297 new Value(index_instr), | 298 new Value(index_instr), |
| 298 index_scale, | 299 index_scale, |
| 299 cid, | 300 cid, |
| 300 Isolate::kNoDeoptId); | 301 Isolate::kNoDeoptId, |
| 302 instr->token_pos()); | |
| 301 instr->ReplaceUsesWith(load); | 303 instr->ReplaceUsesWith(load); |
| 302 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); | 304 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); |
| 303 } | 305 } |
| 304 | 306 |
| 305 | 307 |
| 306 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, | 308 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
| 307 intptr_t index, | 309 intptr_t index, |
| 308 Representation rep, | 310 Representation rep, |
| 309 intptr_t cid) { | 311 intptr_t cid) { |
| 310 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), | 312 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 940 call->ReplaceWith(replacement, current_iterator()); | 942 call->ReplaceWith(replacement, current_iterator()); |
| 941 } | 943 } |
| 942 | 944 |
| 943 | 945 |
| 944 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, | 946 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, |
| 945 intptr_t deopt_id, | 947 intptr_t deopt_id, |
| 946 Environment* deopt_environment, | 948 Environment* deopt_environment, |
| 947 Instruction* insert_before) { | 949 Instruction* insert_before) { |
| 948 if (to_check->Type()->ToCid() != kSmiCid) { | 950 if (to_check->Type()->ToCid() != kSmiCid) { |
| 949 InsertBefore(insert_before, | 951 InsertBefore(insert_before, |
| 950 new CheckSmiInstr(new Value(to_check), deopt_id), | 952 new CheckSmiInstr(new Value(to_check), |
| 953 deopt_id, | |
| 954 insert_before->token_pos()), | |
| 951 deopt_environment, | 955 deopt_environment, |
| 952 Definition::kEffect); | 956 Definition::kEffect); |
| 953 } | 957 } |
| 954 } | 958 } |
| 955 | 959 |
| 956 | 960 |
| 957 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 961 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
| 958 const ICData& unary_checks, | 962 const ICData& unary_checks, |
| 959 intptr_t deopt_id) { | 963 intptr_t deopt_id, |
| 964 intptr_t token_pos) { | |
| 960 if ((unary_checks.NumberOfChecks() == 1) && | 965 if ((unary_checks.NumberOfChecks() == 1) && |
| 961 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 966 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
| 962 return new CheckSmiInstr(new Value(to_check), deopt_id); | 967 return new CheckSmiInstr(new Value(to_check), |
| 968 deopt_id, | |
| 969 token_pos); | |
| 963 } | 970 } |
| 964 return new CheckClassInstr(new Value(to_check), deopt_id, unary_checks); | 971 return new CheckClassInstr( |
| 972 new Value(to_check), deopt_id, unary_checks, token_pos); | |
| 965 } | 973 } |
| 966 | 974 |
| 967 | 975 |
| 968 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 976 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
| 969 const ICData& unary_checks, | 977 const ICData& unary_checks, |
| 970 intptr_t deopt_id, | 978 intptr_t deopt_id, |
| 971 Environment* deopt_environment, | 979 Environment* deopt_environment, |
| 972 Instruction* insert_before) { | 980 Instruction* insert_before) { |
| 973 // Type propagation has not run yet, we cannot eliminate the check. | 981 // Type propagation has not run yet, we cannot eliminate the check. |
| 974 Instruction* check = GetCheckClass(to_check, unary_checks, deopt_id); | 982 Instruction* check = GetCheckClass( |
| 983 to_check, unary_checks, deopt_id, insert_before->token_pos()); | |
| 975 InsertBefore(insert_before, check, deopt_environment, Definition::kEffect); | 984 InsertBefore(insert_before, check, deopt_environment, Definition::kEffect); |
| 976 } | 985 } |
| 977 | 986 |
| 978 | 987 |
| 979 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 988 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { |
| 980 AddCheckClass(call->ArgumentAt(0), | 989 AddCheckClass(call->ArgumentAt(0), |
| 981 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), | 990 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), |
| 982 call->deopt_id(), | 991 call->deopt_id(), |
| 983 call->env(), | 992 call->env(), |
| 984 call); | 993 call); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1155 Definition* type_args = NULL; | 1164 Definition* type_args = NULL; |
| 1156 switch (array_cid) { | 1165 switch (array_cid) { |
| 1157 case kArrayCid: | 1166 case kArrayCid: |
| 1158 case kGrowableObjectArrayCid: { | 1167 case kGrowableObjectArrayCid: { |
| 1159 const Class& instantiator_class = Class::Handle(target.Owner()); | 1168 const Class& instantiator_class = Class::Handle(target.Owner()); |
| 1160 intptr_t type_arguments_field_offset = | 1169 intptr_t type_arguments_field_offset = |
| 1161 instantiator_class.type_arguments_field_offset(); | 1170 instantiator_class.type_arguments_field_offset(); |
| 1162 LoadFieldInstr* load_type_args = | 1171 LoadFieldInstr* load_type_args = |
| 1163 new LoadFieldInstr(new Value(array), | 1172 new LoadFieldInstr(new Value(array), |
| 1164 type_arguments_field_offset, | 1173 type_arguments_field_offset, |
| 1165 Type::ZoneHandle()); // No type. | 1174 Type::ZoneHandle(), |
| 1175 call->token_pos()); // No type. | |
| 1166 cursor = flow_graph()->AppendTo(cursor, | 1176 cursor = flow_graph()->AppendTo(cursor, |
| 1167 load_type_args, | 1177 load_type_args, |
| 1168 NULL, | 1178 NULL, |
| 1169 Definition::kValue); | 1179 Definition::kValue); |
| 1170 | 1180 |
| 1171 instantiator = array; | 1181 instantiator = array; |
| 1172 type_args = load_type_args; | 1182 type_args = load_type_args; |
| 1173 break; | 1183 break; |
| 1174 } | 1184 } |
| 1175 case kTypedDataInt8ArrayCid: | 1185 case kTypedDataInt8ArrayCid: |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1236 // Check if store barrier is needed. Byte arrays don't need a store barrier. | 1246 // Check if store barrier is needed. Byte arrays don't need a store barrier. |
| 1237 StoreBarrierType needs_store_barrier = | 1247 StoreBarrierType needs_store_barrier = |
| 1238 (RawObject::IsTypedDataClassId(array_cid) || | 1248 (RawObject::IsTypedDataClassId(array_cid) || |
| 1239 RawObject::IsTypedDataViewClassId(array_cid) || | 1249 RawObject::IsTypedDataViewClassId(array_cid) || |
| 1240 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier | 1250 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier |
| 1241 : kEmitStoreBarrier; | 1251 : kEmitStoreBarrier; |
| 1242 if (!value_check.IsNull()) { | 1252 if (!value_check.IsNull()) { |
| 1243 // No store barrier needed because checked value is a smi, an unboxed mint, | 1253 // No store barrier needed because checked value is a smi, an unboxed mint, |
| 1244 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. | 1254 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. |
| 1245 needs_store_barrier = kNoStoreBarrier; | 1255 needs_store_barrier = kNoStoreBarrier; |
| 1246 Instruction* check = | 1256 Instruction* check = GetCheckClass( |
| 1247 GetCheckClass(stored_value, value_check, call->deopt_id()); | 1257 stored_value, value_check, call->deopt_id(), call->token_pos()); |
| 1248 cursor = flow_graph()->AppendTo(cursor, | 1258 cursor = flow_graph()->AppendTo(cursor, |
| 1249 check, | 1259 check, |
| 1250 call->env(), | 1260 call->env(), |
| 1251 Definition::kEffect); | 1261 Definition::kEffect); |
| 1252 } | 1262 } |
| 1253 | 1263 |
| 1254 if (array_cid == kTypedDataFloat32ArrayCid) { | 1264 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1255 stored_value = | 1265 stored_value = |
| 1256 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); | 1266 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); |
| 1257 cursor = flow_graph()->AppendTo(cursor, | 1267 cursor = flow_graph()->AppendTo(cursor, |
| 1258 stored_value, | 1268 stored_value, |
| 1259 NULL, | 1269 NULL, |
| 1260 Definition::kValue); | 1270 Definition::kValue); |
| 1261 } | 1271 } |
| 1262 | 1272 |
| 1263 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1273 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1264 *last = new StoreIndexedInstr(new Value(array), | 1274 *last = new StoreIndexedInstr(new Value(array), |
| 1265 new Value(index), | 1275 new Value(index), |
| 1266 new Value(stored_value), | 1276 new Value(stored_value), |
| 1267 needs_store_barrier, | 1277 needs_store_barrier, |
| 1268 index_scale, | 1278 index_scale, |
| 1269 array_cid, | 1279 array_cid, |
| 1270 call->deopt_id()); | 1280 call->deopt_id(), |
| 1281 call->token_pos()); | |
| 1271 flow_graph()->AppendTo(cursor, | 1282 flow_graph()->AppendTo(cursor, |
| 1272 *last, | 1283 *last, |
| 1273 call->env(), | 1284 call->env(), |
| 1274 Definition::kEffect); | 1285 Definition::kEffect); |
| 1275 return true; | 1286 return true; |
| 1276 } | 1287 } |
| 1277 | 1288 |
| 1278 | 1289 |
| 1279 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, | 1290 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, |
| 1280 const Function& target, | 1291 const Function& target, |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1496 | 1507 |
| 1497 | 1508 |
| 1498 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1509 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
| 1499 intptr_t array_cid, | 1510 intptr_t array_cid, |
| 1500 Definition** array, | 1511 Definition** array, |
| 1501 Definition* index, | 1512 Definition* index, |
| 1502 Instruction** cursor) { | 1513 Instruction** cursor) { |
| 1503 // Insert index smi check. | 1514 // Insert index smi check. |
| 1504 *cursor = flow_graph()->AppendTo(*cursor, | 1515 *cursor = flow_graph()->AppendTo(*cursor, |
| 1505 new CheckSmiInstr(new Value(index), | 1516 new CheckSmiInstr(new Value(index), |
| 1506 call->deopt_id()), | 1517 call->deopt_id(), |
| 1518 call->token_pos()), | |
| 1507 call->env(), | 1519 call->env(), |
| 1508 Definition::kEffect); | 1520 Definition::kEffect); |
| 1509 | 1521 |
| 1510 // Insert array length load and bounds check. | 1522 // Insert array length load and bounds check. |
| 1511 const bool is_immutable = | 1523 const bool is_immutable = |
| 1512 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid); | 1524 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid); |
| 1513 LoadFieldInstr* length = | 1525 LoadFieldInstr* length = |
| 1514 new LoadFieldInstr(new Value(*array), | 1526 new LoadFieldInstr(new Value(*array), |
| 1515 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 1527 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 1516 Type::ZoneHandle(Type::SmiType()), | 1528 Type::ZoneHandle(Type::SmiType()), |
| 1529 call->token_pos(), | |
| 1517 is_immutable); | 1530 is_immutable); |
| 1518 length->set_result_cid(kSmiCid); | 1531 length->set_result_cid(kSmiCid); |
| 1519 length->set_recognized_kind( | 1532 length->set_recognized_kind( |
| 1520 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 1533 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 1521 *cursor = flow_graph()->AppendTo(*cursor, | 1534 *cursor = flow_graph()->AppendTo(*cursor, |
| 1522 length, | 1535 length, |
| 1523 NULL, | 1536 NULL, |
| 1524 Definition::kValue); | 1537 Definition::kValue); |
| 1525 | 1538 |
| 1526 *cursor = flow_graph()->AppendTo(*cursor, | 1539 *cursor = flow_graph()->AppendTo(*cursor, |
| 1527 new CheckArrayBoundInstr( | 1540 new CheckArrayBoundInstr( |
| 1528 new Value(length), | 1541 new Value(length), |
| 1529 new Value(index), | 1542 new Value(index), |
| 1530 call->deopt_id()), | 1543 call->deopt_id()), |
| 1531 call->env(), | 1544 call->env(), |
| 1532 Definition::kEffect); | 1545 Definition::kEffect); |
| 1533 | 1546 |
| 1534 if (array_cid == kGrowableObjectArrayCid) { | 1547 if (array_cid == kGrowableObjectArrayCid) { |
| 1535 // Insert data elements load. | 1548 // Insert data elements load. |
| 1536 LoadFieldInstr* elements = | 1549 LoadFieldInstr* elements = |
| 1537 new LoadFieldInstr(new Value(*array), | 1550 new LoadFieldInstr(new Value(*array), |
| 1538 GrowableObjectArray::data_offset(), | 1551 GrowableObjectArray::data_offset(), |
| 1539 Type::ZoneHandle(Type::DynamicType())); | 1552 Type::ZoneHandle(Type::DynamicType()), |
| 1553 call->token_pos()); | |
| 1540 elements->set_result_cid(kArrayCid); | 1554 elements->set_result_cid(kArrayCid); |
| 1541 *cursor = flow_graph()->AppendTo(*cursor, | 1555 *cursor = flow_graph()->AppendTo(*cursor, |
| 1542 elements, | 1556 elements, |
| 1543 NULL, | 1557 NULL, |
| 1544 Definition::kValue); | 1558 Definition::kValue); |
| 1545 // Load from the data from backing store which is a fixed-length array. | 1559 // Load from the data from backing store which is a fixed-length array. |
| 1546 *array = elements; | 1560 *array = elements; |
| 1547 array_cid = kArrayCid; | 1561 array_cid = kArrayCid; |
| 1548 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 1562 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 1549 LoadUntaggedInstr* elements = | 1563 LoadUntaggedInstr* elements = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1588 deopt_id = ic_data.HasDeoptReasons() ? | 1602 deopt_id = ic_data.HasDeoptReasons() ? |
| 1589 Isolate::kNoDeoptId : call->deopt_id(); | 1603 Isolate::kNoDeoptId : call->deopt_id(); |
| 1590 } | 1604 } |
| 1591 | 1605 |
| 1592 // Array load and return. | 1606 // Array load and return. |
| 1593 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1607 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1594 *last = new LoadIndexedInstr(new Value(array), | 1608 *last = new LoadIndexedInstr(new Value(array), |
| 1595 new Value(index), | 1609 new Value(index), |
| 1596 index_scale, | 1610 index_scale, |
| 1597 array_cid, | 1611 array_cid, |
| 1598 deopt_id); | 1612 deopt_id, |
| 1613 call->token_pos()); | |
| 1599 cursor = flow_graph()->AppendTo( | 1614 cursor = flow_graph()->AppendTo( |
| 1600 cursor, | 1615 cursor, |
| 1601 *last, | 1616 *last, |
| 1602 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1617 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1603 Definition::kValue); | 1618 Definition::kValue); |
| 1604 | 1619 |
| 1605 if (array_cid == kTypedDataFloat32ArrayCid) { | 1620 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1606 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 1621 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 1607 flow_graph()->AppendTo(cursor, | 1622 flow_graph()->AppendTo(cursor, |
| 1608 *last, | 1623 *last, |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1775 | 1790 |
| 1776 intptr_t cid = kIllegalCid; | 1791 intptr_t cid = kIllegalCid; |
| 1777 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 1792 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
| 1778 if (TryStringLengthOneEquality(call, op_kind)) { | 1793 if (TryStringLengthOneEquality(call, op_kind)) { |
| 1779 return true; | 1794 return true; |
| 1780 } else { | 1795 } else { |
| 1781 return false; | 1796 return false; |
| 1782 } | 1797 } |
| 1783 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1798 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1784 InsertBefore(call, | 1799 InsertBefore(call, |
| 1785 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1800 new CheckSmiInstr(new Value(left), |
| 1801 call->deopt_id(), | |
| 1802 call->token_pos()), | |
| 1786 call->env(), | 1803 call->env(), |
| 1787 Definition::kEffect); | 1804 Definition::kEffect); |
| 1788 InsertBefore(call, | 1805 InsertBefore(call, |
| 1789 new CheckSmiInstr(new Value(right), call->deopt_id()), | 1806 new CheckSmiInstr(new Value(right), |
| 1807 call->deopt_id(), | |
| 1808 call->token_pos()), | |
| 1790 call->env(), | 1809 call->env(), |
| 1791 Definition::kEffect); | 1810 Definition::kEffect); |
| 1792 cid = kSmiCid; | 1811 cid = kSmiCid; |
| 1793 } else if (HasTwoMintOrSmi(ic_data) && | 1812 } else if (HasTwoMintOrSmi(ic_data) && |
| 1794 FlowGraphCompiler::SupportsUnboxedMints()) { | 1813 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1795 cid = kMintCid; | 1814 cid = kMintCid; |
| 1796 } else if (HasTwoDoubleOrSmi(ic_data)) { | 1815 } else if (HasTwoDoubleOrSmi(ic_data)) { |
| 1797 // Use double comparison. | 1816 // Use double comparison. |
| 1798 if (SmiFitsInDouble()) { | 1817 if (SmiFitsInDouble()) { |
| 1799 cid = kDoubleCid; | 1818 cid = kDoubleCid; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1873 const ICData& ic_data = *call->ic_data(); | 1892 const ICData& ic_data = *call->ic_data(); |
| 1874 ASSERT(ic_data.NumArgsTested() == 2); | 1893 ASSERT(ic_data.NumArgsTested() == 2); |
| 1875 | 1894 |
| 1876 ASSERT(call->ArgumentCount() == 2); | 1895 ASSERT(call->ArgumentCount() == 2); |
| 1877 Definition* left = call->ArgumentAt(0); | 1896 Definition* left = call->ArgumentAt(0); |
| 1878 Definition* right = call->ArgumentAt(1); | 1897 Definition* right = call->ArgumentAt(1); |
| 1879 | 1898 |
| 1880 intptr_t cid = kIllegalCid; | 1899 intptr_t cid = kIllegalCid; |
| 1881 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1900 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1882 InsertBefore(call, | 1901 InsertBefore(call, |
| 1883 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1902 new CheckSmiInstr(new Value(left), |
| 1903 call->deopt_id(), | |
| 1904 call->token_pos()), | |
| 1884 call->env(), | 1905 call->env(), |
| 1885 Definition::kEffect); | 1906 Definition::kEffect); |
| 1886 InsertBefore(call, | 1907 InsertBefore(call, |
| 1887 new CheckSmiInstr(new Value(right), call->deopt_id()), | 1908 new CheckSmiInstr(new Value(right), |
| 1909 call->deopt_id(), | |
| 1910 call->token_pos()), | |
| 1888 call->env(), | 1911 call->env(), |
| 1889 Definition::kEffect); | 1912 Definition::kEffect); |
| 1890 cid = kSmiCid; | 1913 cid = kSmiCid; |
| 1891 } else if (HasTwoMintOrSmi(ic_data) && | 1914 } else if (HasTwoMintOrSmi(ic_data) && |
| 1892 FlowGraphCompiler::SupportsUnboxedMints()) { | 1915 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1893 cid = kMintCid; | 1916 cid = kMintCid; |
| 1894 } else if (HasTwoDoubleOrSmi(ic_data)) { | 1917 } else if (HasTwoDoubleOrSmi(ic_data)) { |
| 1895 // Use double comparison. | 1918 // Use double comparison. |
| 1896 if (SmiFitsInDouble()) { | 1919 if (SmiFitsInDouble()) { |
| 1897 cid = kDoubleCid; | 1920 cid = kDoubleCid; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2051 InsertBefore(call, | 2074 InsertBefore(call, |
| 2052 new CheckEitherNonSmiInstr(new Value(left), | 2075 new CheckEitherNonSmiInstr(new Value(left), |
| 2053 new Value(right), | 2076 new Value(right), |
| 2054 call->deopt_id()), | 2077 call->deopt_id()), |
| 2055 call->env(), | 2078 call->env(), |
| 2056 Definition::kEffect); | 2079 Definition::kEffect); |
| 2057 } | 2080 } |
| 2058 | 2081 |
| 2059 BinaryDoubleOpInstr* double_bin_op = | 2082 BinaryDoubleOpInstr* double_bin_op = |
| 2060 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), | 2083 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), |
| 2061 call->deopt_id()); | 2084 call->deopt_id(), call->token_pos()); |
| 2062 ReplaceCall(call, double_bin_op); | 2085 ReplaceCall(call, double_bin_op); |
| 2063 } else if (operands_type == kMintCid) { | 2086 } else if (operands_type == kMintCid) { |
| 2064 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 2087 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 2065 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 2088 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 2066 ShiftMintOpInstr* shift_op = | 2089 ShiftMintOpInstr* shift_op = |
| 2067 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 2090 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), |
| 2068 call->deopt_id()); | 2091 call->deopt_id()); |
| 2069 ReplaceCall(call, shift_op); | 2092 ReplaceCall(call, shift_op); |
| 2070 } else { | 2093 } else { |
| 2071 BinaryMintOpInstr* bin_op = | 2094 BinaryMintOpInstr* bin_op = |
| 2072 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 2095 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 2073 call->deopt_id()); | 2096 call->deopt_id()); |
| 2074 ReplaceCall(call, bin_op); | 2097 ReplaceCall(call, bin_op); |
| 2075 } | 2098 } |
| 2076 } else if (operands_type == kFloat32x4Cid) { | 2099 } else if (operands_type == kFloat32x4Cid) { |
| 2077 return InlineFloat32x4BinaryOp(call, op_kind); | 2100 return InlineFloat32x4BinaryOp(call, op_kind); |
| 2078 } else if (operands_type == kInt32x4Cid) { | 2101 } else if (operands_type == kInt32x4Cid) { |
| 2079 return InlineInt32x4BinaryOp(call, op_kind); | 2102 return InlineInt32x4BinaryOp(call, op_kind); |
| 2080 } else if (operands_type == kFloat64x2Cid) { | 2103 } else if (operands_type == kFloat64x2Cid) { |
| 2081 return InlineFloat64x2BinaryOp(call, op_kind); | 2104 return InlineFloat64x2BinaryOp(call, op_kind); |
| 2082 } else if (op_kind == Token::kMOD) { | 2105 } else if (op_kind == Token::kMOD) { |
| 2083 ASSERT(operands_type == kSmiCid); | 2106 ASSERT(operands_type == kSmiCid); |
| 2084 if (right->IsConstant()) { | 2107 if (right->IsConstant()) { |
| 2085 const Object& obj = right->AsConstant()->value(); | 2108 const Object& obj = right->AsConstant()->value(); |
| 2086 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { | 2109 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
| 2087 // Insert smi check and attach a copy of the original environment | 2110 // Insert smi check and attach a copy of the original environment |
| 2088 // because the smi operation can still deoptimize. | 2111 // because the smi operation can still deoptimize. |
| 2089 InsertBefore(call, | 2112 InsertBefore(call, |
| 2090 new CheckSmiInstr(new Value(left), call->deopt_id()), | 2113 new CheckSmiInstr(new Value(left), |
| 2114 call->deopt_id(), | |
| 2115 call->token_pos()), | |
| 2091 call->env(), | 2116 call->env(), |
| 2092 Definition::kEffect); | 2117 Definition::kEffect); |
| 2093 ConstantInstr* constant = | 2118 ConstantInstr* constant = |
| 2094 flow_graph()->GetConstant(Smi::Handle( | 2119 flow_graph()->GetConstant(Smi::Handle( |
| 2095 Smi::New(Smi::Cast(obj).Value() - 1))); | 2120 Smi::New(Smi::Cast(obj).Value() - 1))); |
| 2096 BinarySmiOpInstr* bin_op = | 2121 BinarySmiOpInstr* bin_op = |
| 2097 new BinarySmiOpInstr(Token::kBIT_AND, | 2122 new BinarySmiOpInstr(Token::kBIT_AND, |
| 2098 new Value(left), | 2123 new Value(left), |
| 2099 new Value(constant), | 2124 new Value(constant), |
| 2100 call->deopt_id()); | 2125 call->deopt_id(), |
| 2126 call->token_pos()); | |
| 2101 ReplaceCall(call, bin_op); | 2127 ReplaceCall(call, bin_op); |
| 2102 return true; | 2128 return true; |
| 2103 } | 2129 } |
| 2104 } | 2130 } |
| 2105 // Insert two smi checks and attach a copy of the original | 2131 // Insert two smi checks and attach a copy of the original |
| 2106 // environment because the smi operation can still deoptimize. | 2132 // environment because the smi operation can still deoptimize. |
| 2107 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2133 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2108 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2134 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2109 BinarySmiOpInstr* bin_op = | 2135 BinarySmiOpInstr* bin_op = |
| 2110 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2136 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 2111 call->deopt_id()); | 2137 call->deopt_id(), call->token_pos()); |
| 2112 ReplaceCall(call, bin_op); | 2138 ReplaceCall(call, bin_op); |
| 2113 } else { | 2139 } else { |
| 2114 ASSERT(operands_type == kSmiCid); | 2140 ASSERT(operands_type == kSmiCid); |
| 2115 // Insert two smi checks and attach a copy of the original | 2141 // Insert two smi checks and attach a copy of the original |
| 2116 // environment because the smi operation can still deoptimize. | 2142 // environment because the smi operation can still deoptimize. |
| 2117 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2143 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2118 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2144 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2119 if (left->IsConstant() && | 2145 if (left->IsConstant() && |
| 2120 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 2146 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| 2121 // Constant should be on the right side. | 2147 // Constant should be on the right side. |
| 2122 Definition* temp = left; | 2148 Definition* temp = left; |
| 2123 left = right; | 2149 left = right; |
| 2124 right = temp; | 2150 right = temp; |
| 2125 } | 2151 } |
| 2126 BinarySmiOpInstr* bin_op = | 2152 BinarySmiOpInstr* bin_op = |
| 2127 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2153 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 2128 call->deopt_id()); | 2154 call->deopt_id(), call->token_pos()); |
| 2129 ReplaceCall(call, bin_op); | 2155 ReplaceCall(call, bin_op); |
| 2130 } | 2156 } |
| 2131 return true; | 2157 return true; |
| 2132 } | 2158 } |
| 2133 | 2159 |
| 2134 | 2160 |
| 2135 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 2161 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
| 2136 Token::Kind op_kind) { | 2162 Token::Kind op_kind) { |
| 2137 ASSERT(call->ArgumentCount() == 1); | 2163 ASSERT(call->ArgumentCount() == 1); |
| 2138 Definition* input = call->ArgumentAt(0); | 2164 Definition* input = call->ArgumentAt(0); |
| 2139 Definition* unary_op = NULL; | 2165 Definition* unary_op = NULL; |
| 2140 if (HasOnlyOneSmi(*call->ic_data())) { | 2166 if (HasOnlyOneSmi(*call->ic_data())) { |
| 2141 InsertBefore(call, | 2167 InsertBefore(call, |
| 2142 new CheckSmiInstr(new Value(input), call->deopt_id()), | 2168 new CheckSmiInstr(new Value(input), |
| 2169 call->deopt_id(), | |
| 2170 call->token_pos()), | |
| 2143 call->env(), | 2171 call->env(), |
| 2144 Definition::kEffect); | 2172 Definition::kEffect); |
| 2145 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); | 2173 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); |
| 2146 } else if ((op_kind == Token::kBIT_NOT) && | 2174 } else if ((op_kind == Token::kBIT_NOT) && |
| 2147 HasOnlySmiOrMint(*call->ic_data()) && | 2175 HasOnlySmiOrMint(*call->ic_data()) && |
| 2148 FlowGraphCompiler::SupportsUnboxedMints()) { | 2176 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 2149 unary_op = new UnaryMintOpInstr( | 2177 unary_op = new UnaryMintOpInstr( |
| 2150 op_kind, new Value(input), call->deopt_id()); | 2178 op_kind, new Value(input), call->deopt_id()); |
| 2151 } else if (HasOnlyOneDouble(*call->ic_data()) && | 2179 } else if (HasOnlyOneDouble(*call->ic_data()) && |
| 2152 (op_kind == Token::kNEGATE)) { | 2180 (op_kind == Token::kNEGATE)) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2227 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); | 2255 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); |
| 2228 ASSERT(!field.IsNull()); | 2256 ASSERT(!field.IsNull()); |
| 2229 | 2257 |
| 2230 if (InstanceCallNeedsClassCheck(call)) { | 2258 if (InstanceCallNeedsClassCheck(call)) { |
| 2231 AddReceiverCheck(call); | 2259 AddReceiverCheck(call); |
| 2232 } | 2260 } |
| 2233 LoadFieldInstr* load = new LoadFieldInstr( | 2261 LoadFieldInstr* load = new LoadFieldInstr( |
| 2234 new Value(call->ArgumentAt(0)), | 2262 new Value(call->ArgumentAt(0)), |
| 2235 &field, | 2263 &field, |
| 2236 AbstractType::ZoneHandle(field.type()), | 2264 AbstractType::ZoneHandle(field.type()), |
| 2265 call->token_pos(), | |
| 2237 field.is_final()); | 2266 field.is_final()); |
| 2238 if (field.guarded_cid() != kIllegalCid) { | 2267 if (field.guarded_cid() != kIllegalCid) { |
| 2239 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2268 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 2240 load->set_result_cid(field.guarded_cid()); | 2269 load->set_result_cid(field.guarded_cid()); |
| 2241 } | 2270 } |
| 2242 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2271 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 2243 } | 2272 } |
| 2244 | 2273 |
| 2245 // Discard the environment from the original instruction because the load | 2274 // Discard the environment from the original instruction because the load |
| 2246 // can't deoptimize. | 2275 // can't deoptimize. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2260 | 2289 |
| 2261 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { | 2290 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { |
| 2262 // Treat length loads as mutable (i.e. affected by side effects) to avoid | 2291 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
| 2263 // hoisting them since we can't hoist the preceding class-check. This | 2292 // hoisting them since we can't hoist the preceding class-check. This |
| 2264 // is because of externalization of strings that affects their class-id. | 2293 // is because of externalization of strings that affects their class-id. |
| 2265 const bool is_immutable = false; | 2294 const bool is_immutable = false; |
| 2266 LoadFieldInstr* load = new LoadFieldInstr( | 2295 LoadFieldInstr* load = new LoadFieldInstr( |
| 2267 new Value(str), | 2296 new Value(str), |
| 2268 String::length_offset(), | 2297 String::length_offset(), |
| 2269 Type::ZoneHandle(Type::SmiType()), | 2298 Type::ZoneHandle(Type::SmiType()), |
| 2299 str->token_pos(), | |
| 2270 is_immutable); | 2300 is_immutable); |
| 2271 load->set_result_cid(kSmiCid); | 2301 load->set_result_cid(kSmiCid); |
| 2272 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 2302 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 2273 return load; | 2303 return load; |
| 2274 } | 2304 } |
| 2275 | 2305 |
| 2276 | 2306 |
| 2277 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2307 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 2278 MethodRecognizer::Kind getter) { | 2308 MethodRecognizer::Kind getter) { |
| 2279 if (!ShouldInlineSimd()) { | 2309 if (!ShouldInlineSimd()) { |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2614 // Returns the LoadIndexedInstr. | 2644 // Returns the LoadIndexedInstr. |
| 2615 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( | 2645 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( |
| 2616 Instruction* call, | 2646 Instruction* call, |
| 2617 intptr_t cid, | 2647 intptr_t cid, |
| 2618 Definition* str, | 2648 Definition* str, |
| 2619 Definition* index, | 2649 Definition* index, |
| 2620 Instruction* cursor) { | 2650 Instruction* cursor) { |
| 2621 | 2651 |
| 2622 cursor = flow_graph()->AppendTo(cursor, | 2652 cursor = flow_graph()->AppendTo(cursor, |
| 2623 new CheckSmiInstr(new Value(index), | 2653 new CheckSmiInstr(new Value(index), |
| 2624 call->deopt_id()), | 2654 call->deopt_id(), |
| 2655 call->token_pos()), | |
| 2625 call->env(), | 2656 call->env(), |
| 2626 Definition::kEffect); | 2657 Definition::kEffect); |
| 2627 | 2658 |
| 2628 // Load the length of the string. | 2659 // Load the length of the string. |
| 2629 LoadFieldInstr* length = BuildLoadStringLength(str); | 2660 LoadFieldInstr* length = BuildLoadStringLength(str); |
| 2630 cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); | 2661 cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); |
| 2631 // Bounds check. | 2662 // Bounds check. |
| 2632 cursor = flow_graph()->AppendTo(cursor, | 2663 cursor = flow_graph()->AppendTo(cursor, |
| 2633 new CheckArrayBoundInstr(new Value(length), | 2664 new CheckArrayBoundInstr(new Value(length), |
| 2634 new Value(index), | 2665 new Value(index), |
| 2635 call->deopt_id()), | 2666 call->deopt_id()), |
| 2636 call->env(), | 2667 call->env(), |
| 2637 Definition::kEffect); | 2668 Definition::kEffect); |
| 2638 | 2669 |
| 2639 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( | 2670 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( |
| 2640 new Value(str), | 2671 new Value(str), |
| 2641 new Value(index), | 2672 new Value(index), |
| 2642 FlowGraphCompiler::ElementSizeFor(cid), | 2673 FlowGraphCompiler::ElementSizeFor(cid), |
| 2643 cid, | 2674 cid, |
| 2644 Isolate::kNoDeoptId); | 2675 Isolate::kNoDeoptId, |
| 2676 call->token_pos()); | |
| 2645 | 2677 |
| 2646 cursor = flow_graph()->AppendTo(cursor, | 2678 cursor = flow_graph()->AppendTo(cursor, |
| 2647 load_indexed, | 2679 load_indexed, |
| 2648 NULL, | 2680 NULL, |
| 2649 Definition::kValue); | 2681 Definition::kValue); |
| 2650 ASSERT(cursor == load_indexed); | 2682 ASSERT(cursor == load_indexed); |
| 2651 return load_indexed; | 2683 return load_indexed; |
| 2652 } | 2684 } |
| 2653 | 2685 |
| 2654 | 2686 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2706 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2738 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
| 2707 InstanceCallInstr* call, | 2739 InstanceCallInstr* call, |
| 2708 MethodRecognizer::Kind recognized_kind) { | 2740 MethodRecognizer::Kind recognized_kind) { |
| 2709 AddReceiverCheck(call); | 2741 AddReceiverCheck(call); |
| 2710 ZoneGrowableArray<Value*>* args = | 2742 ZoneGrowableArray<Value*>* args = |
| 2711 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 2743 new ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 2712 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 2744 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 2713 args->Add(new Value(call->ArgumentAt(i))); | 2745 args->Add(new Value(call->ArgumentAt(i))); |
| 2714 } | 2746 } |
| 2715 InvokeMathCFunctionInstr* invoke = | 2747 InvokeMathCFunctionInstr* invoke = |
| 2716 new InvokeMathCFunctionInstr(args, call->deopt_id(), recognized_kind); | 2748 new InvokeMathCFunctionInstr(args, |
| 2749 call->deopt_id(), | |
| 2750 recognized_kind, | |
| 2751 call->token_pos()); | |
| 2717 ReplaceCall(call, invoke); | 2752 ReplaceCall(call, invoke); |
| 2718 } | 2753 } |
| 2719 | 2754 |
| 2720 | 2755 |
| 2721 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | 2756 static bool IsSupportedByteArrayViewCid(intptr_t cid) { |
| 2722 switch (cid) { | 2757 switch (cid) { |
| 2723 case kTypedDataInt8ArrayCid: | 2758 case kTypedDataInt8ArrayCid: |
| 2724 case kTypedDataUint8ArrayCid: | 2759 case kTypedDataUint8ArrayCid: |
| 2725 case kExternalTypedDataUint8ArrayCid: | 2760 case kExternalTypedDataUint8ArrayCid: |
| 2726 case kTypedDataUint8ClampedArrayCid: | 2761 case kTypedDataUint8ClampedArrayCid: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2758 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | 2793 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && |
| 2759 (ic_data.NumberOfChecks() == 1) && | 2794 (ic_data.NumberOfChecks() == 1) && |
| 2760 (class_ids[0] == kGrowableObjectArrayCid)) { | 2795 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2761 // This is an internal method, no need to check argument types. | 2796 // This is an internal method, no need to check argument types. |
| 2762 Definition* array = call->ArgumentAt(0); | 2797 Definition* array = call->ArgumentAt(0); |
| 2763 Definition* value = call->ArgumentAt(1); | 2798 Definition* value = call->ArgumentAt(1); |
| 2764 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2799 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2765 GrowableObjectArray::data_offset(), | 2800 GrowableObjectArray::data_offset(), |
| 2766 new Value(array), | 2801 new Value(array), |
| 2767 new Value(value), | 2802 new Value(value), |
| 2768 kEmitStoreBarrier); | 2803 kEmitStoreBarrier, |
| 2804 call->token_pos()); | |
| 2769 ReplaceCall(call, store); | 2805 ReplaceCall(call, store); |
| 2770 return true; | 2806 return true; |
| 2771 } | 2807 } |
| 2772 | 2808 |
| 2773 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | 2809 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && |
| 2774 (ic_data.NumberOfChecks() == 1) && | 2810 (ic_data.NumberOfChecks() == 1) && |
| 2775 (class_ids[0] == kGrowableObjectArrayCid)) { | 2811 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2776 // This is an internal method, no need to check argument types nor | 2812 // This is an internal method, no need to check argument types nor |
| 2777 // range. | 2813 // range. |
| 2778 Definition* array = call->ArgumentAt(0); | 2814 Definition* array = call->ArgumentAt(0); |
| 2779 Definition* value = call->ArgumentAt(1); | 2815 Definition* value = call->ArgumentAt(1); |
| 2780 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2816 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2781 GrowableObjectArray::length_offset(), | 2817 GrowableObjectArray::length_offset(), |
| 2782 new Value(array), | 2818 new Value(array), |
| 2783 new Value(value), | 2819 new Value(value), |
| 2784 kEmitStoreBarrier); | 2820 kEmitStoreBarrier, |
| 2821 call->token_pos()); | |
| 2785 ReplaceCall(call, store); | 2822 ReplaceCall(call, store); |
| 2786 return true; | 2823 return true; |
| 2787 } | 2824 } |
| 2788 | 2825 |
| 2789 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 2826 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
| 2790 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 2827 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && |
| 2791 (ic_data.NumberOfChecks() == 1) && | 2828 (ic_data.NumberOfChecks() == 1) && |
| 2792 ((class_ids[0] == kOneByteStringCid) || | 2829 ((class_ids[0] == kOneByteStringCid) || |
| 2793 (class_ids[0] == kTwoByteStringCid))) { | 2830 (class_ids[0] == kTwoByteStringCid))) { |
| 2794 return TryReplaceInstanceCallWithInline(call); | 2831 return TryReplaceInstanceCallWithInline(call); |
| 2795 } | 2832 } |
| 2796 | 2833 |
| 2797 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 2834 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 2798 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 2835 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 2799 // This is an internal method, no need to check argument types nor | 2836 // This is an internal method, no need to check argument types nor |
| 2800 // range. | 2837 // range. |
| 2801 Definition* str = call->ArgumentAt(0); | 2838 Definition* str = call->ArgumentAt(0); |
| 2802 Definition* index = call->ArgumentAt(1); | 2839 Definition* index = call->ArgumentAt(1); |
| 2803 Definition* value = call->ArgumentAt(2); | 2840 Definition* value = call->ArgumentAt(2); |
| 2804 StoreIndexedInstr* store_op = new StoreIndexedInstr( | 2841 StoreIndexedInstr* store_op = new StoreIndexedInstr( |
| 2805 new Value(str), | 2842 new Value(str), |
| 2806 new Value(index), | 2843 new Value(index), |
| 2807 new Value(value), | 2844 new Value(value), |
| 2808 kNoStoreBarrier, | 2845 kNoStoreBarrier, |
| 2809 1, // Index scale | 2846 1, // Index scale |
| 2810 kOneByteStringCid, | 2847 kOneByteStringCid, |
| 2811 call->deopt_id()); | 2848 call->deopt_id(), |
| 2849 call->token_pos()); | |
| 2812 ReplaceCall(call, store_op); | 2850 ReplaceCall(call, store_op); |
| 2813 return true; | 2851 return true; |
| 2814 } | 2852 } |
| 2815 return false; | 2853 return false; |
| 2816 } | 2854 } |
| 2817 | 2855 |
| 2818 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 2856 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 2819 (ic_data.NumberOfChecks() == 1) && | 2857 (ic_data.NumberOfChecks() == 1) && |
| 2820 (class_ids[0] == kSmiCid)) { | 2858 (class_ids[0] == kSmiCid)) { |
| 2821 AddReceiverCheck(call); | 2859 AddReceiverCheck(call); |
| 2822 ReplaceCall(call, new SmiToDoubleInstr(new Value(call->ArgumentAt(0)))); | 2860 ReplaceCall(call, |
| 2861 new SmiToDoubleInstr(new Value(call->ArgumentAt(0)), | |
| 2862 call->token_pos())); | |
| 2823 return true; | 2863 return true; |
| 2824 } | 2864 } |
| 2825 | 2865 |
| 2826 if (class_ids[0] == kDoubleCid) { | 2866 if (class_ids[0] == kDoubleCid) { |
| 2827 switch (recognized_kind) { | 2867 switch (recognized_kind) { |
| 2828 case MethodRecognizer::kDoubleToInteger: { | 2868 case MethodRecognizer::kDoubleToInteger: { |
| 2829 AddReceiverCheck(call); | 2869 AddReceiverCheck(call); |
| 2830 ASSERT(call->HasICData()); | 2870 ASSERT(call->HasICData()); |
| 2831 const ICData& ic_data = *call->ic_data(); | 2871 const ICData& ic_data = *call->ic_data(); |
| 2832 Definition* input = call->ArgumentAt(0); | 2872 Definition* input = call->ArgumentAt(0); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2955 int32_mask->AsConstant()->value()); | 2995 int32_mask->AsConstant()->value()); |
| 2956 const int64_t mask_value = mask_literal.AsInt64Value(); | 2996 const int64_t mask_value = mask_literal.AsInt64Value(); |
| 2957 ASSERT(mask_value >= 0); | 2997 ASSERT(mask_value >= 0); |
| 2958 if (mask_value > Smi::kMaxValue) { | 2998 if (mask_value > Smi::kMaxValue) { |
| 2959 // The result will not be Smi. | 2999 // The result will not be Smi. |
| 2960 return false; | 3000 return false; |
| 2961 } | 3001 } |
| 2962 BinarySmiOpInstr* left_shift = | 3002 BinarySmiOpInstr* left_shift = |
| 2963 new BinarySmiOpInstr(Token::kSHL, | 3003 new BinarySmiOpInstr(Token::kSHL, |
| 2964 new Value(value), new Value(count), | 3004 new Value(value), new Value(count), |
| 2965 call->deopt_id()); | 3005 call->deopt_id(), call->token_pos()); |
| 2966 left_shift->set_is_truncating(true); | 3006 left_shift->set_is_truncating(true); |
| 2967 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3007 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
| 2968 // No BIT_AND operation needed. | 3008 // No BIT_AND operation needed. |
| 2969 ReplaceCall(call, left_shift); | 3009 ReplaceCall(call, left_shift); |
| 2970 } else { | 3010 } else { |
| 2971 InsertBefore(call, left_shift, call->env(), Definition::kValue); | 3011 InsertBefore(call, left_shift, call->env(), Definition::kValue); |
| 2972 BinarySmiOpInstr* bit_and = | 3012 BinarySmiOpInstr* bit_and = |
| 2973 new BinarySmiOpInstr(Token::kBIT_AND, | 3013 new BinarySmiOpInstr(Token::kBIT_AND, |
| 2974 new Value(left_shift), new Value(int32_mask), | 3014 new Value(left_shift), new Value(int32_mask), |
| 2975 call->deopt_id()); | 3015 call->deopt_id(), call->token_pos()); |
| 2976 ReplaceCall(call, bit_and); | 3016 ReplaceCall(call, bit_and); |
| 2977 } | 3017 } |
| 2978 return true; | 3018 return true; |
| 2979 } | 3019 } |
| 2980 | 3020 |
| 2981 if (HasTwoMintOrSmi(ic_data) && | 3021 if (HasTwoMintOrSmi(ic_data) && |
| 2982 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3022 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 2983 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3023 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
| 2984 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3024 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
| 2985 return false; | 3025 return false; |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3408 // Set deopt_id if we can optimistically assume that the result is Smi. | 3448 // Set deopt_id if we can optimistically assume that the result is Smi. |
| 3409 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 3449 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
| 3410 deopt_id = ic_data.HasDeoptReasons() ? | 3450 deopt_id = ic_data.HasDeoptReasons() ? |
| 3411 Isolate::kNoDeoptId : call->deopt_id(); | 3451 Isolate::kNoDeoptId : call->deopt_id(); |
| 3412 } | 3452 } |
| 3413 | 3453 |
| 3414 *last = new LoadIndexedInstr(new Value(array), | 3454 *last = new LoadIndexedInstr(new Value(array), |
| 3415 new Value(index), | 3455 new Value(index), |
| 3416 1, | 3456 1, |
| 3417 view_cid, | 3457 view_cid, |
| 3418 deopt_id); | 3458 deopt_id, |
| 3459 call->token_pos()); | |
| 3419 cursor = flow_graph()->AppendTo( | 3460 cursor = flow_graph()->AppendTo( |
| 3420 cursor, | 3461 cursor, |
| 3421 *last, | 3462 *last, |
| 3422 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3463 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3423 Definition::kValue); | 3464 Definition::kValue); |
| 3424 | 3465 |
| 3425 if (view_cid == kTypedDataFloat32ArrayCid) { | 3466 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3426 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 3467 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 3427 flow_graph()->AppendTo(cursor, | 3468 flow_graph()->AppendTo(cursor, |
| 3428 *last, | 3469 *last, |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3549 Definition::kValue); | 3590 Definition::kValue); |
| 3550 } | 3591 } |
| 3551 | 3592 |
| 3552 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3593 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
| 3553 *last = new StoreIndexedInstr(new Value(array), | 3594 *last = new StoreIndexedInstr(new Value(array), |
| 3554 new Value(index), | 3595 new Value(index), |
| 3555 new Value(stored_value), | 3596 new Value(stored_value), |
| 3556 needs_store_barrier, | 3597 needs_store_barrier, |
| 3557 1, // Index scale | 3598 1, // Index scale |
| 3558 view_cid, | 3599 view_cid, |
| 3559 call->deopt_id()); | 3600 call->deopt_id(), |
| 3601 call->token_pos()); | |
| 3560 | 3602 |
| 3561 flow_graph()->AppendTo(cursor, | 3603 flow_graph()->AppendTo(cursor, |
| 3562 *last, | 3604 *last, |
| 3563 call->deopt_id() != Isolate::kNoDeoptId ? | 3605 call->deopt_id() != Isolate::kNoDeoptId ? |
| 3564 call->env() : NULL, | 3606 call->env() : NULL, |
| 3565 Definition::kEffect); | 3607 Definition::kEffect); |
| 3566 return true; | 3608 return true; |
| 3567 } | 3609 } |
| 3568 | 3610 |
| 3569 | 3611 |
| 3570 | 3612 |
| 3571 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( | 3613 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
| 3572 Instruction* call, | 3614 Instruction* call, |
| 3573 intptr_t array_cid, | 3615 intptr_t array_cid, |
| 3574 intptr_t view_cid, | 3616 intptr_t view_cid, |
| 3575 Definition** array, | 3617 Definition** array, |
| 3576 Definition* byte_index, | 3618 Definition* byte_index, |
| 3577 Instruction** cursor) { | 3619 Instruction** cursor) { |
| 3578 // Insert byte_index smi check. | 3620 // Insert byte_index smi check. |
| 3579 *cursor = flow_graph()->AppendTo(*cursor, | 3621 *cursor = flow_graph()->AppendTo(*cursor, |
| 3580 new CheckSmiInstr(new Value(byte_index), | 3622 new CheckSmiInstr(new Value(byte_index), |
| 3581 call->deopt_id()), | 3623 call->deopt_id(), |
| 3624 call->token_pos()), | |
| 3582 call->env(), | 3625 call->env(), |
| 3583 Definition::kEffect); | 3626 Definition::kEffect); |
| 3584 | 3627 |
| 3585 const bool is_immutable = true; | 3628 const bool is_immutable = true; |
| 3586 LoadFieldInstr* length = | 3629 LoadFieldInstr* length = |
| 3587 new LoadFieldInstr(new Value(*array), | 3630 new LoadFieldInstr(new Value(*array), |
| 3588 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 3631 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 3589 Type::ZoneHandle(Type::SmiType()), | 3632 Type::ZoneHandle(Type::SmiType()), |
| 3633 call->token_pos(), | |
| 3590 is_immutable); | 3634 is_immutable); |
| 3591 length->set_result_cid(kSmiCid); | 3635 length->set_result_cid(kSmiCid); |
| 3592 length->set_recognized_kind( | 3636 length->set_recognized_kind( |
| 3593 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 3637 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 3594 *cursor = flow_graph()->AppendTo(*cursor, | 3638 *cursor = flow_graph()->AppendTo(*cursor, |
| 3595 length, | 3639 length, |
| 3596 NULL, | 3640 NULL, |
| 3597 Definition::kValue); | 3641 Definition::kValue); |
| 3598 | 3642 |
| 3599 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); | 3643 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 3600 ConstantInstr* bytes_per_element = | 3644 ConstantInstr* bytes_per_element = |
| 3601 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); | 3645 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); |
| 3602 BinarySmiOpInstr* len_in_bytes = | 3646 BinarySmiOpInstr* len_in_bytes = |
| 3603 new BinarySmiOpInstr(Token::kMUL, | 3647 new BinarySmiOpInstr(Token::kMUL, |
| 3604 new Value(length), | 3648 new Value(length), |
| 3605 new Value(bytes_per_element), | 3649 new Value(bytes_per_element), |
| 3606 call->deopt_id()); | 3650 call->deopt_id(), call->token_pos()); |
| 3607 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3651 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
| 3608 Definition::kValue); | 3652 Definition::kValue); |
| 3609 | 3653 |
| 3610 ConstantInstr* length_adjustment = | 3654 ConstantInstr* length_adjustment = |
| 3611 flow_graph()->GetConstant(Smi::Handle(Smi::New( | 3655 flow_graph()->GetConstant(Smi::Handle(Smi::New( |
| 3612 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); | 3656 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); |
| 3613 // adjusted_length = len_in_bytes - (element_size - 1). | 3657 // adjusted_length = len_in_bytes - (element_size - 1). |
| 3614 BinarySmiOpInstr* adjusted_length = | 3658 BinarySmiOpInstr* adjusted_length = |
| 3615 new BinarySmiOpInstr(Token::kSUB, | 3659 new BinarySmiOpInstr(Token::kSUB, |
| 3616 new Value(len_in_bytes), | 3660 new Value(len_in_bytes), |
| 3617 new Value(length_adjustment), | 3661 new Value(length_adjustment), |
| 3618 call->deopt_id()); | 3662 call->deopt_id(), call->token_pos()); |
| 3619 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3663 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
| 3620 Definition::kValue); | 3664 Definition::kValue); |
| 3621 | 3665 |
| 3622 // Check adjusted_length > 0. | 3666 // Check adjusted_length > 0. |
| 3623 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 3667 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 3624 *cursor = flow_graph()->AppendTo(*cursor, | 3668 *cursor = flow_graph()->AppendTo(*cursor, |
| 3625 new CheckArrayBoundInstr( | 3669 new CheckArrayBoundInstr( |
| 3626 new Value(adjusted_length), | 3670 new Value(adjusted_length), |
| 3627 new Value(zero), | 3671 new Value(zero), |
| 3628 call->deopt_id()), | 3672 call->deopt_id()), |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4129 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4173 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
| 4130 // We know that first argument is double, the second is num. | 4174 // We know that first argument is double, the second is num. |
| 4131 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4175 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
| 4132 // instructions contain type checks and conversions to double. | 4176 // instructions contain type checks and conversions to double. |
| 4133 ZoneGrowableArray<Value*>* args = | 4177 ZoneGrowableArray<Value*>* args = |
| 4134 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4178 new ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 4135 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4179 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 4136 args->Add(new Value(call->ArgumentAt(i))); | 4180 args->Add(new Value(call->ArgumentAt(i))); |
| 4137 } | 4181 } |
| 4138 InvokeMathCFunctionInstr* invoke = | 4182 InvokeMathCFunctionInstr* invoke = |
| 4139 new InvokeMathCFunctionInstr(args, call->deopt_id(), recognized_kind); | 4183 new InvokeMathCFunctionInstr(args, |
| 4184 call->deopt_id(), | |
| 4185 recognized_kind, | |
| 4186 call->token_pos()); | |
| 4140 ReplaceCall(call, invoke); | 4187 ReplaceCall(call, invoke); |
| 4141 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( | 4188 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( |
| 4142 String::Handle(call->function().name()))) { | 4189 String::Handle(call->function().name()))) { |
| 4143 // Check for core library get:_classId. | 4190 // Check for core library get:_classId. |
| 4144 intptr_t cid = Class::Handle(call->function().Owner()).id(); | 4191 intptr_t cid = Class::Handle(call->function().Owner()).id(); |
| 4145 // Currently only implemented for a subset of classes. | 4192 // Currently only implemented for a subset of classes. |
| 4146 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 4193 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
| 4147 (cid == kExternalOneByteStringCid) || | 4194 (cid == kExternalOneByteStringCid) || |
| 4148 (cid == kGrowableObjectArrayCid) || | 4195 (cid == kGrowableObjectArrayCid) || |
| 4149 (cid == kImmutableArrayCid) || (cid == kArrayCid)); | 4196 (cid == kImmutableArrayCid) || (cid == kArrayCid)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4245 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); | 4292 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); |
| 4246 ASSERT(!field.IsNull()); | 4293 ASSERT(!field.IsNull()); |
| 4247 | 4294 |
| 4248 if (InstanceCallNeedsClassCheck(instr)) { | 4295 if (InstanceCallNeedsClassCheck(instr)) { |
| 4249 AddReceiverCheck(instr); | 4296 AddReceiverCheck(instr); |
| 4250 } | 4297 } |
| 4251 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4298 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
| 4252 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 4299 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
| 4253 InsertBefore(instr, | 4300 InsertBefore(instr, |
| 4254 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), | 4301 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), |
| 4255 instr->deopt_id()), | 4302 instr->deopt_id(), |
| 4303 instr->token_pos()), | |
| 4256 instr->env(), | 4304 instr->env(), |
| 4257 Definition::kEffect); | 4305 Definition::kEffect); |
| 4258 needs_store_barrier = kNoStoreBarrier; | 4306 needs_store_barrier = kNoStoreBarrier; |
| 4259 } | 4307 } |
| 4260 | 4308 |
| 4261 if (field.guarded_cid() != kDynamicCid) { | 4309 if (field.guarded_cid() != kDynamicCid) { |
| 4262 InsertBefore(instr, | 4310 InsertBefore(instr, |
| 4263 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), | 4311 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), |
| 4264 field, | 4312 field, |
| 4265 instr->deopt_id()), | 4313 instr->deopt_id()), |
| 4266 instr->env(), | 4314 instr->env(), |
| 4267 Definition::kEffect); | 4315 Definition::kEffect); |
| 4268 } | 4316 } |
| 4269 | 4317 |
| 4270 // Field guard was detached. | 4318 // Field guard was detached. |
| 4271 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 4319 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 4272 field, | 4320 field, |
| 4273 new Value(instr->ArgumentAt(0)), | 4321 new Value(instr->ArgumentAt(0)), |
| 4274 new Value(instr->ArgumentAt(1)), | 4322 new Value(instr->ArgumentAt(1)), |
| 4275 needs_store_barrier); | 4323 needs_store_barrier, |
| 4324 instr->token_pos()); | |
| 4276 | 4325 |
| 4277 if (store->IsUnboxedStore()) { | 4326 if (store->IsUnboxedStore()) { |
| 4278 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4327 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 4279 } | 4328 } |
| 4280 | 4329 |
| 4281 // Discard the environment from the original instruction because the store | 4330 // Discard the environment from the original instruction because the store |
| 4282 // can't deoptimize. | 4331 // can't deoptimize. |
| 4283 instr->RemoveEnvironment(); | 4332 instr->RemoveEnvironment(); |
| 4284 ReplaceCall(instr, store); | 4333 ReplaceCall(instr, store); |
| 4285 return true; | 4334 return true; |
| (...skipping 4604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8890 void FlowGraphOptimizer::EliminateEnvironments() { | 8939 void FlowGraphOptimizer::EliminateEnvironments() { |
| 8891 // After this pass we can no longer perform LICM and hoist instructions | 8940 // After this pass we can no longer perform LICM and hoist instructions |
| 8892 // that can deoptimize. | 8941 // that can deoptimize. |
| 8893 | 8942 |
| 8894 flow_graph_->disallow_licm(); | 8943 flow_graph_->disallow_licm(); |
| 8895 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 8944 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 8896 BlockEntryInstr* block = block_order_[i]; | 8945 BlockEntryInstr* block = block_order_[i]; |
| 8897 block->RemoveEnvironment(); | 8946 block->RemoveEnvironment(); |
| 8898 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 8947 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 8899 Instruction* current = it.Current(); | 8948 Instruction* current = it.Current(); |
| 8900 if (!current->CanDeoptimize()) current->RemoveEnvironment(); | 8949 if (!current->CanDeoptimize() && !FLAG_source_lines) { |
|
Florian Schneider
2014/04/29 20:04:21
Note that this flag changes the number of uses for
srdjan
2014/04/30 15:00:53
Removed since it changes code.
| |
| 8950 // --source-lines needs deopt environments. | |
| 8951 current->RemoveEnvironment(); | |
| 8952 } | |
| 8901 } | 8953 } |
| 8902 } | 8954 } |
| 8903 } | 8955 } |
| 8904 | 8956 |
| 8905 | 8957 |
| 8906 // Right now we are attempting to sink allocation only into | 8958 // Right now we are attempting to sink allocation only into |
| 8907 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8959 // deoptimization exit. So candidate should only be used in StoreInstanceField |
| 8908 // instructions that write into fields of the allocated object. | 8960 // instructions that write into fields of the allocated object. |
| 8909 // We do not support materialization of the object that has type arguments. | 8961 // We do not support materialization of the object that has type arguments. |
| 8910 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { | 8962 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9070 const Class& cls, | 9122 const Class& cls, |
| 9071 const ZoneGrowableArray<const Object*>& slots) { | 9123 const ZoneGrowableArray<const Object*>& slots) { |
| 9072 ZoneGrowableArray<Value*>* values = | 9124 ZoneGrowableArray<Value*>* values = |
| 9073 new ZoneGrowableArray<Value*>(slots.length()); | 9125 new ZoneGrowableArray<Value*>(slots.length()); |
| 9074 | 9126 |
| 9075 // Insert load instruction for every field. | 9127 // Insert load instruction for every field. |
| 9076 for (intptr_t i = 0; i < slots.length(); i++) { | 9128 for (intptr_t i = 0; i < slots.length(); i++) { |
| 9077 LoadFieldInstr* load = slots[i]->IsField() | 9129 LoadFieldInstr* load = slots[i]->IsField() |
| 9078 ? new LoadFieldInstr(new Value(alloc), | 9130 ? new LoadFieldInstr(new Value(alloc), |
| 9079 &Field::Cast(*slots[i]), | 9131 &Field::Cast(*slots[i]), |
| 9080 AbstractType::ZoneHandle()) | 9132 AbstractType::ZoneHandle(), |
| 9133 alloc->token_pos()) | |
| 9081 : new LoadFieldInstr(new Value(alloc), | 9134 : new LoadFieldInstr(new Value(alloc), |
| 9082 Smi::Cast(*slots[i]).Value(), | 9135 Smi::Cast(*slots[i]).Value(), |
| 9083 AbstractType::ZoneHandle()); | 9136 AbstractType::ZoneHandle(), |
| 9137 alloc->token_pos()); | |
| 9084 flow_graph_->InsertBefore( | 9138 flow_graph_->InsertBefore( |
| 9085 exit, load, NULL, Definition::kValue); | 9139 exit, load, NULL, Definition::kValue); |
| 9086 values->Add(new Value(load)); | 9140 values->Add(new Value(load)); |
| 9087 } | 9141 } |
| 9088 | 9142 |
| 9089 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); | 9143 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); |
| 9090 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); | 9144 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); |
| 9091 | 9145 |
| 9092 // Replace all mentions of this allocation with a newly inserted | 9146 // Replace all mentions of this allocation with a newly inserted |
| 9093 // MaterializeObject instruction. | 9147 // MaterializeObject instruction. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9140 } | 9194 } |
| 9141 | 9195 |
| 9142 // Insert materializations at environment uses. | 9196 // Insert materializations at environment uses. |
| 9143 for (intptr_t i = 0; i < exits.length(); i++) { | 9197 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9144 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9198 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9145 } | 9199 } |
| 9146 } | 9200 } |
| 9147 | 9201 |
| 9148 | 9202 |
| 9149 } // namespace dart | 9203 } // namespace dart |
| OLD | NEW |