| 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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); | 314 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); |
| 315 ConstantInstr* index_instr = | 315 ConstantInstr* index_instr = |
| 316 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); | 316 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); |
| 317 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | 317 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), |
| 318 new Value(index_instr), | 318 new Value(index_instr), |
| 319 index_scale, | 319 index_scale, |
| 320 cid, | 320 cid, |
| 321 Isolate::kNoDeoptId, | 321 Isolate::kNoDeoptId, |
| 322 instr->token_pos()); | 322 instr->token_pos()); |
| 323 instr->ReplaceUsesWith(load); | 323 instr->ReplaceUsesWith(load); |
| 324 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); | 324 flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue); |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, | 328 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
| 329 intptr_t index, | 329 intptr_t index, |
| 330 Representation rep, | 330 Representation rep, |
| 331 intptr_t cid) { | 331 intptr_t cid) { |
| 332 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), | 332 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), |
| 333 index, | 333 index, |
| 334 rep, | 334 rep, |
| 335 cid); | 335 cid); |
| 336 instr->ReplaceUsesWith(extract); | 336 instr->ReplaceUsesWith(extract); |
| 337 flow_graph()->InsertAfter(instr, extract, NULL, Definition::kValue); | 337 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); |
| 338 } | 338 } |
| 339 | 339 |
| 340 | 340 |
| 341 // Dart: | 341 // Dart: |
| 342 // var x = d % 10; | 342 // var x = d % 10; |
| 343 // var y = d ~/ 10; | 343 // var y = d ~/ 10; |
| 344 // var z = x + y; | 344 // var z = x + y; |
| 345 // | 345 // |
| 346 // IL: | 346 // IL: |
| 347 // v4 <- %(v2, v3) | 347 // v4 <- %(v2, v3) |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 | 609 |
| 610 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 610 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
| 611 converted = new BoxIntegerInstr(use->CopyWithType()); | 611 converted = new BoxIntegerInstr(use->CopyWithType()); |
| 612 | 612 |
| 613 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 613 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
| 614 ASSERT(CanUnboxDouble()); | 614 ASSERT(CanUnboxDouble()); |
| 615 // Convert by boxing/unboxing. | 615 // Convert by boxing/unboxing. |
| 616 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | 616 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. |
| 617 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); | 617 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); |
| 618 use->BindTo(boxed); | 618 use->BindTo(boxed); |
| 619 InsertBefore(insert_before, boxed, NULL, Definition::kValue); | 619 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
| 620 | 620 |
| 621 const intptr_t deopt_id = (deopt_target != NULL) ? | 621 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 622 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 622 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 623 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); | 623 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); |
| 624 | 624 |
| 625 } else if ((from == kUnboxedDouble) && (to == kTagged)) { | 625 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 626 ASSERT(CanUnboxDouble()); | 626 ASSERT(CanUnboxDouble()); |
| 627 converted = new BoxDoubleInstr(use->CopyWithType()); | 627 converted = new BoxDoubleInstr(use->CopyWithType()); |
| 628 | 628 |
| 629 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 629 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 } else if (from == kUnboxedFloat32x4) { | 681 } else if (from == kUnboxedFloat32x4) { |
| 682 boxed = new BoxFloat32x4Instr(use->CopyWithType()); | 682 boxed = new BoxFloat32x4Instr(use->CopyWithType()); |
| 683 } else if (from == kUnboxedMint) { | 683 } else if (from == kUnboxedMint) { |
| 684 boxed = new BoxIntegerInstr(use->CopyWithType()); | 684 boxed = new BoxIntegerInstr(use->CopyWithType()); |
| 685 } else if (from == kUnboxedFloat64x2) { | 685 } else if (from == kUnboxedFloat64x2) { |
| 686 boxed = new BoxFloat64x2Instr(use->CopyWithType()); | 686 boxed = new BoxFloat64x2Instr(use->CopyWithType()); |
| 687 } else { | 687 } else { |
| 688 UNIMPLEMENTED(); | 688 UNIMPLEMENTED(); |
| 689 } | 689 } |
| 690 use->BindTo(boxed); | 690 use->BindTo(boxed); |
| 691 InsertBefore(insert_before, boxed, NULL, Definition::kValue); | 691 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
| 692 Value* to_value = new Value(boxed); | 692 Value* to_value = new Value(boxed); |
| 693 if (to == kUnboxedDouble) { | 693 if (to == kUnboxedDouble) { |
| 694 converted = new UnboxDoubleInstr(to_value, deopt_id); | 694 converted = new UnboxDoubleInstr(to_value, deopt_id); |
| 695 } else if (to == kUnboxedInt32x4) { | 695 } else if (to == kUnboxedInt32x4) { |
| 696 converted = new UnboxInt32x4Instr(to_value, deopt_id); | 696 converted = new UnboxInt32x4Instr(to_value, deopt_id); |
| 697 } else if (to == kUnboxedFloat32x4) { | 697 } else if (to == kUnboxedFloat32x4) { |
| 698 converted = new UnboxFloat32x4Instr(to_value, deopt_id); | 698 converted = new UnboxFloat32x4Instr(to_value, deopt_id); |
| 699 } else if (to == kUnboxedMint) { | 699 } else if (to == kUnboxedMint) { |
| 700 converted = new UnboxIntegerInstr(to_value, deopt_id); | 700 converted = new UnboxIntegerInstr(to_value, deopt_id); |
| 701 } else if (to == kUnboxedFloat64x2) { | 701 } else if (to == kUnboxedFloat64x2) { |
| 702 converted = new UnboxFloat64x2Instr(to_value, deopt_id); | 702 converted = new UnboxFloat64x2Instr(to_value, deopt_id); |
| 703 } else { | 703 } else { |
| 704 UNIMPLEMENTED(); | 704 UNIMPLEMENTED(); |
| 705 } | 705 } |
| 706 } | 706 } |
| 707 ASSERT(converted != NULL); | 707 ASSERT(converted != NULL); |
| 708 InsertBefore(insert_before, converted, use->instruction()->env(), | 708 InsertBefore(insert_before, converted, use->instruction()->env(), |
| 709 Definition::kValue); | 709 FlowGraph::kValue); |
| 710 if (is_environment_use) { | 710 if (is_environment_use) { |
| 711 use->BindToEnvironment(converted); | 711 use->BindToEnvironment(converted); |
| 712 } else { | 712 } else { |
| 713 use->BindTo(converted); | 713 use->BindTo(converted); |
| 714 } | 714 } |
| 715 } | 715 } |
| 716 | 716 |
| 717 | 717 |
| 718 void FlowGraphOptimizer::ConvertUse(Value* use, Representation from_rep) { | 718 void FlowGraphOptimizer::ConvertUse(Value* use, Representation from_rep) { |
| 719 const Representation to_rep = | 719 const Representation to_rep = |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, | 977 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check, |
| 978 intptr_t deopt_id, | 978 intptr_t deopt_id, |
| 979 Environment* deopt_environment, | 979 Environment* deopt_environment, |
| 980 Instruction* insert_before) { | 980 Instruction* insert_before) { |
| 981 if (to_check->Type()->ToCid() != kSmiCid) { | 981 if (to_check->Type()->ToCid() != kSmiCid) { |
| 982 InsertBefore(insert_before, | 982 InsertBefore(insert_before, |
| 983 new CheckSmiInstr(new Value(to_check), | 983 new CheckSmiInstr(new Value(to_check), |
| 984 deopt_id, | 984 deopt_id, |
| 985 insert_before->token_pos()), | 985 insert_before->token_pos()), |
| 986 deopt_environment, | 986 deopt_environment, |
| 987 Definition::kEffect); | 987 FlowGraph::kEffect); |
| 988 } | 988 } |
| 989 } | 989 } |
| 990 | 990 |
| 991 | 991 |
| 992 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 992 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
| 993 const ICData& unary_checks, | 993 const ICData& unary_checks, |
| 994 intptr_t deopt_id, | 994 intptr_t deopt_id, |
| 995 intptr_t token_pos) { | 995 intptr_t token_pos) { |
| 996 if ((unary_checks.NumberOfChecks() == 1) && | 996 if ((unary_checks.NumberOfChecks() == 1) && |
| 997 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 997 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
| 998 return new CheckSmiInstr(new Value(to_check), | 998 return new CheckSmiInstr(new Value(to_check), |
| 999 deopt_id, | 999 deopt_id, |
| 1000 token_pos); | 1000 token_pos); |
| 1001 } | 1001 } |
| 1002 return new CheckClassInstr( | 1002 return new CheckClassInstr( |
| 1003 new Value(to_check), deopt_id, unary_checks, token_pos); | 1003 new Value(to_check), deopt_id, unary_checks, token_pos); |
| 1004 } | 1004 } |
| 1005 | 1005 |
| 1006 | 1006 |
| 1007 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 1007 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
| 1008 const ICData& unary_checks, | 1008 const ICData& unary_checks, |
| 1009 intptr_t deopt_id, | 1009 intptr_t deopt_id, |
| 1010 Environment* deopt_environment, | 1010 Environment* deopt_environment, |
| 1011 Instruction* insert_before) { | 1011 Instruction* insert_before) { |
| 1012 // Type propagation has not run yet, we cannot eliminate the check. | 1012 // Type propagation has not run yet, we cannot eliminate the check. |
| 1013 Instruction* check = GetCheckClass( | 1013 Instruction* check = GetCheckClass( |
| 1014 to_check, unary_checks, deopt_id, insert_before->token_pos()); | 1014 to_check, unary_checks, deopt_id, insert_before->token_pos()); |
| 1015 InsertBefore(insert_before, check, deopt_environment, Definition::kEffect); | 1015 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); |
| 1016 } | 1016 } |
| 1017 | 1017 |
| 1018 | 1018 |
| 1019 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { | 1019 void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) { |
| 1020 AddCheckClass(call->ArgumentAt(0), | 1020 AddCheckClass(call->ArgumentAt(0), |
| 1021 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), | 1021 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()), |
| 1022 call->deopt_id(), | 1022 call->deopt_id(), |
| 1023 call->env(), | 1023 call->env(), |
| 1024 call); | 1024 call); |
| 1025 } | 1025 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 intptr_t type_arguments_field_offset = | 1200 intptr_t type_arguments_field_offset = |
| 1201 instantiator_class.type_arguments_field_offset(); | 1201 instantiator_class.type_arguments_field_offset(); |
| 1202 LoadFieldInstr* load_type_args = | 1202 LoadFieldInstr* load_type_args = |
| 1203 new LoadFieldInstr(new Value(array), | 1203 new LoadFieldInstr(new Value(array), |
| 1204 type_arguments_field_offset, | 1204 type_arguments_field_offset, |
| 1205 Type::ZoneHandle(), // No type. | 1205 Type::ZoneHandle(), // No type. |
| 1206 call->token_pos()); | 1206 call->token_pos()); |
| 1207 cursor = flow_graph()->AppendTo(cursor, | 1207 cursor = flow_graph()->AppendTo(cursor, |
| 1208 load_type_args, | 1208 load_type_args, |
| 1209 NULL, | 1209 NULL, |
| 1210 Definition::kValue); | 1210 FlowGraph::kValue); |
| 1211 | 1211 |
| 1212 instantiator = array; | 1212 instantiator = array; |
| 1213 type_args = load_type_args; | 1213 type_args = load_type_args; |
| 1214 break; | 1214 break; |
| 1215 } | 1215 } |
| 1216 case kTypedDataInt8ArrayCid: | 1216 case kTypedDataInt8ArrayCid: |
| 1217 case kTypedDataUint8ArrayCid: | 1217 case kTypedDataUint8ArrayCid: |
| 1218 case kTypedDataUint8ClampedArrayCid: | 1218 case kTypedDataUint8ClampedArrayCid: |
| 1219 case kExternalTypedDataUint8ArrayCid: | 1219 case kExternalTypedDataUint8ArrayCid: |
| 1220 case kExternalTypedDataUint8ClampedArrayCid: | 1220 case kExternalTypedDataUint8ClampedArrayCid: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 new Value(type_args), | 1258 new Value(type_args), |
| 1259 value_type, | 1259 value_type, |
| 1260 Symbols::Value()); | 1260 Symbols::Value()); |
| 1261 // Newly inserted instructions that can deoptimize or throw an exception | 1261 // Newly inserted instructions that can deoptimize or throw an exception |
| 1262 // must have a deoptimization id that is valid for lookup in the unoptimized | 1262 // must have a deoptimization id that is valid for lookup in the unoptimized |
| 1263 // code. | 1263 // code. |
| 1264 assert_value->deopt_id_ = call->deopt_id(); | 1264 assert_value->deopt_id_ = call->deopt_id(); |
| 1265 cursor = flow_graph()->AppendTo(cursor, | 1265 cursor = flow_graph()->AppendTo(cursor, |
| 1266 assert_value, | 1266 assert_value, |
| 1267 call->env(), | 1267 call->env(), |
| 1268 Definition::kValue); | 1268 FlowGraph::kValue); |
| 1269 } | 1269 } |
| 1270 | 1270 |
| 1271 array_cid = PrepareInlineIndexedOp(call, | 1271 array_cid = PrepareInlineIndexedOp(call, |
| 1272 array_cid, | 1272 array_cid, |
| 1273 &array, | 1273 &array, |
| 1274 index, | 1274 index, |
| 1275 &cursor); | 1275 &cursor); |
| 1276 | 1276 |
| 1277 // Check if store barrier is needed. Byte arrays don't need a store barrier. | 1277 // Check if store barrier is needed. Byte arrays don't need a store barrier. |
| 1278 StoreBarrierType needs_store_barrier = | 1278 StoreBarrierType needs_store_barrier = |
| 1279 (RawObject::IsTypedDataClassId(array_cid) || | 1279 (RawObject::IsTypedDataClassId(array_cid) || |
| 1280 RawObject::IsTypedDataViewClassId(array_cid) || | 1280 RawObject::IsTypedDataViewClassId(array_cid) || |
| 1281 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier | 1281 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier |
| 1282 : kEmitStoreBarrier; | 1282 : kEmitStoreBarrier; |
| 1283 if (!value_check.IsNull()) { | 1283 if (!value_check.IsNull()) { |
| 1284 // No store barrier needed because checked value is a smi, an unboxed mint, | 1284 // No store barrier needed because checked value is a smi, an unboxed mint, |
| 1285 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. | 1285 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. |
| 1286 needs_store_barrier = kNoStoreBarrier; | 1286 needs_store_barrier = kNoStoreBarrier; |
| 1287 Instruction* check = GetCheckClass( | 1287 Instruction* check = GetCheckClass( |
| 1288 stored_value, value_check, call->deopt_id(), call->token_pos()); | 1288 stored_value, value_check, call->deopt_id(), call->token_pos()); |
| 1289 cursor = flow_graph()->AppendTo(cursor, | 1289 cursor = flow_graph()->AppendTo(cursor, |
| 1290 check, | 1290 check, |
| 1291 call->env(), | 1291 call->env(), |
| 1292 Definition::kEffect); | 1292 FlowGraph::kEffect); |
| 1293 } | 1293 } |
| 1294 | 1294 |
| 1295 if (array_cid == kTypedDataFloat32ArrayCid) { | 1295 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1296 stored_value = | 1296 stored_value = |
| 1297 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); | 1297 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); |
| 1298 cursor = flow_graph()->AppendTo(cursor, | 1298 cursor = flow_graph()->AppendTo(cursor, |
| 1299 stored_value, | 1299 stored_value, |
| 1300 NULL, | 1300 NULL, |
| 1301 Definition::kValue); | 1301 FlowGraph::kValue); |
| 1302 } | 1302 } |
| 1303 | 1303 |
| 1304 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1304 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1305 *last = new StoreIndexedInstr(new Value(array), | 1305 *last = new StoreIndexedInstr(new Value(array), |
| 1306 new Value(index), | 1306 new Value(index), |
| 1307 new Value(stored_value), | 1307 new Value(stored_value), |
| 1308 needs_store_barrier, | 1308 needs_store_barrier, |
| 1309 index_scale, | 1309 index_scale, |
| 1310 array_cid, | 1310 array_cid, |
| 1311 call->deopt_id(), | 1311 call->deopt_id(), |
| 1312 call->token_pos()); | 1312 call->token_pos()); |
| 1313 flow_graph()->AppendTo(cursor, | 1313 flow_graph()->AppendTo(cursor, |
| 1314 *last, | 1314 *last, |
| 1315 call->env(), | 1315 call->env(), |
| 1316 Definition::kEffect); | 1316 FlowGraph::kEffect); |
| 1317 return true; | 1317 return true; |
| 1318 } | 1318 } |
| 1319 | 1319 |
| 1320 | 1320 |
| 1321 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, | 1321 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, |
| 1322 const Function& target, | 1322 const Function& target, |
| 1323 Instruction* call, | 1323 Instruction* call, |
| 1324 Definition* receiver, | 1324 Definition* receiver, |
| 1325 intptr_t token_pos, | 1325 intptr_t token_pos, |
| 1326 const ICData& ic_data, | 1326 const ICData& ic_data, |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 intptr_t array_cid, | 1560 intptr_t array_cid, |
| 1561 Definition** array, | 1561 Definition** array, |
| 1562 Definition* index, | 1562 Definition* index, |
| 1563 Instruction** cursor) { | 1563 Instruction** cursor) { |
| 1564 // Insert index smi check. | 1564 // Insert index smi check. |
| 1565 *cursor = flow_graph()->AppendTo(*cursor, | 1565 *cursor = flow_graph()->AppendTo(*cursor, |
| 1566 new CheckSmiInstr(new Value(index), | 1566 new CheckSmiInstr(new Value(index), |
| 1567 call->deopt_id(), | 1567 call->deopt_id(), |
| 1568 call->token_pos()), | 1568 call->token_pos()), |
| 1569 call->env(), | 1569 call->env(), |
| 1570 Definition::kEffect); | 1570 FlowGraph::kEffect); |
| 1571 | 1571 |
| 1572 // Insert array length load and bounds check. | 1572 // Insert array length load and bounds check. |
| 1573 LoadFieldInstr* length = | 1573 LoadFieldInstr* length = |
| 1574 new LoadFieldInstr(new Value(*array), | 1574 new LoadFieldInstr(new Value(*array), |
| 1575 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 1575 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 1576 Type::ZoneHandle(Type::SmiType()), | 1576 Type::ZoneHandle(Type::SmiType()), |
| 1577 call->token_pos()); | 1577 call->token_pos()); |
| 1578 length->set_is_immutable( | 1578 length->set_is_immutable( |
| 1579 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); | 1579 CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid)); |
| 1580 length->set_result_cid(kSmiCid); | 1580 length->set_result_cid(kSmiCid); |
| 1581 length->set_recognized_kind( | 1581 length->set_recognized_kind( |
| 1582 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 1582 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 1583 *cursor = flow_graph()->AppendTo(*cursor, | 1583 *cursor = flow_graph()->AppendTo(*cursor, |
| 1584 length, | 1584 length, |
| 1585 NULL, | 1585 NULL, |
| 1586 Definition::kValue); | 1586 FlowGraph::kValue); |
| 1587 | 1587 |
| 1588 *cursor = flow_graph()->AppendTo(*cursor, | 1588 *cursor = flow_graph()->AppendTo(*cursor, |
| 1589 new CheckArrayBoundInstr( | 1589 new CheckArrayBoundInstr( |
| 1590 new Value(length), | 1590 new Value(length), |
| 1591 new Value(index), | 1591 new Value(index), |
| 1592 call->deopt_id()), | 1592 call->deopt_id()), |
| 1593 call->env(), | 1593 call->env(), |
| 1594 Definition::kEffect); | 1594 FlowGraph::kEffect); |
| 1595 | 1595 |
| 1596 if (array_cid == kGrowableObjectArrayCid) { | 1596 if (array_cid == kGrowableObjectArrayCid) { |
| 1597 // Insert data elements load. | 1597 // Insert data elements load. |
| 1598 LoadFieldInstr* elements = | 1598 LoadFieldInstr* elements = |
| 1599 new LoadFieldInstr(new Value(*array), | 1599 new LoadFieldInstr(new Value(*array), |
| 1600 GrowableObjectArray::data_offset(), | 1600 GrowableObjectArray::data_offset(), |
| 1601 Type::ZoneHandle(Type::DynamicType()), | 1601 Type::ZoneHandle(Type::DynamicType()), |
| 1602 call->token_pos()); | 1602 call->token_pos()); |
| 1603 elements->set_result_cid(kArrayCid); | 1603 elements->set_result_cid(kArrayCid); |
| 1604 *cursor = flow_graph()->AppendTo(*cursor, | 1604 *cursor = flow_graph()->AppendTo(*cursor, |
| 1605 elements, | 1605 elements, |
| 1606 NULL, | 1606 NULL, |
| 1607 Definition::kValue); | 1607 FlowGraph::kValue); |
| 1608 // Load from the data from backing store which is a fixed-length array. | 1608 // Load from the data from backing store which is a fixed-length array. |
| 1609 *array = elements; | 1609 *array = elements; |
| 1610 array_cid = kArrayCid; | 1610 array_cid = kArrayCid; |
| 1611 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 1611 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 1612 LoadUntaggedInstr* elements = | 1612 LoadUntaggedInstr* elements = |
| 1613 new LoadUntaggedInstr(new Value(*array), | 1613 new LoadUntaggedInstr(new Value(*array), |
| 1614 ExternalTypedData::data_offset()); | 1614 ExternalTypedData::data_offset()); |
| 1615 *cursor = flow_graph()->AppendTo(*cursor, | 1615 *cursor = flow_graph()->AppendTo(*cursor, |
| 1616 elements, | 1616 elements, |
| 1617 NULL, | 1617 NULL, |
| 1618 Definition::kValue); | 1618 FlowGraph::kValue); |
| 1619 *array = elements; | 1619 *array = elements; |
| 1620 } | 1620 } |
| 1621 return array_cid; | 1621 return array_cid; |
| 1622 } | 1622 } |
| 1623 | 1623 |
| 1624 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, | 1624 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, |
| 1625 Instruction* call, | 1625 Instruction* call, |
| 1626 Definition* receiver, | 1626 Definition* receiver, |
| 1627 const ICData& ic_data, | 1627 const ICData& ic_data, |
| 1628 TargetEntryInstr** entry, | 1628 TargetEntryInstr** entry, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1657 *last = new LoadIndexedInstr(new Value(array), | 1657 *last = new LoadIndexedInstr(new Value(array), |
| 1658 new Value(index), | 1658 new Value(index), |
| 1659 index_scale, | 1659 index_scale, |
| 1660 array_cid, | 1660 array_cid, |
| 1661 deopt_id, | 1661 deopt_id, |
| 1662 call->token_pos()); | 1662 call->token_pos()); |
| 1663 cursor = flow_graph()->AppendTo( | 1663 cursor = flow_graph()->AppendTo( |
| 1664 cursor, | 1664 cursor, |
| 1665 *last, | 1665 *last, |
| 1666 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1666 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1667 Definition::kValue); | 1667 FlowGraph::kValue); |
| 1668 | 1668 |
| 1669 if (array_cid == kTypedDataFloat32ArrayCid) { | 1669 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1670 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 1670 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 1671 flow_graph()->AppendTo(cursor, | 1671 flow_graph()->AppendTo(cursor, |
| 1672 *last, | 1672 *last, |
| 1673 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1673 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1674 Definition::kValue); | 1674 FlowGraph::kValue); |
| 1675 } | 1675 } |
| 1676 return true; | 1676 return true; |
| 1677 } | 1677 } |
| 1678 | 1678 |
| 1679 | 1679 |
| 1680 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1680 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 1681 // Check for monomorphic IC data. | 1681 // Check for monomorphic IC data. |
| 1682 if (!call->HasICData()) return false; | 1682 if (!call->HasICData()) return false; |
| 1683 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 1683 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); |
| 1684 if (ic_data.NumberOfChecks() != 1) return false; | 1684 if (ic_data.NumberOfChecks() != 1) return false; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)); | 1788 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)); |
| 1789 AddCheckClass(right, | 1789 AddCheckClass(right, |
| 1790 unary_checks_1, | 1790 unary_checks_1, |
| 1791 call->deopt_id(), | 1791 call->deopt_id(), |
| 1792 call->env(), | 1792 call->env(), |
| 1793 call); | 1793 call); |
| 1794 // String-to-char-code instructions returns -1 (illegal charcode) if | 1794 // String-to-char-code instructions returns -1 (illegal charcode) if |
| 1795 // string is not of length one. | 1795 // string is not of length one. |
| 1796 StringToCharCodeInstr* char_code_right = | 1796 StringToCharCodeInstr* char_code_right = |
| 1797 new StringToCharCodeInstr(new Value(right), kOneByteStringCid); | 1797 new StringToCharCodeInstr(new Value(right), kOneByteStringCid); |
| 1798 InsertBefore(call, char_code_right, call->env(), Definition::kValue); | 1798 InsertBefore(call, char_code_right, call->env(), FlowGraph::kValue); |
| 1799 right_val = new Value(char_code_right); | 1799 right_val = new Value(char_code_right); |
| 1800 } | 1800 } |
| 1801 | 1801 |
| 1802 // Comparing char-codes instead of strings. | 1802 // Comparing char-codes instead of strings. |
| 1803 EqualityCompareInstr* comp = | 1803 EqualityCompareInstr* comp = |
| 1804 new EqualityCompareInstr(call->token_pos(), | 1804 new EqualityCompareInstr(call->token_pos(), |
| 1805 op_kind, | 1805 op_kind, |
| 1806 left_val, | 1806 left_val, |
| 1807 right_val, | 1807 right_val, |
| 1808 kSmiCid, | 1808 kSmiCid, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1843 return true; | 1843 return true; |
| 1844 } else { | 1844 } else { |
| 1845 return false; | 1845 return false; |
| 1846 } | 1846 } |
| 1847 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1847 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1848 InsertBefore(call, | 1848 InsertBefore(call, |
| 1849 new CheckSmiInstr(new Value(left), | 1849 new CheckSmiInstr(new Value(left), |
| 1850 call->deopt_id(), | 1850 call->deopt_id(), |
| 1851 call->token_pos()), | 1851 call->token_pos()), |
| 1852 call->env(), | 1852 call->env(), |
| 1853 Definition::kEffect); | 1853 FlowGraph::kEffect); |
| 1854 InsertBefore(call, | 1854 InsertBefore(call, |
| 1855 new CheckSmiInstr(new Value(right), | 1855 new CheckSmiInstr(new Value(right), |
| 1856 call->deopt_id(), | 1856 call->deopt_id(), |
| 1857 call->token_pos()), | 1857 call->token_pos()), |
| 1858 call->env(), | 1858 call->env(), |
| 1859 Definition::kEffect); | 1859 FlowGraph::kEffect); |
| 1860 cid = kSmiCid; | 1860 cid = kSmiCid; |
| 1861 } else if (HasTwoMintOrSmi(ic_data) && | 1861 } else if (HasTwoMintOrSmi(ic_data) && |
| 1862 FlowGraphCompiler::SupportsUnboxedMints()) { | 1862 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1863 cid = kMintCid; | 1863 cid = kMintCid; |
| 1864 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1864 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
| 1865 // Use double comparison. | 1865 // Use double comparison. |
| 1866 if (SmiFitsInDouble()) { | 1866 if (SmiFitsInDouble()) { |
| 1867 cid = kDoubleCid; | 1867 cid = kDoubleCid; |
| 1868 } else { | 1868 } else { |
| 1869 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1869 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
| 1870 // We cannot use double comparison on two smis. Need polymorphic | 1870 // We cannot use double comparison on two smis. Need polymorphic |
| 1871 // call. | 1871 // call. |
| 1872 return false; | 1872 return false; |
| 1873 } else { | 1873 } else { |
| 1874 InsertBefore(call, | 1874 InsertBefore(call, |
| 1875 new CheckEitherNonSmiInstr(new Value(left), | 1875 new CheckEitherNonSmiInstr(new Value(left), |
| 1876 new Value(right), | 1876 new Value(right), |
| 1877 call->deopt_id()), | 1877 call->deopt_id()), |
| 1878 call->env(), | 1878 call->env(), |
| 1879 Definition::kEffect); | 1879 FlowGraph::kEffect); |
| 1880 cid = kDoubleCid; | 1880 cid = kDoubleCid; |
| 1881 } | 1881 } |
| 1882 } | 1882 } |
| 1883 } else { | 1883 } else { |
| 1884 // Check if ICDData contains checks with Smi/Null combinations. In that case | 1884 // Check if ICDData contains checks with Smi/Null combinations. In that case |
| 1885 // we can still emit the optimized Smi equality operation but need to add | 1885 // we can still emit the optimized Smi equality operation but need to add |
| 1886 // checks for null or Smi. | 1886 // checks for null or Smi. |
| 1887 GrowableArray<intptr_t> smi_or_null(2); | 1887 GrowableArray<intptr_t> smi_or_null(2); |
| 1888 smi_or_null.Add(kSmiCid); | 1888 smi_or_null.Add(kSmiCid); |
| 1889 smi_or_null.Add(kNullCid); | 1889 smi_or_null.Add(kNullCid); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1945 Definition* left = call->ArgumentAt(0); | 1945 Definition* left = call->ArgumentAt(0); |
| 1946 Definition* right = call->ArgumentAt(1); | 1946 Definition* right = call->ArgumentAt(1); |
| 1947 | 1947 |
| 1948 intptr_t cid = kIllegalCid; | 1948 intptr_t cid = kIllegalCid; |
| 1949 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1949 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| 1950 InsertBefore(call, | 1950 InsertBefore(call, |
| 1951 new CheckSmiInstr(new Value(left), | 1951 new CheckSmiInstr(new Value(left), |
| 1952 call->deopt_id(), | 1952 call->deopt_id(), |
| 1953 call->token_pos()), | 1953 call->token_pos()), |
| 1954 call->env(), | 1954 call->env(), |
| 1955 Definition::kEffect); | 1955 FlowGraph::kEffect); |
| 1956 InsertBefore(call, | 1956 InsertBefore(call, |
| 1957 new CheckSmiInstr(new Value(right), | 1957 new CheckSmiInstr(new Value(right), |
| 1958 call->deopt_id(), | 1958 call->deopt_id(), |
| 1959 call->token_pos()), | 1959 call->token_pos()), |
| 1960 call->env(), | 1960 call->env(), |
| 1961 Definition::kEffect); | 1961 FlowGraph::kEffect); |
| 1962 cid = kSmiCid; | 1962 cid = kSmiCid; |
| 1963 } else if (HasTwoMintOrSmi(ic_data) && | 1963 } else if (HasTwoMintOrSmi(ic_data) && |
| 1964 FlowGraphCompiler::SupportsUnboxedMints()) { | 1964 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1965 cid = kMintCid; | 1965 cid = kMintCid; |
| 1966 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { | 1966 } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) { |
| 1967 // Use double comparison. | 1967 // Use double comparison. |
| 1968 if (SmiFitsInDouble()) { | 1968 if (SmiFitsInDouble()) { |
| 1969 cid = kDoubleCid; | 1969 cid = kDoubleCid; |
| 1970 } else { | 1970 } else { |
| 1971 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 1971 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
| 1972 // We cannot use double comparison on two smis. Need polymorphic | 1972 // We cannot use double comparison on two smis. Need polymorphic |
| 1973 // call. | 1973 // call. |
| 1974 return false; | 1974 return false; |
| 1975 } else { | 1975 } else { |
| 1976 InsertBefore(call, | 1976 InsertBefore(call, |
| 1977 new CheckEitherNonSmiInstr(new Value(left), | 1977 new CheckEitherNonSmiInstr(new Value(left), |
| 1978 new Value(right), | 1978 new Value(right), |
| 1979 call->deopt_id()), | 1979 call->deopt_id()), |
| 1980 call->env(), | 1980 call->env(), |
| 1981 Definition::kEffect); | 1981 FlowGraph::kEffect); |
| 1982 cid = kDoubleCid; | 1982 cid = kDoubleCid; |
| 1983 } | 1983 } |
| 1984 } | 1984 } |
| 1985 } else { | 1985 } else { |
| 1986 return false; | 1986 return false; |
| 1987 } | 1987 } |
| 1988 ASSERT(cid != kIllegalCid); | 1988 ASSERT(cid != kIllegalCid); |
| 1989 RelationalOpInstr* comp = new RelationalOpInstr(call->token_pos(), | 1989 RelationalOpInstr* comp = new RelationalOpInstr(call->token_pos(), |
| 1990 op_kind, | 1990 op_kind, |
| 1991 new Value(left), | 1991 new Value(left), |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 } | 2121 } |
| 2122 // Check that either left or right are not a smi. Result of a | 2122 // Check that either left or right are not a smi. Result of a |
| 2123 // binary operation with two smis is a smi not a double, except '/' which | 2123 // binary operation with two smis is a smi not a double, except '/' which |
| 2124 // returns a double for two smis. | 2124 // returns a double for two smis. |
| 2125 if (op_kind != Token::kDIV) { | 2125 if (op_kind != Token::kDIV) { |
| 2126 InsertBefore(call, | 2126 InsertBefore(call, |
| 2127 new CheckEitherNonSmiInstr(new Value(left), | 2127 new CheckEitherNonSmiInstr(new Value(left), |
| 2128 new Value(right), | 2128 new Value(right), |
| 2129 call->deopt_id()), | 2129 call->deopt_id()), |
| 2130 call->env(), | 2130 call->env(), |
| 2131 Definition::kEffect); | 2131 FlowGraph::kEffect); |
| 2132 } | 2132 } |
| 2133 | 2133 |
| 2134 BinaryDoubleOpInstr* double_bin_op = | 2134 BinaryDoubleOpInstr* double_bin_op = |
| 2135 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), | 2135 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), |
| 2136 call->deopt_id(), call->token_pos()); | 2136 call->deopt_id(), call->token_pos()); |
| 2137 ReplaceCall(call, double_bin_op); | 2137 ReplaceCall(call, double_bin_op); |
| 2138 } else if (operands_type == kMintCid) { | 2138 } else if (operands_type == kMintCid) { |
| 2139 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 2139 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 2140 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 2140 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 2141 ShiftMintOpInstr* shift_op = | 2141 ShiftMintOpInstr* shift_op = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2159 if (right->IsConstant()) { | 2159 if (right->IsConstant()) { |
| 2160 const Object& obj = right->AsConstant()->value(); | 2160 const Object& obj = right->AsConstant()->value(); |
| 2161 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { | 2161 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) { |
| 2162 // Insert smi check and attach a copy of the original environment | 2162 // Insert smi check and attach a copy of the original environment |
| 2163 // because the smi operation can still deoptimize. | 2163 // because the smi operation can still deoptimize. |
| 2164 InsertBefore(call, | 2164 InsertBefore(call, |
| 2165 new CheckSmiInstr(new Value(left), | 2165 new CheckSmiInstr(new Value(left), |
| 2166 call->deopt_id(), | 2166 call->deopt_id(), |
| 2167 call->token_pos()), | 2167 call->token_pos()), |
| 2168 call->env(), | 2168 call->env(), |
| 2169 Definition::kEffect); | 2169 FlowGraph::kEffect); |
| 2170 ConstantInstr* constant = | 2170 ConstantInstr* constant = |
| 2171 flow_graph()->GetConstant(Smi::Handle( | 2171 flow_graph()->GetConstant(Smi::Handle( |
| 2172 Smi::New(Smi::Cast(obj).Value() - 1))); | 2172 Smi::New(Smi::Cast(obj).Value() - 1))); |
| 2173 BinarySmiOpInstr* bin_op = | 2173 BinarySmiOpInstr* bin_op = |
| 2174 new BinarySmiOpInstr(Token::kBIT_AND, | 2174 new BinarySmiOpInstr(Token::kBIT_AND, |
| 2175 new Value(left), | 2175 new Value(left), |
| 2176 new Value(constant), | 2176 new Value(constant), |
| 2177 call->deopt_id(), | 2177 call->deopt_id(), |
| 2178 call->token_pos()); | 2178 call->token_pos()); |
| 2179 ReplaceCall(call, bin_op); | 2179 ReplaceCall(call, bin_op); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 Token::Kind op_kind) { | 2214 Token::Kind op_kind) { |
| 2215 ASSERT(call->ArgumentCount() == 1); | 2215 ASSERT(call->ArgumentCount() == 1); |
| 2216 Definition* input = call->ArgumentAt(0); | 2216 Definition* input = call->ArgumentAt(0); |
| 2217 Definition* unary_op = NULL; | 2217 Definition* unary_op = NULL; |
| 2218 if (HasOnlyOneSmi(*call->ic_data())) { | 2218 if (HasOnlyOneSmi(*call->ic_data())) { |
| 2219 InsertBefore(call, | 2219 InsertBefore(call, |
| 2220 new CheckSmiInstr(new Value(input), | 2220 new CheckSmiInstr(new Value(input), |
| 2221 call->deopt_id(), | 2221 call->deopt_id(), |
| 2222 call->token_pos()), | 2222 call->token_pos()), |
| 2223 call->env(), | 2223 call->env(), |
| 2224 Definition::kEffect); | 2224 FlowGraph::kEffect); |
| 2225 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); | 2225 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); |
| 2226 } else if ((op_kind == Token::kBIT_NOT) && | 2226 } else if ((op_kind == Token::kBIT_NOT) && |
| 2227 HasOnlySmiOrMint(*call->ic_data()) && | 2227 HasOnlySmiOrMint(*call->ic_data()) && |
| 2228 FlowGraphCompiler::SupportsUnboxedMints()) { | 2228 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 2229 unary_op = new UnaryMintOpInstr( | 2229 unary_op = new UnaryMintOpInstr( |
| 2230 op_kind, new Value(input), call->deopt_id()); | 2230 op_kind, new Value(input), call->deopt_id()); |
| 2231 } else if (HasOnlyOneDouble(*call->ic_data()) && | 2231 } else if (HasOnlyOneDouble(*call->ic_data()) && |
| 2232 (op_kind == Token::kNEGATE) && | 2232 (op_kind == Token::kNEGATE) && |
| 2233 CanUnboxDouble()) { | 2233 CanUnboxDouble()) { |
| 2234 AddReceiverCheck(call); | 2234 AddReceiverCheck(call); |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2701 intptr_t cid, | 2701 intptr_t cid, |
| 2702 Definition* str, | 2702 Definition* str, |
| 2703 Definition* index, | 2703 Definition* index, |
| 2704 Instruction* cursor) { | 2704 Instruction* cursor) { |
| 2705 | 2705 |
| 2706 cursor = flow_graph()->AppendTo(cursor, | 2706 cursor = flow_graph()->AppendTo(cursor, |
| 2707 new CheckSmiInstr(new Value(index), | 2707 new CheckSmiInstr(new Value(index), |
| 2708 call->deopt_id(), | 2708 call->deopt_id(), |
| 2709 call->token_pos()), | 2709 call->token_pos()), |
| 2710 call->env(), | 2710 call->env(), |
| 2711 Definition::kEffect); | 2711 FlowGraph::kEffect); |
| 2712 | 2712 |
| 2713 // Load the length of the string. | 2713 // Load the length of the string. |
| 2714 LoadFieldInstr* length = BuildLoadStringLength(str); | 2714 LoadFieldInstr* length = BuildLoadStringLength(str); |
| 2715 cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); | 2715 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); |
| 2716 // Bounds check. | 2716 // Bounds check. |
| 2717 cursor = flow_graph()->AppendTo(cursor, | 2717 cursor = flow_graph()->AppendTo(cursor, |
| 2718 new CheckArrayBoundInstr(new Value(length), | 2718 new CheckArrayBoundInstr(new Value(length), |
| 2719 new Value(index), | 2719 new Value(index), |
| 2720 call->deopt_id()), | 2720 call->deopt_id()), |
| 2721 call->env(), | 2721 call->env(), |
| 2722 Definition::kEffect); | 2722 FlowGraph::kEffect); |
| 2723 | 2723 |
| 2724 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( | 2724 LoadIndexedInstr* load_indexed = new LoadIndexedInstr( |
| 2725 new Value(str), | 2725 new Value(str), |
| 2726 new Value(index), | 2726 new Value(index), |
| 2727 FlowGraphCompiler::ElementSizeFor(cid), | 2727 FlowGraphCompiler::ElementSizeFor(cid), |
| 2728 cid, | 2728 cid, |
| 2729 Isolate::kNoDeoptId, | 2729 Isolate::kNoDeoptId, |
| 2730 call->token_pos()); | 2730 call->token_pos()); |
| 2731 | 2731 |
| 2732 cursor = flow_graph()->AppendTo(cursor, | 2732 cursor = flow_graph()->AppendTo(cursor, |
| 2733 load_indexed, | 2733 load_indexed, |
| 2734 NULL, | 2734 NULL, |
| 2735 Definition::kValue); | 2735 FlowGraph::kValue); |
| 2736 ASSERT(cursor == load_indexed); | 2736 ASSERT(cursor == load_indexed); |
| 2737 return load_indexed; | 2737 return load_indexed; |
| 2738 } | 2738 } |
| 2739 | 2739 |
| 2740 | 2740 |
| 2741 bool FlowGraphOptimizer::InlineStringCodeUnitAt( | 2741 bool FlowGraphOptimizer::InlineStringCodeUnitAt( |
| 2742 Instruction* call, | 2742 Instruction* call, |
| 2743 intptr_t cid, | 2743 intptr_t cid, |
| 2744 TargetEntryInstr** entry, | 2744 TargetEntryInstr** entry, |
| 2745 Definition** last) { | 2745 Definition** last) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2775 | 2775 |
| 2776 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), | 2776 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2777 call->GetBlock()->try_index()); | 2777 call->GetBlock()->try_index()); |
| 2778 (*entry)->InheritDeoptTarget(call); | 2778 (*entry)->InheritDeoptTarget(call); |
| 2779 | 2779 |
| 2780 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2780 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
| 2781 | 2781 |
| 2782 StringFromCharCodeInstr* char_at = | 2782 StringFromCharCodeInstr* char_at = |
| 2783 new StringFromCharCodeInstr(new Value(*last), cid); | 2783 new StringFromCharCodeInstr(new Value(*last), cid); |
| 2784 | 2784 |
| 2785 flow_graph()->AppendTo(*last, char_at, NULL, Definition::kValue); | 2785 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
| 2786 *last = char_at; | 2786 *last = char_at; |
| 2787 | 2787 |
| 2788 return true; | 2788 return true; |
| 2789 } | 2789 } |
| 2790 | 2790 |
| 2791 | 2791 |
| 2792 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2792 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
| 2793 InstanceCallInstr* call, | 2793 InstanceCallInstr* call, |
| 2794 MethodRecognizer::Kind recognized_kind) { | 2794 MethodRecognizer::Kind recognized_kind) { |
| 2795 AddReceiverCheck(call); | 2795 AddReceiverCheck(call); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 } | 3070 } |
| 3071 BinarySmiOpInstr* left_shift = | 3071 BinarySmiOpInstr* left_shift = |
| 3072 new BinarySmiOpInstr(Token::kSHL, | 3072 new BinarySmiOpInstr(Token::kSHL, |
| 3073 new Value(value), new Value(count), | 3073 new Value(value), new Value(count), |
| 3074 call->deopt_id(), call->token_pos()); | 3074 call->deopt_id(), call->token_pos()); |
| 3075 left_shift->set_is_truncating(true); | 3075 left_shift->set_is_truncating(true); |
| 3076 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { | 3076 if ((kBitsPerWord == 32) && (mask_value == 0xffffffffLL)) { |
| 3077 // No BIT_AND operation needed. | 3077 // No BIT_AND operation needed. |
| 3078 ReplaceCall(call, left_shift); | 3078 ReplaceCall(call, left_shift); |
| 3079 } else { | 3079 } else { |
| 3080 InsertBefore(call, left_shift, call->env(), Definition::kValue); | 3080 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
| 3081 BinarySmiOpInstr* bit_and = | 3081 BinarySmiOpInstr* bit_and = |
| 3082 new BinarySmiOpInstr(Token::kBIT_AND, | 3082 new BinarySmiOpInstr(Token::kBIT_AND, |
| 3083 new Value(left_shift), new Value(int32_mask), | 3083 new Value(left_shift), new Value(int32_mask), |
| 3084 call->deopt_id(), call->token_pos()); | 3084 call->deopt_id(), call->token_pos()); |
| 3085 ReplaceCall(call, bit_and); | 3085 ReplaceCall(call, bit_and); |
| 3086 } | 3086 } |
| 3087 return true; | 3087 return true; |
| 3088 } | 3088 } |
| 3089 | 3089 |
| 3090 if (HasTwoMintOrSmi(ic_data) && | 3090 if (HasTwoMintOrSmi(ic_data) && |
| 3091 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { | 3091 HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 3092 if (!FlowGraphCompiler::SupportsUnboxedMints() || | 3092 if (!FlowGraphCompiler::SupportsUnboxedMints() || |
| 3093 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { | 3093 ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) { |
| 3094 return false; | 3094 return false; |
| 3095 } | 3095 } |
| 3096 ShiftMintOpInstr* left_shift = | 3096 ShiftMintOpInstr* left_shift = |
| 3097 new ShiftMintOpInstr(Token::kSHL, | 3097 new ShiftMintOpInstr(Token::kSHL, |
| 3098 new Value(value), new Value(count), | 3098 new Value(value), new Value(count), |
| 3099 call->deopt_id()); | 3099 call->deopt_id()); |
| 3100 InsertBefore(call, left_shift, call->env(), Definition::kValue); | 3100 InsertBefore(call, left_shift, call->env(), FlowGraph::kValue); |
| 3101 BinaryMintOpInstr* bit_and = | 3101 BinaryMintOpInstr* bit_and = |
| 3102 new BinaryMintOpInstr(Token::kBIT_AND, | 3102 new BinaryMintOpInstr(Token::kBIT_AND, |
| 3103 new Value(left_shift), new Value(int32_mask), | 3103 new Value(left_shift), new Value(int32_mask), |
| 3104 call->deopt_id()); | 3104 call->deopt_id()); |
| 3105 ReplaceCall(call, bit_and); | 3105 ReplaceCall(call, bit_and); |
| 3106 return true; | 3106 return true; |
| 3107 } | 3107 } |
| 3108 } | 3108 } |
| 3109 return false; | 3109 return false; |
| 3110 } | 3110 } |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3523 *last = new LoadIndexedInstr(new Value(array), | 3523 *last = new LoadIndexedInstr(new Value(array), |
| 3524 new Value(index), | 3524 new Value(index), |
| 3525 1, | 3525 1, |
| 3526 view_cid, | 3526 view_cid, |
| 3527 deopt_id, | 3527 deopt_id, |
| 3528 call->token_pos()); | 3528 call->token_pos()); |
| 3529 cursor = flow_graph()->AppendTo( | 3529 cursor = flow_graph()->AppendTo( |
| 3530 cursor, | 3530 cursor, |
| 3531 *last, | 3531 *last, |
| 3532 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3532 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3533 Definition::kValue); | 3533 FlowGraph::kValue); |
| 3534 | 3534 |
| 3535 if (view_cid == kTypedDataFloat32ArrayCid) { | 3535 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3536 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); | 3536 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 3537 flow_graph()->AppendTo(cursor, | 3537 flow_graph()->AppendTo(cursor, |
| 3538 *last, | 3538 *last, |
| 3539 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3539 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3540 Definition::kValue); | 3540 FlowGraph::kValue); |
| 3541 } | 3541 } |
| 3542 return true; | 3542 return true; |
| 3543 } | 3543 } |
| 3544 | 3544 |
| 3545 | 3545 |
| 3546 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, | 3546 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, |
| 3547 Instruction* call, | 3547 Instruction* call, |
| 3548 Definition* receiver, | 3548 Definition* receiver, |
| 3549 intptr_t array_cid, | 3549 intptr_t array_cid, |
| 3550 intptr_t view_cid, | 3550 intptr_t view_cid, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3649 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 3649 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
| 3650 call); | 3650 call); |
| 3651 } | 3651 } |
| 3652 | 3652 |
| 3653 if (view_cid == kTypedDataFloat32ArrayCid) { | 3653 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3654 stored_value = | 3654 stored_value = |
| 3655 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); | 3655 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); |
| 3656 cursor = flow_graph()->AppendTo(cursor, | 3656 cursor = flow_graph()->AppendTo(cursor, |
| 3657 stored_value, | 3657 stored_value, |
| 3658 NULL, | 3658 NULL, |
| 3659 Definition::kValue); | 3659 FlowGraph::kValue); |
| 3660 } | 3660 } |
| 3661 | 3661 |
| 3662 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3662 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
| 3663 *last = new StoreIndexedInstr(new Value(array), | 3663 *last = new StoreIndexedInstr(new Value(array), |
| 3664 new Value(index), | 3664 new Value(index), |
| 3665 new Value(stored_value), | 3665 new Value(stored_value), |
| 3666 needs_store_barrier, | 3666 needs_store_barrier, |
| 3667 1, // Index scale | 3667 1, // Index scale |
| 3668 view_cid, | 3668 view_cid, |
| 3669 call->deopt_id(), | 3669 call->deopt_id(), |
| 3670 call->token_pos()); | 3670 call->token_pos()); |
| 3671 | 3671 |
| 3672 flow_graph()->AppendTo(cursor, | 3672 flow_graph()->AppendTo(cursor, |
| 3673 *last, | 3673 *last, |
| 3674 call->deopt_id() != Isolate::kNoDeoptId ? | 3674 call->deopt_id() != Isolate::kNoDeoptId ? |
| 3675 call->env() : NULL, | 3675 call->env() : NULL, |
| 3676 Definition::kEffect); | 3676 FlowGraph::kEffect); |
| 3677 return true; | 3677 return true; |
| 3678 } | 3678 } |
| 3679 | 3679 |
| 3680 | 3680 |
| 3681 | 3681 |
| 3682 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( | 3682 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
| 3683 Instruction* call, | 3683 Instruction* call, |
| 3684 intptr_t array_cid, | 3684 intptr_t array_cid, |
| 3685 intptr_t view_cid, | 3685 intptr_t view_cid, |
| 3686 Definition** array, | 3686 Definition** array, |
| 3687 Definition* byte_index, | 3687 Definition* byte_index, |
| 3688 Instruction** cursor) { | 3688 Instruction** cursor) { |
| 3689 // Insert byte_index smi check. | 3689 // Insert byte_index smi check. |
| 3690 *cursor = flow_graph()->AppendTo(*cursor, | 3690 *cursor = flow_graph()->AppendTo(*cursor, |
| 3691 new CheckSmiInstr(new Value(byte_index), | 3691 new CheckSmiInstr(new Value(byte_index), |
| 3692 call->deopt_id(), | 3692 call->deopt_id(), |
| 3693 call->token_pos()), | 3693 call->token_pos()), |
| 3694 call->env(), | 3694 call->env(), |
| 3695 Definition::kEffect); | 3695 FlowGraph::kEffect); |
| 3696 | 3696 |
| 3697 LoadFieldInstr* length = | 3697 LoadFieldInstr* length = |
| 3698 new LoadFieldInstr(new Value(*array), | 3698 new LoadFieldInstr(new Value(*array), |
| 3699 CheckArrayBoundInstr::LengthOffsetFor(array_cid), | 3699 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 3700 Type::ZoneHandle(Type::SmiType()), | 3700 Type::ZoneHandle(Type::SmiType()), |
| 3701 call->token_pos()); | 3701 call->token_pos()); |
| 3702 length->set_is_immutable(true); | 3702 length->set_is_immutable(true); |
| 3703 length->set_result_cid(kSmiCid); | 3703 length->set_result_cid(kSmiCid); |
| 3704 length->set_recognized_kind( | 3704 length->set_recognized_kind( |
| 3705 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); | 3705 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 3706 *cursor = flow_graph()->AppendTo(*cursor, | 3706 *cursor = flow_graph()->AppendTo(*cursor, |
| 3707 length, | 3707 length, |
| 3708 NULL, | 3708 NULL, |
| 3709 Definition::kValue); | 3709 FlowGraph::kValue); |
| 3710 | 3710 |
| 3711 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); | 3711 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 3712 ConstantInstr* bytes_per_element = | 3712 ConstantInstr* bytes_per_element = |
| 3713 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); | 3713 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); |
| 3714 BinarySmiOpInstr* len_in_bytes = | 3714 BinarySmiOpInstr* len_in_bytes = |
| 3715 new BinarySmiOpInstr(Token::kMUL, | 3715 new BinarySmiOpInstr(Token::kMUL, |
| 3716 new Value(length), | 3716 new Value(length), |
| 3717 new Value(bytes_per_element), | 3717 new Value(bytes_per_element), |
| 3718 call->deopt_id(), call->token_pos()); | 3718 call->deopt_id(), call->token_pos()); |
| 3719 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), | 3719 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
| 3720 Definition::kValue); | 3720 FlowGraph::kValue); |
| 3721 | 3721 |
| 3722 ConstantInstr* length_adjustment = | 3722 ConstantInstr* length_adjustment = |
| 3723 flow_graph()->GetConstant(Smi::Handle(Smi::New( | 3723 flow_graph()->GetConstant(Smi::Handle(Smi::New( |
| 3724 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); | 3724 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); |
| 3725 // adjusted_length = len_in_bytes - (element_size - 1). | 3725 // adjusted_length = len_in_bytes - (element_size - 1). |
| 3726 BinarySmiOpInstr* adjusted_length = | 3726 BinarySmiOpInstr* adjusted_length = |
| 3727 new BinarySmiOpInstr(Token::kSUB, | 3727 new BinarySmiOpInstr(Token::kSUB, |
| 3728 new Value(len_in_bytes), | 3728 new Value(len_in_bytes), |
| 3729 new Value(length_adjustment), | 3729 new Value(length_adjustment), |
| 3730 call->deopt_id(), call->token_pos()); | 3730 call->deopt_id(), call->token_pos()); |
| 3731 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), | 3731 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
| 3732 Definition::kValue); | 3732 FlowGraph::kValue); |
| 3733 | 3733 |
| 3734 // Check adjusted_length > 0. | 3734 // Check adjusted_length > 0. |
| 3735 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 3735 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 3736 *cursor = flow_graph()->AppendTo(*cursor, | 3736 *cursor = flow_graph()->AppendTo(*cursor, |
| 3737 new CheckArrayBoundInstr( | 3737 new CheckArrayBoundInstr( |
| 3738 new Value(adjusted_length), | 3738 new Value(adjusted_length), |
| 3739 new Value(zero), | 3739 new Value(zero), |
| 3740 call->deopt_id()), | 3740 call->deopt_id()), |
| 3741 call->env(), | 3741 call->env(), |
| 3742 Definition::kEffect); | 3742 FlowGraph::kEffect); |
| 3743 // Check 0 <= byte_index < adjusted_length. | 3743 // Check 0 <= byte_index < adjusted_length. |
| 3744 *cursor = flow_graph()->AppendTo(*cursor, | 3744 *cursor = flow_graph()->AppendTo(*cursor, |
| 3745 new CheckArrayBoundInstr( | 3745 new CheckArrayBoundInstr( |
| 3746 new Value(adjusted_length), | 3746 new Value(adjusted_length), |
| 3747 new Value(byte_index), | 3747 new Value(byte_index), |
| 3748 call->deopt_id()), | 3748 call->deopt_id()), |
| 3749 call->env(), | 3749 call->env(), |
| 3750 Definition::kEffect); | 3750 FlowGraph::kEffect); |
| 3751 | 3751 |
| 3752 if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 3752 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 3753 LoadUntaggedInstr* elements = | 3753 LoadUntaggedInstr* elements = |
| 3754 new LoadUntaggedInstr(new Value(*array), | 3754 new LoadUntaggedInstr(new Value(*array), |
| 3755 ExternalTypedData::data_offset()); | 3755 ExternalTypedData::data_offset()); |
| 3756 *cursor = flow_graph()->AppendTo(*cursor, | 3756 *cursor = flow_graph()->AppendTo(*cursor, |
| 3757 elements, | 3757 elements, |
| 3758 NULL, | 3758 NULL, |
| 3759 Definition::kValue); | 3759 FlowGraph::kValue); |
| 3760 *array = elements; | 3760 *array = elements; |
| 3761 } | 3761 } |
| 3762 return array_cid; | 3762 return array_cid; |
| 3763 } | 3763 } |
| 3764 | 3764 |
| 3765 | 3765 |
| 3766 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call, | 3766 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call, |
| 3767 intptr_t view_cid) { | 3767 intptr_t view_cid) { |
| 3768 const bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || | 3768 const bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || |
| 3769 (view_cid == kTypedDataInt32x4ArrayCid); | 3769 (view_cid == kTypedDataInt32x4ArrayCid); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3997 current_iterator()->RemoveCurrentFromGraph(); | 3997 current_iterator()->RemoveCurrentFromGraph(); |
| 3998 return; | 3998 return; |
| 3999 } | 3999 } |
| 4000 } | 4000 } |
| 4001 | 4001 |
| 4002 if (TypeCheckAsClassEquality(type)) { | 4002 if (TypeCheckAsClassEquality(type)) { |
| 4003 LoadClassIdInstr* left_cid = new LoadClassIdInstr(new Value(left)); | 4003 LoadClassIdInstr* left_cid = new LoadClassIdInstr(new Value(left)); |
| 4004 InsertBefore(call, | 4004 InsertBefore(call, |
| 4005 left_cid, | 4005 left_cid, |
| 4006 NULL, | 4006 NULL, |
| 4007 Definition::kValue); | 4007 FlowGraph::kValue); |
| 4008 const intptr_t type_cid = Class::Handle(type.type_class()).id(); | 4008 const intptr_t type_cid = Class::Handle(type.type_class()).id(); |
| 4009 ConstantInstr* cid = | 4009 ConstantInstr* cid = |
| 4010 flow_graph()->GetConstant(Smi::Handle(Smi::New(type_cid))); | 4010 flow_graph()->GetConstant(Smi::Handle(Smi::New(type_cid))); |
| 4011 | 4011 |
| 4012 StrictCompareInstr* check_cid = | 4012 StrictCompareInstr* check_cid = |
| 4013 new StrictCompareInstr(call->token_pos(), | 4013 new StrictCompareInstr(call->token_pos(), |
| 4014 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, | 4014 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, |
| 4015 new Value(left_cid), | 4015 new Value(left_cid), |
| 4016 new Value(cid), | 4016 new Value(cid), |
| 4017 false); // No number check. | 4017 false); // No number check. |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4412 if (InstanceCallNeedsClassCheck(instr)) { | 4412 if (InstanceCallNeedsClassCheck(instr)) { |
| 4413 AddReceiverCheck(instr); | 4413 AddReceiverCheck(instr); |
| 4414 } | 4414 } |
| 4415 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4415 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
| 4416 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 4416 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
| 4417 InsertBefore(instr, | 4417 InsertBefore(instr, |
| 4418 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), | 4418 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), |
| 4419 instr->deopt_id(), | 4419 instr->deopt_id(), |
| 4420 instr->token_pos()), | 4420 instr->token_pos()), |
| 4421 instr->env(), | 4421 instr->env(), |
| 4422 Definition::kEffect); | 4422 FlowGraph::kEffect); |
| 4423 needs_store_barrier = kNoStoreBarrier; | 4423 needs_store_barrier = kNoStoreBarrier; |
| 4424 } | 4424 } |
| 4425 | 4425 |
| 4426 if (field.guarded_cid() != kDynamicCid) { | 4426 if (field.guarded_cid() != kDynamicCid) { |
| 4427 InsertBefore(instr, | 4427 InsertBefore(instr, |
| 4428 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), | 4428 new GuardFieldInstr(new Value(instr->ArgumentAt(1)), |
| 4429 field, | 4429 field, |
| 4430 instr->deopt_id()), | 4430 instr->deopt_id()), |
| 4431 instr->env(), | 4431 instr->env(), |
| 4432 Definition::kEffect); | 4432 FlowGraph::kEffect); |
| 4433 } | 4433 } |
| 4434 | 4434 |
| 4435 // Field guard was detached. | 4435 // Field guard was detached. |
| 4436 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 4436 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 4437 field, | 4437 field, |
| 4438 new Value(instr->ArgumentAt(0)), | 4438 new Value(instr->ArgumentAt(0)), |
| 4439 new Value(instr->ArgumentAt(1)), | 4439 new Value(instr->ArgumentAt(1)), |
| 4440 needs_store_barrier, | 4440 needs_store_barrier, |
| 4441 instr->token_pos()); | 4441 instr->token_pos()); |
| 4442 | 4442 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4710 | 4710 |
| 4711 | 4711 |
| 4712 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, | 4712 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, |
| 4713 Range* constraint_range, | 4713 Range* constraint_range, |
| 4714 Instruction* after) { | 4714 Instruction* after) { |
| 4715 // No need to constrain constants. | 4715 // No need to constrain constants. |
| 4716 if (defn->IsConstant()) return NULL; | 4716 if (defn->IsConstant()) return NULL; |
| 4717 | 4717 |
| 4718 ConstraintInstr* constraint = | 4718 ConstraintInstr* constraint = |
| 4719 new ConstraintInstr(new Value(defn), constraint_range); | 4719 new ConstraintInstr(new Value(defn), constraint_range); |
| 4720 flow_graph_->InsertAfter(after, constraint, NULL, Definition::kValue); | 4720 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); |
| 4721 RenameDominatedUses(defn, constraint, constraint); | 4721 RenameDominatedUses(defn, constraint, constraint); |
| 4722 constraints_.Add(constraint); | 4722 constraints_.Add(constraint); |
| 4723 return constraint; | 4723 return constraint; |
| 4724 } | 4724 } |
| 4725 | 4725 |
| 4726 | 4726 |
| 4727 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { | 4727 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { |
| 4728 BranchInstr* branch = use->instruction()->AsBranch(); | 4728 BranchInstr* branch = use->instruction()->AsBranch(); |
| 4729 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); | 4729 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); |
| 4730 if ((rel_op != NULL) && (rel_op->operation_cid() == kSmiCid)) { | 4730 if ((rel_op != NULL) && (rel_op->operation_cid() == kSmiCid)) { |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5149 current->DebugName(), | 5149 current->DebugName(), |
| 5150 current->GetDeoptId(), | 5150 current->GetDeoptId(), |
| 5151 current->GetBlock()->block_id(), | 5151 current->GetBlock()->block_id(), |
| 5152 pre_header->block_id()); | 5152 pre_header->block_id()); |
| 5153 } | 5153 } |
| 5154 // Move the instruction out of the loop. | 5154 // Move the instruction out of the loop. |
| 5155 current->RemoveEnvironment(); | 5155 current->RemoveEnvironment(); |
| 5156 it->RemoveCurrentFromGraph(); | 5156 it->RemoveCurrentFromGraph(); |
| 5157 GotoInstr* last = pre_header->last_instruction()->AsGoto(); | 5157 GotoInstr* last = pre_header->last_instruction()->AsGoto(); |
| 5158 // Using kind kEffect will not assign a fresh ssa temporary index. | 5158 // Using kind kEffect will not assign a fresh ssa temporary index. |
| 5159 flow_graph()->InsertBefore(last, current, last->env(), Definition::kEffect); | 5159 flow_graph()->InsertBefore(last, current, last->env(), FlowGraph::kEffect); |
| 5160 current->deopt_id_ = last->GetDeoptId(); | 5160 current->deopt_id_ = last->GetDeoptId(); |
| 5161 } | 5161 } |
| 5162 | 5162 |
| 5163 | 5163 |
| 5164 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, | 5164 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, |
| 5165 BlockEntryInstr* header, | 5165 BlockEntryInstr* header, |
| 5166 BlockEntryInstr* pre_header, | 5166 BlockEntryInstr* pre_header, |
| 5167 CheckSmiInstr* current) { | 5167 CheckSmiInstr* current) { |
| 5168 PhiInstr* phi = current->value()->definition()->AsPhi(); | 5168 PhiInstr* phi = current->value()->definition()->AsPhi(); |
| 5169 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { | 5169 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { |
| (...skipping 4218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9388 ComparisonInstr* new_comparison = | 9388 ComparisonInstr* new_comparison = |
| 9389 comparison->CopyWithNewOperands(comparison->left()->Copy(), | 9389 comparison->CopyWithNewOperands(comparison->left()->Copy(), |
| 9390 comparison->right()->Copy()); | 9390 comparison->right()->Copy()); |
| 9391 IfThenElseInstr* if_then_else = new IfThenElseInstr( | 9391 IfThenElseInstr* if_then_else = new IfThenElseInstr( |
| 9392 new_comparison, | 9392 new_comparison, |
| 9393 if_true->Copy(), | 9393 if_true->Copy(), |
| 9394 if_false->Copy()); | 9394 if_false->Copy()); |
| 9395 flow_graph->InsertBefore(branch, | 9395 flow_graph->InsertBefore(branch, |
| 9396 if_then_else, | 9396 if_then_else, |
| 9397 NULL, | 9397 NULL, |
| 9398 Definition::kValue); | 9398 FlowGraph::kValue); |
| 9399 | 9399 |
| 9400 phi->ReplaceUsesWith(if_then_else); | 9400 phi->ReplaceUsesWith(if_then_else); |
| 9401 | 9401 |
| 9402 // Connect IfThenElseInstr to the first instruction in the merge block | 9402 // Connect IfThenElseInstr to the first instruction in the merge block |
| 9403 // effectively eliminating diamond control flow. | 9403 // effectively eliminating diamond control flow. |
| 9404 // Current block as well as pred1 and pred2 blocks are no longer in | 9404 // Current block as well as pred1 and pred2 blocks are no longer in |
| 9405 // the graph at this point. | 9405 // the graph at this point. |
| 9406 if_then_else->LinkTo(join->next()); | 9406 if_then_else->LinkTo(join->next()); |
| 9407 pred->set_last_instruction(join->last_instruction()); | 9407 pred->set_last_instruction(join->last_instruction()); |
| 9408 | 9408 |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9633 LoadFieldInstr* load = slots[i]->IsField() | 9633 LoadFieldInstr* load = slots[i]->IsField() |
| 9634 ? new LoadFieldInstr(new Value(alloc), | 9634 ? new LoadFieldInstr(new Value(alloc), |
| 9635 &Field::Cast(*slots[i]), | 9635 &Field::Cast(*slots[i]), |
| 9636 AbstractType::ZoneHandle(), | 9636 AbstractType::ZoneHandle(), |
| 9637 alloc->token_pos()) | 9637 alloc->token_pos()) |
| 9638 : new LoadFieldInstr(new Value(alloc), | 9638 : new LoadFieldInstr(new Value(alloc), |
| 9639 Smi::Cast(*slots[i]).Value(), | 9639 Smi::Cast(*slots[i]).Value(), |
| 9640 AbstractType::ZoneHandle(), | 9640 AbstractType::ZoneHandle(), |
| 9641 alloc->token_pos()); | 9641 alloc->token_pos()); |
| 9642 flow_graph_->InsertBefore( | 9642 flow_graph_->InsertBefore( |
| 9643 exit, load, NULL, Definition::kValue); | 9643 exit, load, NULL, FlowGraph::kValue); |
| 9644 values->Add(new Value(load)); | 9644 values->Add(new Value(load)); |
| 9645 } | 9645 } |
| 9646 | 9646 |
| 9647 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); | 9647 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, slots, values); |
| 9648 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); | 9648 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); |
| 9649 | 9649 |
| 9650 // Replace all mentions of this allocation with a newly inserted | 9650 // Replace all mentions of this allocation with a newly inserted |
| 9651 // MaterializeObject instruction. | 9651 // MaterializeObject instruction. |
| 9652 // We must preserve the identity: all mentions are replaced by the same | 9652 // We must preserve the identity: all mentions are replaced by the same |
| 9653 // materialization. | 9653 // materialization. |
| 9654 for (Environment::DeepIterator env_it(exit->env()); | 9654 for (Environment::DeepIterator env_it(exit->env()); |
| 9655 !env_it.Done(); | 9655 !env_it.Done(); |
| 9656 env_it.Advance()) { | 9656 env_it.Advance()) { |
| 9657 Value* use = env_it.CurrentValue(); | 9657 Value* use = env_it.CurrentValue(); |
| 9658 if (use->definition() == alloc) { | 9658 if (use->definition() == alloc) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9698 } | 9698 } |
| 9699 | 9699 |
| 9700 // Insert materializations at environment uses. | 9700 // Insert materializations at environment uses. |
| 9701 for (intptr_t i = 0; i < exits.length(); i++) { | 9701 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9702 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9702 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9703 } | 9703 } |
| 9704 } | 9704 } |
| 9705 | 9705 |
| 9706 | 9706 |
| 9707 } // namespace dart | 9707 } // namespace dart |
| OLD | NEW |