| 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 Scanner::kNoSourcePos); |
| 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(), // No type. |
| 1175 call->token_pos()); |
| 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 LoadFieldInstr* length = | 1523 LoadFieldInstr* length = |
| 1512 new LoadFieldInstr(new Value(*array), | 1524 new LoadFieldInstr(new Value(*array), |
| 1513 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 1525 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 1514 Type::ZoneHandle(Type::SmiType())); | 1526 Type::ZoneHandle(Type::SmiType()), |
| 1527 call->token_pos()); |
| 1515 length->set_is_immutable( | 1528 length->set_is_immutable( |
| 1516 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); | 1529 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); |
| 1517 length->set_result_cid(kSmiCid); | 1530 length->set_result_cid(kSmiCid); |
| 1518 length->set_recognized_kind( | 1531 length->set_recognized_kind( |
| 1519 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 1532 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 1520 *cursor = flow_graph()->AppendTo(*cursor, | 1533 *cursor = flow_graph()->AppendTo(*cursor, |
| 1521 length, | 1534 length, |
| 1522 NULL, | 1535 NULL, |
| 1523 Definition::kValue); | 1536 Definition::kValue); |
| 1524 | 1537 |
| 1525 *cursor = flow_graph()->AppendTo(*cursor, | 1538 *cursor = flow_graph()->AppendTo(*cursor, |
| 1526 new CheckArrayBoundInstr( | 1539 new CheckArrayBoundInstr( |
| 1527 new Value(length), | 1540 new Value(length), |
| 1528 new Value(index), | 1541 new Value(index), |
| 1529 call->deopt_id()), | 1542 call->deopt_id()), |
| 1530 call->env(), | 1543 call->env(), |
| 1531 Definition::kEffect); | 1544 Definition::kEffect); |
| 1532 | 1545 |
| 1533 if (array_cid == kGrowableObjectArrayCid) { | 1546 if (array_cid == kGrowableObjectArrayCid) { |
| 1534 // Insert data elements load. | 1547 // Insert data elements load. |
| 1535 LoadFieldInstr* elements = | 1548 LoadFieldInstr* elements = |
| 1536 new LoadFieldInstr(new Value(*array), | 1549 new LoadFieldInstr(new Value(*array), |
| 1537 GrowableObjectArray::data_offset(), | 1550 GrowableObjectArray::data_offset(), |
| 1538 Type::ZoneHandle(Type::DynamicType())); | 1551 Type::ZoneHandle(Type::DynamicType()), |
| 1552 call->token_pos()); |
| 1539 elements->set_result_cid(kArrayCid); | 1553 elements->set_result_cid(kArrayCid); |
| 1540 *cursor = flow_graph()->AppendTo(*cursor, | 1554 *cursor = flow_graph()->AppendTo(*cursor, |
| 1541 elements, | 1555 elements, |
| 1542 NULL, | 1556 NULL, |
| 1543 Definition::kValue); | 1557 Definition::kValue); |
| 1544 // Load from the data from backing store which is a fixed-length array. | 1558 // Load from the data from backing store which is a fixed-length array. |
| 1545 *array = elements; | 1559 *array = elements; |
| 1546 array_cid = kArrayCid; | 1560 array_cid = kArrayCid; |
| 1547 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 1561 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 1548 LoadUntaggedInstr* elements = | 1562 LoadUntaggedInstr* elements = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1587 deopt_id = ic_data.HasDeoptReasons() ? | 1601 deopt_id = ic_data.HasDeoptReasons() ? |
| 1588 Isolate::kNoDeoptId : call->deopt_id(); | 1602 Isolate::kNoDeoptId : call->deopt_id(); |
| 1589 } | 1603 } |
| 1590 | 1604 |
| 1591 // Array load and return. | 1605 // Array load and return. |
| 1592 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1606 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1593 *last = new LoadIndexedInstr(new Value(array), | 1607 *last = new LoadIndexedInstr(new Value(array), |
| 1594 new Value(index), | 1608 new Value(index), |
| 1595 index_scale, | 1609 index_scale, |
| 1596 array_cid, | 1610 array_cid, |
| 1597 deopt_id); | 1611 deopt_id, |
| 1612 call->token_pos()); |
| 1598 cursor = flow_graph()->AppendTo( | 1613 cursor = flow_graph()->AppendTo( |
| 1599 cursor, | 1614 cursor, |
| 1600 *last, | 1615 *last, |
| 1601 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1616 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1602 Definition::kValue); | 1617 Definition::kValue); |
| 1603 | 1618 |
| 1604 if (array_cid == kTypedDataFloat32ArrayCid) { | 1619 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1605 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 1620 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 1606 flow_graph()->AppendTo(cursor, | 1621 flow_graph()->AppendTo(cursor, |
| 1607 *last, | 1622 *last, |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 | 1789 |
| 1775 intptr_t cid = kIllegalCid; | 1790 intptr_t cid = kIllegalCid; |
| 1776 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 1791 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
| 1777 if (TryStringLengthOneEquality(call, op_kind)) { | 1792 if (TryStringLengthOneEquality(call, op_kind)) { |
| 1778 return true; | 1793 return true; |
| 1779 } else { | 1794 } else { |
| 1780 return false; | 1795 return false; |
| 1781 } | 1796 } |
| 1782 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1797 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1783 InsertBefore(call, | 1798 InsertBefore(call, |
| 1784 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1799 new CheckSmiInstr(new Value(left), |
| 1800 call->deopt_id(), |
| 1801 call->token_pos()), |
| 1785 call->env(), | 1802 call->env(), |
| 1786 Definition::kEffect); | 1803 Definition::kEffect); |
| 1787 InsertBefore(call, | 1804 InsertBefore(call, |
| 1788 new CheckSmiInstr(new Value(right), call->deopt_id()), | 1805 new CheckSmiInstr(new Value(right), |
| 1806 call->deopt_id(), |
| 1807 call->token_pos()), |
| 1789 call->env(), | 1808 call->env(), |
| 1790 Definition::kEffect); | 1809 Definition::kEffect); |
| 1791 cid = kSmiCid; | 1810 cid = kSmiCid; |
| 1792 } else if (HasTwoMintOrSmi(ic_data) && | 1811 } else if (HasTwoMintOrSmi(ic_data) && |
| 1793 FlowGraphCompiler::SupportsUnboxedMints()) { | 1812 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1794 cid = kMintCid; | 1813 cid = kMintCid; |
| 1795 } else if (HasTwoDoubleOrSmi(ic_data)) { | 1814 } else if (HasTwoDoubleOrSmi(ic_data)) { |
| 1796 // Use double comparison. | 1815 // Use double comparison. |
| 1797 if (SmiFitsInDouble()) { | 1816 if (SmiFitsInDouble()) { |
| 1798 cid = kDoubleCid; | 1817 cid = kDoubleCid; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1872 const ICData& ic_data = *call->ic_data(); | 1891 const ICData& ic_data = *call->ic_data(); |
| 1873 ASSERT(ic_data.NumArgsTested() == 2); | 1892 ASSERT(ic_data.NumArgsTested() == 2); |
| 1874 | 1893 |
| 1875 ASSERT(call->ArgumentCount() == 2); | 1894 ASSERT(call->ArgumentCount() == 2); |
| 1876 Definition* left = call->ArgumentAt(0); | 1895 Definition* left = call->ArgumentAt(0); |
| 1877 Definition* right = call->ArgumentAt(1); | 1896 Definition* right = call->ArgumentAt(1); |
| 1878 | 1897 |
| 1879 intptr_t cid = kIllegalCid; | 1898 intptr_t cid = kIllegalCid; |
| 1880 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1899 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1881 InsertBefore(call, | 1900 InsertBefore(call, |
| 1882 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1901 new CheckSmiInstr(new Value(left), |
| 1902 call->deopt_id(), |
| 1903 call->token_pos()), |
| 1883 call->env(), | 1904 call->env(), |
| 1884 Definition::kEffect); | 1905 Definition::kEffect); |
| 1885 InsertBefore(call, | 1906 InsertBefore(call, |
| 1886 new CheckSmiInstr(new Value(right), call->deopt_id()), | 1907 new CheckSmiInstr(new Value(right), |
| 1908 call->deopt_id(), |
| 1909 call->token_pos()), |
| 1887 call->env(), | 1910 call->env(), |
| 1888 Definition::kEffect); | 1911 Definition::kEffect); |
| 1889 cid = kSmiCid; | 1912 cid = kSmiCid; |
| 1890 } else if (HasTwoMintOrSmi(ic_data) && | 1913 } else if (HasTwoMintOrSmi(ic_data) && |
| 1891 FlowGraphCompiler::SupportsUnboxedMints()) { | 1914 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1892 cid = kMintCid; | 1915 cid = kMintCid; |
| 1893 } else if (HasTwoDoubleOrSmi(ic_data)) { | 1916 } else if (HasTwoDoubleOrSmi(ic_data)) { |
| 1894 // Use double comparison. | 1917 // Use double comparison. |
| 1895 if (SmiFitsInDouble()) { | 1918 if (SmiFitsInDouble()) { |
| 1896 cid = kDoubleCid; | 1919 cid = kDoubleCid; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2050 InsertBefore(call, | 2073 InsertBefore(call, |
| 2051 new CheckEitherNonSmiInstr(new Value(left), | 2074 new CheckEitherNonSmiInstr(new Value(left), |
| 2052 new Value(right), | 2075 new Value(right), |
| 2053 call->deopt_id()), | 2076 call->deopt_id()), |
| 2054 call->env(), | 2077 call->env(), |
| 2055 Definition::kEffect); | 2078 Definition::kEffect); |
| 2056 } | 2079 } |
| 2057 | 2080 |
| 2058 BinaryDoubleOpInstr* double_bin_op = | 2081 BinaryDoubleOpInstr* double_bin_op = |
| 2059 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), | 2082 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), |
| 2060 call->deopt_id()); | 2083 call->deopt_id(), call->token_pos()); |
| 2061 ReplaceCall(call, double_bin_op); | 2084 ReplaceCall(call, double_bin_op); |
| 2062 } else if (operands_type == kMintCid) { | 2085 } else if (operands_type == kMintCid) { |
| 2063 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 2086 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 2064 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 2087 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 2065 ShiftMintOpInstr* shift_op = | 2088 ShiftMintOpInstr* shift_op = |
| 2066 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 2089 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), |
| 2067 call->deopt_id()); | 2090 call->deopt_id()); |
| 2068 ReplaceCall(call, shift_op); | 2091 ReplaceCall(call, shift_op); |
| 2069 } else { | 2092 } else { |
| 2070 BinaryMintOpInstr* bin_op = | 2093 BinaryMintOpInstr* bin_op = |
| 2071 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 2094 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 2072 call->deopt_id()); | 2095 call->deopt_id()); |
| 2073 ReplaceCall(call, bin_op); | 2096 ReplaceCall(call, bin_op); |
| 2074 } | 2097 } |
| 2075 } else if (operands_type == kFloat32x4Cid) { | 2098 } else if (operands_type == kFloat32x4Cid) { |
| 2076 return InlineFloat32x4BinaryOp(call, op_kind); | 2099 return InlineFloat32x4BinaryOp(call, op_kind); |
| 2077 } else if (operands_type == kInt32x4Cid) { | 2100 } else if (operands_type == kInt32x4Cid) { |
| 2078 return InlineInt32x4BinaryOp(call, op_kind); | 2101 return InlineInt32x4BinaryOp(call, op_kind); |
| 2079 } else if (operands_type == kFloat64x2Cid) { | 2102 } else if (operands_type == kFloat64x2Cid) { |
| 2080 return InlineFloat64x2BinaryOp(call, op_kind); | 2103 return InlineFloat64x2BinaryOp(call, op_kind); |
| 2081 } else if (op_kind == Token::kMOD) { | 2104 } else if (op_kind == Token::kMOD) { |
| 2082 ASSERT(operands_type == kSmiCid); | 2105 ASSERT(operands_type == kSmiCid); |
| 2083 if (right->IsConstant()) { | 2106 if (right->IsConstant()) { |
| 2084 const Object& obj = right->AsConstant()->value(); | 2107 const Object& obj = right->AsConstant()->value(); |
| 2085 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { | 2108 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
| 2086 // Insert smi check and attach a copy of the original environment | 2109 // Insert smi check and attach a copy of the original environment |
| 2087 // because the smi operation can still deoptimize. | 2110 // because the smi operation can still deoptimize. |
| 2088 InsertBefore(call, | 2111 InsertBefore(call, |
| 2089 new CheckSmiInstr(new Value(left), call->deopt_id()), | 2112 new CheckSmiInstr(new Value(left), |
| 2113 call->deopt_id(), |
| 2114 call->token_pos()), |
| 2090 call->env(), | 2115 call->env(), |
| 2091 Definition::kEffect); | 2116 Definition::kEffect); |
| 2092 ConstantInstr* constant = | 2117 ConstantInstr* constant = |
| 2093 flow_graph()->GetConstant(Smi::Handle( | 2118 flow_graph()->GetConstant(Smi::Handle( |
| 2094 Smi::New(Smi::Cast(obj).Value() - 1))); | 2119 Smi::New(Smi::Cast(obj).Value() - 1))); |
| 2095 BinarySmiOpInstr* bin_op = | 2120 BinarySmiOpInstr* bin_op = |
| 2096 new BinarySmiOpInstr(Token::kBIT_AND, | 2121 new BinarySmiOpInstr(Token::kBIT_AND, |
| 2097 new Value(left), | 2122 new Value(left), |
| 2098 new Value(constant), | 2123 new Value(constant), |
| 2099 call->deopt_id()); | 2124 call->deopt_id(), |
| 2125 call->token_pos()); |
| 2100 ReplaceCall(call, bin_op); | 2126 ReplaceCall(call, bin_op); |
| 2101 return true; | 2127 return true; |
| 2102 } | 2128 } |
| 2103 } | 2129 } |
| 2104 // Insert two smi checks and attach a copy of the original | 2130 // Insert two smi checks and attach a copy of the original |
| 2105 // environment because the smi operation can still deoptimize. | 2131 // environment because the smi operation can still deoptimize. |
| 2106 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2132 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2107 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2133 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2108 BinarySmiOpInstr* bin_op = | 2134 BinarySmiOpInstr* bin_op = |
| 2109 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2135 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 2110 call->deopt_id()); | 2136 call->deopt_id(), call->token_pos()); |
| 2111 ReplaceCall(call, bin_op); | 2137 ReplaceCall(call, bin_op); |
| 2112 } else { | 2138 } else { |
| 2113 ASSERT(operands_type == kSmiCid); | 2139 ASSERT(operands_type == kSmiCid); |
| 2114 // Insert two smi checks and attach a copy of the original | 2140 // Insert two smi checks and attach a copy of the original |
| 2115 // environment because the smi operation can still deoptimize. | 2141 // environment because the smi operation can still deoptimize. |
| 2116 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 2142 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 2117 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 2143 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 2118 if (left->IsConstant() && | 2144 if (left->IsConstant() && |
| 2119 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 2145 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| 2120 // Constant should be on the right side. | 2146 // Constant should be on the right side. |
| 2121 Definition* temp = left; | 2147 Definition* temp = left; |
| 2122 left = right; | 2148 left = right; |
| 2123 right = temp; | 2149 right = temp; |
| 2124 } | 2150 } |
| 2125 BinarySmiOpInstr* bin_op = | 2151 BinarySmiOpInstr* bin_op = |
| 2126 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), | 2152 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 2127 call->deopt_id()); | 2153 call->deopt_id(), call->token_pos()); |
| 2128 ReplaceCall(call, bin_op); | 2154 ReplaceCall(call, bin_op); |
| 2129 } | 2155 } |
| 2130 return true; | 2156 return true; |
| 2131 } | 2157 } |
| 2132 | 2158 |
| 2133 | 2159 |
| 2134 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 2160 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
| 2135 Token::Kind op_kind) { | 2161 Token::Kind op_kind) { |
| 2136 ASSERT(call->ArgumentCount() == 1); | 2162 ASSERT(call->ArgumentCount() == 1); |
| 2137 Definition* input = call->ArgumentAt(0); | 2163 Definition* input = call->ArgumentAt(0); |
| 2138 Definition* unary_op = NULL; | 2164 Definition* unary_op = NULL; |
| 2139 if (HasOnlyOneSmi(*call->ic_data())) { | 2165 if (HasOnlyOneSmi(*call->ic_data())) { |
| 2140 InsertBefore(call, | 2166 InsertBefore(call, |
| 2141 new CheckSmiInstr(new Value(input), call->deopt_id()), | 2167 new CheckSmiInstr(new Value(input), |
| 2168 call->deopt_id(), |
| 2169 call->token_pos()), |
| 2142 call->env(), | 2170 call->env(), |
| 2143 Definition::kEffect); | 2171 Definition::kEffect); |
| 2144 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); | 2172 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); |
| 2145 } else if ((op_kind == Token::kBIT_NOT) && | 2173 } else if ((op_kind == Token::kBIT_NOT) && |
| 2146 HasOnlySmiOrMint(*call->ic_data()) && | 2174 HasOnlySmiOrMint(*call->ic_data()) && |
| 2147 FlowGraphCompiler::SupportsUnboxedMints()) { | 2175 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 2148 unary_op = new UnaryMintOpInstr( | 2176 unary_op = new UnaryMintOpInstr( |
| 2149 op_kind, new Value(input), call->deopt_id()); | 2177 op_kind, new Value(input), call->deopt_id()); |
| 2150 } else if (HasOnlyOneDouble(*call->ic_data()) && | 2178 } else if (HasOnlyOneDouble(*call->ic_data()) && |
| 2151 (op_kind == Token::kNEGATE)) { | 2179 (op_kind == Token::kNEGATE)) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2225 String::Handle(Field::NameFromGetter(call->function_name())); | 2253 String::Handle(Field::NameFromGetter(call->function_name())); |
| 2226 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); | 2254 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); |
| 2227 ASSERT(!field.IsNull()); | 2255 ASSERT(!field.IsNull()); |
| 2228 | 2256 |
| 2229 if (InstanceCallNeedsClassCheck(call)) { | 2257 if (InstanceCallNeedsClassCheck(call)) { |
| 2230 AddReceiverCheck(call); | 2258 AddReceiverCheck(call); |
| 2231 } | 2259 } |
| 2232 LoadFieldInstr* load = new LoadFieldInstr( | 2260 LoadFieldInstr* load = new LoadFieldInstr( |
| 2233 new Value(call->ArgumentAt(0)), | 2261 new Value(call->ArgumentAt(0)), |
| 2234 &field, | 2262 &field, |
| 2235 AbstractType::ZoneHandle(field.type())); | 2263 AbstractType::ZoneHandle(field.type()), |
| 2264 call->token_pos()); |
| 2236 load->set_is_immutable(field.is_final()); | 2265 load->set_is_immutable(field.is_final()); |
| 2237 if (field.guarded_cid() != kIllegalCid) { | 2266 if (field.guarded_cid() != kIllegalCid) { |
| 2238 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2267 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 2239 load->set_result_cid(field.guarded_cid()); | 2268 load->set_result_cid(field.guarded_cid()); |
| 2240 } | 2269 } |
| 2241 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2270 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 2242 } | 2271 } |
| 2243 | 2272 |
| 2244 // Discard the environment from the original instruction because the load | 2273 // Discard the environment from the original instruction because the load |
| 2245 // can't deoptimize. | 2274 // can't deoptimize. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2257 } | 2286 } |
| 2258 | 2287 |
| 2259 | 2288 |
| 2260 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { | 2289 static LoadFieldInstr* BuildLoadStringLength(Definition* str) { |
| 2261 // Treat length loads as mutable (i.e. affected by side effects) to avoid | 2290 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
| 2262 // hoisting them since we can't hoist the preceding class-check. This | 2291 // hoisting them since we can't hoist the preceding class-check. This |
| 2263 // is because of externalization of strings that affects their class-id. | 2292 // is because of externalization of strings that affects their class-id. |
| 2264 LoadFieldInstr* load = new LoadFieldInstr( | 2293 LoadFieldInstr* load = new LoadFieldInstr( |
| 2265 new Value(str), | 2294 new Value(str), |
| 2266 String::length_offset(), | 2295 String::length_offset(), |
| 2267 Type::ZoneHandle(Type::SmiType())); | 2296 Type::ZoneHandle(Type::SmiType()), |
| 2297 str->token_pos()); |
| 2268 load->set_result_cid(kSmiCid); | 2298 load->set_result_cid(kSmiCid); |
| 2269 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 2299 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 2270 return load; | 2300 return load; |
| 2271 } | 2301 } |
| 2272 | 2302 |
| 2273 | 2303 |
| 2274 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2304 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 2275 MethodRecognizer::Kind getter) { | 2305 MethodRecognizer::Kind getter) { |
| 2276 if (!ShouldInlineSimd()) { | 2306 if (!ShouldInlineSimd()) { |
| 2277 return false; | 2307 return false; |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 // Returns the LoadIndexedInstr. | 2641 // Returns the LoadIndexedInstr. |
| 2612 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( | 2642 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( |
| 2613 Instruction* call, | 2643 Instruction* call, |
| 2614 intptr_t cid, | 2644 intptr_t cid, |
| 2615 Definition* str, | 2645 Definition* str, |
| 2616 Definition* index, | 2646 Definition* index, |
| 2617 Instruction* cursor) { | 2647 Instruction* cursor) { |
| 2618 | 2648 |
| 2619 cursor = flow_graph()->AppendTo(cursor, | 2649 cursor = flow_graph()->AppendTo(cursor, |
| 2620 new CheckSmiInstr(new Value(index), | 2650 new CheckSmiInstr(new Value(index), |
| 2621 call->deopt_id()), | 2651 call->deopt_id(), |
| 2652 call->token_pos()), |
| 2622 call->env(), | 2653 call->env(), |
| 2623 Definition::kEffect); | 2654 Definition::kEffect); |
| 2624 | 2655 |
| 2625 // Load the length of the string. | 2656 // Load the length of the string. |
| 2626 LoadFieldInstr* length = BuildLoadStringLength(str); | 2657 LoadFieldInstr* length = BuildLoadStringLength(str); |
| 2627 cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); | 2658 cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); |
| 2628 // Bounds check. | 2659 // Bounds check. |
| 2629 cursor = flow_graph()->AppendTo(cursor, | 2660 cursor = flow_graph()->AppendTo(cursor, |
| 2630 new CheckArrayBoundInstr(new Value(length), | 2661 new CheckArrayBoundInstr(new Value(length), |
| 2631 new Value(index), | 2662 new Value(index), |
| 2632 call->deopt_id()), | 2663 call->deopt_id()), |
| 2633 call->env(), | 2664 call->env(), |
| 2634 Definition::kEffect); | 2665 Definition::kEffect); |
| 2635 | 2666 |
| 2636 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( | 2667 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( |
| 2637 new Value(str), | 2668 new Value(str), |
| 2638 new Value(index), | 2669 new Value(index), |
| 2639 FlowGraphCompiler::ElementSizeFor(cid), | 2670 FlowGraphCompiler::ElementSizeFor(cid), |
| 2640 cid, | 2671 cid, |
| 2641 Isolate::kNoDeoptId); | 2672 Isolate::kNoDeoptId, |
| 2673 call->token_pos()); |
| 2642 | 2674 |
| 2643 cursor = flow_graph()->AppendTo(cursor, | 2675 cursor = flow_graph()->AppendTo(cursor, |
| 2644 load_indexed, | 2676 load_indexed, |
| 2645 NULL, | 2677 NULL, |
| 2646 Definition::kValue); | 2678 Definition::kValue); |
| 2647 ASSERT(cursor == load_indexed); | 2679 ASSERT(cursor == load_indexed); |
| 2648 return load_indexed; | 2680 return load_indexed; |
| 2649 } | 2681 } |
| 2650 | 2682 |
| 2651 | 2683 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2703 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2735 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
| 2704 InstanceCallInstr* call, | 2736 InstanceCallInstr* call, |
| 2705 MethodRecognizer::Kind recognized_kind) { | 2737 MethodRecognizer::Kind recognized_kind) { |
| 2706 AddReceiverCheck(call); | 2738 AddReceiverCheck(call); |
| 2707 ZoneGrowableArray<Value*>* args = | 2739 ZoneGrowableArray<Value*>* args = |
| 2708 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 2740 new ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 2709 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 2741 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 2710 args->Add(new Value(call->ArgumentAt(i))); | 2742 args->Add(new Value(call->ArgumentAt(i))); |
| 2711 } | 2743 } |
| 2712 InvokeMathCFunctionInstr* invoke = | 2744 InvokeMathCFunctionInstr* invoke = |
| 2713 new InvokeMathCFunctionInstr(args, call->deopt_id(), recognized_kind); | 2745 new InvokeMathCFunctionInstr(args, |
| 2746 call->deopt_id(), |
| 2747 recognized_kind, |
| 2748 call->token_pos()); |
| 2714 ReplaceCall(call, invoke); | 2749 ReplaceCall(call, invoke); |
| 2715 } | 2750 } |
| 2716 | 2751 |
| 2717 | 2752 |
| 2718 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | 2753 static bool IsSupportedByteArrayViewCid(intptr_t cid) { |
| 2719 switch (cid) { | 2754 switch (cid) { |
| 2720 case kTypedDataInt8ArrayCid: | 2755 case kTypedDataInt8ArrayCid: |
| 2721 case kTypedDataUint8ArrayCid: | 2756 case kTypedDataUint8ArrayCid: |
| 2722 case kExternalTypedDataUint8ArrayCid: | 2757 case kExternalTypedDataUint8ArrayCid: |
| 2723 case kTypedDataUint8ClampedArrayCid: | 2758 case kTypedDataUint8ClampedArrayCid: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2755 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | 2790 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && |
| 2756 (ic_data.NumberOfChecks() == 1) && | 2791 (ic_data.NumberOfChecks() == 1) && |
| 2757 (class_ids[0] == kGrowableObjectArrayCid)) { | 2792 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2758 // This is an internal method, no need to check argument types. | 2793 // This is an internal method, no need to check argument types. |
| 2759 Definition* array = call->ArgumentAt(0); | 2794 Definition* array = call->ArgumentAt(0); |
| 2760 Definition* value = call->ArgumentAt(1); | 2795 Definition* value = call->ArgumentAt(1); |
| 2761 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2796 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2762 GrowableObjectArray::data_offset(), | 2797 GrowableObjectArray::data_offset(), |
| 2763 new Value(array), | 2798 new Value(array), |
| 2764 new Value(value), | 2799 new Value(value), |
| 2765 kEmitStoreBarrier); | 2800 kEmitStoreBarrier, |
| 2801 call->token_pos()); |
| 2766 ReplaceCall(call, store); | 2802 ReplaceCall(call, store); |
| 2767 return true; | 2803 return true; |
| 2768 } | 2804 } |
| 2769 | 2805 |
| 2770 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | 2806 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && |
| 2771 (ic_data.NumberOfChecks() == 1) && | 2807 (ic_data.NumberOfChecks() == 1) && |
| 2772 (class_ids[0] == kGrowableObjectArrayCid)) { | 2808 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2773 // This is an internal method, no need to check argument types nor | 2809 // This is an internal method, no need to check argument types nor |
| 2774 // range. | 2810 // range. |
| 2775 Definition* array = call->ArgumentAt(0); | 2811 Definition* array = call->ArgumentAt(0); |
| 2776 Definition* value = call->ArgumentAt(1); | 2812 Definition* value = call->ArgumentAt(1); |
| 2777 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 2813 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2778 GrowableObjectArray::length_offset(), | 2814 GrowableObjectArray::length_offset(), |
| 2779 new Value(array), | 2815 new Value(array), |
| 2780 new Value(value), | 2816 new Value(value), |
| 2781 kEmitStoreBarrier); | 2817 kEmitStoreBarrier, |
| 2818 call->token_pos()); |
| 2782 ReplaceCall(call, store); | 2819 ReplaceCall(call, store); |
| 2783 return true; | 2820 return true; |
| 2784 } | 2821 } |
| 2785 | 2822 |
| 2786 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 2823 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
| 2787 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 2824 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && |
| 2788 (ic_data.NumberOfChecks() == 1) && | 2825 (ic_data.NumberOfChecks() == 1) && |
| 2789 ((class_ids[0] == kOneByteStringCid) || | 2826 ((class_ids[0] == kOneByteStringCid) || |
| 2790 (class_ids[0] == kTwoByteStringCid))) { | 2827 (class_ids[0] == kTwoByteStringCid))) { |
| 2791 return TryReplaceInstanceCallWithInline(call); | 2828 return TryReplaceInstanceCallWithInline(call); |
| 2792 } | 2829 } |
| 2793 | 2830 |
| 2794 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 2831 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 2795 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 2832 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 2796 // This is an internal method, no need to check argument types nor | 2833 // This is an internal method, no need to check argument types nor |
| 2797 // range. | 2834 // range. |
| 2798 Definition* str = call->ArgumentAt(0); | 2835 Definition* str = call->ArgumentAt(0); |
| 2799 Definition* index = call->ArgumentAt(1); | 2836 Definition* index = call->ArgumentAt(1); |
| 2800 Definition* value = call->ArgumentAt(2); | 2837 Definition* value = call->ArgumentAt(2); |
| 2801 StoreIndexedInstr* store_op = new StoreIndexedInstr( | 2838 StoreIndexedInstr* store_op = new StoreIndexedInstr( |
| 2802 new Value(str), | 2839 new Value(str), |
| 2803 new Value(index), | 2840 new Value(index), |
| 2804 new Value(value), | 2841 new Value(value), |
| 2805 kNoStoreBarrier, | 2842 kNoStoreBarrier, |
| 2806 1, // Index scale | 2843 1, // Index scale |
| 2807 kOneByteStringCid, | 2844 kOneByteStringCid, |
| 2808 call->deopt_id()); | 2845 call->deopt_id(), |
| 2846 call->token_pos()); |
| 2809 ReplaceCall(call, store_op); | 2847 ReplaceCall(call, store_op); |
| 2810 return true; | 2848 return true; |
| 2811 } | 2849 } |
| 2812 return false; | 2850 return false; |
| 2813 } | 2851 } |
| 2814 | 2852 |
| 2815 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 2853 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 2816 (ic_data.NumberOfChecks() == 1) && | 2854 (ic_data.NumberOfChecks() == 1) && |
| 2817 (class_ids[0] == kSmiCid)) { | 2855 (class_ids[0] == kSmiCid)) { |
| 2818 AddReceiverCheck(call); | 2856 AddReceiverCheck(call); |
| 2819 ReplaceCall(call, new SmiToDoubleInstr(new Value(call->ArgumentAt(0)))); | 2857 ReplaceCall(call, |
| 2858 new SmiToDoubleInstr(new Value(call->ArgumentAt(0)), |
| 2859 call->token_pos())); |
| 2820 return true; | 2860 return true; |
| 2821 } | 2861 } |
| 2822 | 2862 |
| 2823 if (class_ids[0] == kDoubleCid) { | 2863 if (class_ids[0] == kDoubleCid) { |
| 2824 switch (recognized_kind) { | 2864 switch (recognized_kind) { |
| 2825 case MethodRecognizer::kDoubleToInteger: { | 2865 case MethodRecognizer::kDoubleToInteger: { |
| 2826 AddReceiverCheck(call); | 2866 AddReceiverCheck(call); |
| 2827 ASSERT(call->HasICData()); | 2867 ASSERT(call->HasICData()); |
| 2828 const ICData& ic_data = *call->ic_data(); | 2868 const ICData& ic_data = *call->ic_data(); |
| 2829 Definition* input = call->ArgumentAt(0); | 2869 Definition* input = call->ArgumentAt(0); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2952 int32_mask->AsConstant()->value()); | 2992 int32_mask->AsConstant()->value()); |
| 2953 const int64_t mask_value = mask_literal.AsInt64Value(); | 2993 const int64_t mask_value = mask_literal.AsInt64Value(); |
| 2954 ASSERT(mask_value >= 0); | 2994 ASSERT(mask_value >= 0); |
| 2955 if (mask_value > Smi::kMaxValue) { | 2995 if (mask_value > Smi::kMaxValue) { |
| 2956 // The result will not be Smi. | 2996 // The result will not be Smi. |
| 2957 return false; | 2997 return false; |
| 2958 } | 2998 } |
| 2959 BinarySmiOpInstr* left_shift = | 2999 BinarySmiOpInstr* left_shift = |
| 2960 new BinarySmiOpInstr(Token::kSHL, | 3000 new BinarySmiOpInstr(Token::kSHL, |
| 2961 new Value(value), new Value(count), | 3001 new Value(value), new Value(count), |
| 2962 call->deopt_id()); | 3002 call->deopt_id(), call->token_pos()); |
| 2963 left_shift->set_is_truncating(true); | 3003 left_shift->set_is_truncating(true); |
| 2964 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3004 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
| 2965 // No BIT_AND operation needed. | 3005 // No BIT_AND operation needed. |
| 2966 ReplaceCall(call, left_shift); | 3006 ReplaceCall(call, left_shift); |
| 2967 } else { | 3007 } else { |
| 2968 InsertBefore(call, left_shift, call->env(), Definition::kValue); | 3008 InsertBefore(call, left_shift, call->env(), Definition::kValue); |
| 2969 BinarySmiOpInstr* bit_and = | 3009 BinarySmiOpInstr* bit_and = |
| 2970 new BinarySmiOpInstr(Token::kBIT_AND, | 3010 new BinarySmiOpInstr(Token::kBIT_AND, |
| 2971 new Value(left_shift), new Value(int32_mask), | 3011 new Value(left_shift), new Value(int32_mask), |
| 2972 call->deopt_id()); | 3012 call->deopt_id(), call->token_pos()); |
| 2973 ReplaceCall(call, bit_and); | 3013 ReplaceCall(call, bit_and); |
| 2974 } | 3014 } |
| 2975 return true; | 3015 return true; |
| 2976 } | 3016 } |
| 2977 | 3017 |
| 2978 if (HasTwoMintOrSmi(ic_data) && | 3018 if (HasTwoMintOrSmi(ic_data) && |
| 2979 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3019 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 2980 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3020 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
| 2981 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3021 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
| 2982 return false; | 3022 return false; |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3405 // Set deopt_id if we can optimistically assume that the result is Smi. | 3445 // Set deopt_id if we can optimistically assume that the result is Smi. |
| 3406 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 3446 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
| 3407 deopt_id = ic_data.HasDeoptReasons() ? | 3447 deopt_id = ic_data.HasDeoptReasons() ? |
| 3408 Isolate::kNoDeoptId : call->deopt_id(); | 3448 Isolate::kNoDeoptId : call->deopt_id(); |
| 3409 } | 3449 } |
| 3410 | 3450 |
| 3411 *last = new LoadIndexedInstr(new Value(array), | 3451 *last = new LoadIndexedInstr(new Value(array), |
| 3412 new Value(index), | 3452 new Value(index), |
| 3413 1, | 3453 1, |
| 3414 view_cid, | 3454 view_cid, |
| 3415 deopt_id); | 3455 deopt_id, |
| 3456 call->token_pos()); |
| 3416 cursor = flow_graph()->AppendTo( | 3457 cursor = flow_graph()->AppendTo( |
| 3417 cursor, | 3458 cursor, |
| 3418 *last, | 3459 *last, |
| 3419 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3460 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3420 Definition::kValue); | 3461 Definition::kValue); |
| 3421 | 3462 |
| 3422 if (view_cid == kTypedDataFloat32ArrayCid) { | 3463 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3423 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 3464 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 3424 flow_graph()->AppendTo(cursor, | 3465 flow_graph()->AppendTo(cursor, |
| 3425 *last, | 3466 *last, |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3546 Definition::kValue); | 3587 Definition::kValue); |
| 3547 } | 3588 } |
| 3548 | 3589 |
| 3549 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3590 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
| 3550 *last = new StoreIndexedInstr(new Value(array), | 3591 *last = new StoreIndexedInstr(new Value(array), |
| 3551 new Value(index), | 3592 new Value(index), |
| 3552 new Value(stored_value), | 3593 new Value(stored_value), |
| 3553 needs_store_barrier, | 3594 needs_store_barrier, |
| 3554 1, // Index scale | 3595 1, // Index scale |
| 3555 view_cid, | 3596 view_cid, |
| 3556 call->deopt_id()); | 3597 call->deopt_id(), |
| 3598 call->token_pos()); |
| 3557 | 3599 |
| 3558 flow_graph()->AppendTo(cursor, | 3600 flow_graph()->AppendTo(cursor, |
| 3559 *last, | 3601 *last, |
| 3560 call->deopt_id() != Isolate::kNoDeoptId ? | 3602 call->deopt_id() != Isolate::kNoDeoptId ? |
| 3561 call->env() : NULL, | 3603 call->env() : NULL, |
| 3562 Definition::kEffect); | 3604 Definition::kEffect); |
| 3563 return true; | 3605 return true; |
| 3564 } | 3606 } |
| 3565 | 3607 |
| 3566 | 3608 |
| 3567 | 3609 |
| 3568 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( | 3610 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
| 3569 Instruction* call, | 3611 Instruction* call, |
| 3570 intptr_t array_cid, | 3612 intptr_t array_cid, |
| 3571 intptr_t view_cid, | 3613 intptr_t view_cid, |
| 3572 Definition** array, | 3614 Definition** array, |
| 3573 Definition* byte_index, | 3615 Definition* byte_index, |
| 3574 Instruction** cursor) { | 3616 Instruction** cursor) { |
| 3575 // Insert byte_index smi check. | 3617 // Insert byte_index smi check. |
| 3576 *cursor = flow_graph()->AppendTo(*cursor, | 3618 *cursor = flow_graph()->AppendTo(*cursor, |
| 3577 new CheckSmiInstr(new Value(byte_index), | 3619 new CheckSmiInstr(new Value(byte_index), |
| 3578 call->deopt_id()), | 3620 call->deopt_id(), |
| 3621 call->token_pos()), |
| 3579 call->env(), | 3622 call->env(), |
| 3580 Definition::kEffect); | 3623 Definition::kEffect); |
| 3581 | 3624 |
| 3582 LoadFieldInstr* length = | 3625 LoadFieldInstr* length = |
| 3583 new LoadFieldInstr(new Value(*array), | 3626 new LoadFieldInstr(new Value(*array), |
| 3584 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 3627 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 3585 Type::ZoneHandle(Type::SmiType())); | 3628 Type::ZoneHandle(Type::SmiType()), |
| 3629 call->token_pos()); |
| 3586 length->set_is_immutable(true); | 3630 length->set_is_immutable(true); |
| 3587 length->set_result_cid(kSmiCid); | 3631 length->set_result_cid(kSmiCid); |
| 3588 length->set_recognized_kind( | 3632 length->set_recognized_kind( |
| 3589 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 3633 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 3590 *cursor = flow_graph()->AppendTo(*cursor, | 3634 *cursor = flow_graph()->AppendTo(*cursor, |
| 3591 length, | 3635 length, |
| 3592 NULL, | 3636 NULL, |
| 3593 Definition::kValue); | 3637 Definition::kValue); |
| 3594 | 3638 |
| 3595 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); | 3639 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 3596 ConstantInstr* bytes_per_element = | 3640 ConstantInstr* bytes_per_element = |
| 3597 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); | 3641 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); |
| 3598 BinarySmiOpInstr* len_in_bytes = | 3642 BinarySmiOpInstr* len_in_bytes = |
| 3599 new BinarySmiOpInstr(Token::kMUL, | 3643 new BinarySmiOpInstr(Token::kMUL, |
| 3600 new Value(length), | 3644 new Value(length), |
| 3601 new Value(bytes_per_element), | 3645 new Value(bytes_per_element), |
| 3602 call->deopt_id()); | 3646 call->deopt_id(), call->token_pos()); |
| 3603 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3647 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
| 3604 Definition::kValue); | 3648 Definition::kValue); |
| 3605 | 3649 |
| 3606 ConstantInstr* length_adjustment = | 3650 ConstantInstr* length_adjustment = |
| 3607 flow_graph()->GetConstant(Smi::Handle(Smi::New( | 3651 flow_graph()->GetConstant(Smi::Handle(Smi::New( |
| 3608 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); | 3652 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); |
| 3609 // adjusted_length = len_in_bytes - (element_size - 1). | 3653 // adjusted_length = len_in_bytes - (element_size - 1). |
| 3610 BinarySmiOpInstr* adjusted_length = | 3654 BinarySmiOpInstr* adjusted_length = |
| 3611 new BinarySmiOpInstr(Token::kSUB, | 3655 new BinarySmiOpInstr(Token::kSUB, |
| 3612 new Value(len_in_bytes), | 3656 new Value(len_in_bytes), |
| 3613 new Value(length_adjustment), | 3657 new Value(length_adjustment), |
| 3614 call->deopt_id()); | 3658 call->deopt_id(), call->token_pos()); |
| 3615 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3659 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
| 3616 Definition::kValue); | 3660 Definition::kValue); |
| 3617 | 3661 |
| 3618 // Check adjusted_length > 0. | 3662 // Check adjusted_length > 0. |
| 3619 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 3663 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 3620 *cursor = flow_graph()->AppendTo(*cursor, | 3664 *cursor = flow_graph()->AppendTo(*cursor, |
| 3621 new CheckArrayBoundInstr( | 3665 new CheckArrayBoundInstr( |
| 3622 new Value(adjusted_length), | 3666 new Value(adjusted_length), |
| 3623 new Value(zero), | 3667 new Value(zero), |
| 3624 call->deopt_id()), | 3668 call->deopt_id()), |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4125 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4169 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
| 4126 // We know that first argument is double, the second is num. | 4170 // We know that first argument is double, the second is num. |
| 4127 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4171 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
| 4128 // instructions contain type checks and conversions to double. | 4172 // instructions contain type checks and conversions to double. |
| 4129 ZoneGrowableArray<Value*>* args = | 4173 ZoneGrowableArray<Value*>* args = |
| 4130 new ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4174 new ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 4131 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4175 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 4132 args->Add(new Value(call->ArgumentAt(i))); | 4176 args->Add(new Value(call->ArgumentAt(i))); |
| 4133 } | 4177 } |
| 4134 InvokeMathCFunctionInstr* invoke = | 4178 InvokeMathCFunctionInstr* invoke = |
| 4135 new InvokeMathCFunctionInstr(args, call->deopt_id(), recognized_kind); | 4179 new InvokeMathCFunctionInstr(args, |
| 4180 call->deopt_id(), |
| 4181 recognized_kind, |
| 4182 call->token_pos()); |
| 4136 ReplaceCall(call, invoke); | 4183 ReplaceCall(call, invoke); |
| 4137 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( | 4184 } else if (Library::PrivateCoreLibName(Symbols::ClassId()).Equals( |
| 4138 String::Handle(call->function().name()))) { | 4185 String::Handle(call->function().name()))) { |
| 4139 // Check for core library get:_classId. | 4186 // Check for core library get:_classId. |
| 4140 intptr_t cid = Class::Handle(call->function().Owner()).id(); | 4187 intptr_t cid = Class::Handle(call->function().Owner()).id(); |
| 4141 // Currently only implemented for a subset of classes. | 4188 // Currently only implemented for a subset of classes. |
| 4142 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 4189 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
| 4143 (cid == kExternalOneByteStringCid) || | 4190 (cid == kExternalOneByteStringCid) || |
| 4144 (cid == kGrowableObjectArrayCid) || | 4191 (cid == kGrowableObjectArrayCid) || |
| 4145 (cid == kImmutableArrayCid) || (cid == kArrayCid)); | 4192 (cid == kImmutableArrayCid) || (cid == kArrayCid)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4241 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); | 4288 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); |
| 4242 ASSERT(!field.IsNull()); | 4289 ASSERT(!field.IsNull()); |
| 4243 | 4290 |
| 4244 if (InstanceCallNeedsClassCheck(instr)) { | 4291 if (InstanceCallNeedsClassCheck(instr)) { |
| 4245 AddReceiverCheck(instr); | 4292 AddReceiverCheck(instr); |
| 4246 } | 4293 } |
| 4247 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4294 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
| 4248 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 4295 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
| 4249 InsertBefore(instr, | 4296 InsertBefore(instr, |
| 4250 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), | 4297 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), |
| 4251 instr->deopt_id()), | 4298 instr->deopt_id(), |
| 4299 instr->token_pos()), |
| 4252 instr->env(), | 4300 instr->env(), |
| 4253 Definition::kEffect); | 4301 Definition::kEffect); |
| 4254 needs_store_barrier = kNoStoreBarrier; | 4302 needs_store_barrier = kNoStoreBarrier; |
| 4255 } | 4303 } |
| 4256 | 4304 |
| 4257 if (field.guarded_cid() != kDynamicCid) { | 4305 if (field.guarded_cid() != kDynamicCid) { |
| 4258 InsertBefore(instr, | 4306 InsertBefore(instr, |
| 4259 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), | 4307 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), |
| 4260 field, | 4308 field, |
| 4261 instr->deopt_id()), | 4309 instr->deopt_id()), |
| 4262 instr->env(), | 4310 instr->env(), |
| 4263 Definition::kEffect); | 4311 Definition::kEffect); |
| 4264 } | 4312 } |
| 4265 | 4313 |
| 4266 // Field guard was detached. | 4314 // Field guard was detached. |
| 4267 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 4315 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 4268 field, | 4316 field, |
| 4269 new Value(instr->ArgumentAt(0)), | 4317 new Value(instr->ArgumentAt(0)), |
| 4270 new Value(instr->ArgumentAt(1)), | 4318 new Value(instr->ArgumentAt(1)), |
| 4271 needs_store_barrier); | 4319 needs_store_barrier, |
| 4320 instr->token_pos()); |
| 4272 | 4321 |
| 4273 if (store->IsUnboxedStore()) { | 4322 if (store->IsUnboxedStore()) { |
| 4274 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4323 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 4275 } | 4324 } |
| 4276 | 4325 |
| 4277 // Discard the environment from the original instruction because the store | 4326 // Discard the environment from the original instruction because the store |
| 4278 // can't deoptimize. | 4327 // can't deoptimize. |
| 4279 instr->RemoveEnvironment(); | 4328 instr->RemoveEnvironment(); |
| 4280 ReplaceCall(instr, store); | 4329 ReplaceCall(instr, store); |
| 4281 return true; | 4330 return true; |
| (...skipping 4606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8888 void FlowGraphOptimizer::EliminateEnvironments() { | 8937 void FlowGraphOptimizer::EliminateEnvironments() { |
| 8889 // After this pass we can no longer perform LICM and hoist instructions | 8938 // After this pass we can no longer perform LICM and hoist instructions |
| 8890 // that can deoptimize. | 8939 // that can deoptimize. |
| 8891 | 8940 |
| 8892 flow_graph_->disallow_licm(); | 8941 flow_graph_->disallow_licm(); |
| 8893 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 8942 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 8894 BlockEntryInstr* block = block_order_[i]; | 8943 BlockEntryInstr* block = block_order_[i]; |
| 8895 block->RemoveEnvironment(); | 8944 block->RemoveEnvironment(); |
| 8896 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 8945 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 8897 Instruction* current = it.Current(); | 8946 Instruction* current = it.Current(); |
| 8898 if (!current->CanDeoptimize()) current->RemoveEnvironment(); | 8947 if (!current->CanDeoptimize()) { |
| 8948 // TODO(srdjan): --source-lines needs deopt environments to get at |
| 8949 // the code for this instruction, however, leaving the environment |
| 8950 // changes code. |
| 8951 current->RemoveEnvironment(); |
| 8952 } |
| 8899 } | 8953 } |
| 8900 } | 8954 } |
| 8901 } | 8955 } |
| 8902 | 8956 |
| 8903 | 8957 |
| 8904 // Right now we are attempting to sink allocation only into | 8958 // Right now we are attempting to sink allocation only into |
| 8905 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8959 // deoptimization exit. So candidate should only be used in StoreInstanceField |
| 8906 // instructions that write into fields of the allocated object. | 8960 // instructions that write into fields of the allocated object. |
| 8907 // 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. |
| 8908 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { | 8962 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9068 const Class& cls, | 9122 const Class& cls, |
| 9069 const ZoneGrowableArray<const Object*>& slots) { | 9123 const ZoneGrowableArray<const Object*>& slots) { |
| 9070 ZoneGrowableArray<Value*>* values = | 9124 ZoneGrowableArray<Value*>* values = |
| 9071 new ZoneGrowableArray<Value*>(slots.length()); | 9125 new ZoneGrowableArray<Value*>(slots.length()); |
| 9072 | 9126 |
| 9073 // Insert load instruction for every field. | 9127 // Insert load instruction for every field. |
| 9074 for (intptr_t i = 0; i < slots.length(); i++) { | 9128 for (intptr_t i = 0; i < slots.length(); i++) { |
| 9075 LoadFieldInstr* load = slots[i]->IsField() | 9129 LoadFieldInstr* load = slots[i]->IsField() |
| 9076 ? new LoadFieldInstr(new Value(alloc), | 9130 ? new LoadFieldInstr(new Value(alloc), |
| 9077 &Field::Cast(*slots[i]), | 9131 &Field::Cast(*slots[i]), |
| 9078 AbstractType::ZoneHandle()) | 9132 AbstractType::ZoneHandle(), |
| 9133 alloc->token_pos()) |
| 9079 : new LoadFieldInstr(new Value(alloc), | 9134 : new LoadFieldInstr(new Value(alloc), |
| 9080 Smi::Cast(*slots[i]).Value(), | 9135 Smi::Cast(*slots[i]).Value(), |
| 9081 AbstractType::ZoneHandle()); | 9136 AbstractType::ZoneHandle(), |
| 9137 alloc->token_pos()); |
| 9082 flow_graph_->InsertBefore( | 9138 flow_graph_->InsertBefore( |
| 9083 exit, load, NULL, Definition::kValue); | 9139 exit, load, NULL, Definition::kValue); |
| 9084 values->Add(new Value(load)); | 9140 values->Add(new Value(load)); |
| 9085 } | 9141 } |
| 9086 | 9142 |
| 9087 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); | 9143 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); |
| 9088 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); | 9144 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); |
| 9089 | 9145 |
| 9090 // Replace all mentions of this allocation with a newly inserted | 9146 // Replace all mentions of this allocation with a newly inserted |
| 9091 // MaterializeObject instruction. | 9147 // MaterializeObject instruction. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9138 } | 9194 } |
| 9139 | 9195 |
| 9140 // Insert materializations at environment uses. | 9196 // Insert materializations at environment uses. |
| 9141 for (intptr_t i = 0; i < exits.length(); i++) { | 9197 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9142 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9198 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9143 } | 9199 } |
| 9144 } | 9200 } |
| 9145 | 9201 |
| 9146 | 9202 |
| 9147 } // namespace dart | 9203 } // namespace dart |
| OLD | NEW |