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 |