OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 ? Type::IntInterface() | 995 ? Type::IntInterface() |
996 : object_store->smi_type(); | 996 : object_store->smi_type(); |
997 } | 997 } |
998 | 998 |
999 | 999 |
1000 intptr_t BinarySmiOpComp::ResultCid() const { | 1000 intptr_t BinarySmiOpComp::ResultCid() const { |
1001 return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid; | 1001 return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid; |
1002 } | 1002 } |
1003 | 1003 |
1004 | 1004 |
| 1005 bool BinarySmiOpComp::CanDeoptimize() const { |
| 1006 switch (op_kind()) { |
| 1007 case Token::kBIT_AND: |
| 1008 case Token::kBIT_OR: |
| 1009 case Token::kBIT_XOR: |
| 1010 return false; |
| 1011 default: |
| 1012 return true; |
| 1013 } |
| 1014 } |
| 1015 |
| 1016 |
1005 RawAbstractType* BinaryMintOpComp::CompileType() const { | 1017 RawAbstractType* BinaryMintOpComp::CompileType() const { |
1006 ObjectStore* object_store = Isolate::Current()->object_store(); | 1018 ObjectStore* object_store = Isolate::Current()->object_store(); |
1007 return object_store->mint_type(); | 1019 return object_store->mint_type(); |
1008 } | 1020 } |
1009 | 1021 |
1010 | 1022 |
1011 intptr_t BinaryMintOpComp::ResultCid() const { | 1023 intptr_t BinaryMintOpComp::ResultCid() const { |
1012 return kMintCid; | 1024 return kMintCid; |
1013 } | 1025 } |
1014 | 1026 |
(...skipping 27 matching lines...) Expand all Loading... |
1042 RawAbstractType* SmiToDoubleComp::CompileType() const { | 1054 RawAbstractType* SmiToDoubleComp::CompileType() const { |
1043 return Type::DoubleInterface(); | 1055 return Type::DoubleInterface(); |
1044 } | 1056 } |
1045 | 1057 |
1046 | 1058 |
1047 RawAbstractType* CheckClassComp::CompileType() const { | 1059 RawAbstractType* CheckClassComp::CompileType() const { |
1048 return AbstractType::null(); | 1060 return AbstractType::null(); |
1049 } | 1061 } |
1050 | 1062 |
1051 | 1063 |
| 1064 RawAbstractType* CheckSmiComp::CompileType() const { |
| 1065 return AbstractType::null(); |
| 1066 } |
| 1067 |
| 1068 |
| 1069 // Optimizations that eliminate or simplify individual computations. |
| 1070 Definition* Computation::TryReplace(BindInstr* instr) const { |
| 1071 return instr; |
| 1072 } |
| 1073 |
| 1074 |
| 1075 Definition* StrictCompareComp::TryReplace(BindInstr* instr) const { |
| 1076 UseVal* left_use = left()->AsUse(); |
| 1077 UseVal* right_use = right()->AsUse(); |
| 1078 if ((right_use == NULL) || (left_use == NULL)) return instr; |
| 1079 if (!right_use->BindsToConstant()) return instr; |
| 1080 const Object& right_constant = right_use->BoundConstant(); |
| 1081 Definition* left = left_use->definition(); |
| 1082 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1083 // Handles e === true. |
| 1084 if ((kind() == Token::kEQ_STRICT) && |
| 1085 (right_constant.raw() == Bool::True()) && |
| 1086 (left_use->ResultCid() == kBoolCid)) { |
| 1087 // Remove the constant from the graph. |
| 1088 BindInstr* right = right_use->definition()->AsBind(); |
| 1089 if (right != NULL) { |
| 1090 right->set_use_list(NULL); |
| 1091 right->RemoveFromGraph(); |
| 1092 } |
| 1093 // Return left subexpression as the replacement for this instruction. |
| 1094 return left; |
| 1095 } |
| 1096 return instr; |
| 1097 } |
| 1098 |
| 1099 |
| 1100 Definition* CheckSmiComp::TryReplace(BindInstr* instr) const { |
| 1101 return (value()->ResultCid() == kSmiCid) ? NULL : instr; |
| 1102 } |
| 1103 |
| 1104 |
1052 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and | 1105 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and |
1053 // PrepareEntry). Only assembly code that can be shared across all architectures | 1106 // PrepareEntry). Only assembly code that can be shared across all architectures |
1054 // can be used. Machine specific register allocation and code generation | 1107 // can be used. Machine specific register allocation and code generation |
1055 // is located in intermediate_language_<arch>.cc | 1108 // is located in intermediate_language_<arch>.cc |
1056 | 1109 |
1057 | |
1058 // True iff. the arguments to a call will be properly pushed and can | |
1059 // be popped after the call. | |
1060 template <typename T> static bool VerifyCallComputation(T* comp) { | |
1061 // Argument values should be consecutive temps. | |
1062 // | |
1063 // TODO(kmillikin): implement stack height tracking so we can also assert | |
1064 // they are on top of the stack. | |
1065 intptr_t previous = -1; | |
1066 for (int i = 0; i < comp->ArgumentCount(); ++i) { | |
1067 Value* val = comp->ArgumentAt(i); | |
1068 if (!val->IsUse()) return false; | |
1069 intptr_t current = val->AsUse()->definition()->temp_index(); | |
1070 if (i != 0) { | |
1071 if (current != (previous + 1)) return false; | |
1072 } | |
1073 previous = current; | |
1074 } | |
1075 return true; | |
1076 } | |
1077 | |
1078 | |
1079 #define __ compiler->assembler()-> | 1110 #define __ compiler->assembler()-> |
1080 | 1111 |
1081 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | 1112 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
1082 // Nothing to do. | 1113 // Nothing to do. |
1083 } | 1114 } |
1084 | 1115 |
1085 | 1116 |
1086 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | 1117 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
1087 __ Bind(compiler->GetBlockLabel(this)); | 1118 __ Bind(compiler->GetBlockLabel(this)); |
1088 if (HasParallelMove()) { | 1119 if (HasParallelMove()) { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 return summary; | 1274 return summary; |
1244 } | 1275 } |
1245 | 1276 |
1246 | 1277 |
1247 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1278 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1248 // Nothing to do. Context register were loaded by register allocator. | 1279 // Nothing to do. Context register were loaded by register allocator. |
1249 ASSERT(locs()->in(0).reg() == CTX); | 1280 ASSERT(locs()->in(0).reg() == CTX); |
1250 } | 1281 } |
1251 | 1282 |
1252 | 1283 |
1253 Definition* StrictCompareComp::TryReplace(BindInstr* instr) { | |
1254 UseVal* left_use = left()->AsUse(); | |
1255 UseVal* right_use = right()->AsUse(); | |
1256 if ((right_use == NULL) || (left_use == NULL)) return NULL; | |
1257 if (!right_use->BindsToConstant()) return NULL; | |
1258 const Object& right_constant = right_use->BoundConstant(); | |
1259 Definition* left = left_use->definition(); | |
1260 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | |
1261 // Handles e === true. | |
1262 if ((kind() == Token::kEQ_STRICT) && | |
1263 (right_constant.raw() == Bool::True()) && | |
1264 (left_use->ResultCid() == kBoolCid)) { | |
1265 // Remove the constant from the graph. | |
1266 BindInstr* right = right_use->definition()->AsBind(); | |
1267 if (right != NULL) { | |
1268 right->set_use_list(NULL); | |
1269 right->RemoveFromGraph(); | |
1270 } | |
1271 // Return left subexpression as the replacement for this instruction. | |
1272 return left; | |
1273 } | |
1274 return NULL; | |
1275 } | |
1276 | |
1277 | |
1278 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | 1284 LocationSummary* StrictCompareComp::MakeLocationSummary() const { |
1279 return LocationSummary::Make(2, | 1285 return LocationSummary::Make(2, |
1280 Location::SameAsFirstInput(), | 1286 Location::SameAsFirstInput(), |
1281 LocationSummary::kNoCall); | 1287 LocationSummary::kNoCall); |
1282 } | 1288 } |
1283 | 1289 |
1284 | 1290 |
1285 void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1291 void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1286 Register left = locs()->in(0).reg(); | 1292 Register left = locs()->in(0).reg(); |
1287 Register right = locs()->in(1).reg(); | 1293 Register right = locs()->in(1).reg(); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 intptr_t fixed_parameter_count) | 1529 intptr_t fixed_parameter_count) |
1524 : values_(definitions.length()), | 1530 : values_(definitions.length()), |
1525 locations_(NULL), | 1531 locations_(NULL), |
1526 fixed_parameter_count_(fixed_parameter_count) { | 1532 fixed_parameter_count_(fixed_parameter_count) { |
1527 for (intptr_t i = 0; i < definitions.length(); ++i) { | 1533 for (intptr_t i = 0; i < definitions.length(); ++i) { |
1528 values_.Add(UseDefinition(definitions[i])); | 1534 values_.Add(UseDefinition(definitions[i])); |
1529 } | 1535 } |
1530 } | 1536 } |
1531 | 1537 |
1532 | 1538 |
| 1539 Environment* Environment::Copy() const { |
| 1540 Environment* copy = new Environment(values().length(), |
| 1541 fixed_parameter_count()); |
| 1542 GrowableArray<Value*>* values_copy = copy->values_ptr(); |
| 1543 for (intptr_t i = 0; i < values().length(); ++i) { |
| 1544 Value* val = values()[i]; |
| 1545 values_copy->Add(val->IsUse() |
| 1546 ? UseDefinition(values()[i]->AsUse()->definition()) |
| 1547 : val); |
| 1548 } |
| 1549 return copy; |
| 1550 } |
| 1551 |
| 1552 |
1533 #undef __ | 1553 #undef __ |
1534 | 1554 |
1535 } // namespace dart | 1555 } // namespace dart |
OLD | NEW |