| OLD | NEW |
| 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 #ifndef DART_PRECOMPILED_RUNTIME | 4 #ifndef DART_PRECOMPILED_RUNTIME |
| 5 #include "vm/jit_optimizer.h" | 5 #include "vm/jit_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| 11 #include "vm/cpu.h" | 11 #include "vm/cpu.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/exceptions.h" | 13 #include "vm/exceptions.h" |
| 14 #include "vm/flow_graph_builder.h" | 14 #include "vm/flow_graph_builder.h" |
| 15 #include "vm/flow_graph_compiler.h" | 15 #include "vm/flow_graph_compiler.h" |
| 16 #include "vm/flow_graph_inliner.h" | 16 #include "vm/flow_graph_inliner.h" |
| 17 #include "vm/flow_graph_range_analysis.h" | 17 #include "vm/flow_graph_range_analysis.h" |
| 18 #include "vm/hash_map.h" | 18 #include "vm/hash_map.h" |
| 19 #include "vm/il_printer.h" | 19 #include "vm/il_printer.h" |
| 20 #include "vm/intermediate_language.h" | 20 #include "vm/intermediate_language.h" |
| 21 #include "vm/object_store.h" | 21 #include "vm/object_store.h" |
| 22 #include "vm/optimizer.h" |
| 22 #include "vm/parser.h" | 23 #include "vm/parser.h" |
| 23 #include "vm/resolver.h" | 24 #include "vm/resolver.h" |
| 24 #include "vm/scopes.h" | 25 #include "vm/scopes.h" |
| 25 #include "vm/stack_frame.h" | 26 #include "vm/stack_frame.h" |
| 26 #include "vm/symbols.h" | 27 #include "vm/symbols.h" |
| 27 | 28 |
| 28 namespace dart { | 29 namespace dart { |
| 29 | 30 |
| 30 // Quick access to the current isolate and zone. | 31 // Quick access to the current isolate and zone. |
| 31 #define I (isolate()) | 32 #define I (isolate()) |
| (...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1234 const TypeArguments& type_arguments = | 1235 const TypeArguments& type_arguments = |
| 1235 TypeArguments::Handle(type.arguments()); | 1236 TypeArguments::Handle(type.arguments()); |
| 1236 const bool is_raw_type = type_arguments.IsNull() || | 1237 const bool is_raw_type = type_arguments.IsNull() || |
| 1237 type_arguments.IsRaw(from_index, num_type_params); | 1238 type_arguments.IsRaw(from_index, num_type_params); |
| 1238 return is_raw_type; | 1239 return is_raw_type; |
| 1239 } | 1240 } |
| 1240 return true; | 1241 return true; |
| 1241 } | 1242 } |
| 1242 | 1243 |
| 1243 | 1244 |
| 1244 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results, | |
| 1245 intptr_t test_cid) { | |
| 1246 for (intptr_t i = 0; i < results.length(); i += 2) { | |
| 1247 if (results[i] == test_cid) return true; | |
| 1248 } | |
| 1249 return false; | |
| 1250 } | |
| 1251 | |
| 1252 | |
| 1253 static void TryAddTest(ZoneGrowableArray<intptr_t>* results, | |
| 1254 intptr_t test_cid, | |
| 1255 bool result) { | |
| 1256 if (!CidTestResultsContains(*results, test_cid)) { | |
| 1257 results->Add(test_cid); | |
| 1258 results->Add(result); | |
| 1259 } | |
| 1260 } | |
| 1261 | |
| 1262 | |
| 1263 // Tries to add cid tests to 'results' so that no deoptimization is | |
| 1264 // necessary. | |
| 1265 // TODO(srdjan): Do also for other than 'int' type. | |
| 1266 static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results, | |
| 1267 const AbstractType& type) { | |
| 1268 ASSERT(results->length() >= 2); // At least on eentry. | |
| 1269 const ClassTable& class_table = *Isolate::Current()->class_table(); | |
| 1270 if ((*results)[0] != kSmiCid) { | |
| 1271 const Class& cls = Class::Handle(class_table.At(kSmiCid)); | |
| 1272 const Class& type_class = Class::Handle(type.type_class()); | |
| 1273 const bool smi_is_subtype = | |
| 1274 cls.IsSubtypeOf(Object::null_type_arguments(), type_class, | |
| 1275 Object::null_type_arguments(), NULL, NULL, Heap::kOld); | |
| 1276 results->Add((*results)[results->length() - 2]); | |
| 1277 results->Add((*results)[results->length() - 2]); | |
| 1278 for (intptr_t i = results->length() - 3; i > 1; --i) { | |
| 1279 (*results)[i] = (*results)[i - 2]; | |
| 1280 } | |
| 1281 (*results)[0] = kSmiCid; | |
| 1282 (*results)[1] = smi_is_subtype; | |
| 1283 } | |
| 1284 | |
| 1285 ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); | |
| 1286 ASSERT(results->length() >= 2); | |
| 1287 if (type.IsIntType()) { | |
| 1288 ASSERT((*results)[0] == kSmiCid); | |
| 1289 TryAddTest(results, kMintCid, true); | |
| 1290 TryAddTest(results, kBigintCid, true); | |
| 1291 // Cannot deoptimize since all tests returning true have been added. | |
| 1292 return false; | |
| 1293 } | |
| 1294 | |
| 1295 return true; // May deoptimize since we have not identified all 'true' tests. | |
| 1296 } | |
| 1297 | |
| 1298 | |
| 1299 // TODO(srdjan): Use ICData to check if always true or false. | 1245 // TODO(srdjan): Use ICData to check if always true or false. |
| 1300 void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 1246 void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 1301 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 1247 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 1302 Definition* left = call->ArgumentAt(0); | 1248 Definition* left = call->ArgumentAt(0); |
| 1303 Definition* instantiator_type_args = NULL; | 1249 Definition* instantiator_type_args = NULL; |
| 1304 Definition* function_type_args = NULL; | 1250 Definition* function_type_args = NULL; |
| 1305 AbstractType& type = AbstractType::ZoneHandle(Z); | 1251 AbstractType& type = AbstractType::ZoneHandle(Z); |
| 1306 if (call->ArgumentCount() == 2) { | 1252 if (call->ArgumentCount() == 2) { |
| 1307 instantiator_type_args = flow_graph()->constant_null(); | 1253 instantiator_type_args = flow_graph()->constant_null(); |
| 1308 function_type_args = flow_graph()->constant_null(); | 1254 function_type_args = flow_graph()->constant_null(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1332 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1278 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 1333 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); | 1279 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
| 1334 if ((number_of_checks > 0) && | 1280 if ((number_of_checks > 0) && |
| 1335 (number_of_checks <= FLAG_max_polymorphic_checks)) { | 1281 (number_of_checks <= FLAG_max_polymorphic_checks)) { |
| 1336 ZoneGrowableArray<intptr_t>* results = | 1282 ZoneGrowableArray<intptr_t>* results = |
| 1337 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); | 1283 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
| 1338 Bool& as_bool = | 1284 Bool& as_bool = |
| 1339 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 1285 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
| 1340 if (as_bool.IsNull()) { | 1286 if (as_bool.IsNull()) { |
| 1341 if (results->length() == number_of_checks * 2) { | 1287 if (results->length() == number_of_checks * 2) { |
| 1342 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1288 const bool can_deopt = |
| 1289 Optimizer::SpecializeTestCidsForNumericTypes(results, type); |
| 1343 TestCidsInstr* test_cids = new (Z) TestCidsInstr( | 1290 TestCidsInstr* test_cids = new (Z) TestCidsInstr( |
| 1344 call->token_pos(), Token::kIS, new (Z) Value(left), *results, | 1291 call->token_pos(), Token::kIS, new (Z) Value(left), *results, |
| 1345 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1292 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
| 1346 // Remove type. | 1293 // Remove type. |
| 1347 ReplaceCall(call, test_cids); | 1294 ReplaceCall(call, test_cids); |
| 1348 return; | 1295 return; |
| 1349 } | 1296 } |
| 1350 } else { | 1297 } else { |
| 1351 // TODO(srdjan): Use TestCidsInstr also for this case. | 1298 // TODO(srdjan): Use TestCidsInstr also for this case. |
| 1352 // One result only. | 1299 // One result only. |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 // Discard the environment from the original instruction because the store | 1719 // Discard the environment from the original instruction because the store |
| 1773 // can't deoptimize. | 1720 // can't deoptimize. |
| 1774 instr->RemoveEnvironment(); | 1721 instr->RemoveEnvironment(); |
| 1775 ReplaceCall(instr, store); | 1722 ReplaceCall(instr, store); |
| 1776 return true; | 1723 return true; |
| 1777 } | 1724 } |
| 1778 | 1725 |
| 1779 | 1726 |
| 1780 } // namespace dart | 1727 } // namespace dart |
| 1781 #endif // DART_PRECOMPILED_RUNTIME | 1728 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |