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

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

Issue 14846022: Use the constant pool for all constants, not just null. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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/intermediate_language.h ('k') | no next file » | 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 } 1046 }
1047 break; 1047 break;
1048 default: 1048 default:
1049 break; 1049 break;
1050 } 1050 }
1051 1051
1052 return NULL; 1052 return NULL;
1053 } 1053 }
1054 1054
1055 1055
1056 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1056 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) {
1057 Definition* result = NULL; 1057 Definition* result = NULL;
1058 1058
1059 result = CanonicalizeCommutativeArithmetic(op_kind(), 1059 result = CanonicalizeCommutativeArithmetic(op_kind(),
1060 kDoubleCid, 1060 kDoubleCid,
1061 left(), 1061 left(),
1062 right()); 1062 right());
1063 if (result != NULL) { 1063 if (result != NULL) {
1064 return result; 1064 return result;
1065 } 1065 }
1066 1066
1067 result = CanonicalizeCommutativeArithmetic(op_kind(), 1067 result = CanonicalizeCommutativeArithmetic(op_kind(),
1068 kDoubleCid, 1068 kDoubleCid,
1069 right(), 1069 right(),
1070 left()); 1070 left());
1071 if (result != NULL) { 1071 if (result != NULL) {
1072 return result; 1072 return result;
1073 } 1073 }
1074 1074
1075 return this; 1075 return this;
1076 } 1076 }
1077 1077
1078 1078
1079 Definition* BinarySmiOpInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1079 Definition* BinarySmiOpInstr::Canonicalize(FlowGraph* flow_graph) {
1080 Definition* result = NULL; 1080 Definition* result = NULL;
1081 1081
1082 result = CanonicalizeCommutativeArithmetic(op_kind(), 1082 result = CanonicalizeCommutativeArithmetic(op_kind(),
1083 kSmiCid, 1083 kSmiCid,
1084 left(), 1084 left(),
1085 right()); 1085 right());
1086 if (result != NULL) { 1086 if (result != NULL) {
1087 return result; 1087 return result;
1088 } 1088 }
1089 1089
1090 result = CanonicalizeCommutativeArithmetic(op_kind(), 1090 result = CanonicalizeCommutativeArithmetic(op_kind(),
1091 kSmiCid, 1091 kSmiCid,
1092 right(), 1092 right(),
1093 left()); 1093 left());
1094 if (result != NULL) { 1094 if (result != NULL) {
1095 return result; 1095 return result;
1096 } 1096 }
1097 1097
1098 return this; 1098 return this;
1099 } 1099 }
1100 1100
1101 1101
1102 Definition* BinaryMintOpInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1102 Definition* BinaryMintOpInstr::Canonicalize(FlowGraph* flow_graph) {
1103 Definition* result = NULL; 1103 Definition* result = NULL;
1104 1104
1105 result = CanonicalizeCommutativeArithmetic(op_kind(), 1105 result = CanonicalizeCommutativeArithmetic(op_kind(),
1106 kMintCid, 1106 kMintCid,
1107 left(), 1107 left(),
1108 right()); 1108 right());
1109 if (result != NULL) { 1109 if (result != NULL) {
1110 return result; 1110 return result;
1111 } 1111 }
1112 1112
1113 result = CanonicalizeCommutativeArithmetic(op_kind(), 1113 result = CanonicalizeCommutativeArithmetic(op_kind(),
1114 kMintCid, 1114 kMintCid,
1115 right(), 1115 right(),
1116 left()); 1116 left());
1117 if (result != NULL) { 1117 if (result != NULL) {
1118 return result; 1118 return result;
1119 } 1119 }
1120 1120
1121 return this; 1121 return this;
1122 } 1122 }
1123 1123
1124 1124
1125 // Optimizations that eliminate or simplify individual instructions. 1125 // Optimizations that eliminate or simplify individual instructions.
1126 Instruction* Instruction::Canonicalize(FlowGraphOptimizer* optimizer) { 1126 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) {
1127 return this; 1127 return this;
1128 } 1128 }
1129 1129
1130 1130
1131 Definition* Definition::Canonicalize(FlowGraphOptimizer* optimizer) { 1131 Definition* Definition::Canonicalize(FlowGraph* flow_graph) {
1132 return this; 1132 return this;
1133 } 1133 }
1134 1134
1135 1135
1136 bool LoadFieldInstr::IsImmutableLengthLoad() const { 1136 bool LoadFieldInstr::IsImmutableLengthLoad() const {
1137 switch (recognized_kind()) { 1137 switch (recognized_kind()) {
1138 case MethodRecognizer::kObjectArrayLength: 1138 case MethodRecognizer::kObjectArrayLength:
1139 case MethodRecognizer::kImmutableArrayLength: 1139 case MethodRecognizer::kImmutableArrayLength:
1140 case MethodRecognizer::kTypedDataLength: 1140 case MethodRecognizer::kTypedDataLength:
1141 case MethodRecognizer::kStringBaseLength: 1141 case MethodRecognizer::kStringBaseLength:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 case kTypedDataFloat32ArrayCid: 1182 case kTypedDataFloat32ArrayCid:
1183 case kTypedDataFloat64ArrayCid: 1183 case kTypedDataFloat64ArrayCid:
1184 case kTypedDataFloat32x4ArrayCid: 1184 case kTypedDataFloat32x4ArrayCid:
1185 return true; 1185 return true;
1186 default: 1186 default:
1187 return false; 1187 return false;
1188 } 1188 }
1189 } 1189 }
1190 1190
1191 1191
1192 Definition* ConstantInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1192 Definition* ConstantInstr::Canonicalize(FlowGraph* flow_graph) {
1193 return HasUses() ? this : NULL; 1193 return HasUses() ? this : NULL;
1194 } 1194 }
1195 1195
1196 1196
1197 Definition* LoadFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1197 Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
1198 if (!IsImmutableLengthLoad()) return this; 1198 if (!IsImmutableLengthLoad()) return this;
1199 1199
1200 // For fixed length arrays if the array is the result of a known constructor 1200 // For fixed length arrays if the array is the result of a known constructor
1201 // call we can replace the length load with the length argument passed to 1201 // call we can replace the length load with the length argument passed to
1202 // the constructor. 1202 // the constructor.
1203 StaticCallInstr* call = instance()->definition()->AsStaticCall(); 1203 StaticCallInstr* call = instance()->definition()->AsStaticCall();
1204 if ((call != NULL) && 1204 if ((call != NULL) &&
1205 call->is_known_list_constructor() && 1205 call->is_known_list_constructor() &&
1206 IsFixedLengthArrayCid(call->Type()->ToCid())) { 1206 IsFixedLengthArrayCid(call->Type()->ToCid())) {
1207 return call->ArgumentAt(1); 1207 return call->ArgumentAt(1);
1208 } 1208 }
1209 return this; 1209 return this;
1210 } 1210 }
1211 1211
1212 1212
1213 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1213 Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) {
1214 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) { 1214 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) {
1215 return value()->definition(); 1215 return value()->definition();
1216 } 1216 }
1217 1217
1218 return this; 1218 return this;
1219 } 1219 }
1220 1220
1221 1221
1222 Definition* AssertAssignableInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1222 Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
1223 if (FLAG_eliminate_type_checks && 1223 if (FLAG_eliminate_type_checks &&
1224 value()->Type()->IsAssignableTo(dst_type())) { 1224 value()->Type()->IsAssignableTo(dst_type())) {
1225 return value()->definition(); 1225 return value()->definition();
1226 } 1226 }
1227 1227
1228 // For uninstantiated target types: If the instantiator type arguments 1228 // For uninstantiated target types: If the instantiator type arguments
1229 // are constant, instantiate the target type here. 1229 // are constant, instantiate the target type here.
1230 if (dst_type().IsInstantiated()) return this; 1230 if (dst_type().IsInstantiated()) return this;
1231 1231
1232 ConstantInstr* constant_type_args = 1232 ConstantInstr* constant_type_args =
1233 instantiator_type_arguments()->definition()->AsConstant(); 1233 instantiator_type_arguments()->definition()->AsConstant();
1234 if (constant_type_args != NULL && 1234 if (constant_type_args != NULL &&
1235 !constant_type_args->value().IsNull() && 1235 !constant_type_args->value().IsNull() &&
1236 constant_type_args->value().IsTypeArguments()) { 1236 constant_type_args->value().IsTypeArguments()) {
1237 const TypeArguments& instantiator_type_args = 1237 const TypeArguments& instantiator_type_args =
1238 TypeArguments::Cast(constant_type_args->value()); 1238 TypeArguments::Cast(constant_type_args->value());
1239 const AbstractType& new_dst_type = AbstractType::Handle( 1239 const AbstractType& new_dst_type = AbstractType::Handle(
1240 dst_type().InstantiateFrom(instantiator_type_args, NULL)); 1240 dst_type().InstantiateFrom(instantiator_type_args, NULL));
1241 set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize())); 1241 set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize()));
1242 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); 1242 ConstantInstr* null_constant = flow_graph->constant_null();
1243 // It is ok to insert instructions before the current during
1244 // forward iteration.
1245 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue);
1246 instantiator_type_arguments()->BindTo(null_constant); 1243 instantiator_type_arguments()->BindTo(null_constant);
1247 } 1244 }
1248 return this; 1245 return this;
1249 } 1246 }
1250 1247
1251 1248
1252 Definition* BoxDoubleInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1249 Definition* BoxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
1253 if (input_use_list() == NULL) { 1250 if (input_use_list() == NULL) {
1254 // Environments can accomodate any representation. No need to box. 1251 // Environments can accomodate any representation. No need to box.
1255 return value()->definition(); 1252 return value()->definition();
1256 } 1253 }
1257 1254
1258 // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double. 1255 // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double.
1259 UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble(); 1256 UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble();
1260 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) { 1257 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) {
1261 return defn->value()->definition(); 1258 return defn->value()->definition();
1262 } 1259 }
1263 1260
1264 return this; 1261 return this;
1265 } 1262 }
1266 1263
1267 1264
1268 Definition* UnboxDoubleInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1265 Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
1269 // Fold away UnboxDouble(BoxDouble(v)). 1266 // Fold away UnboxDouble(BoxDouble(v)).
1270 BoxDoubleInstr* defn = value()->definition()->AsBoxDouble(); 1267 BoxDoubleInstr* defn = value()->definition()->AsBoxDouble();
1271 return (defn != NULL) ? defn->value()->definition() : this; 1268 return (defn != NULL) ? defn->value()->definition() : this;
1272 } 1269 }
1273 1270
1274 1271
1275 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1272 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) {
1276 // Only handle strict-compares. 1273 // Only handle strict-compares.
1277 if (comparison()->IsStrictCompare()) { 1274 if (comparison()->IsStrictCompare()) {
1278 Definition* replacement = comparison()->Canonicalize(optimizer); 1275 Definition* replacement = comparison()->Canonicalize(flow_graph);
1279 if ((replacement == comparison()) || (replacement == NULL)) { 1276 if ((replacement == comparison()) || (replacement == NULL)) {
1280 return this; 1277 return this;
1281 } 1278 }
1282 ComparisonInstr* comp = replacement->AsComparison(); 1279 ComparisonInstr* comp = replacement->AsComparison();
1283 if ((comp == NULL) || comp->CanDeoptimize()) { 1280 if ((comp == NULL) || comp->CanDeoptimize()) {
1284 return this; 1281 return this;
1285 } 1282 }
1286 1283
1287 // Check that comparison is not serving as a pending deoptimization target 1284 // Check that comparison is not serving as a pending deoptimization target
1288 // for conversions. 1285 // for conversions.
(...skipping 20 matching lines...) Expand all
1309 // value of the comparison is not used outside the branch anymore. 1306 // value of the comparison is not used outside the branch anymore.
1310 ASSERT(comp->input_use_list() == NULL); 1307 ASSERT(comp->input_use_list() == NULL);
1311 comp->ClearSSATempIndex(); 1308 comp->ClearSSATempIndex();
1312 comp->ClearTempIndex(); 1309 comp->ClearTempIndex();
1313 } 1310 }
1314 } 1311 }
1315 return this; 1312 return this;
1316 } 1313 }
1317 1314
1318 1315
1319 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1316 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
1320 if (!right()->BindsToConstant()) { 1317 if (!right()->BindsToConstant()) {
1321 return this; 1318 return this;
1322 } 1319 }
1323 const Object& right_constant = right()->BoundConstant(); 1320 const Object& right_constant = right()->BoundConstant();
1324 Definition* left_defn = left()->definition(); 1321 Definition* left_defn = left()->definition();
1325 // TODO(fschneider): Handle other cases: e === false and e !== true/false. 1322 // TODO(fschneider): Handle other cases: e === false and e !== true/false.
1326 // Handles e === true. 1323 // Handles e === true.
1327 if ((kind() == Token::kEQ_STRICT) && 1324 if ((kind() == Token::kEQ_STRICT) &&
1328 (right_constant.raw() == Bool::True().raw()) && 1325 (right_constant.raw() == Bool::True().raw()) &&
1329 (left()->Type()->ToCid() == kBoolCid)) { 1326 (left()->Type()->ToCid() == kBoolCid)) {
1330 // Return left subexpression as the replacement for this instruction. 1327 // Return left subexpression as the replacement for this instruction.
1331 return left_defn; 1328 return left_defn;
1332 } 1329 }
1333 // x = (a === b); y = x !== true; -> y = a !== b. 1330 // x = (a === b); y = x !== true; -> y = a !== b.
1334 // In order to merge two strict comares, 'left_strict' must have only one use. 1331 // In order to merge two strict comares, 'left_strict' must have only one use.
1335 // Do not check left's cid as it is required to be a strict compare. 1332 // Do not check left's cid as it is required to be a strict compare.
1336 StrictCompareInstr* left_strict = left_defn->AsStrictCompare(); 1333 StrictCompareInstr* left_strict = left_defn->AsStrictCompare();
1337 if ((kind() == Token::kNE_STRICT) && 1334 if ((kind() == Token::kNE_STRICT) &&
1338 (right_constant.raw() == Bool::True().raw()) && 1335 (right_constant.raw() == Bool::True().raw()) &&
1339 (left_strict != NULL) && 1336 (left_strict != NULL) &&
1340 (left_strict->HasOnlyUse(left()))) { 1337 (left_strict->HasOnlyUse(left()))) {
1341 left_strict->set_kind(Token::NegateComparison(left_strict->kind())); 1338 left_strict->set_kind(Token::NegateComparison(left_strict->kind()));
1342 return left_strict; 1339 return left_strict;
1343 } 1340 }
1344 1341
1345 return this; 1342 return this;
1346 } 1343 }
1347 1344
1348 1345
1349 Instruction* CheckClassInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1346 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
1350 // TODO(vegorov): Replace class checks with null checks when ToNullableCid 1347 // TODO(vegorov): Replace class checks with null checks when ToNullableCid
1351 // matches. 1348 // matches.
1352 1349
1353 const intptr_t value_cid = value()->Type()->ToCid(); 1350 const intptr_t value_cid = value()->Type()->ToCid();
1354 if (value_cid == kDynamicCid) { 1351 if (value_cid == kDynamicCid) {
1355 return this; 1352 return this;
1356 } 1353 }
1357 1354
1358 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; 1355 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this;
1359 } 1356 }
1360 1357
1361 1358
1362 Instruction* GuardFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1359 Instruction* GuardFieldInstr::Canonicalize(FlowGraph* flow_graph) {
1363 if (field().guarded_cid() == kDynamicCid) { 1360 if (field().guarded_cid() == kDynamicCid) {
1364 return NULL; // Nothing to guard. 1361 return NULL; // Nothing to guard.
1365 } 1362 }
1366 1363
1367 if (field().is_nullable() && value()->Type()->IsNull()) { 1364 if (field().is_nullable() && value()->Type()->IsNull()) {
1368 return NULL; 1365 return NULL;
1369 } 1366 }
1370 1367
1371 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() 1368 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid()
1372 : value()->Type()->ToCid(); 1369 : value()->Type()->ToCid();
1373 if (field().guarded_cid() == cid) { 1370 if (field().guarded_cid() == cid) {
1374 return NULL; // Value is guaranteed to have this cid. 1371 return NULL; // Value is guaranteed to have this cid.
1375 } 1372 }
1376 1373
1377 return this; 1374 return this;
1378 } 1375 }
1379 1376
1380 1377
1381 Instruction* CheckSmiInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1378 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) {
1382 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this; 1379 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this;
1383 } 1380 }
1384 1381
1385 1382
1386 Instruction* CheckEitherNonSmiInstr::Canonicalize( 1383 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) {
1387 FlowGraphOptimizer* optimizer) {
1388 if ((left()->Type()->ToCid() == kDoubleCid) || 1384 if ((left()->Type()->ToCid() == kDoubleCid) ||
1389 (right()->Type()->ToCid() == kDoubleCid)) { 1385 (right()->Type()->ToCid() == kDoubleCid)) {
1390 return NULL; // Remove from the graph. 1386 return NULL; // Remove from the graph.
1391 } 1387 }
1392 return this; 1388 return this;
1393 } 1389 }
1394 1390
1395 1391
1396 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and 1392 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and
1397 // PrepareEntry). Only assembly code that can be shared across all architectures 1393 // PrepareEntry). Only assembly code that can be shared across all architectures
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 default: 2427 default:
2432 UNREACHABLE(); 2428 UNREACHABLE();
2433 } 2429 }
2434 return kPowRuntimeEntry; 2430 return kPowRuntimeEntry;
2435 } 2431 }
2436 2432
2437 2433
2438 #undef __ 2434 #undef __
2439 2435
2440 } // namespace dart 2436 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698