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

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

Issue 19395003: Cleanups. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 | « no previous file | runtime/vm/intermediate_language.h » ('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/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 if (smi_shift_left == NULL) return; 224 if (smi_shift_left == NULL) return;
225 225
226 // Pattern recognized. 226 // Pattern recognized.
227 smi_shift_left->set_is_truncating(true); 227 smi_shift_left->set_is_truncating(true);
228 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); 228 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
229 if (bit_and_instr->IsBinaryMintOp()) { 229 if (bit_and_instr->IsBinaryMintOp()) {
230 // Replace Mint op with Smi op. 230 // Replace Mint op with Smi op.
231 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( 231 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr(
232 Token::kBIT_AND, 232 Token::kBIT_AND,
233 bit_and_instr->AsBinaryMintOp()->instance_call(),
234 new Value(left_instr), 233 new Value(left_instr),
235 new Value(right_instr)); 234 new Value(right_instr),
235 bit_and_instr->deopt_id());
236 bit_and_instr->ReplaceWith(smi_op, current_iterator()); 236 bit_and_instr->ReplaceWith(smi_op, current_iterator());
237 } 237 }
238 } 238 }
239 239
240 240
241 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the 241 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
242 // shift can be a truncating Smi shift-left and result is always Smi. 242 // shift can be a truncating Smi shift-left and result is always Smi.
243 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { 243 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() {
244 if (!FLAG_truncating_left_shift) return; 244 if (!FLAG_truncating_left_shift) return;
245 ASSERT(current_iterator_ == NULL); 245 ASSERT(current_iterator_ == NULL);
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 CheckArrayBoundInstr::LengthOffsetFor(class_id), 727 CheckArrayBoundInstr::LengthOffsetFor(class_id),
728 Type::ZoneHandle(Type::SmiType()), 728 Type::ZoneHandle(Type::SmiType()),
729 is_immutable); 729 is_immutable);
730 length->set_result_cid(kSmiCid); 730 length->set_result_cid(kSmiCid);
731 length->set_recognized_kind( 731 length->set_recognized_kind(
732 LoadFieldInstr::RecognizedKindFromArrayCid(class_id)); 732 LoadFieldInstr::RecognizedKindFromArrayCid(class_id));
733 InsertBefore(call, length, NULL, Definition::kValue); 733 InsertBefore(call, length, NULL, Definition::kValue);
734 InsertBefore(call, 734 InsertBefore(call,
735 new CheckArrayBoundInstr(new Value(length), 735 new CheckArrayBoundInstr(new Value(length),
736 new Value(*index), 736 new Value(*index),
737 call), 737 call->deopt_id()),
738 call->env(), 738 call->env(),
739 Definition::kEffect); 739 Definition::kEffect);
740 740
741 if (class_id == kGrowableObjectArrayCid) { 741 if (class_id == kGrowableObjectArrayCid) {
742 // Insert data elements load. 742 // Insert data elements load.
743 LoadFieldInstr* elements = 743 LoadFieldInstr* elements =
744 new LoadFieldInstr(new Value(*array), 744 new LoadFieldInstr(new Value(*array),
745 GrowableObjectArray::data_offset(), 745 GrowableObjectArray::data_offset(),
746 Type::ZoneHandle(Type::DynamicType())); 746 Type::ZoneHandle(Type::DynamicType()));
747 elements->set_result_cid(kArrayCid); 747 elements->set_result_cid(kArrayCid);
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 1099
1100 ASSERT(call->ArgumentCount() == 2); 1100 ASSERT(call->ArgumentCount() == 2);
1101 Definition* left = call->ArgumentAt(0); 1101 Definition* left = call->ArgumentAt(0);
1102 Definition* right = call->ArgumentAt(1); 1102 Definition* right = call->ArgumentAt(1);
1103 if (operands_type == kDoubleCid) { 1103 if (operands_type == kDoubleCid) {
1104 // Check that either left or right are not a smi. Result of a 1104 // Check that either left or right are not a smi. Result of a
1105 // binary operation with two smis is a smi not a double. 1105 // binary operation with two smis is a smi not a double.
1106 InsertBefore(call, 1106 InsertBefore(call,
1107 new CheckEitherNonSmiInstr(new Value(left), 1107 new CheckEitherNonSmiInstr(new Value(left),
1108 new Value(right), 1108 new Value(right),
1109 call), 1109 call->deopt_id()),
1110 call->env(), 1110 call->env(),
1111 Definition::kEffect); 1111 Definition::kEffect);
1112 1112
1113 BinaryDoubleOpInstr* double_bin_op = 1113 BinaryDoubleOpInstr* double_bin_op =
1114 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), 1114 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right),
1115 call); 1115 call->deopt_id());
1116 ReplaceCall(call, double_bin_op); 1116 ReplaceCall(call, double_bin_op);
1117 } else if (operands_type == kMintCid) { 1117 } else if (operands_type == kMintCid) {
1118 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; 1118 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false;
1119 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { 1119 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
1120 ShiftMintOpInstr* shift_op = 1120 ShiftMintOpInstr* shift_op =
1121 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), 1121 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right),
1122 call); 1122 call->deopt_id());
1123 ReplaceCall(call, shift_op); 1123 ReplaceCall(call, shift_op);
1124 } else { 1124 } else {
1125 BinaryMintOpInstr* bin_op = 1125 BinaryMintOpInstr* bin_op =
1126 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), 1126 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right),
1127 call); 1127 call->deopt_id());
1128 ReplaceCall(call, bin_op); 1128 ReplaceCall(call, bin_op);
1129 } 1129 }
1130 } else if (operands_type == kFloat32x4Cid) { 1130 } else if (operands_type == kFloat32x4Cid) {
1131 // Type check left. 1131 // Type check left.
1132 AddCheckClass(left, 1132 AddCheckClass(left,
1133 ICData::ZoneHandle( 1133 ICData::ZoneHandle(
1134 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1134 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1135 call->deopt_id(), 1135 call->deopt_id(),
1136 call->env(), 1136 call->env(),
1137 call); 1137 call);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 1178
1179 // Insert smi check and attach a copy of the original environment 1179 // Insert smi check and attach a copy of the original environment
1180 // because the smi operation can still deoptimize. 1180 // because the smi operation can still deoptimize.
1181 InsertBefore(call, 1181 InsertBefore(call,
1182 new CheckSmiInstr(new Value(left), call->deopt_id()), 1182 new CheckSmiInstr(new Value(left), call->deopt_id()),
1183 call->env(), 1183 call->env(),
1184 Definition::kEffect); 1184 Definition::kEffect);
1185 ConstantInstr* constant = 1185 ConstantInstr* constant =
1186 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1))); 1186 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1)));
1187 BinarySmiOpInstr* bin_op = 1187 BinarySmiOpInstr* bin_op =
1188 new BinarySmiOpInstr(Token::kBIT_AND, call, 1188 new BinarySmiOpInstr(Token::kBIT_AND,
1189 new Value(left), 1189 new Value(left),
1190 new Value(constant)); 1190 new Value(constant),
1191 call->deopt_id());
1191 ReplaceCall(call, bin_op); 1192 ReplaceCall(call, bin_op);
1192 } else { 1193 } else {
1193 ASSERT(operands_type == kSmiCid); 1194 ASSERT(operands_type == kSmiCid);
1194 // Insert two smi checks and attach a copy of the original 1195 // Insert two smi checks and attach a copy of the original
1195 // environment because the smi operation can still deoptimize. 1196 // environment because the smi operation can still deoptimize.
1196 AddCheckSmi(left, call->deopt_id(), call->env(), call); 1197 AddCheckSmi(left, call->deopt_id(), call->env(), call);
1197 AddCheckSmi(right, call->deopt_id(), call->env(), call); 1198 AddCheckSmi(right, call->deopt_id(), call->env(), call);
1198 if (left->IsConstant() && 1199 if (left->IsConstant() &&
1199 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { 1200 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
1200 // Constant should be on the right side. 1201 // Constant should be on the right side.
1201 Definition* temp = left; 1202 Definition* temp = left;
1202 left = right; 1203 left = right;
1203 right = temp; 1204 right = temp;
1204 } 1205 }
1205 BinarySmiOpInstr* bin_op = 1206 BinarySmiOpInstr* bin_op =
1206 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); 1207 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right),
1208 call->deopt_id());
1207 ReplaceCall(call, bin_op); 1209 ReplaceCall(call, bin_op);
1208 } 1210 }
1209 return true; 1211 return true;
1210 } 1212 }
1211 1213
1212 1214
1213 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 1215 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
1214 Token::Kind op_kind) { 1216 Token::Kind op_kind) {
1215 ASSERT(call->ArgumentCount() == 1); 1217 ASSERT(call->ArgumentCount() == 1);
1216 Definition* input = call->ArgumentAt(0); 1218 Definition* input = call->ArgumentAt(0);
1217 Definition* unary_op = NULL; 1219 Definition* unary_op = NULL;
1218 if (HasOnlyOneSmi(*call->ic_data())) { 1220 if (HasOnlyOneSmi(*call->ic_data())) {
1219 InsertBefore(call, 1221 InsertBefore(call,
1220 new CheckSmiInstr(new Value(input), call->deopt_id()), 1222 new CheckSmiInstr(new Value(input), call->deopt_id()),
1221 call->env(), 1223 call->env(),
1222 Definition::kEffect); 1224 Definition::kEffect);
1223 unary_op = new UnarySmiOpInstr(op_kind, call, new Value(input)); 1225 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id());
1224 } else if ((op_kind == Token::kBIT_NOT) && 1226 } else if ((op_kind == Token::kBIT_NOT) &&
1225 HasOnlySmiOrMint(*call->ic_data()) && 1227 HasOnlySmiOrMint(*call->ic_data()) &&
1226 FlowGraphCompiler::SupportsUnboxedMints()) { 1228 FlowGraphCompiler::SupportsUnboxedMints()) {
1227 unary_op = new UnaryMintOpInstr(op_kind, new Value(input), call); 1229 unary_op = new UnaryMintOpInstr(
1230 op_kind, new Value(input), call->deopt_id());
1228 } else if (HasOnlyOneDouble(*call->ic_data()) && 1231 } else if (HasOnlyOneDouble(*call->ic_data()) &&
1229 (op_kind == Token::kNEGATE)) { 1232 (op_kind == Token::kNEGATE)) {
1230 AddReceiverCheck(call); 1233 AddReceiverCheck(call);
1231 ConstantInstr* minus_one = 1234 ConstantInstr* minus_one =
1232 flow_graph()->GetConstant(Double::ZoneHandle(Double::NewCanonical(-1))); 1235 flow_graph()->GetConstant(Double::ZoneHandle(Double::NewCanonical(-1)));
1233 unary_op = new BinaryDoubleOpInstr(Token::kMUL, 1236 unary_op = new BinaryDoubleOpInstr(Token::kMUL,
1234 new Value(input), 1237 new Value(input),
1235 new Value(minus_one), 1238 new Value(minus_one),
1236 call); 1239 call->deopt_id());
1237 } 1240 }
1238 if (unary_op == NULL) return false; 1241 if (unary_op == NULL) return false;
1239 1242
1240 ReplaceCall(call, unary_op); 1243 ReplaceCall(call, unary_op);
1241 return true; 1244 return true;
1242 } 1245 }
1243 1246
1244 1247
1245 // Using field class 1248 // Using field class
1246 static RawField* GetField(intptr_t class_id, const String& field_name) { 1249 static RawField* GetField(intptr_t class_id, const String& field_name) {
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 skip_check = constant_index.IsSmi() && 1611 skip_check = constant_index.IsSmi() &&
1609 (Smi::Cast(constant_index).Value() < constant_string.Length()); 1612 (Smi::Cast(constant_index).Value() < constant_string.Length());
1610 } 1613 }
1611 if (!skip_check) { 1614 if (!skip_check) {
1612 // Insert bounds check. 1615 // Insert bounds check.
1613 LoadFieldInstr* length = BuildLoadStringLength(str); 1616 LoadFieldInstr* length = BuildLoadStringLength(str);
1614 InsertBefore(call, length, NULL, Definition::kValue); 1617 InsertBefore(call, length, NULL, Definition::kValue);
1615 InsertBefore(call, 1618 InsertBefore(call,
1616 new CheckArrayBoundInstr(new Value(length), 1619 new CheckArrayBoundInstr(new Value(length),
1617 new Value(index), 1620 new Value(index),
1618 call), 1621 call->deopt_id()),
1619 call->env(), 1622 call->env(),
1620 Definition::kEffect); 1623 Definition::kEffect);
1621 } 1624 }
1622 return new LoadIndexedInstr(new Value(str), 1625 return new LoadIndexedInstr(new Value(str),
1623 new Value(index), 1626 new Value(index),
1624 FlowGraphCompiler::ElementSizeFor(cid), 1627 FlowGraphCompiler::ElementSizeFor(cid),
1625 cid, 1628 cid,
1626 Isolate::kNoDeoptId); // Can't deoptimize. 1629 Isolate::kNoDeoptId); // Can't deoptimize.
1627 } 1630 }
1628 1631
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1763 AddReceiverCheck(call); 1766 AddReceiverCheck(call);
1764 ASSERT(call->HasICData()); 1767 ASSERT(call->HasICData());
1765 const ICData& ic_data = *call->ic_data(); 1768 const ICData& ic_data = *call->ic_data();
1766 Definition* input = call->ArgumentAt(0); 1769 Definition* input = call->ArgumentAt(0);
1767 Definition* d2i_instr = NULL; 1770 Definition* d2i_instr = NULL;
1768 if (ic_data.deopt_reason() == kDeoptDoubleToSmi) { 1771 if (ic_data.deopt_reason() == kDeoptDoubleToSmi) {
1769 // Do not repeatedly deoptimize because result didn't fit into Smi. 1772 // Do not repeatedly deoptimize because result didn't fit into Smi.
1770 d2i_instr = new DoubleToIntegerInstr(new Value(input), call); 1773 d2i_instr = new DoubleToIntegerInstr(new Value(input), call);
1771 } else { 1774 } else {
1772 // Optimistically assume result fits into Smi. 1775 // Optimistically assume result fits into Smi.
1773 d2i_instr = new DoubleToSmiInstr(new Value(input), call); 1776 d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id());
1774 } 1777 }
1775 ReplaceCall(call, d2i_instr); 1778 ReplaceCall(call, d2i_instr);
1776 return true; 1779 return true;
1777 } 1780 }
1778 case MethodRecognizer::kDoubleMod: 1781 case MethodRecognizer::kDoubleMod:
1779 case MethodRecognizer::kDoublePow: 1782 case MethodRecognizer::kDoublePow:
1780 case MethodRecognizer::kDoubleRound: 1783 case MethodRecognizer::kDoubleRound:
1781 ReplaceWithMathCFunction(call, recognized_kind); 1784 ReplaceWithMathCFunction(call, recognized_kind);
1782 return true; 1785 return true;
1783 case MethodRecognizer::kDoubleTruncate: 1786 case MethodRecognizer::kDoubleTruncate:
1784 case MethodRecognizer::kDoubleFloor: 1787 case MethodRecognizer::kDoubleFloor:
1785 case MethodRecognizer::kDoubleCeil: 1788 case MethodRecognizer::kDoubleCeil:
1786 if (!CPUFeatures::double_truncate_round_supported()) { 1789 if (!CPUFeatures::double_truncate_round_supported()) {
1787 ReplaceWithMathCFunction(call, recognized_kind); 1790 ReplaceWithMathCFunction(call, recognized_kind);
1788 } else { 1791 } else {
1789 AddReceiverCheck(call); 1792 AddReceiverCheck(call);
1790 DoubleToDoubleInstr* d2d_instr = 1793 DoubleToDoubleInstr* d2d_instr =
1791 new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)), 1794 new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)),
1792 call, 1795 recognized_kind, call->deopt_id());
1793 recognized_kind);
1794 ReplaceCall(call, d2d_instr); 1796 ReplaceCall(call, d2d_instr);
1795 } 1797 }
1796 return true; 1798 return true;
1797 default: 1799 default:
1798 // Unsupported method. 1800 // Unsupported method.
1799 return false; 1801 return false;
1800 } 1802 }
1801 } 1803 }
1802 1804
1803 if (IsSupportedByteArrayViewCid(class_ids[0]) && 1805 if (IsSupportedByteArrayViewCid(class_ids[0]) &&
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 length->set_recognized_kind( 2234 length->set_recognized_kind(
2233 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid)); 2235 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid));
2234 InsertBefore(call, length, NULL, Definition::kValue); 2236 InsertBefore(call, length, NULL, Definition::kValue);
2235 2237
2236 // len_in_bytes = length * kBytesPerElement(receiver) 2238 // len_in_bytes = length * kBytesPerElement(receiver)
2237 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); 2239 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
2238 ConstantInstr* bytes_per_element = 2240 ConstantInstr* bytes_per_element =
2239 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); 2241 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
2240 BinarySmiOpInstr* len_in_bytes = 2242 BinarySmiOpInstr* len_in_bytes =
2241 new BinarySmiOpInstr(Token::kMUL, 2243 new BinarySmiOpInstr(Token::kMUL,
2242 call,
2243 new Value(length), 2244 new Value(length),
2244 new Value(bytes_per_element)); 2245 new Value(bytes_per_element),
2246 call->deopt_id());
2245 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); 2247 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue);
2246 2248
2247 // Check byte_index < len_in_bytes. 2249 // Check byte_index < len_in_bytes.
2248 InsertBefore(call, 2250 InsertBefore(call,
2249 new CheckArrayBoundInstr(new Value(len_in_bytes), 2251 new CheckArrayBoundInstr(new Value(len_in_bytes),
2250 new Value(byte_index), 2252 new Value(byte_index),
2251 call), 2253 call->deopt_id()),
2252 call->env(), 2254 call->env(),
2253 Definition::kEffect); 2255 Definition::kEffect);
2254 2256
2255 // Insert load of elements for external typed arrays. 2257 // Insert load of elements for external typed arrays.
2256 if (RawObject::IsExternalTypedDataClassId(receiver_cid)) { 2258 if (RawObject::IsExternalTypedDataClassId(receiver_cid)) {
2257 LoadUntaggedInstr* elements = 2259 LoadUntaggedInstr* elements =
2258 new LoadUntaggedInstr(new Value(*array), 2260 new LoadUntaggedInstr(new Value(*array),
2259 ExternalTypedData::data_offset()); 2261 ExternalTypedData::data_offset());
2260 InsertBefore(call, elements, NULL, Definition::kValue); 2262 InsertBefore(call, elements, NULL, Definition::kValue);
2261 *array = elements; 2263 *array = elements;
(...skipping 4922 matching lines...) Expand 10 before | Expand all | Expand 10 after
7184 7186
7185 // Insert materializations at environment uses. 7187 // Insert materializations at environment uses.
7186 const Class& cls = Class::Handle(alloc->constructor().Owner()); 7188 const Class& cls = Class::Handle(alloc->constructor().Owner());
7187 for (intptr_t i = 0; i < exits.length(); i++) { 7189 for (intptr_t i = 0; i < exits.length(); i++) {
7188 CreateMaterializationAt(exits[i], alloc, cls, *fields); 7190 CreateMaterializationAt(exits[i], alloc, cls, *fields);
7189 } 7191 }
7190 } 7192 }
7191 7193
7192 7194
7193 } // namespace dart 7195 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698