Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

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

Powered by Google App Engine
This is Rietveld 408576698