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

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

Powered by Google App Engine
This is Rietveld 408576698